]> Frank Brehm's Git Trees - pixelpark/create-vmware-tpl.git/commitdiff
Nearly finishing bin/create-vmware-template
authorFrank Brehm <frank.brehm@pixelpark.com>
Wed, 31 Oct 2018 12:18:52 +0000 (13:18 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Wed, 31 Oct 2018 12:18:52 +0000 (13:18 +0100)
lib/cr_vmware_tpl/handler.py
python_fb_tools

index 349687916d5be57e37360f5efdbd493cd050451f..2b8451c5ce4aca0a453eb8d53ea9b60b743e8a8e 100644 (file)
@@ -45,7 +45,7 @@ from fb_tools.vsphere.iface import VsphereVmInterface
 
 from .config import CrTplConfiguration
 
-__version__ = '0.10.9'
+__version__ = '0.10.10'
 
 LOG = logging.getLogger(__name__)
 TZ = pytz.timezone('Europe/Berlin')
@@ -206,154 +206,13 @@ class CrTplHandler(BaseHandler):
                     self.poweroff_vm()
                     self.change_mac_address()
 
-        return 0
-
-
-#        LOG.debug("Connecting to vSphere host {h}:{p} as {u!r} ...".format(
-#            h=self.config.vsphere_host, p=self.config.vsphere_port,
-#            u=self.config.vsphere_user))
-
-#        ssl_context = None
-#        if hasattr(ssl, '_create_unverified_context'):
-#            ssl_context = ssl._create_unverified_context()
-
-#        self.service_instance = SmartConnect(
-#            host=self.config.vsphere_host, port=self.config.vsphere_port,
-#            user=self.config.vsphere_user, pwd=self.config.password,
-#            sslContext=ssl_context)
-
-#        if not self.service_instance:
-#            raise CannotConnectVsphereError(
-#                host=self.config.vsphere_host, port=self.config.vsphere_port,
-#                user=self.config.vsphere_user)
-
-        try:
-#            self.get_cluster()
-#            self.ensure_vm_folder()
-            if self.rotate_only:
-                LOG.warn("Only executing of template rotating.")
-            else:
-#                self.check_network()
-#                self.create_vm()
-#                self.tpl_vm = self.get_temp_tpl_vm()
-#                if not self.tpl_vm:
-#                    raise HandlerError(
-#                        "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 cleaning up the VM!!!")
-                else:
-                    self.post_install_tasks_ssh()
-                    if self.postinstall_errors:
-                        self.purge_template_vm()
-                        return 10
-                    else:
-                        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()
-        finally:
-            LOG.debug("Disconnecting from vSphere host {h}:{p} ...".format(
-                h=self.config.vsphere_host, p=self.config.vsphere_port))
-            Disconnect(self.service_instance)
+        if not self.abort and not self.postinstall_errors:
+            self.rotate_templates()
+            if not self.rotate_only:
+                self.rename_and_change_vm()
 
         return 0
 
-    # -------------------------------------------------------------------------
-    def get_obj(self, content, vimtype, name):
-
-        obj = None
-        container = content.viewManager.CreateContainerView(content.rootFolder, vimtype, True)
-        for c in container.view:
-            if c.name == name:
-                obj = c
-                break
-
-        return obj
-
-    # -------------------------------------------------------------------------
-    def get_obj_list(self, content, vimtype):
-
-        result = []
-
-        container = content.viewManager.CreateContainerView(content.rootFolder, vimtype, True)
-        for c in container.view:
-            result.append(c)
-
-        return result
-
-    # -------------------------------------------------------------------------
-    def wait_for_tasks(self, tasks):
-
-        LOG.debug("Waiting for tasks to finish ...")
-
-        property_collector = self.service_instance.content.propertyCollector
-        task_list = [str(task) for task in tasks]
-        LOG.debug("Waiting for tasks {} to finish ...".format(task_list))
-        # Create filter
-        obj_specs = [vmodl.query.PropertyCollector.ObjectSpec(obj=task) for task in tasks]
-        property_spec = vmodl.query.PropertyCollector.PropertySpec(
-            type=vim.Task, pathSet=[], all=True)
-        filter_spec = vmodl.query.PropertyCollector.FilterSpec()
-        filter_spec.objectSet = obj_specs
-        filter_spec.propSet = [property_spec]
-        pcfilter = property_collector.CreateFilter(filter_spec, True)
-        try:
-            version, state = None, None
-            # Loop looking for updates till the state moves to a completed state.
-            while len(task_list):
-                update = property_collector.WaitForUpdates(version)
-                for filter_set in update.filterSet:
-                    time.sleep(0.1)
-                    LOG.debug("Waiting ...")
-                    for obj_set in filter_set.objectSet:
-                        task = obj_set.obj
-                        for change in obj_set.changeSet:
-                            if change.name == 'info':
-                                state = change.val.state
-                            elif change.name == 'info.state':
-                                state = change.val
-                            else:
-                                continue
-
-                            if not str(task) in task_list:
-                                continue
-
-                            if state == vim.TaskInfo.State.success:
-                                # Remove task from taskList
-                                task_list.remove(str(task))
-                            elif state == vim.TaskInfo.State.error:
-                                raise task.info.error
-                    # Move to next version
-                version = update.version
-        finally:
-            if pcfilter:
-                pcfilter.Destroy()
-
-    # -------------------------------------------------------------------------
-    def get_tpl_folder(self, vm_folder=None):
-
-        if not vm_folder:
-            content = self.service_instance.RetrieveContent()
-            dc = self.get_obj(content, [vim.Datacenter], self.config.dc)
-            vm_folder = dc.vmFolder
-
-        for child in vm_folder.childEntity:
-            if not isinstance(child, vim.Folder):
-                continue
-            if self.verbose > 3:
-                LOG.debug("Found vim.Folder {!r} in root VM folder.".format(child.name))
-            if child.name == self.config.folder:
-                LOG.info("VM-Folder {!r} already exists.".format(self.config.folder))
-                return child
-
-        return None
-
     # -------------------------------------------------------------------------
     def check_for_temp_tpl_vm(self, no_error=False):
 
@@ -377,44 +236,6 @@ class CrTplHandler(BaseHandler):
 
         return self.vsphere.get_vm(self.config.template_vm, as_vmw_obj=True)
 
-    # -------------------------------------------------------------------------
-    def get_templates(self):
-
-        templates = []
-
-        content = self.service_instance.RetrieveContent()
-        dc = self.get_obj(content, [vim.Datacenter], self.config.dc)
-
-        for child in dc.vmFolder.childEntity:
-            tpl_list = self._get_templates(child)
-            if tpl_list and len(tpl_list):
-                templates.extend(tpl_list)
-
-        return templates
-
-    # -------------------------------------------------------------------------
-    def _get_templates(self, child, depth=1):
-
-        tpl_list = []
-
-        if hasattr(child, 'childEntity'):
-            if depth > self.max_depth:
-                return None
-            templates = []
-            for sub_child in child.childEntity:
-                tpl_list = self._get_templates(sub_child, depth + 1)
-                if tpl_list and len(tpl_list):
-                    templates.extend(tpl_list)
-            return templates
-
-        if hasattr(child, 'summary'):
-            summary = child.summary
-            vm_name = summary.config.name
-            if summary.config.template and vm_name.startswith(self.config.template_name):
-                tpl_list.append(child)
-
-        return tpl_list
-
     # -------------------------------------------------------------------------
     def select_data_store(self):
 
@@ -497,16 +318,6 @@ class CrTplHandler(BaseHandler):
             name=self.config.template_vm, vm_folder=tpl_vm_folder, vm_config_spec=vm_spec,
             pool=self.cluster.resource_pool, max_wait=15)
 
