From 0bb200df309d4f0682122202f32147f4f6387e78 Mon Sep 17 00:00:00 2001 From: Antoine Catton <acatton@tiolive.com> Date: Mon, 19 Sep 2011 13:08:09 +0200 Subject: [PATCH] Merge Antoine Catton work on promises. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Squashed commit of the following: commit 29caaa556d1d641f6b2241db84d2d8b588689a82 Merge: 32d5fef 13d6e1d Author: Antoine Catton <acatton@tiolive.com> Date: Mon Sep 19 11:49:27 2011 +0200 Merge branch 'master' into promises Conflicts: slapos/recipe/kvm/__init__.py commit 32d5fef49f22e3a47ca0b0728e502d177979b214 Author: Antoine Catton <acatton@tiolive.com> Date: Wed Aug 24 16:45:31 2011 +0200 Minor: Use pkg_resources the right way http://peak.telecommunity.com/DevCenter/PkgResources commit e2fae493ab6a96fa10cbe6531ee1a1ba9c16bb4c Author: Antoine Catton <acatton@tiolive.com> Date: Wed Aug 24 16:00:02 2011 +0200 Minor: some typo fix to get the recipe working commit 3764ab93da5031f9b5ea59072090d2b961a791cf Author: Antoine Catton <acatton@tiolive.com> Date: Wed Aug 24 15:53:17 2011 +0200 Minor: typo fix commit 259026f718e0e37c5c151fb40dbf85866f6ab87f Author: Antoine Catton <acatton@tiolive.com> Date: Wed Aug 24 15:33:04 2011 +0200 Cleanup: use createPromiseWrapper instead of easy_install.script - Install the socket_connection_attempt script into bin/ directory - Create promises running this script specifying the right command line arguments commit a870a4d77a3b72d79354e557ee0b8571da9a7459 Author: Antoine Catton <acatton@tiolive.com> Date: Wed Aug 24 13:44:50 2011 +0200 Minor: remove appending promise path to path_list commit 260df1be27ac382061809aa8851130cd26f74be0 Author: Åukasz Nowak <luke@nexedi.com> Date: Thu Jul 28 14:40:29 2011 +0200 Do not expose python's shabang. commit 7db31e9b6759183a54390480a77032009bf2e9ae Author: Antoine Catton <acatton@tiolive.com> Date: Thu Jul 28 14:13:03 2011 +0200 Replaced the usage python script as template by the easy_install capability usage. commit 3f62cda3a2a9e64cc92cd4c01585b422bb30ff0e Author: Antoine Catton <acatton@tiolive.com> Date: Tue Jul 26 15:34:13 2011 +0200 Adding promises to kvm software release. Not tested yet Minor: removed magic number 5900 commit 2e36426bd11e4833ec3be6a8e2b664e343760417 Author: Antoine Catton <acatton@tiolive.com> Date: Tue Jul 26 13:38:14 2011 +0200 Trailing spaces on KVM recipe commit 02ed180bd0002cbfe387875ec917e4d6e214e40e Author: Antoine Catton <acatton@tiolive.com> Date: Mon Jul 25 16:57:43 2011 +0200 Method createPromise in slapos.librecipe This method create a promise script which should return 0 whether the promise was kept. --- slapos/recipe/kvm/__init__.py | 42 ++++++++++++++++++- .../recipe/kvm/socket_connection_attempt.py | 26 ++++++++++++ .../kvm/template/port_listening_promise.in | 4 ++ slapos/recipe/librecipe/__init__.py | 13 ++++++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 slapos/recipe/kvm/socket_connection_attempt.py create mode 100644 slapos/recipe/kvm/template/port_listening_promise.in diff --git a/slapos/recipe/kvm/__init__.py b/slapos/recipe/kvm/__init__.py index d0ed230de..12d4b7877 100644 --- a/slapos/recipe/kvm/__init__.py +++ b/slapos/recipe/kvm/__init__.py @@ -37,6 +37,9 @@ import hashlib class Recipe(BaseSlapRecipe): + # To avoid magic numbers + VNC_BASE_PORT = 5900 + def _install(self): """ Set the connection dictionnary for the computer partition and create a list @@ -54,9 +57,25 @@ class Recipe(BaseSlapRecipe): self.ca_conf = self.installCertificateAuthority() self.key_path, self.certificate_path = self.requestCertificate('noVNC') + # Install the socket_connection_attempt script + catcher = zc.buildout.easy_install.scripts( + [('check_port_listening', __name__ + 'socket_connection_attempt', 'connection_attempt')], + self.ws, + sys.executable, + self.bin_directory, + ) + # Save the check_port_listening script path + check_port_listening_script = catcher[0] + # Get the port_listening_promise template path, and save it + self.port_listening_promise_path = pkg_resources.resource_filename( + __name__, 'template/port_listening_promise.in') + self.port_listening_promise_conf = dict( + check_port_listening_script=check_port_listening_script, + ) + kvm_conf = self.installKvm(vnc_ip = self.getLocalIPv4Address()) - vnc_port = 5900 + kvm_conf['vnc_display'] + vnc_port = Recipe.VNC_BASE_PORT + kvm_conf['vnc_display'] noVNC_conf = self.installNoVnc(source_ip = self.getGlobalIPv6Address(), source_port = 6080, @@ -164,6 +183,17 @@ class Recipe(BaseSlapRecipe): ##slapreport_runner_path = self.instanciate_wrapper("slapreport", # [database_path, python_path]) + # Add VNC promise + self.port_listening_promise_conf.update( + hostname=kvm_conf['vnc_ip'], + port=Recipe.VNC_BASE_PORT + kvm_conf['vnc_display'], + ) + self.createPromiseWrapper("vnc_promise", + self.substituteTemplate(self.port_listening_promise_path, + self.port_listening_promise_conf, + ) + ) + return kvm_conf def installNoVnc(self, source_ip, source_port, target_ip, target_port): @@ -207,6 +237,16 @@ class Recipe(BaseSlapRecipe): self.path_list.append(websockify_runner_path) + # Add noVNC promise + self.port_listening_promise_conf.update(hostname=noVNC_conf['source_ip'], + port=noVNC_conf['source_port'], + ) + self.createPromiseWrapper("novnc_promise", + self.substituteTemplate(self.port_listening_promise_path, + self.port_listening_promise_conf, + ) + ) + return noVNC_conf def linkBinary(self): diff --git a/slapos/recipe/kvm/socket_connection_attempt.py b/slapos/recipe/kvm/socket_connection_attempt.py new file mode 100644 index 000000000..dfd9fad4b --- /dev/null +++ b/slapos/recipe/kvm/socket_connection_attempt.py @@ -0,0 +1,26 @@ +import socket +import sys + +def connection_attempt(): + + try: + hostname, port = sys.argv[1:3] + except ValueError: + print >> sys.stderr, """Bad command line. + Usage: %s hostname|ip port""" % sys.argv[0] + sys.exit(1) + + connection_okay = False + + try: + s = socket.create_connection((hostname, port)) + connection_okay = True + s.close() + except (socket.error, socket.timeout): + connection_okay = False + + if not connection_okay: + print >> sys.stderr, "%(port)s on %(ip)s isn't listening" % { + 'port': port, 'ip': hostname + } + sys.exit(127) diff --git a/slapos/recipe/kvm/template/port_listening_promise.in b/slapos/recipe/kvm/template/port_listening_promise.in new file mode 100644 index 000000000..15fa390d0 --- /dev/null +++ b/slapos/recipe/kvm/template/port_listening_promise.in @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +"%(check_port_listening_script)s" "%(hostname)s" "%(port)s" +exit $? diff --git a/slapos/recipe/librecipe/__init__.py b/slapos/recipe/librecipe/__init__.py index e0eb9d547..c49c6c772 100644 --- a/slapos/recipe/librecipe/__init__.py +++ b/slapos/recipe/librecipe/__init__.py @@ -60,6 +60,7 @@ class BaseSlapRecipe: 'xml_report') self.destroy_script_location = os.path.join(self, self.work_directory, 'sbin', 'destroy') + self.promise_directory = os.path.join(self.etc_directory, 'promise') # default directory structure information self.default_directory_list = [ @@ -71,6 +72,7 @@ class BaseSlapRecipe: self.etc_directory, # CP/etc - configuration container self.wrapper_directory, # CP/etc/run - for wrappers self.wrapper_report_directory, # CP/etc/report - for report wrappers + self.promise_directory, # CP/etc/promise - for promise checking scripts self.var_directory, # CP/var - partition "internal" container for logs, # and another metadata self.wrapper_xml_report_directory, # CP/var/xml_report - for xml_report wrappers @@ -243,3 +245,14 @@ class BaseSlapRecipe: def _install(self): """Hook which shall be implemented in children class""" raise NotImplementedError('Shall be implemented by subclass') + + def createPromiseWrapper(self, promise_name, file_content): + """Create a promise wrapper. + + This wrapper aim to check if the software release is doing its job. + + Return the promise file path. + """ + promise_path = os.path.join(self.promise_directory, promise_name) + self._writeExecutable(promise_path, file_content) + return promise_path -- 2.30.9