From: Claudio-Daniel Freire Date: Tue, 26 Apr 2011 12:22:57 +0000 (+0200) Subject: Slight design change: separate build from install of applications. X-Git-Tag: nepi_v2~122 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=6d5cfd1760b0ef5fbe39b202455a1635b3286caa;p=nepi.git Slight design change: separate build from install of applications. This will enable easier and more efficient mass-deployment of identical applications using the spanning tree method. --- diff --git a/src/nepi/testbeds/planetlab/application.py b/src/nepi/testbeds/planetlab/application.py index e4ff0758..bcc8eb6e 100644 --- a/src/nepi/testbeds/planetlab/application.py +++ b/src/nepi/testbeds/planetlab/application.py @@ -25,6 +25,7 @@ class Application(object): self.sudo = False self.build = None + self.install = None self.depends = None self.buildDepends = None self.sources = None @@ -228,6 +229,16 @@ class Application(object): if proc.wait(): raise RuntimeError, "Failed to set up application: %s %s" % (out,err,) + def _replace_paths(self, command): + """ + Replace all special path tags with shell-escaped actual paths. + """ + # need to append ${HOME} if paths aren't absolute, to MAKE them absolute. + root = '' if self.home_path.startswith('/') else "${HOME}/" + return ( command + .replace("${SOURCES}", root+server.shell_escape(self.home_path)) + .replace("${BUILD}", root+server.shell_escape(os.path.join(self.home_path,'build'))) ) + def _build(self): if self.sources: sources = self.sources.split(' ') @@ -264,10 +275,10 @@ class Application(object): if self.build: - # Install build dependencies + # Build sources (out,err),proc = server.popen_ssh_command( - "cd %(home)s ; %(command)s" % { - 'command' : self.build, + "cd %(home)s && mkdir -p build && cd build && %(command)s" % { + 'command' : self._replace_paths(self.build), 'home' : server.shell_escape(self.home_path), }, host = self.node.hostname, @@ -281,4 +292,38 @@ class Application(object): if proc.wait(): raise RuntimeError, "Failed instal build sources: %s %s" % (out,err,) + # Make archive + (out,err),proc = server.popen_ssh_command( + "cd %(home)s && tar czf build.tar.gz build" % { + 'command' : self._replace_paths(self.build), + 'home' : server.shell_escape(self.home_path), + }, + host = self.node.hostname, + port = None, + user = self.slicename, + agent = None, + ident_key = self.ident_path, + server_key = self.node.server_key + ) + + if proc.wait(): + raise RuntimeError, "Failed instal build sources: %s %s" % (out,err,) + + if self.install: + # Install application + (out,err),proc = server.popen_ssh_command( + "cd %(home)s && cd build && %(command)s" % { + 'command' : self._replace_paths(self.install), + 'home' : server.shell_escape(self.home_path), + }, + host = self.node.hostname, + port = None, + user = self.slicename, + agent = None, + ident_key = self.ident_path, + server_key = self.node.server_key + ) + + if proc.wait(): + raise RuntimeError, "Failed instal build sources: %s %s" % (out,err,) diff --git a/src/nepi/testbeds/planetlab/metadata_v01.py b/src/nepi/testbeds/planetlab/metadata_v01.py index 2d6b7f00..78a9831d 100644 --- a/src/nepi/testbeds/planetlab/metadata_v01.py +++ b/src/nepi/testbeds/planetlab/metadata_v01.py @@ -408,9 +408,27 @@ attributes = dict({ "build": dict({ "name": "build", "help": "Build commands to execute after deploying the sources. " - "Sources will be in the initial working folder. " - "Example: cd my-app && ./configure && make && make install.\n" - "Try to make the commands return with a nonzero exit code on error.", + "Sources will be in the ${SOURCES} folder. " + "Example: tar xzf ${SOURCES}/my-app.tgz && cd my-app && ./configure && make && make clean.\n" + "Try to make the commands return with a nonzero exit code on error.\n" + "Also, do not install any programs here, use the 'install' attribute. This will " + "help keep the built files constrained to the build folder (which may " + "not be the home folder), and will result in faster deployment. Also, " + "make sure to clean up temporary files, to reduce bandwidth usage between " + "nodes when transferring built packages.", + "type": Attribute.STRING, + "flags": Attribute.DesignOnly, + "validation_function": validation.is_string + }), + "install": dict({ + "name": "install", + "help": "Commands to transfer built files to their final destinations. " + "Sources will be in the initial working folder, and a special " + "tag ${SOURCES} can be used to reference the experiment's " + "home folder (where the application commands will run).\n" + "ALL sources and targets needed for execution must be copied there, " + "if building has been enabled.\n" + "That is, 'slave' nodes will not automatically get any source files.", "type": Attribute.STRING, "flags": Attribute.DesignOnly, "validation_function": validation.is_string @@ -486,7 +504,7 @@ factories_info = dict({ "stop_function": stop_application, "configure_function": configure_application, "box_attributes": ["command", "sudo", "stdin", - "depends", "build-depends", "build", + "depends", "build-depends", "build", "install", "sources" ], "connector_types": ["node"], "traces": ["stdout", "stderr"] diff --git a/test/testbeds/planetlab/execute.py b/test/testbeds/planetlab/execute.py index 2eb91cd5..f20c1276 100755 --- a/test/testbeds/planetlab/execute.py +++ b/test/testbeds/planetlab/execute.py @@ -126,7 +126,8 @@ class PlanetLabExecuteTestCase(unittest.TestCase): 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 consts.c -o consts") + 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_connect(10, "node", 2, "apps")