from .config import CrTplConfiguration
-__version__ = '0.10.9'
+__version__ = '0.10.10'
LOG = logging.getLogger(__name__)
TZ = pytz.timezone('Europe/Berlin')
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):
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):
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):
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):
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
"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:
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 = {}
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(' ')))
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):
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))