From: Frank Brehm Date: Wed, 31 Oct 2018 12:18:52 +0000 (+0100) Subject: Nearly finishing bin/create-vmware-template X-Git-Tag: 0.3.2^2~14 X-Git-Url: https://git.uhu-banane.org/?a=commitdiff_plain;h=696f919b4b97e501eb0b98ac43c3282a3374e9b3;p=pixelpark%2Fcreate-vmware-tpl.git Nearly finishing bin/create-vmware-template --- diff --git a/lib/cr_vmware_tpl/handler.py b/lib/cr_vmware_tpl/handler.py index 3496879..2b8451c 100644 --- a/lib/cr_vmware_tpl/handler.py +++ b/lib/cr_vmware_tpl/handler.py @@ -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)) diff --git a/python_fb_tools b/python_fb_tools index e46d386..7a34f28 160000 --- a/python_fb_tools +++ b/python_fb_tools @@ -1 +1 @@ -Subproject commit e46d386775b93f051cd5cc81880e94b3ebd4f19b +Subproject commit 7a34f2835ed37ebff36ac08fa726b8cefdc477c9