# -*- 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()

        print("Mini-NDN experiments:")
        for experiment in experimentNames:
            print("  %s" % 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.isCliEnabled = True
        self.nlsrSecurity = False
        self.nPings = 300
        self.testbed = False
        self.workDir = "/tmp"
        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"

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, ndn_utils/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("--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",
                        help="Specify the working directory; default is /tmp")

    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'])

    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.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

    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)

        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)

    # Use nfd.conf as default configuration for NFD, else use the sample

    nfdConfFile = "%s/nfd.conf" % INSTALL_DIR
    if os.path.isfile("/usr/local/etc/ndn/nfd.conf") == True:
        shutil.copy2("/usr/local/etc/ndn/nfd.conf", nfdConfFile)
    elif os.path.isfile("/usr/local/etc/ndn/nfd.conf.sample") == True:
        shutil.copy2("/usr/local/etc/ndn/nfd.conf.sample", nfdConfFile)
    else:
        sys.exit("nfd.conf or nfd.conf.sample cannot be found in the expected directory. Exit.")

    call(["sudo", "sed", "-i", 's|default_level [A-Z]*$|default_level $LOG_LEVEL|g', nfdConfFile])

    # 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)

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

    # NLSR initialization
    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
        }

        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.SIGINT, signal_handler)

    options = parse_args()

    setLogLevel('info')
    execute(options)
