# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2015-2017, The University of Memphis,
#                          Arizona Board of Regents,
#                          Regents of the University of California.
#
# This file is part of Mini-NDN.
# See AUTHORS.md for a complete list of Mini-NDN authors and contributors.
#
# Mini-NDN is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Mini-NDN is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Mini-NDN, e.g., in COPYING.md file.
# If not, see <http://www.gnu.org/licenses/>.
#
# This file incorporates work covered by the following copyright and
# permission notice:
#
#   Mininet 2.3.0d1 License
#
#   Copyright (c) 2013-2016 Open Networking Laboratory
#   Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
#   The Leland Stanford Junior University
#
#   Original authors: Bob Lantz and Brandon Heller
#
#   We are making Mininet available for public use and benefit with the
#   expectation that others will use, modify and enhance the Software and
#   contribute those enhancements back to the community. However, since we
#   would like to make the Software available for broadest use, with as few
#   restrictions as possible permission is hereby granted, free of charge, to
#   any person obtaining a copy of this Software to deal in the Software
#   under the copyrights without restriction, including without limitation
#   the rights to use, copy, modify, merge, publish, distribute, sublicense,
#   and/or sell copies of the Software, and to permit persons to whom the
#   Software is furnished to do so, subject to the following conditions:
#
#   The above copyright notice and this permission notice shall be included
#   in all copies or substantial portions of the Software.
#
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
#   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
#   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
#   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
#   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
#   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
#   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
#   The name and trademarks of copyright holder(s) may NOT be used in
#   advertising or publicity pertaining to the Software or any derivatives
#   without specific, written prior permission.

from mininet.topo import Topo
from mininet.net import Mininet
from mininet.log import setLogLevel, output, info
from mininet.link import TCLink
from mininet.util import ipStr, ipParse

from mininet.examples.cluster import MininetCluster, RoundRobinPlacer, ClusterCleanup
from mininet.examples.clustercli import ClusterCLI

from ndn import ExperimentManager
from ndn.ndn_host import NdnHost, CpuLimitedNdnHost, RemoteNdnHost
from ndn.conf_parser import parse_hosts, parse_switches, parse_links
from ndn.remote_ndn_link import RemoteNdnLink, RemoteGRENdnLink
from ndn.placer import GuidedPlacer, PopulatePlacement
from ndn.util import ssh, scp, MiniNDNCLI

import os.path, time
import shutil
import argparse
import datetime
from os.path import expanduser
import sys
import signal
from subprocess import call
import glob
from functools import partial
import re

from ndn.nlsr import Nlsr, NlsrConfigGenerator
from ndn.nfd import Nfd

VERSION_NUMBER = "0.3.0"
INSTALL_DIR='/usr/local/etc/mini-ndn/'

class PrintExperimentNames(argparse.Action):
    def __init__(self, option_strings, dest, nargs=0, help=None):
        super(PrintExperimentNames, self).__init__(option_strings=option_strings, dest=dest, nargs=nargs, help=help)

    def __call__(self, parser, namespace, values, option_string=None):
        experimentNames = ExperimentManager.getExperimentNames()
        experimentArgs = ExperimentManager.getExperimentArgs()

        print("Mini-NDN experiments:")
        for experiment in experimentNames:
            print("  {}".format(experiment))
            if experiment in experimentArgs:
                print("      ({})".format(experimentArgs[experiment]))

        sys.exit(0)

class ProgramOptions:
    def __init__(self):
        self.ctime = 60
        self.experimentName = None
        self.nFaces = 3
        self.templateFile = "minindn.conf"
        self.routingType = "link-state"
        self.isNlsrEnabled = True
        self.isCliEnabled = True
        self.nlsrSecurity = False
        self.nPings = 300
        self.testbed = False
        self.workDir = "/tmp/minindn"
        self.resultDir = None
        self.pctTraffic = 1.0
        self.cluster = None
        self.servers = None
        self.guided = None
        self.placer = None
        self.tunnelType = None
        self.faceType = "udp"
        self.arbArgs = {}
        self.csSize = 65536

def createResultsDir(resultDir, faces, rType):
    if faces == 0:
        faces = "all"

    routingChoice = "/{}/".format(rType)

    resultDir = "{}/{}/faces-{}".format(resultDir, routingChoice, faces)
    resultDir = os.path.abspath(resultDir)

    if not os.path.isdir(resultDir):
        os.makedirs(resultDir)
    else:
        print("Results directory (%s) already exists!" % resultDir)
        sys.exit(1);

    print("Results will be stored at: %s" % resultDir)
    return resultDir

