From d7de4f2de28e4ef0f2ea3d3a09d22fda79db65b3 Mon Sep 17 00:00:00 2001 From: Claudio-Daniel Freire Date: Mon, 2 May 2011 18:42:51 +0200 Subject: [PATCH] Ticket #29: introduce some "standard" box attributes to support testbed-in-testbed deployment --- src/nepi/testbeds/planetlab/metadata_v01.py | 12 +++++++++++- src/nepi/testbeds/planetlab/node.py | 17 +++++++++++++++++ src/nepi/util/constants.py | 3 +++ src/nepi/util/proxy.py | 20 ++++++++++++++------ src/nepi/util/server.py | 6 +++++- 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/nepi/testbeds/planetlab/metadata_v01.py b/src/nepi/testbeds/planetlab/metadata_v01.py index 9c85c048..27d96796 100644 --- a/src/nepi/testbeds/planetlab/metadata_v01.py +++ b/src/nepi/testbeds/planetlab/metadata_v01.py @@ -8,7 +8,7 @@ from nepi.core import metadata from nepi.core.attributes import Attribute from nepi.util import validation from nepi.util.constants import STATUS_NOT_STARTED, STATUS_RUNNING, \ - STATUS_FINISHED + STATUS_FINISHED, ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP import functools import os @@ -679,6 +679,13 @@ attributes = dict({ "flags": Attribute.DesignOnly, "validation_function": validation.is_string }), + ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP: dict({ + "name": ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP, + "help": "Commands to set up the environment needed to run NEPI testbeds", + "type": Attribute.STRING, + "flags": Attribute.Invisible | Attribute.ReadOnly, + "validation_function": validation.is_string + }), "netpipe_mode": dict({ "name": "mode", @@ -792,6 +799,9 @@ factories_info = dict({ "max_reliability", "min_bandwidth", "max_bandwidth", + + # NEPI-in-NEPI attributes + ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP, ], "connector_types": ["devs", "apps", "pipes", "deps"] }), diff --git a/src/nepi/testbeds/planetlab/node.py b/src/nepi/testbeds/planetlab/node.py index 245e636b..73593af2 100644 --- a/src/nepi/testbeds/planetlab/node.py +++ b/src/nepi/testbeds/planetlab/node.py @@ -8,6 +8,7 @@ import rspawn import time import os import collections +import cStringIO from nepi.util import server @@ -68,6 +69,22 @@ class Node(object): # Those are filled when an actual node is allocated self._node_id = None + @property + def _nepi_testbed_environment_setup(self): + command = cStringIO.StringIO() + command.write('PYTHONPATH=$PYTHONPATH:%s' % ( + ':'.join(["${HOME}/"+server.shell_escape(s) for s in self.pythonpath]) + )) + command.write(' PATH=$PATH:%s' % ( + ':'.join(["${HOME}/"+server.shell_escape(s) for s in self.pythonpath]) + )) + if self.node.env: + for envkey, envvals in self.node.env.iteritems(): + for envval in envvals: + command.write(' %s=%s' % (envkey, envval)) + command.write(self.command) + return command.getvalue() + def build_filters(self, target_filters, filter_map): for attr, tag in filter_map.iteritems(): value = getattr(self, attr, None) diff --git a/src/nepi/util/constants.py b/src/nepi/util/constants.py index cb94c2e9..ac23fedd 100644 --- a/src/nepi/util/constants.py +++ b/src/nepi/util/constants.py @@ -20,3 +20,6 @@ TESTBED_STATUS_STOPPED = 7 TIME_NOW = "0s" + +ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP = "_nepi_testbed_environment_setup" + diff --git a/src/nepi/util/proxy.py b/src/nepi/util/proxy.py index 9b7b447f..1be195ac 100644 --- a/src/nepi/util/proxy.py +++ b/src/nepi/util/proxy.py @@ -4,7 +4,7 @@ import base64 from nepi.core.attributes import AttributesMap, Attribute from nepi.util import server, validation -from nepi.util.constants import TIME_NOW +from nepi.util.constants import TIME_NOW, ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP import getpass import cPickle import sys @@ -317,6 +317,10 @@ def create_testbed_controller(testbed_id, testbed_version, access_config): else access_config.get_attribute_value("mode") launch = True if not access_config \ else not access_config.get_attribute_value("recover") + environment_setup = access_config \ + and access_config.has_attribute(ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP) \ + and access_config.get_attribute_value(ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP) \ + or "" if not mode or mode == AccessConfiguration.MODE_SINGLE_PROCESS: if not launch: raise ValueError, "Unsupported instantiation mode: %s with lanch=False" % (mode,) @@ -326,7 +330,8 @@ def create_testbed_controller(testbed_id, testbed_version, access_config): get_access_config_params(access_config) return TestbedControllerProxy(root_dir, log_level, testbed_id = testbed_id, testbed_version = testbed_version, host = host, port = port, - user = user, agent = agent, launch = launch) + user = user, agent = agent, launch = launch, + environment_setup = environment_setup) raise RuntimeError("Unsupported access configuration '%s'" % mode) def _build_testbed_controller(testbed_id, testbed_version): @@ -770,7 +775,8 @@ class ExperimentControllerServer(server.Server): class TestbedControllerProxy(object): def __init__(self, root_dir, log_level, testbed_id = None, testbed_version = None, launch = True, host = None, - port = None, user = None, agent = None): + port = None, user = None, agent = None, + environment_setup = ""): if launch: if testbed_id == None or testbed_version == None: raise RuntimeError("To launch a TesbedInstance server a \ @@ -783,7 +789,8 @@ class TestbedControllerProxy(object): s.run()" % (root_dir, log_level, testbed_id, testbed_version) proc = server.popen_ssh_subprocess(python_code, host = host, - port = port, user = user, agent = agent) + port = port, user = user, agent = agent, + environment_setup = environment_setup) if proc.poll(): err = proc.stderr.read() raise RuntimeError("Server could not be executed: %s" % \ @@ -1178,7 +1185,7 @@ class TestbedControllerProxy(object): class ExperimentControllerProxy(object): def __init__(self, root_dir, log_level, experiment_xml = None, launch = True, host = None, port = None, user = None, - agent = None): + agent = None, environment_setup = ""): if launch: # launch server if experiment_xml == None: @@ -1191,7 +1198,8 @@ class ExperimentControllerProxy(object): s = ExperimentControllerServer(%r, %r, %r);\ s.run()" % (root_dir, log_level, xml) proc = server.popen_ssh_subprocess(python_code, host = host, - port = port, user = user, agent = agent) + port = port, user = user, agent = agent, + environment_setup = environment_setup) if proc.poll(): err = proc.stderr.read() raise RuntimeError("Server could not be executed: %s" % \ diff --git a/src/nepi/util/server.py b/src/nepi/util/server.py index 7d4bd88c..44c64084 100644 --- a/src/nepi/util/server.py +++ b/src/nepi/util/server.py @@ -616,12 +616,16 @@ def popen_ssh_subprocess(python_code, host, port, user, agent, python_path = None, ident_key = None, server_key = None, - tty = False): + tty = False, + environment_setup = ""): if python_path: python_path.replace("'", r"'\''") cmd = """PYTHONPATH="$PYTHONPATH":'%s' """ % python_path else: cmd = "" + if environment_setup: + cmd += environment_setup + cmd += " " # Uncomment for debug (to run everything under strace) # We had to verify if strace works (cannot nest them) #cmd += "if strace echo >/dev/null 2>&1; then CMD='strace -ff -tt -s 200 -o strace.out'; else CMD=''; fi\n" -- 2.47.0