Beispiel #1
0
    def make_experiment_desc(self, use_sfa=False):
        testbed_id = self.testbed_id
        slicename = self.slicename
        plchost = self.plchost
        pl_ssh_key = os.environ.get(
            "PL_SSH_KEY", "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'], ))
        pl_user, pl_pwd = test_util.pl_auth()

        exp_desc = ExperimentDescription()
        pl_provider = FactoriesProvider(testbed_id)
        pl_desc = exp_desc.add_testbed_description(pl_provider)
        pl_desc.set_attribute_value("homeDirectory", self.root_dir)
        pl_desc.set_attribute_value("slice", slicename)
        pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
        pl_desc.set_attribute_value("authUser", pl_user)
        pl_desc.set_attribute_value("authPass", pl_pwd)
        pl_desc.set_attribute_value("plcHost", plchost)
        pl_desc.set_attribute_value("tapPortBase", self.port_base)
        pl_desc.set_attribute_value(
            "p2pDeployment",
            False)  # it's interactive, we don't want it in tests
        pl_desc.set_attribute_value("cleanProc", True)
        pl_desc.set_attribute_value("plLogLevel", "DEBUG")
        if use_sfa:
            pl_desc.set_attribute_value("sfa", True)
            pl_desc.set_attribute_value("sliceHrn", self.slicehrn)

        return pl_desc, exp_desc
Beispiel #2
0
    def make_experiment_desc(self, use_sfa=False):
        testbed_id = self.testbed_id
        slicename = self.slicename
        plchost = self.plchost
        pl_ssh_key = os.environ.get("PL_SSH_KEY", "%s/.ssh/id_rsa_planetlab" % (os.environ["HOME"],))
        pl_user, pl_pwd = test_util.pl_auth()

        exp_desc = ExperimentDescription()
        pl_provider = FactoriesProvider(testbed_id)
        pl_desc = exp_desc.add_testbed_description(pl_provider)
        pl_desc.set_attribute_value("homeDirectory", self.root_dir)
        pl_desc.set_attribute_value("slice", slicename)
        pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
        pl_desc.set_attribute_value("authUser", pl_user)
        pl_desc.set_attribute_value("authPass", pl_pwd)
        pl_desc.set_attribute_value("plcHost", plchost)
        pl_desc.set_attribute_value("tapPortBase", self.port_base)
        pl_desc.set_attribute_value("p2pDeployment", False)  # it's interactive, we don't want it in tests
        pl_desc.set_attribute_value("cleanProc", True)
        pl_desc.set_attribute_value("plLogLevel", "DEBUG")
        if use_sfa:
            pl_desc.set_attribute_value("sfa", True)
            pl_desc.set_attribute_value("sliceHrn", self.slicehrn)

        return pl_desc, exp_desc
Beispiel #3
0
    def make_instance(self):
        testbed_id = self.testbed_id
        slicename = self.slicename
        plchost = self.plchost

        instance = planetlab.TestbedController()
        pl_ssh_key = os.environ.get(
            "PL_SSH_KEY", "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'], ))
        slicename = os.environ.get("PL_SLICE", slicename)
        pl_user, pl_pwd = test_util.pl_auth()

        instance.defer_configure("homeDirectory", self.root_dir)
        instance.defer_configure("slice", slicename)
        instance.defer_configure("sliceSSHKey", pl_ssh_key)
        instance.defer_configure("authUser", pl_user)
        instance.defer_configure("authPass", pl_pwd)
        instance.defer_configure("plcHost", plchost)
        instance.defer_configure("tapPortBase", self.port_base)
        instance.defer_configure(
            "p2pDeployment",
            False)  # it's interactive, we don't want it in tests
        instance.defer_configure("cleanProc", True)

        # Hack, but we need vsys_vnet
        instance.do_setup()
        vnet = instance.vsys_vnet
        self.net_prefix = vnet.rsplit('.', 1)[0]

        return instance
Beispiel #4
0
 def make_instance(self):
     testbed_id = self.testbed_id
     slicename = self.slicename
     plchost = self.plchost
     
     instance = planetlab.TestbedController()
     pl_ssh_key = os.environ.get(
         "PL_SSH_KEY",
         "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
     slicename = os.environ.get(
         "PL_SLICE",
         slicename)
     pl_user, pl_pwd = test_util.pl_auth()
     
     instance.defer_configure("homeDirectory", self.root_dir)
     instance.defer_configure("slice", slicename)
     instance.defer_configure("sliceSSHKey", pl_ssh_key)
     instance.defer_configure("authUser", pl_user)
     instance.defer_configure("authPass", pl_pwd)
     instance.defer_configure("plcHost", plchost)
     instance.defer_configure("tapPortBase", self.port_base)
     instance.defer_configure("p2pDeployment", False) # it's interactive, we don't want it in tests
     instance.defer_configure("cleanProc", True)
     
     # Hack, but we need vsys_vnet
     instance.do_setup()
     vnet = instance.vsys_vnet
     self.net_prefix = vnet.rsplit('.',1)[0]
     
     return instance
Beispiel #5
0
    def make_experiment_desc(self):
        testbed_id = self.testbed_id

        slicename1 = self.slicename1
        plchost1 = self.plchost1

        slicename2 = self.slicename2
        plchost2 = self.plchost2

        pl_ssh_key = os.environ.get(
            "PL_SSH_KEY", "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'], ))
        pl_user, pl_pwd = test_util.pl_auth()

        exp_desc = ExperimentDescription()
        pl_provider = FactoriesProvider(testbed_id)
        pl_desc = exp_desc.add_testbed_description(pl_provider)
        pl_desc.set_attribute_value("homeDirectory", self.root_dir)
        pl_desc.set_attribute_value("slice", slicename1)
        pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
        pl_desc.set_attribute_value("authUser", pl_user)
        pl_desc.set_attribute_value("authPass", pl_pwd)
        pl_desc.set_attribute_value("plcHost", plchost1)
        pl_desc.set_attribute_value("tapPortBase", self.port_base)
        pl_desc.set_attribute_value(
            "p2pDeployment",
            False)  # it's interactive, we don't want it in tests
        pl_desc.set_attribute_value("cleanProc", True)

        pl_desc2 = exp_desc.add_testbed_description(pl_provider)
        pl_desc2.set_attribute_value("homeDirectory", self.root_dir + "v2")
        pl_desc2.set_attribute_value("slice", slicename2)
        pl_desc2.set_attribute_value("sliceSSHKey", pl_ssh_key)
        pl_desc2.set_attribute_value("authUser", pl_user)
        pl_desc2.set_attribute_value("authPass", pl_pwd)
        pl_desc2.set_attribute_value("plcHost", plchost2)
        pl_desc2.set_attribute_value("tapPortBase", self.port_base + 500)
        pl_desc2.set_attribute_value(
            "p2pDeployment",
            False)  # it's interactive, we don't want it in tests
        pl_desc2.set_attribute_value("cleanProc", True)

        return pl_desc, pl_desc2, exp_desc
Beispiel #6
0
    def make_experiment_desc(self):
        testbed_id = self.testbed_id
        
        slicename1 = self.slicename1
        plchost1 = self.plchost1
        
        slicename2 = self.slicename2
        plchost2 = self.plchost2
        
        pl_ssh_key = os.environ.get(
            "PL_SSH_KEY",
            "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'],) )
        pl_user, pl_pwd = test_util.pl_auth()

        exp_desc = ExperimentDescription()
        pl_provider = FactoriesProvider(testbed_id)
        pl_desc = exp_desc.add_testbed_description(pl_provider)
        pl_desc.set_attribute_value("homeDirectory", self.root_dir)
        pl_desc.set_attribute_value("slice", slicename1)
        pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
        pl_desc.set_attribute_value("authUser", pl_user)
        pl_desc.set_attribute_value("authPass", pl_pwd)
        pl_desc.set_attribute_value("plcHost", plchost1)
        pl_desc.set_attribute_value("tapPortBase", self.port_base)
        pl_desc.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
        pl_desc.set_attribute_value("cleanProc", True)

        pl_desc2 = exp_desc.add_testbed_description(pl_provider)
        pl_desc2.set_attribute_value("homeDirectory", self.root_dir+"v2")
        pl_desc2.set_attribute_value("slice", slicename2)
        pl_desc2.set_attribute_value("sliceSSHKey", pl_ssh_key)
        pl_desc2.set_attribute_value("authUser", pl_user)
        pl_desc2.set_attribute_value("authPass", pl_pwd)
        pl_desc2.set_attribute_value("plcHost", plchost2)
        pl_desc2.set_attribute_value("tapPortBase", self.port_base+500)
        pl_desc2.set_attribute_value("p2pDeployment", False) # it's interactive, we don't want it in tests
        pl_desc2.set_attribute_value("cleanProc", True)
        
        return pl_desc, pl_desc2, exp_desc
Beispiel #7
0
class PlanetLabMultiIntegrationTestCase(unittest.TestCase):
    testbed_id = "planetlab"

    slicename1 = "inria_nepi"
    plchost1 = "nepiplc.pl.sophia.inria.fr"

    slicename2 = "inria_nepi12"
    plchost2 = "www.planet-lab.eu"

    host1pl1 = "nepi1.pl.sophia.inria.fr"
    host2pl1 = "nepi2.pl.sophia.inria.fr"

    host1pl2 = "planetlab1.utt.fr"
    host2pl2 = "planetlab2.utt.fr"

    port_base = 2000 + (os.getpid() % 1000) * 13

    def setUp(self):
        self.root_dir = tempfile.mkdtemp()
        self.__class__.port_base = self.port_base + 100

    def tearDown(self):
        try:
            shutil.rmtree(self.root_dir)
        except:
            # retry
            time.sleep(0.1)
            shutil.rmtree(self.root_dir)

    def make_experiment_desc(self):
        testbed_id = self.testbed_id

        slicename1 = self.slicename1
        plchost1 = self.plchost1

        slicename2 = self.slicename2
        plchost2 = self.plchost2

        pl_ssh_key = os.environ.get(
            "PL_SSH_KEY", "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'], ))
        pl_user, pl_pwd = test_util.pl_auth()

        exp_desc = ExperimentDescription()
        pl_provider = FactoriesProvider(testbed_id)
        pl_desc = exp_desc.add_testbed_description(pl_provider)
        pl_desc.set_attribute_value("homeDirectory", self.root_dir)
        pl_desc.set_attribute_value("slice", slicename1)
        pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
        pl_desc.set_attribute_value("authUser", pl_user)
        pl_desc.set_attribute_value("authPass", pl_pwd)
        pl_desc.set_attribute_value("plcHost", plchost1)
        pl_desc.set_attribute_value("tapPortBase", self.port_base)
        pl_desc.set_attribute_value(
            "p2pDeployment",
            False)  # it's interactive, we don't want it in tests
        pl_desc.set_attribute_value("cleanProc", True)

        pl_desc2 = exp_desc.add_testbed_description(pl_provider)
        pl_desc2.set_attribute_value("homeDirectory", self.root_dir + "v2")
        pl_desc2.set_attribute_value("slice", slicename2)
        pl_desc2.set_attribute_value("sliceSSHKey", pl_ssh_key)
        pl_desc2.set_attribute_value("authUser", pl_user)
        pl_desc2.set_attribute_value("authPass", pl_pwd)
        pl_desc2.set_attribute_value("plcHost", plchost2)
        pl_desc2.set_attribute_value("tapPortBase", self.port_base + 500)
        pl_desc2.set_attribute_value(
            "p2pDeployment",
            False)  # it's interactive, we don't want it in tests
        pl_desc2.set_attribute_value("cleanProc", True)

        return pl_desc, pl_desc2, exp_desc

    def make_pl_tapnode(self, pl, tapip, hostname, label_prefix):
        node1 = pl.create("Node")
        node1.set_attribute_value("hostname", hostname)
        node1.set_attribute_value("label", label_prefix)
        iface1 = pl.create("NodeInterface")
        iface1.set_attribute_value("label", label_prefix + "iface")
        if tapip:
            tap1 = pl.create("TapInterface")
            tap1.enable_trace("packets")  # for error output
            tap1.set_attribute_value("label", label_prefix + "tap")

            node1.connector("devs").connect(tap1.connector("node"))

            tap1ip = tap1.add_address()
            tap1ip.set_attribute_value("Address", tapip)
            tap1ip.set_attribute_value("NetPrefix", 24)
            tap1ip.set_attribute_value("Broadcast", False)
        else:
            tap1 = None
            tap1ip = None
        inet = pl.create("Internet")
        node1.connector("devs").connect(iface1.connector("node"))
        iface1.connector("inet").connect(inet.connector("devs"))

        return node1, iface1, tap1, tap1ip, inet

    def make_ns_in_pl(self, pl, exp, node1, iface1, root):
        ns3_testbed_id = "ns3"

        # Add NS3 support in node1
        plnepi = pl.create("NepiDependency")
        plns3 = pl.create("NS3Dependency")
        plnepi.connector("node").connect(node1.connector("deps"))
        plns3.connector("node").connect(node1.connector("deps"))

        # Create NS3 testbed running in node1
        ns3_provider = FactoriesProvider(ns3_testbed_id)
        ns3_desc = exp.add_testbed_description(ns3_provider)
        ns3_desc.set_attribute_value("rootDirectory", root)
        ns3_desc.set_attribute_value("SimulatorImplementationType",
                                     "ns3::RealtimeSimulatorImpl")
        ns3_desc.set_attribute_value("ChecksumEnabled", True)
        ns3_desc.set_attribute_value(
            DC.DEPLOYMENT_HOST, "{#[%s].addr[0].[Address]#}" %
            (iface1.get_attribute_value("label"), ))
        ns3_desc.set_attribute_value(DC.DEPLOYMENT_USER,
                                     pl.get_attribute_value("slice"))
        ns3_desc.set_attribute_value(DC.DEPLOYMENT_KEY,
                                     pl.get_attribute_value("sliceSSHKey"))
        ns3_desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
        ns3_desc.set_attribute_value(DC.DEPLOYMENT_COMMUNICATION,
                                     DC.ACCESS_SSH)
        ns3_desc.set_attribute_value(
            DC.DEPLOYMENT_ENVIRONMENT_SETUP, "{#[%s].[%s]#}" % (
                node1.get_attribute_value("label"),
                ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP,
            ))
        ns3_desc.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)

        return ns3_desc

    def _test_plns3_crossconnect(self, proto):
        pl, pl2, exp = self.make_experiment_desc()

        # Create PL node, ifaces, assign addresses
        node1, iface1, _, _, inet1 = self.make_pl_tapnode(
            pl, None, self.host1pl1, "node1")
        node2, iface2, tap2, tap2ip, inet2 = self.make_pl_tapnode(
            pl2, "192.168.2.3", self.host1pl2, "node2")

        # Create NS3 instance in node1
        # With a node and all required protocols to be pinged
        ns3 = self.make_ns_in_pl(pl, exp, node1, iface1, "tb-ns-rcross-1")

        ns1 = ns3.create("ns3::Node")
        ipv41 = ns3.create("ns3::Ipv4L3Protocol")
        arp1 = ns3.create("ns3::ArpL3Protocol")
        icmp1 = ns3.create("ns3::Icmpv4L4Protocol")
        ns1.connector("protos").connect(ipv41.connector("node"))
        ns1.connector("protos").connect(arp1.connector("node"))
        ns1.connector("protos").connect(icmp1.connector("node"))
        ns1if = ns3.create("ns3::FdNetDevice")
        ns1if.enable_trace("FdPcapTrace")
        ns1if.set_attribute_value("label", "ns1if")
        ns1tc = ns3.create("ns3::Nepi::TunChannel")
        ns1.connector("devs").connect(ns1if.connector("node"))
        ns1tc.connector("fd->").connect(ns1if.connector("->fd"))
        ip1 = ns1if.add_address()
        ip1.set_attribute_value("Address", "192.168.2.2")
        ip1.set_attribute_value("NetPrefix", 24)
        ip1.set_attribute_value("Broadcast", False)

        # Connect the two
        tap2.connector(proto).connect(ns1tc.connector(proto))

        # Create PlanetLab ping application, pinging the from one PL to another
        ping = pl2.create("Application")
        ping.set_attribute_value("command",
                                 "ping -qc10 {#[ns1if].addr[0].[Address]#}")
        ping.enable_trace("stdout")
        ping.enable_trace("stderr")
        ping.connector("node").connect(node2.connector("apps"))

        comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.

--- .* ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time \d*ms.*
"""

        xml = exp.to_xml()

        controller = ExperimentController(xml, self.root_dir)

        try:
            controller.start()

            while not controller.is_finished(ping.guid):
                time.sleep(0.5)

            ping_result = controller.trace(ping.guid, "stdout")
            tap2_trace = controller.trace(tap2.guid, "packets")
        finally:
            try:
                controller.stop()
            except:
                import traceback
                traceback.print_exc()
            try:
                controller.shutdown()
            except:
                import traceback
                traceback.print_exc()

        # asserts at the end, to make sure there's proper cleanup
        self.assertTrue(
            re.match(comp_result, ping_result,
                     re.MULTILINE), "Unexpected trace:\n%s\nTap trace:\n%s\n" %
            (ping_result, tap2_trace))

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    @test_util.skipUnless(
        os.environ.get('NEPI_FULL_TESTS',
                       '').lower() in ('1', 'yes', 'true', 'on'),
        "Test is expensive, requires NEPI_FULL_TESTS=yes")
    def test_plns3_crossconnect_udp(self):
        self._test_plns3_crossconnect("udp")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    @test_util.skipUnless(
        os.environ.get('NEPI_FULL_TESTS',
                       '').lower() in ('1', 'yes', 'true', 'on'),
        "Test is expensive, requires NEPI_FULL_TESTS=yes")
    def test_plns3_crossconnect_tcp(self):
        self._test_plns3_crossconnect("tcp")
Beispiel #8
0
class PlanetLabIntegrationTestCase(unittest.TestCase):
    testbed_id = "planetlab"
    slicename = "inria_nepi"
    slicehrn = "nepi.inria.nepi"
    plchost = "nepiplc.pl.sophia.inria.fr"

    host1 = "nepi1.pl.sophia.inria.fr"
    host2 = "nepi2.pl.sophia.inria.fr"
    host3 = "nepi3.pl.sophia.inria.fr"
    host4 = "nepi5.pl.sophia.inria.fr"

    port_base = 2000 + (os.getpid() % 1000) * 13

    def setUp(self):
        self.root_dir = tempfile.mkdtemp()
        self.__class__.port_base = self.port_base + 100

    def tearDown(self):
        try:
            shutil.rmtree(self.root_dir)
        except:
            # retry
            time.sleep(0.1)
            shutil.rmtree(self.root_dir)

    def make_experiment_desc(self, use_sfa=False):
        testbed_id = self.testbed_id
        slicename = self.slicename
        plchost = self.plchost
        pl_ssh_key = os.environ.get(
            "PL_SSH_KEY", "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'], ))
        pl_user, pl_pwd = test_util.pl_auth()

        exp_desc = ExperimentDescription()
        pl_provider = FactoriesProvider(testbed_id)
        pl_desc = exp_desc.add_testbed_description(pl_provider)
        pl_desc.set_attribute_value("homeDirectory", self.root_dir)
        pl_desc.set_attribute_value("slice", slicename)
        pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
        pl_desc.set_attribute_value("authUser", pl_user)
        pl_desc.set_attribute_value("authPass", pl_pwd)
        pl_desc.set_attribute_value("plcHost", plchost)
        pl_desc.set_attribute_value("tapPortBase", self.port_base)
        pl_desc.set_attribute_value(
            "p2pDeployment",
            False)  # it's interactive, we don't want it in tests
        pl_desc.set_attribute_value("cleanProc", True)
        pl_desc.set_attribute_value("plLogLevel", "DEBUG")
        if use_sfa:
            pl_desc.set_attribute_value("sfa", True)
            pl_desc.set_attribute_value("sliceHrn", self.slicehrn)

        return pl_desc, exp_desc

    def _test_simple(self,
                     daemonize_testbed,
                     controller_access_configuration,
                     environ=None,
                     use_sfa=False):
        pl, exp = self.make_experiment_desc(use_sfa)

        node1 = pl.create("Node")
        node2 = pl.create("Node")
        node1.set_attribute_value("hostname", self.host1)
        node2.set_attribute_value("hostname", self.host2)
        iface1 = pl.create("NodeInterface")
        iface2 = pl.create("NodeInterface")
        iface2.set_attribute_value("label", "node2iface")
        inet = pl.create("Internet")
        node1.connector("devs").connect(iface1.connector("node"))
        node2.connector("devs").connect(iface2.connector("node"))
        iface1.connector("inet").connect(inet.connector("devs"))
        iface2.connector("inet").connect(inet.connector("devs"))
        app = pl.create("Application")
        app.set_attribute_value(
            "command", "ping -qc1 {#[node2iface].addr[0].[Address]#}")
        app.enable_trace("stdout")
        app.connector("node").connect(node1.connector("apps"))

        if daemonize_testbed:
            pl.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
            inst_root_dir = os.path.join(self.root_dir, "instance")
            os.mkdir(inst_root_dir)
            pl.set_attribute_value(DC.ROOT_DIRECTORY, inst_root_dir)
            pl.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)

            if environ:
                pl.set_attribute_value(DC.DEPLOYMENT_ENVIRONMENT_SETUP,
                                       environ)

        xml = exp.to_xml()

        if controller_access_configuration:
            controller = proxy.create_experiment_controller(
                xml, controller_access_configuration)
        else:
            controller = ExperimentController(xml, self.root_dir)

        try:
            controller.start()
            while not controller.is_finished(app.guid):
                time.sleep(0.5)
            ping_result = controller.trace(app.guid, "stdout")
            comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.

--- .* ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time \d*ms.*
"""
            self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
                            "Unexpected trace:\n" + ping_result)

        finally:
            try:
                controller.stop()
            except:
                import traceback
                traceback.print_exc()
            try:
                controller.shutdown()
            except:
                import traceback
                traceback.print_exc()

    def _test_spanning_deployment(self, use_sfa=False):
        pl, exp = self.make_experiment_desc(use_sfa)

        pl.set_attribute_value(
            "p2pDeployment", True)  # we do want it here - even if interactive

        from nepi.testbeds import planetlab as plpackage

        nodes = [pl.create("Node") for i in xrange(4)]
        ifaces = [pl.create("NodeInterface") for node in nodes]
        inet = pl.create("Internet")
        for node, iface in zip(nodes, ifaces):
            node.connector("devs").connect(iface.connector("node"))
            iface.connector("inet").connect(inet.connector("devs"))

        apps = []
        for node in nodes:
            app = pl.create("Application")
            app.set_attribute_value("command", "./consts")
            app.set_attribute_value("buildDepends", "gcc")
            app.set_attribute_value("build",
                                    "gcc ${SOURCES}/consts.c -o consts")
            app.set_attribute_value("install", "cp consts ${SOURCES}/consts")
            app.set_attribute_value(
                "sources",
                os.path.join(os.path.dirname(plpackage.__file__), 'scripts',
                             'consts.c'))
            app.enable_trace("stdout")
            app.enable_trace("stderr")
            app.enable_trace("buildlog")
            node.connector("apps").connect(app.connector("node"))
            apps.append(app)

        comp_result = \
r""".*ETH_P_ALL = 0x[0-9a-fA-F]{8}
ETH_P_IP = 0x[0-9a-fA-F]{8}
TUNGETIFF = 0x[0-9a-fA-F]{8}
TUNSETIFF = 0x[0-9a-fA-F]{8}
IFF_NO_PI = 0x[0-9a-fA-F]{8}
IFF_TAP = 0x[0-9a-fA-F]{8}
IFF_TUN = 0x[0-9a-fA-F]{8}
IFF_VNET_HDR = 0x[0-9a-fA-F]{8}
TUN_PKT_STRIP = 0x[0-9a-fA-F]{8}
IFHWADDRLEN = 0x[0-9a-fA-F]{8}
IFNAMSIZ = 0x[0-9a-fA-F]{8}
IFREQ_SZ = 0x[0-9a-fA-F]{8}
FIONREAD = 0x[0-9a-fA-F]{8}.*
"""

        comp_build = r".*(Identity added|gcc).*"

        xml = exp.to_xml()

        controller = ExperimentController(xml, self.root_dir)
        try:
            controller.start()
            while not all(controller.is_finished(app.guid) for app in apps):
                time.sleep(0.5)

            for app in apps:
                app_result = controller.trace(app.guid, "stdout") or ""
                self.assertTrue(
                    re.match(comp_result, app_result, re.MULTILINE),
                    "Unexpected trace:\n" + app_result)

                build_result = controller.trace(app.guid, "buildlog") or ""
                self.assertTrue(
                    re.match(comp_build, build_result,
                             re.MULTILINE | re.DOTALL),
                    "Unexpected trace:\n" + build_result)

        finally:
            try:
                controller.stop()
            except:
                import traceback
                traceback.print_exc()
            try:
                controller.shutdown()
            except:
                import traceback
                traceback.print_exc()

    def _test_recover(self,
                      daemonize_testbed,
                      controller_access_configuration,
                      environ=None,
                      use_sfa=False):
        pl, exp = self.make_experiment_desc(use_sfa)

        pl.set_attribute_value(DC.RECOVERY_POLICY, DC.POLICY_RECOVER)

        node1 = pl.create("Node")
        node2 = pl.create("Node")
        node1.set_attribute_value("hostname", self.host1)
        node2.set_attribute_value("hostname", self.host2)

        iface1 = pl.create("NodeInterface")
        iface2 = pl.create("NodeInterface")
        inet = pl.create("Internet")
        node1.connector("devs").connect(iface1.connector("node"))
        node2.connector("devs").connect(iface2.connector("node"))
        iface1.connector("inet").connect(inet.connector("devs"))
        iface2.connector("inet").connect(inet.connector("devs"))

        tap1 = pl.create("TapInterface")
        tap2 = pl.create("TapInterface")
        node1.connector("devs").connect(tap1.connector("node"))
        node2.connector("devs").connect(tap2.connector("node"))
        tap1.connector("udp").connect(tap2.connector("udp"))

        tap1ip = tap1.add_address()
        tap1ip.set_attribute_value("Address", "192.168.2.2")
        tap1ip.set_attribute_value("NetPrefix", 24)
        tap1ip.set_attribute_value("Broadcast", False)

        tap2ip = tap2.add_address()
        tap2ip.set_attribute_value("Address", "192.168.2.3")
        tap2ip.set_attribute_value("NetPrefix", 24)
        tap2ip.set_attribute_value("Broadcast", False)

        app = pl.create("Application")
        app.set_attribute_value("command", "ping -qc10 192.168.2.3")
        app.enable_trace("stdout")
        app.connector("node").connect(node1.connector("apps"))

        if daemonize_testbed:
            pl.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
            inst_root_dir = os.path.join(self.root_dir, "instance")
            os.mkdir(inst_root_dir)
            pl.set_attribute_value(DC.ROOT_DIRECTORY, inst_root_dir)
            pl.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)

            if environ:
                pl.set_attribute_value(DC.DEPLOYMENT_ENVIRONMENT_SETUP,
                                       environ)

        xml = exp.to_xml()

        if controller_access_configuration:
            controller = proxy.create_experiment_controller(
                xml, controller_access_configuration)
        else:
            controller = ExperimentController(xml, self.root_dir)

        try:
            controller.start()

            # purposedly break connection
            controller = None

            # recover
            if controller_access_configuration:
                controller_access_configuration.set_attribute_value(
                    DC.RECOVER, True)
                controller = proxy.create_experiment_controller(
                    None, controller_access_configuration)
            else:
                controller = ExperimentController(None, self.root_dir)
                controller.recover()

            while not controller.is_finished(app.guid):
                time.sleep(0.5)
            ping_result = controller.trace(app.guid, "stdout")
            comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.

--- .* ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time \d*ms.*
"""
            self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
                            "Unexpected trace:\n" + ping_result)

        finally:
            if controller is not None:
                try:
                    controller.stop()
                except:
                    import traceback
                    traceback.print_exc()
                try:
                    controller.shutdown()
                except:
                    import traceback
                    traceback.print_exc()

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_simple(self):
        self._test_simple(daemonize_testbed=False,
                          controller_access_configuration=None)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_simple_sfa(self):
        self._test_simple(daemonize_testbed=False,
                          controller_access_configuration=None,
                          use_sfa=True)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    @test_util.skipUnless(
        os.environ.get('NEPI_FULL_TESTS',
                       '').lower() in ('1', 'yes', 'true', 'on'),
        "Test is interactive, requires NEPI_FULL_TESTS=yes")
    def test_spanning_deployment(self):
        self._test_spanning_deployment()

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    @test_util.skipUnless(
        os.environ.get('NEPI_FULL_TESTS',
                       '').lower() in ('1', 'yes', 'true', 'on'),
        "Test is interactive, requires NEPI_FULL_TESTS=yes")
    def test_spanning_deployment_sfa(self):
        self._test_spanning_deployment(use_sfa=True)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_simple_daemonized(self):
        access_config = proxy.AccessConfiguration({
            DC.DEPLOYMENT_MODE: DC.MODE_DAEMON,
            DC.ROOT_DIRECTORY: self.root_dir,
            DC.LOG_LEVEL: DC.DEBUG_LEVEL,
        })

        self._test_simple(daemonize_testbed=False,
                          controller_access_configuration=access_config)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_simple_daemonized_sfa(self):
        access_config = proxy.AccessConfiguration({
            DC.DEPLOYMENT_MODE: DC.MODE_DAEMON,
            DC.ROOT_DIRECTORY: self.root_dir,
            DC.LOG_LEVEL: DC.DEBUG_LEVEL,
        })

        self._test_simple(daemonize_testbed=False,
                          controller_access_configuration=access_config,
                          use_sfa=True)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_z_simple_ssh(
            self):  # _z_ cause we want it last - it messes up the process :(
        # Recreate environment
        environ = ' ; '.join(
            map("export %s=%r".__mod__, os.environ.iteritems()))

        env = test_util.test_environment()

        access_config = proxy.AccessConfiguration({
            DC.DEPLOYMENT_MODE:
            DC.MODE_DAEMON,
            DC.ROOT_DIRECTORY:
            self.root_dir,
            DC.LOG_LEVEL:
            DC.DEBUG_LEVEL,
            DC.DEPLOYMENT_COMMUNICATION:
            DC.ACCESS_SSH,
            DC.DEPLOYMENT_PORT:
            env.port,
            DC.USE_AGENT:
            True,
            DC.DEPLOYMENT_ENVIRONMENT_SETUP:
            environ,
        })

        self._test_simple(daemonize_testbed=False,
                          controller_access_configuration=access_config,
                          environ=environ)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_recover(self):
        self._test_recover(daemonize_testbed=False,
                           controller_access_configuration=None)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_recover_sfa(self):
        self._test_recover(daemonize_testbed=False,
                           controller_access_configuration=None,
                           use_sfa=True)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_recover_daemonized(self):
        access_config = proxy.AccessConfiguration({
            DC.DEPLOYMENT_MODE: DC.MODE_DAEMON,
            DC.ROOT_DIRECTORY: self.root_dir,
            DC.LOG_LEVEL: DC.DEBUG_LEVEL,
        })

        self._test_recover(daemonize_testbed=False,
                           controller_access_configuration=access_config)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_recover_daemonized_sfa(self):
        access_config = proxy.AccessConfiguration({
            DC.DEPLOYMENT_MODE: DC.MODE_DAEMON,
            DC.ROOT_DIRECTORY: self.root_dir,
            DC.LOG_LEVEL: DC.DEBUG_LEVEL,
        })

        self._test_recover(daemonize_testbed=False,
                           controller_access_configuration=access_config,
                           use_sfa=True)
Beispiel #9
0
class PlanetLabMultiIntegrationTestCase(unittest.TestCase):
    testbed_id = "planetlab"

    slicename1 = "inria_nepi"
    plchost1 = "nepiplc.pl.sophia.inria.fr"
    plcvnet1 = "192.168.2"

    slicename2 = "inria_nepi2"
    plchost2 = "nepiplc.pl.sophia.inria.fr"
    plcvnet2 = "192.168.3"

    host1pl1 = "nepi1.pl.sophia.inria.fr"
    host2pl1 = "nepi2.pl.sophia.inria.fr"

    host1pl2 = "nepi3.pl.sophia.inria.fr"
    host2pl2 = "nepi5.pl.sophia.inria.fr"

    port_base = 2000 + (os.getpid() % 1000) * 13

    def setUp(self):
        self.root_dir = tempfile.mkdtemp()
        self.__class__.port_base = self.port_base + 100

    def tearDown(self):
        try:
            shutil.rmtree(self.root_dir)
        except:
            # retry
            time.sleep(0.1)
            shutil.rmtree(self.root_dir)

    def make_experiment_desc(self):
        testbed_id = self.testbed_id

        slicename1 = self.slicename1
        plchost1 = self.plchost1

        slicename2 = self.slicename2
        plchost2 = self.plchost2

        pl_ssh_key = os.environ.get(
            "PL_SSH_KEY", "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'], ))
        pl_user, pl_pwd = test_util.pl_auth()

        exp_desc = ExperimentDescription()
        pl_provider = FactoriesProvider(testbed_id)
        pl_desc = exp_desc.add_testbed_description(pl_provider)
        pl_desc.set_attribute_value("homeDirectory", self.root_dir)
        pl_desc.set_attribute_value("slice", slicename1)
        pl_desc.set_attribute_value("sliceSSHKey", pl_ssh_key)
        pl_desc.set_attribute_value("authUser", pl_user)
        pl_desc.set_attribute_value("authPass", pl_pwd)
        pl_desc.set_attribute_value("plcHost", plchost1)
        pl_desc.set_attribute_value("tapPortBase", self.port_base)
        pl_desc.set_attribute_value(
            "p2pDeployment",
            False)  # it's interactive, we don't want it in tests
        pl_desc.set_attribute_value("cleanProc", True)
        pl_desc.set_attribute_value("plLogLevel", "DEBUG")

        pl_desc2 = exp_desc.add_testbed_description(pl_provider)
        pl_desc2.set_attribute_value("homeDirectory", self.root_dir + "v2")
        pl_desc2.set_attribute_value("slice", slicename2)
        pl_desc2.set_attribute_value("sliceSSHKey", pl_ssh_key)
        pl_desc2.set_attribute_value("authUser", pl_user)
        pl_desc2.set_attribute_value("authPass", pl_pwd)
        pl_desc2.set_attribute_value("plcHost", plchost2)
        pl_desc2.set_attribute_value("tapPortBase", self.port_base + 500)
        pl_desc2.set_attribute_value(
            "p2pDeployment",
            False)  # it's interactive, we don't want it in tests
        pl_desc2.set_attribute_value("cleanProc", True)
        pl_desc2.set_attribute_value("plLogLevel", "DEBUG")

        return pl_desc, pl_desc2, exp_desc

    def make_pl_tapnode(self, pl, tapip, hostname, label_prefix):
        node1 = pl.create("Node")
        node1.set_attribute_value("hostname", hostname)
        node1.set_attribute_value("label", label_prefix)
        iface1 = pl.create("NodeInterface")
        iface1.set_attribute_value("label", label_prefix + "iface")
        tap1 = pl.create("TapInterface")
        tap1.enable_trace("packets")  # for error output
        tap1.set_attribute_value("label", label_prefix + "tap")
        inet = pl.create("Internet")
        node1.connector("devs").connect(iface1.connector("node"))
        node1.connector("devs").connect(tap1.connector("node"))
        iface1.connector("inet").connect(inet.connector("devs"))

        tap1ip = tap1.add_address()
        tap1ip.set_attribute_value("Address", tapip)
        tap1ip.set_attribute_value("NetPrefix", 24)
        tap1ip.set_attribute_value("Broadcast", False)

        return node1, iface1, tap1, tap1ip, inet

    def _test_plpl_crossconnect(self, proto, recover=False):
        pl, pl2, exp = self.make_experiment_desc()

        if recover:
            pl.set_attribute_value(DC.RECOVERY_POLICY, DC.POLICY_RECOVER)
            pl2.set_attribute_value(DC.RECOVERY_POLICY, DC.POLICY_RECOVER)

        # Create PL node, ifaces, assign addresses
        node1, iface1, tap1, tap1ip, inet1 = self.make_pl_tapnode(
            pl, self.plcvnet1 + ".2", self.host1pl1, "node1")
        node2, iface2, tap2, tap2ip, inet2 = self.make_pl_tapnode(
            pl2, self.plcvnet2 + ".3", self.host1pl2, "node2")

        # Connect the two
        tap1.connector(proto).connect(tap2.connector(proto))
        tap1.set_attribute_value("pointopoint",
                                 "{#[node2tap].addr[0].[Address]#}")
        tap2.set_attribute_value("pointopoint",
                                 "{#[node1tap].addr[0].[Address]#}")

        # Disable encryption for GRE
        if proto == "gre":
            tap1.set_attribute_value("tun_cipher", "PLAIN")
            tap2.set_attribute_value("tun_cipher", "PLAIN")

        # Create PlanetLab ping application, pinging the from one PL to another
        ping = pl.create("Application")
        ping.set_attribute_value(
            "command", "ping -qc10 {#[node2tap].addr[0].[Address]#}")
        ping.enable_trace("stdout")
        ping.enable_trace("stderr")
        ping.connector("node").connect(node1.connector("apps"))

        comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.

--- .* ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time \d*ms.*
"""

        xml = exp.to_xml()

        try:
            controller = ExperimentController(xml, self.root_dir)
            controller.start()

            if recover:
                controller = None
                controller = ExperimentController(None, self.root_dir)
                controller.recover()

            while not controller.is_finished(ping.guid):
                time.sleep(0.5)

            ping_result = controller.trace(ping.guid, "stdout")
            tap_trace = controller.trace(tap1.guid, "packets")
            tap2_trace = controller.trace(tap2.guid, "packets")

        finally:
            if controller is not None:
                try:
                    controller.stop()
                except:
                    import traceback
                    traceback.print_exc()
                try:
                    controller.shutdown()
                except:
                    import traceback
                    traceback.print_exc()

        # asserts at the end, to make sure there's proper cleanup
        self.assertTrue(
            re.match(comp_result, ping_result, re.MULTILINE),
            "Unexpected trace:\n%s\nTap trace at origin:\n%s\nTap trace at destination:\n%s\n"
            % (ping_result, tap_trace, tap2_trace))

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_plpl_crossconnect_udp(self):
        self._test_plpl_crossconnect("udp")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_plpl_crossconnect_tcp(self):
        self._test_plpl_crossconnect("tcp")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_plpl_crossconnect_gre(self):
        self._test_plpl_crossconnect("gre")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_plpl_crossconnect_udp_recover(self):
        self._test_plpl_crossconnect("udp", recover=True)
Beispiel #10
0
class PlanetLabExecuteTestCase(unittest.TestCase):
    testbed_id = "planetlab"
    slicename = "inria_nepi"
    plchost = "nepiplc.pl.sophia.inria.fr"

    host1 = "nepi1.pl.sophia.inria.fr"
    host2 = "nepi2.pl.sophia.inria.fr"

    port_base = 2000 + (os.getpid() % 1000) * 13

    PLR50_PY = os.path.join(os.path.dirname(planetlab.__file__), 'scripts',
                            'plr50.py')
    PLR50_C = os.path.join(os.path.dirname(planetlab.__file__), 'scripts',
                           'plr50.c')
    TOS_PY = os.path.join(os.path.dirname(planetlab.__file__), 'scripts',
                          'tosqueue.py')
    CLS_PY = os.path.join(os.path.dirname(planetlab.__file__), 'scripts',
                          'classqueue.py')

    def setUp(self):
        self.root_dir = tempfile.mkdtemp()
        self.__class__.port_base = self.port_base + 100

    def tearDown(self):
        try:
            shutil.rmtree(self.root_dir)
        except:
            # retry
            time.sleep(0.1)
            shutil.rmtree(self.root_dir)

    def make_instance(self):
        testbed_id = self.testbed_id
        slicename = self.slicename
        plchost = self.plchost

        instance = planetlab.TestbedController()
        pl_ssh_key = os.environ.get(
            "PL_SSH_KEY", "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'], ))
        slicename = os.environ.get("PL_SLICE", slicename)
        pl_user, pl_pwd = test_util.pl_auth()

        instance.defer_configure("homeDirectory", self.root_dir)
        instance.defer_configure("slice", slicename)
        instance.defer_configure("sliceSSHKey", pl_ssh_key)
        instance.defer_configure("authUser", pl_user)
        instance.defer_configure("authPass", pl_pwd)
        instance.defer_configure("plcHost", plchost)
        instance.defer_configure("tapPortBase", self.port_base)
        instance.defer_configure(
            "p2pDeployment",
            False)  # it's interactive, we don't want it in tests
        instance.defer_configure("cleanProc", True)

        # Hack, but we need vsys_vnet
        instance.do_setup()
        vnet = instance.vsys_vnet
        self.net_prefix = vnet.rsplit('.', 1)[0]

        return instance

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_simple(self):
        instance = self.make_instance()

        instance.defer_create(2, "Node")
        instance.defer_create_set(2, "hostname", self.host1)
        instance.defer_create(3, "Node")
        instance.defer_create_set(3, "hostname", self.host2)
        instance.defer_create(4, "NodeInterface")
        instance.defer_connect(2, "devs", 4, "node")
        instance.defer_create(5, "NodeInterface")
        instance.defer_connect(3, "devs", 5, "node")
        instance.defer_create(6, "Internet")
        instance.defer_connect(4, "inet", 6, "devs")
        instance.defer_connect(5, "inet", 6, "devs")
        instance.defer_create(7, "Application")
        instance.defer_create_set(7, "command",
                                  "ping -qc1 {#[GUID-5].addr[0].[Address]#}")
        instance.defer_add_trace(7, "stdout")
        instance.defer_add_trace(7, "stderr")
        instance.defer_connect(7, "node", 2, "apps")

        comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.

--- .* ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time \d*ms.*
"""

        try:
            instance.do_setup()
            instance.do_create()
            instance.do_connect_init()
            instance.do_connect_compl()
            instance.do_preconfigure()

            # Manually replace netref
            instance.set(
                7, "command",
                instance.get(7, "command").replace(
                    "{#[GUID-5].addr[0].[Address]#}",
                    instance.get_address(5, 0, "Address")))

            instance.do_configure()

            instance.do_prestart()
            instance.start()
            while instance.status(7) != AS.STATUS_FINISHED:
                time.sleep(0.5)
            ping_result = instance.trace(7, "stdout") or ""
            instance.stop()
        finally:
            try:
                instance.shutdown()
            except:
                pass

        # asserts at the end, to make sure there's proper cleanup
        self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
                        "Unexpected trace:\n" + ping_result)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_depends(self):
        instance = self.make_instance()

        instance.defer_create(2, "Node")
        instance.defer_create_set(2, "hostname", self.host1)
        instance.defer_create(3, "NodeInterface")
        instance.defer_connect(2, "devs", 3, "node")
        instance.defer_create(4, "Internet")
        instance.defer_connect(3, "inet", 4, "devs")
        instance.defer_create(5, "Application")
        instance.defer_create_set(5, "command", "gfortran --version")
        instance.defer_create_set(5, "depends", "gcc-gfortran")
        instance.defer_add_trace(5, "stdout")
        instance.defer_add_trace(5, "stderr")
        instance.defer_connect(5, "node", 2, "apps")

        try:
            instance.do_setup()
            instance.do_create()
            instance.do_connect_init()
            instance.do_connect_compl()
            instance.do_preconfigure()
            instance.do_configure()

            instance.do_prestart()
            instance.start()
            while instance.status(5) != AS.STATUS_FINISHED:
                time.sleep(0.5)
            ping_result = instance.trace(5, "stdout") or ""
            comp_result = r".*GNU Fortran \(GCC\).*"
            instance.stop()
        finally:
            try:
                instance.shutdown()
            except:
                pass

        # asserts at the end, to make sure there's proper cleanup
        self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
                        "Unexpected trace:\n" + ping_result)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_build(self):
        instance = self.make_instance()

        instance.defer_create(2, "Node")
        instance.defer_create_set(2, "hostname", self.host1)
        instance.defer_create(3, "NodeInterface")
        instance.defer_connect(2, "devs", 3, "node")
        instance.defer_create(4, "Internet")
        instance.defer_connect(3, "inet", 4, "devs")
        instance.defer_create(10, "Application")
        instance.defer_create_set(10, "command", "./consts")
        instance.defer_create_set(10, "buildDepends", "gcc")
        instance.defer_create_set(10, "build",
                                  "gcc ${SOURCES}/consts.c -o consts")
        instance.defer_create_set(10, "install", "cp consts ${SOURCES}/consts")
        instance.defer_create_set(
            10, "sources",
            os.path.join(os.path.dirname(planetlab.__file__), 'scripts',
                         'consts.c'))
        instance.defer_add_trace(10, "stdout")
        instance.defer_add_trace(10, "stderr")
        instance.defer_connect(10, "node", 2, "apps")

        comp_result = \
r""".*ETH_P_ALL = 0x[0-9a-fA-F]{8}
ETH_P_IP = 0x[0-9a-fA-F]{8}
TUNGETIFF = 0x[0-9a-fA-F]{8}
TUNSETIFF = 0x[0-9a-fA-F]{8}
IFF_NO_PI = 0x[0-9a-fA-F]{8}
IFF_TAP = 0x[0-9a-fA-F]{8}
IFF_TUN = 0x[0-9a-fA-F]{8}
IFF_VNET_HDR = 0x[0-9a-fA-F]{8}
TUN_PKT_STRIP = 0x[0-9a-fA-F]{8}
IFHWADDRLEN = 0x[0-9a-fA-F]{8}
IFNAMSIZ = 0x[0-9a-fA-F]{8}
IFREQ_SZ = 0x[0-9a-fA-F]{8}
FIONREAD = 0x[0-9a-fA-F]{8}.*
"""

        try:
            instance.do_setup()
            instance.do_create()
            instance.do_connect_init()
            instance.do_connect_compl()
            instance.do_preconfigure()
            instance.do_configure()

            instance.do_prestart()
            instance.start()
            while instance.status(10) != AS.STATUS_FINISHED:
                time.sleep(0.5)
            ping_result = instance.trace(10, "stdout") or ""
            instance.stop()
        finally:
            try:
                instance.shutdown()
            except:
                pass

        # asserts at the end, to make sure there's proper cleanup
        self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
                        "Unexpected trace:\n" + ping_result)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_simple_vsys(self):
        instance = self.make_instance()

        instance.defer_create(2, "Node")
        instance.defer_create_set(2, "hostname", self.host1)
        instance.defer_create(3, "NodeInterface")
        instance.defer_connect(2, "devs", 3, "node")
        instance.defer_create(4, "Internet")
        instance.defer_connect(3, "inet", 4, "devs")
        instance.defer_create(5, "TunInterface")
        instance.defer_add_address(5, self.net_prefix + ".2", 24, False)
        instance.defer_connect(2, "devs", 5, "node")
        instance.defer_create(6, "Application")
        instance.defer_create_set(
            6, "command", """
set -e
netconfig help > /dev/null
test -e /vsys/vif_up.in > /dev/null
test -e /vsys/vif_up.out > /dev/null
test -e /vsys/fd_tuntap.control > /dev/null
echo 'OKIDOKI'
""")
        instance.defer_create_set(6, "sudo",
                                  True)  # only sudo has access to /vsys
        instance.defer_add_trace(6, "stdout")
        instance.defer_add_trace(6, "stderr")
        instance.defer_connect(6, "node", 2, "apps")

        try:
            instance.do_setup()
            instance.do_create()
            instance.do_connect_init()
            instance.do_connect_compl()
            instance.do_preconfigure()
            instance.do_configure()

            instance.do_prestart()
            instance.start()
            while instance.status(6) != AS.STATUS_FINISHED:
                time.sleep(0.5)
            test_result = (instance.trace(6, "stdout") or "").strip()
            comp_result = "OKIDOKI"
            instance.stop()
        finally:
            try:
                instance.shutdown()
            except:
                pass

        # asserts at the end, to make sure there's proper cleanup
        self.assertEqual(comp_result, test_result)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_emulation(self):
        instance = self.make_instance()

        instance.defer_create(2, "Node")
        instance.defer_create_set(2, "hostname", self.host1)
        instance.defer_create(3, "NodeInterface")
        instance.defer_connect(2, "devs", 3, "node")
        instance.defer_create(4, "Internet")
        instance.defer_connect(3, "inet", 4, "devs")
        instance.defer_create(7, "NetPipe")
        instance.defer_create_set(7, "mode", "CLIENT")
        instance.defer_create_set(7, "portList", "80")
        instance.defer_create_set(7, "bwOut", 12.0 / 1024.0)  # 12kbps
        instance.defer_create_set(7, "bwIn", 64.0 / 1024.0)  # 64kbps
        instance.defer_create_set(7, "plrOut",
                                  0.01)  # 1% plr outbound - high loss
        instance.defer_create_set(7, "plrIn",
                                  0.001)  # 0.1% plr inbound - regular loss
        instance.defer_create_set(7, "delayOut",
                                  int(1500 * 8 / (12.0 / 1024.0) /
                                      1000))  # tx delay at 12kbps in ms
        instance.defer_create_set(7, "delayIn",
                                  int(1500 * 8 / (64.0 / 1024.0) /
                                      1000))  # rx delay at 64kbps in ms
        instance.defer_add_trace(7, "netpipeStats")
        instance.defer_connect(2, "pipes", 7, "node")
        instance.defer_create(8, "Application")
        instance.defer_create_set(
            8, "command",
            "time wget -q -O /dev/null http://www.google.com/")  # Fetch ~10kb
        instance.defer_add_trace(8, "stdout")
        instance.defer_add_trace(8, "stderr")
        instance.defer_connect(8, "node", 2, "apps")

        try:
            instance.do_setup()
            instance.do_create()
            instance.do_connect_init()
            instance.do_connect_compl()
            instance.do_preconfigure()
            instance.do_configure()

            instance.do_prestart()
            instance.start()
            while instance.status(8) != AS.STATUS_FINISHED:
                time.sleep(0.5)
            test_result = (instance.trace(8, "stderr") or "").strip()
            comp_result = r".*real\s*(?P<min>[0-9]+)m(?P<sec>[0-9]+[.][0-9]+)s.*"
            netpipe_stats = instance.trace(7, "netpipeStats")

            instance.stop()
        finally:
            try:
                instance.shutdown()
            except:
                pass

        # asserts at the end, to make sure there's proper cleanup
        match = re.match(comp_result, test_result, re.MULTILINE)
        self.assertTrue(match, "Unexpected output: %s" % (test_result, ))

        minutes = int(match.group("min"))
        seconds = float(match.group("sec"))
        self.assertTrue((minutes * 60 + seconds) > 1.0,
                        "Emulation not effective: %s" % (test_result, ))

        self.assertTrue(netpipe_stats, "Unavailable netpipe stats")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def _pingtest(self,
                  TunClass,
                  ConnectionProto,
                  Cipher,
                  Filter1=None,
                  Filter2=None,
                  Filter1args=None,
                  Filter2args=None,
                  PLREX=None,
                  flood=False):
        instance = self.make_instance()

        instance.defer_create(2, "Node")
        instance.defer_create_set(2, "hostname", self.host1)
        instance.defer_create(3, "Node")
        instance.defer_create_set(3, "hostname", self.host2)
        instance.defer_create(4, "NodeInterface")
        instance.defer_connect(2, "devs", 4, "node")
        instance.defer_create(5, "Internet")
        instance.defer_connect(4, "inet", 5, "devs")
        instance.defer_create(6, "NodeInterface")
        instance.defer_connect(3, "devs", 6, "node")
        instance.defer_connect(6, "inet", 5, "devs")
        instance.defer_create(7, TunClass)
        instance.defer_create_set(7, "tun_cipher", Cipher)
        instance.defer_add_trace(7, "packets")
        instance.defer_add_address(7, self.net_prefix + ".2", 24, False)
        if flood:
            instance.defer_create_set(7, "bwlimit", 128)
        instance.defer_connect(2, "devs", 7, "node")
        instance.defer_create(8, TunClass)
        instance.defer_create_set(8, "tun_cipher", Cipher)
        instance.defer_add_trace(8, "packets")
        instance.defer_add_address(8, self.net_prefix + ".3", 24, False)
        instance.defer_connect(3, "devs", 8, "node")
        instance.defer_create(9, "Application")
        if flood:
            instance.defer_create_set(
                9, "command",
                "sudo -S ping -s 1000 -l 1000 -qfc1000 {#[GUID-8].addr[0].[Address]#} ; sleep 20 ; ping -qc10 {#[GUID-8].addr[0].[Address]#}"
            )
        else:
            instance.defer_create_set(
                9, "command", "ping -qc10 {#[GUID-8].addr[0].[Address]#}")
        instance.defer_add_trace(9, "stdout")
        instance.defer_add_trace(9, "stderr")
        instance.defer_connect(9, "node", 2, "apps")

        if Filter1:
            instance.defer_create(10, "TunFilter")
            instance.defer_create_set(10, "module", Filter1)
            if Filter1args:
                instance.defer_create_set(10, "args", Filter1args)
            instance.defer_connect(7, "fd->", 10, "->fd")

        if Filter2:
            instance.defer_create(11, "TunFilter")
            instance.defer_create_set(11, "module", Filter2)
            if Filter2args:
                instance.defer_create_set(11, "args", Filter2args)
            instance.defer_connect(8, "fd->", 11, "->fd")

        if PLREX is None:
            if Filter1 and Filter2:
                plr = "[5-9][0-9]"
            elif Filter1 or Filter2:
                plr = "[3-9][0-9]"
            else:
                plr = "0"
        else:
            plr = PLREX

        instance.defer_connect((10 if Filter1 else 7), ConnectionProto,
                               (11 if Filter2 else 8), ConnectionProto)

        comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.

--- .* ping statistics ---
10 packets transmitted, [0-9]+ received,.* %s%% packet loss, time \d*ms.*
""" % (plr, )
        if flood:
            comp_result = ".*" + comp_result

        try:
            instance.do_setup()
            instance.do_create()
            instance.do_connect_init()
            instance.do_connect_compl()
            instance.do_preconfigure()

            # Manually replace netref
            instance.set(
                9, "command",
                instance.get(9, "command").replace(
                    "{#[GUID-8].addr[0].[Address]#}",
                    instance.get_address(8, 0, "Address")))

            instance.do_configure()

            instance.do_prestart()
            instance.start()
            while instance.status(9) != AS.STATUS_FINISHED:
                time.sleep(0.5)
            ping_result = instance.trace(9, "stdout") or ""
            packets1 = instance.trace(7, "packets") or ""
            packets2 = instance.trace(8, "packets") or ""
            instance.stop()
        finally:
            try:
                instance.shutdown()
            except:
                pass

        # asserts at the end, to make sure there's proper cleanup
        self.assertTrue(
            re.match(comp_result, ping_result, re.MULTILINE | re.DOTALL),
            "Unexpected trace:\n%s\nPackets @ source:\n%s\nPackets @ target:\n%s"
            % (ping_result, packets1, packets2))

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tun_ping(self):
        self._pingtest("TunInterface", "tcp", "AES")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tun_ping_udp(self):
        self._pingtest("TunInterface", "udp", "AES")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tun_ping_gre(self):
        self._pingtest("TunInterface", "gre", "PLAIN")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tun_ping_flood(self):
        self._pingtest("TunInterface", "tcp", "PLAIN", flood=True)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tun_ping_flood_udp(self):
        self._pingtest("TunInterface", "udp", "PLAIN", flood=True)

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tap_ping(self):
        self._pingtest("TapInterface", "tcp", "AES")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tap_ping_udp(self):
        self._pingtest("TapInterface", "udp", "AES")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tap_ping_gre(self):
        self._pingtest("TapInterface", "gre", "PLAIN")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tap_ping_udp_loss1_py(self):
        self._pingtest("TapInterface", "udp", "AES", self.PLR50_PY, None,
                       "plr=50")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tap_ping_udp_loss2_py(self):
        self._pingtest("TapInterface", "udp", "AES", self.PLR50_PY,
                       self.PLR50_PY, "plr=40", "plr=40")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tap_ping_udp_loss1_c(self):
        self._pingtest("TapInterface", "udp", "AES", self.PLR50_C, None,
                       "plr=50")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tap_ping_udp_loss2_c(self):
        self._pingtest("TapInterface", "udp", "AES", self.PLR50_C,
                       self.PLR50_C, "plr=40", "plr=40")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tun_ping_udp_tos(self):
        self._pingtest("TunInterface", "udp", "AES", self.TOS_PY, self.TOS_PY,
                       "size=1000", "size=1000", "0")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_tun_ping_udp_class(self):
        self._pingtest("TunInterface", "udp", "AES", self.CLS_PY, self.CLS_PY,
                       "size=10", "size=10", "0")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_nepi_depends(self):
        instance = self.make_instance()

        instance.defer_create(2, "Node")
        instance.defer_create_set(2, "hostname", self.host1)
        instance.defer_create(3, "NodeInterface")
        instance.defer_connect(2, "devs", 3, "node")
        instance.defer_create(4, "Internet")
        instance.defer_connect(3, "inet", 4, "devs")
        instance.defer_create(5, "NepiDependency")
        instance.defer_connect(5, "node", 2, "deps")
        instance.defer_create(12, "Application")
        instance.defer_connect(12, "node", 2, "apps")
        instance.defer_create_set(12, "command", "python -c 'import nepi'")
        instance.defer_add_trace(12, "stderr")

        try:
            instance.do_setup()
            instance.do_create()
            instance.do_connect_init()
            instance.do_connect_compl()
            instance.do_preconfigure()
            instance.do_configure()

            instance.do_prestart()
            instance.start()
            while instance.status(12) != AS.STATUS_FINISHED:
                time.sleep(0.5)
            ping_result = (instance.trace(12, "stderr") or "").strip()
            instance.stop()
        finally:
            try:
                instance.shutdown()
            except:
                pass

        # asserts at the end, to make sure there's proper cleanup
        self.assertEqual(ping_result, "")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    @test_util.skipUnless(
        os.environ.get('NEPI_FULL_TESTS',
                       '').lower() in ('1', 'yes', 'true', 'on'),
        "Test is expensive, requires NEPI_FULL_TESTS=yes")
    def test_ns3_depends(self):
        instance = self.make_instance()

        instance.defer_create(2, "Node")
        instance.defer_create_set(2, "hostname", self.host1)
        instance.defer_create(3, "NodeInterface")
        instance.defer_connect(2, "devs", 3, "node")
        instance.defer_create(4, "Internet")
        instance.defer_connect(3, "inet", 4, "devs")
        instance.defer_create(5, "NepiDependency")
        instance.defer_connect(5, "node", 2, "deps")
        instance.defer_create(6, "NS3Dependency")
        instance.defer_connect(6, "node", 2, "deps")
        instance.defer_create(12, "Application")
        instance.defer_connect(12, "node", 2, "apps")
        instance.defer_create_set(
            12, "command",
            "python -c 'import nepi.testbeds.ns3.execute ; tb = nepi.testbeds.ns3.execute.TestbedController() ; mod = tb._configure_ns3_module()'"
        )
        instance.defer_add_trace(12, "stderr")

        try:
            instance.do_setup()
            instance.do_create()
            instance.do_connect_init()
            instance.do_connect_compl()
            instance.do_preconfigure()
            instance.do_configure()

            instance.do_prestart()
            instance.start()
            while instance.status(12) != AS.STATUS_FINISHED:
                time.sleep(0.5)
            ping_result = (instance.trace(12, "stderr") or "").strip()
            instance.stop()
        finally:
            try:
                instance.shutdown()
            except:
                pass

        # asserts at the end, to make sure there's proper cleanup
        self.assertEqual(ping_result, "")

    @test_util.skipUnless(
        test_util.pl_auth() is not None,
        "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)"
    )
    def test_discovery(self):
        instance = self.make_instance()

        instance.defer_create(2, "Node")
        instance.defer_create_set(2, "operatingSystem", "f12")
        instance.defer_create(3, "Node")
        instance.defer_create_set(3, "operatingSystem", "f12")
        instance.defer_create(4, "NodeInterface")
        instance.defer_connect(2, "devs", 4, "node")
        instance.defer_create(5, "NodeInterface")
        instance.defer_connect(3, "devs", 5, "node")
        instance.defer_create(6, "Internet")
        instance.defer_connect(4, "inet", 6, "devs")
        instance.defer_connect(5, "inet", 6, "devs")
        instance.defer_create(7, "Application")
        instance.defer_create_set(7, "command",
                                  "ping -qc1 {#[GUID-5].addr[0].[Address]#}")
        instance.defer_add_trace(7, "stdout")
        instance.defer_add_trace(7, "stderr")
        instance.defer_connect(7, "node", 2, "apps")

        comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.

--- .* ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time \d*ms.*
"""

        try:
            instance.do_setup()
            instance.do_create()
            instance.do_connect_init()
            instance.do_connect_compl()
            instance.do_preconfigure()

            # Manually replace netref
            instance.set(
                7, "command",
                instance.get(7, "command").replace(
                    "{#[GUID-5].addr[0].[Address]#}",
                    instance.get_address(5, 0, "Address")))

            instance.do_configure()

            instance.do_prestart()
            instance.start()
            while instance.status(7) != AS.STATUS_FINISHED:
                time.sleep(0.5)
            ping_result = instance.trace(7, "stdout") or ""
            instance.stop()
        finally:
            try:
                instance.shutdown()
            except:
                pass

        # asserts at the end, to make sure there's proper cleanup
        self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
                        "Unexpected trace:\n" + ping_result)