def parse_args():
    parser = argparse.ArgumentParser(prog='minindn')

    # nargs='?' required here since optional argument
    parser.add_argument('tempfile', nargs='?', default=INSTALL_DIR + 'default-topology.conf',
                        help="If no template_file is given, topologies/default-topology.conf (given sample file) will be used.")

    parser.add_argument("--ctime", type=int, default=60,
                        help="Specify convergence time for the topology (Default: 60 seconds)")

    parser.add_argument("--experiment",
                        help="Runs the specified experiment")

    parser.add_argument("--faces", type=int, default=3,
                        help="Specify number of faces 0-60")

    parser.add_argument("--routing", dest="routingType", default='link-state', choices=['link-state', 'hr', 'dry'],
                        help="""choices for routing are 'link-state' for link state, 'hr' for hyperbolic, and 'dry'
                        to test hyperbolic routing and compare with link state. Default is link-state.""")

    parser.add_argument("--no-nlsr", action="store_false", dest="isNlsrEnabled",
                        help="Run mini-ndn without NLSR routing")

    parser.add_argument("--list-experiments", action=PrintExperimentNames,
                        help="Lists the names of all available experiments")

    parser.add_argument("--no-cli", action="store_false", dest="isCliEnabled",
                        help="Run experiments and exit without showing the command line interface")

    parser.add_argument("--nPings", type=int, default=300,
                        help="Number of pings to perform between each node in the experiment")

    # store_true stores default value of False
    parser.add_argument("--nlsr-security", action="store_true", dest="nlsrSecurity",
                        help="Enables NLSR security")

    parser.add_argument("-t", "--testbed", action="store_true", dest="testbed",
                         help="Instantiates a snapshot of the NDN Testbed irrespective of the tempfile provided")

    parser.add_argument("--work-dir", action="store", dest="workDir", default="/tmp/minindn",
                        help="Specify the working directory; default is /tmp/minindn")

    parser.add_argument("--result-dir", action="store", dest="resultDir", default=None,
                        help="Specify the full path destination folder where experiment results will be moved")

    parser.add_argument("--pct-traffic", dest="pctTraffic", type=float, default=1.0,
                        help="Specify the percentage of nodes each node should ping")

    parser.add_argument('--version', '-V', action='version', version='%(prog)s ' + VERSION_NUMBER,
                        help='Displays version information')

    parser.add_argument("--cluster", metavar='localhost,server2,...',
                        help="Run cluster edition")

    parser.add_argument("--placement", default='guided',
                        choices=['roundRobin', 'guided'])

    parser.add_argument("--place-list", dest="placeList",
                        help="""Provide corresponding number of nodes (comma separated) to put on
                        each node respectively of --cluster when guided placement is used""")

    parser.add_argument("--tunnel-type", dest="tunnelType", default='ssh',
                        choices=['ssh', 'gre'])

    parser.add_argument("--face-type", dest='faceType', default='udp', choices=['udp', 'tcp'])

    parser.add_argument("--cs-size", dest='csSize', type=int, default=65536,
                        help="Set CS size in NFD's conf file")

    args, unknownArgs = parser.parse_known_args()

    unknownArgsList = []
    for arg in unknownArgs:
        if arg.startswith(("--")):
            parser.add_argument(arg)
            unknownArgsList.append(arg.split("--")[1])

    args = parser.parse_args()

    options = ProgramOptions()
    options.templateFile = args.tempfile
    options.ctime = args.ctime
    options.experimentName = args.experiment
    options.nFaces = args.faces
    options.routingType = args.routingType
    options.isNlsrEnabled = args.isNlsrEnabled
    options.isCliEnabled = args.isCliEnabled
    options.nlsrSecurity = args.nlsrSecurity
    options.nPings = args.nPings

    options.testbed = args.testbed
    options.workDir = args.workDir
    options.resultDir = args.resultDir
    options.pctTraffic = args.pctTraffic
    options.cluster = args.cluster
    options.placement = args.placement
    options.tunnelType = args.tunnelType
    options.placeList = args.placeList
    options.faceType = args.faceType
    options.csSize = args.csSize

    for k in args.__dict__:
        if k in unknownArgsList:
            options.arbArgs[k] = args.__dict__[k]

    if options.experimentName is not None and options.experimentName not in ExperimentManager.getExperimentNames():
        print("No experiment named %s" % options.experimentName)
        sys.exit(1)

    if options.experimentName is not None and options.resultDir is None:
        print("No results folder specified; experiment results will remain in the working directory")

    if options.cluster is not None:
        servers = options.cluster.split(',')
        for server in servers:
            ClusterCleanup.add(server)
        options.servers = servers

        if options.placement == "roundRobin":
            options.placement = RoundRobinPlacer
        elif options.placement == "guided":
            if options.placeList is None or not re.match("^[0-9,]+$", options.placeList):
                print("Please specify correctly how many nodes you want to place on each node!")
                sys.exit(1)
            else:
                try:
                    options.placeList = map(int, options.placeList.split(","))
                except ValueError:
                    print("Please specify the nodes correctly, no comma at the beginning/end!")
                    sys.exit(1)

                PopulatePlacement(options.placeList)
                options.placement = GuidedPlacer

        if options.tunnelType == "ssh":
            options.tunnelType = RemoteNdnLink
        else:
            options.tunnelType = RemoteGRENdnLink

    return options