-#    # -------------------------------------------------------------------------
-#    def poweron_vm(self):
-#
-#        LOG.info("Powering on VM {!r} ...".format(self.config.template_vm))
-#
-#        task = self.tpl_vm.PowerOnVM_Task()
-#        self.wait_for_tasks([task])
-#        self.ts_start_install = time.time()
-#        LOG.debug("VM {!r} successful powered on.".format(self.config.template_vm))
-
     # -------------------------------------------------------------------------
     def wait_for_finish_install(self):
 
@@ -670,18 +481,6 @@ class CrTplHandler(BaseHandler):
         if self.postinstall_errors:
             LOG.warn("Template VM {!r} has to be removed.".format(self.config.template_vm))
 
-#    # -------------------------------------------------------------------------
-#    def purge_template_vm(self):
-#
-#        self.vsphere.poweroff_vm(self.tpl_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):
 
@@ -778,7 +577,7 @@ class CrTplHandler(BaseHandler):
             cur_duration = cur_time - start_waiting
         print('', flush=True)
 
-        LOG.info("Powering off VM {!r} per SSH ...".format(self.config.template_vm))
+        LOG.info("Last actions before powering off VM {!r} ...".format(self.config.template_vm))
 
         ssh = None
 
@@ -821,8 +620,7 @@ class CrTplHandler(BaseHandler):
                 "Cannot shut down VM {h!r}, is currently in state {s!r}.".format(
                     h=self.config.template_vm, s=guest_state))
 
