]> Frank Brehm's Git Trees - pixelpark/create-vmware-tpl.git/commitdiff
Handling post install errors
authorFrank Brehm <frank.brehm@pixelpark.com>
Wed, 16 May 2018 15:17:58 +0000 (17:17 +0200)
committerFrank Brehm <frank.brehm@pixelpark.com>
Wed, 16 May 2018 15:17:58 +0000 (17:17 +0200)
lib/cr_vmware_tpl/app.py
lib/cr_vmware_tpl/handler.py

index e21c85b261c80b054900de213afff9f5046e9fcf..64c037a2dd7bbe21eafcabc36193418499aa4bdf 100644 (file)
@@ -34,7 +34,7 @@ from .config import CrTplConfiguration
 
 from .handler import ExpectedHandlerError, CrTplHandler
 
-__version__ = '0.5.1'
+__version__ = '0.6.1'
 LOG = logging.getLogger(__name__)
 
 
@@ -443,7 +443,8 @@ class CrTplApplication(PpBaseObject):
         LOG.info("Starting ...")
 
         try:
-            self.handler()
+            ret = self.handler()
+            self.exit(ret)
         except ExpectedHandlerError as e:
             self.handle_error(str(e), "Temporary VM")
             self.exit(5)
index a062c47d0560209710db16bf34739ab3850e2fc9..1e25c1459b6a349c5c6011acb4634358c02df6c8 100644 (file)
@@ -36,7 +36,7 @@ from .obj import PpBaseObject
 
 from .config import CrTplConfiguration
 
-__version__ = '0.8.2'
+__version__ = '0.9.1'
 LOG = logging.getLogger(__name__)
 TZ = pytz.timezone('Europe/Berlin')
 
@@ -170,6 +170,7 @@ class CrTplHandler(PpBaseObject):
         self.max_wait_for_shutdown = 600
         self.rotate_only = False
         self.abort = False
+        self.postinstall_errors = None
 
         if initialized:
             self.initialized = True
@@ -220,14 +221,19 @@ class CrTplHandler(PpBaseObject):
                         "Could not find VM after creating.")
                 self.poweron_vm()
                 self.wait_for_finish_install()
+                self.get_postinstall_error()
                 if self.abort:
                     LOG.warn("Aborting after creation of template VM.")
-                    LOG.warn("You are responsible yourself to clewaning up the VM!!!")
+                    LOG.warn("You are responsible yourself to cleaning up the VM!!!")
                 else:
-                    self.post_install_tasks_ssh()
-                    self.poweroff_vm()
-                    self.change_mac_address()
-            if not self.abort:
+                    if self.postinstall_errors:
+                        self.purge_template_vm()
+                        return 10
+                    else:
+                        self.post_install_tasks_ssh()
+                        self.poweroff_vm()
+                        self.change_mac_address()
+            if not self.abort and not self.postinstall_errors:
                 self.rotate_templates()
                 if not self.rotate_only:
                     self.rename_and_change_vm()
@@ -236,6 +242,8 @@ class CrTplHandler(PpBaseObject):
                 h=self.config.vsphere_host, p=self.config.vsphere_port))
             Disconnect(self.service_instance)
 
+        return 0
+
     # -------------------------------------------------------------------------
     def get_obj(self, content, vimtype, name):
 
@@ -781,6 +789,70 @@ class CrTplHandler(PpBaseObject):
             raise ExpectedHandlerError(
                 "SSH not available after {:0.1f} seconds, giving up.".format(duration))
 
+    # -------------------------------------------------------------------------
+    def get_postinstall_error(self):
+
+        LOG.info("Trying to get possible post-installation errors ...")
+
+        ssh = None
+        cmd = textwrap.dedent("""\
+        if [ -f /root/postinst-error.txt ] ; then
+            cat /root/postinst-error.txt
+        fi
+        """)
+
+        try:
+
+            LOG.debug("Initializing paramiko SSHClient")
+            ssh = paramiko.SSHClient()
+            LOG.debug("Loading SSH system host keys.")
+            ssh.load_system_host_keys()
+            LOG.debug("Setting SSH missing host key policy to AutoAddPolicy.")
+            ssh.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
+
+            LOG.debug("Connecting to {h!r}, port {p} as {u!r} per SSH ...".format(
+                h=self.config.template_vm, p=self.ssh_port, u=self.ssh_user))
+            ssh.connect(
+                self.config.template_vm, port=self.ssh_port, timeout=self.ssh_timeout,
+                username=self.ssh_user, key_filename=self.private_ssh_key)
+
+            LOG.debug("Trying to read /root/postinst-error.txt ...")
+            if self.verbose > 1:
+                LOG.debug("Commands to execute:\n{}".format(cmd))
+
+            stdin, stdout, stderr = ssh.exec_command(
+                cmd, timeout=self.ssh_timeout)
+
+            output = to_str(stdout.read()).strip()
+            err = to_str(stderr.read()).strip()
+
+            LOG.debug("Output on STDERR:\n{}".format(err))
+
+            if output:
+                self.postinstall_errors = output
+                LOG.error("Got postinstall errors:\n{}".format(output))
+
+        finally:
+            if ssh:
+                if self.verbose > 2:
+                    LOG.debug("Closing SSH connection.")
+                ssh.close()
+
+        if self.postinstall_errors:
+            LOG.warn("Template VM {!r} has to be removed.".format(self.config.template_vm))
+
+    # -------------------------------------------------------------------------
+    def purge_template_vm(self):
+
+        self.poweroff_vm()
+
+        LOG.info("Purging VM {!r} because of errors.".format(self.config.template_vm))
+        vm = self.get_temp_tpl_vm()
+        task = vm.Destroy_Task()
+        self.wait_for_tasks([task])
+
+        LOG.warn("Successful removed VM {!r}.".format(self.config.template_vm))
+
     # -------------------------------------------------------------------------
     def post_install_tasks_ssh(self):