class NdnTopo(Topo):
    def __init__(self, conf_arq, workDir, **opts):
        Topo.__init__(self, **opts)

        global hosts_conf
        global links_conf
        hosts_conf = parse_hosts(conf_arq)
        switches_conf = parse_switches(conf_arq)
        links_conf = parse_links(conf_arq)

        self.isTCLink = False
        self.isLimited = False

        for host in hosts_conf:
            if host.cpu != None and self.isLimited != True:
                self.isLimited = True
            self.addHost(host.name, app=host.app, params=host.uri_tuples, cpu=host.cpu,
                         cores=host.cores,cache=host.cache, workdir=workDir)
            if (options.routingType != 'link-state' and (host.params.get('radius') is None
                or host.params.get('angle') is None)):
                info('Hyperbolic coordinates in topology file are either missing or misconfigured.\n' \
                     'Check that each node has one radius value and one or two angle value(s).\n')
                sys.exit(1)

        for switch in switches_conf:
            self.addSwitch(switch.name)

        for link in links_conf:
            if len(link.linkDict) == 0:
                self.addLink(link.h1, link.h2)
            else:
                self.addLink(link.h1, link.h2, **link.linkDict)
                self.isTCLink = True

        info('Parse of ' + conf_arq + ' done.\n')

def execute(options):
    "Create a network based on template_file"

    if options.testbed:
        options.templateFile = INSTALL_DIR + 'minindn.testbed.conf'

    if os.path.exists(options.templateFile) == False:
        info('Template file cannot be found. Exiting...\n')
        sys.exit(1)

    if options.cluster is not None and options.placement == GuidedPlacer:
        num_nodes = 0
        with open(options.templateFile, 'r') as topo:
            for line in topo:
                if ': _' in line:
                    num_nodes += 1

        if sum(options.placeList) != num_nodes:
            print("Placement list sum is not equal to number of nodes!")
            sys.exit(1)

    # Copy nfd.conf to remote hosts - this assumes that NDN versions across
    # the cluster are at least compatible if not the same
    if options.cluster is not None:
        for server in options.servers:
            if server != "localhost":
                login = "mininet@%s" % server
                src = nfdConfFile
                dst = "%s:/tmp/nfd.conf" % (login)
                scp(src, dst)
                ssh(login, "sudo cp /tmp/nfd.conf %s" % src)

    if options.resultDir is not None:
        options.resultDir = createResultsDir(options.resultDir, options.nFaces, options.routingType)

    topo = NdnTopo(options.templateFile, options.workDir)

    t = datetime.datetime.now()

    if topo.isTCLink == True and topo.isLimited == True:
        net = Mininet(topo,host=CpuLimitedNdnHost,link=TCLink)
    elif topo.isTCLink == True and topo.isLimited == False:
        if options.cluster is not None:
            mn = partial(MininetCluster, servers=options.servers, placement=options.placement)
            net = mn(topo=topo, host=RemoteNdnHost, link=options.tunnelType)
        else:
            net = Mininet(topo, host=NdnHost, link=TCLink)
    elif topo.isTCLink == False and topo.isLimited == True:
        net = Mininet(topo, host=CpuLimitedNdnHost)
    else:
        net = Mininet(topo, host=NdnHost)

    t2 = datetime.datetime.now()

    delta = t2 - t

    info('Setup time: ' + str(delta.seconds) + '\n')

    net.start()

    # Giving proper IPs to intf so neighbor nodes can communicate
    # This is one way of giving connectivity, another way could be
    # to insert a switch between each pair of neighbors
    ndnNetBase = "1.0.0.0"
    interfaces = []
    for host in net.hosts:
        for intf in host.intfList():
            link = intf.link
            node1, node2 = link.intf1.node, link.intf2.node

            if node1 in net.switches or node2 in net.switches:
                continue

            if link.intf1 not in interfaces and link.intf2 not in interfaces:
                interfaces.append(link.intf1)
                interfaces.append(link.intf2)
                node1.setIP(ipStr(ipParse(ndnNetBase) + 1) + '/30', intf=link.intf1)
                node2.setIP(ipStr(ipParse(ndnNetBase) + 2) + '/30', intf=link.intf2)
                ndnNetBase = ipStr(ipParse(ndnNetBase) + 4)

    time.sleep(2)
    info('Starting NFD on nodes\n')
    for host in net.hosts:
        host.nfd = Nfd(host, options.csSize)
        host.nfd.start()

    if options.isNlsrEnabled is True:

        # NLSR Security
        if options.nlsrSecurity is True:
            Nlsr.createKeysAndCertificates(net, options.workDir)

        # NLSR initialization
        info('Starting NLSR on nodes\n')
        for host in net.hosts:
            conf = next(x for x in hosts_conf if x.name == host.name)
            host.nlsrParameters = conf.nlsrParameters

            if options.nFaces is not None:
                host.nlsrParameters["max-faces-per-prefix"] = options.nFaces

            if options.routingType == 'dry':
                host.nlsrParameters["hyperbolic-state"] = "dry-run"

            elif options.routingType == 'hr':
                host.nlsrParameters["hyperbolic-state"] = "on"

            # Generate NLSR configuration file
            configGenerator = NlsrConfigGenerator(host, options.nlsrSecurity, options.faceType)
            configGenerator.createConfigFile()

            # Start NLSR
            host.nlsr = Nlsr(host, configGenerator.neighborIPs, options.faceType)
            host.nlsr.start()

    for host in net.hosts:
        if 'app' in host.params:
            if host.params['app'] != '':
                app = host.params['app']
                print("Starting " + app + " on node " + host.name)
                print(host.cmd(app))

    # Load experiment
    experimentName = options.experimentName

    if experimentName is not None:
        print("Loading experiment: %s" % experimentName)

        experimentArgs = {
            "net": net,
            "ctime": options.ctime,
            "nPings": options.nPings,
            "strategy": Nfd.STRATEGY_BEST_ROUTE,
            "pctTraffic": options.pctTraffic,
            "nlsrSecurity": options.nlsrSecurity,
            "workDir": options.workDir,
            "arbArgs" : options.arbArgs
        }

        experiment = ExperimentManager.create(experimentName, experimentArgs)

        if experiment is not None:
            experiment.start()
        else:
            print("ERROR: Experiment '%s' does not exist" % experimentName)
            return

    if options.isCliEnabled is True:
        MiniNDNCLI(net)

    net.stop()

    if options.resultDir is not None:
        print("Moving results to %s" % options.resultDir)
        for file in glob.glob('%s/*' % options.workDir):
            shutil.move(file, options.resultDir)
        if options.cluster is not None:
            for server in options.servers:
                if server != "localhost":
                    login = "mininet@%s" % server
                    src = "%s:%s/*" % (login, options.workDir)
                    dst = options.resultDir
                    scp(src, dst)
            print("Please clean work directories of other machines before running the cluster again")

def signal_handler(signal, frame):
    print('Cleaning up...')
    call(["nfd-stop"])
    call(["sudo", "mn", "--clean"])
    sys.exit(1)

if __name__ == '__main__':

    hosts_conf = []
    links_conf = []

    signal.signal(signal.SIGQUIT, signal_handler)

    options = parse_args()

    setLogLevel('info')

    # No exceptions are raised in ndn presently, and Mininet relies
    # on generic Exception. If this situation changes this may well
    # need to be altered.
    try:
        execute(options)
    except Exception as e:
        print("Mininet Error: {}".format(e))
        call(["nfd-stop"])
        call(["sudo", "mn", "--clean"])
        sys.exit(1)