-#        LOG.debug("Shutting down VM {!r} ...".format(self.config.template_vm))
-#        start_shutdown = time.time()
+        LOG.info("Powering off VM {!r} per SSH ...".format(self.config.template_vm))
 
         try:
 
@@ -921,15 +719,19 @@ class CrTplHandler(BaseHandler):
         LOG.info("Searching for existing templates and rotate them ...")
         re_is_numeric = re.compile(r'^\s*(\d+)\s*$')
 
-        templates = self.get_templates()
-        templates_ts = {}
-        templates_sorted = []
+        pattern_tpl = r'^' + re.escape(self.config.template_name)
+        re_tpl = re.compile(pattern_tpl, re.IGNORECASE)
 
+        templates = self.vsphere.get_vms(re_tpl, is_template=True)
         if not templates:
             LOG.info("Did not found any existing templates.")
             return
-
         LOG.debug("Found {} existing templates.".format(len(templates)))
+
+        templates_ts = {}
+        templates_sorted = []
+        new_template_names = {}
+
         for template in templates:
             tpl_name = template.summary.config.name
             val_map = {}
@@ -938,8 +740,9 @@ class CrTplHandler(BaseHandler):
                 value = extra_cfg.value
                 val_map[key] = value
             created = time.time()
-            if val_map['created'] and re_is_numeric.match(val_map['created']):
-                created = float(val_map['created'])
+            if 'created' in val_map:
+                if val_map['created'] and re_is_numeric.match(val_map['created']):
+                    created = float(val_map['created'])
             ts_created = datetime.datetime.fromtimestamp(created, tz=TZ)
             LOG.debug("Found template {n!r}, created: {ts}.".format(
                 n=tpl_name, ts=ts_created.isoformat(' ')))
@@ -968,18 +771,28 @@ class CrTplHandler(BaseHandler):
             tpl_name = template.summary.config.name
             if tpl_name in templates_to_remove:
                 LOG.info("Removing template {!r} ...".format(tpl_name))
-                task = template.Destroy_Task()
-                self.wait_for_tasks([task])
+                self.vsphere.purge_vm(template)
                 LOG.debug("Successful removed template {!r}.".format(tpl_name))
                 continue
             if tpl_name.strip().lower() == self.config.template_name.strip().lower():
                 created = templates_ts[tpl_name]
                 ts_created = datetime.datetime.fromtimestamp(created, tz=TZ)
-                new_name = tpl_name + '.' + ts_created.strftime('%Y-%m-%d_%H-%M-%S')
+                i = 0
+                dt = ts_created.strftime('%Y-%m-%d_%H-%M-%S')
+                new_name = "{t}.{d}".format(t=tpl_name, d=dt)
+                tname = new_name.strip().lower()
+                while tname in new_template_names:
+                    new_name = "{t}.{d}-{i}".format(t=tpl_name, d=dt, i=i)
+                    tname = new_name.strip().lower()
+                    i += 1
+                new_template_names[tname] = 1
                 LOG.info("Renaming template {o!r} => {n!r} ...".format(o=tpl_name, n=new_name))
                 task = template.Rename_Task(new_name)
-                self.wait_for_tasks([task])
+                self.vsphere.wait_for_tasks([task])
                 LOG.debug("Successful renamed template into {!r}.".format(new_name))
+            else:
+                tname = tpl_name.strip().lower()
+                new_template_names[tname] = 1
 
     # -------------------------------------------------------------------------
     def rename_and_change_vm(self):
@@ -989,7 +802,7 @@ class CrTplHandler(BaseHandler):
 
         vm = self.get_temp_tpl_vm()
         task = vm.Rename_Task(self.config.template_name)
-        self.wait_for_tasks([task])
+        self.vsphere.wait_for_tasks([task])
         LOG.debug("Successful renamed VM into {!r}.".format(self.config.template_name))
 
         LOG.info("Changing VM {!r} into a VMWare template ...".format(self.config.template_name))
index e46d386775b93f051cd5cc81880e94b3ebd4f19b..7a34f2835ed37ebff36ac08fa726b8cefdc477c9 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e46d386775b93f051cd5cc81880e94b3ebd4f19b
+Subproject commit 7a34f2835ed37ebff36ac08fa726b8cefdc477c9