import os
import logging
import ssl
+import re
+import random
# Third party modules
import six
from .config import CrTplConfiguration
-__version__ = '0.3.1'
+__version__ = '0.3.2'
LOG = logging.getLogger(__name__)
return msg
+# =============================================================================
+class NoDatastoreFoundError(HandlerError):
+ """Special error class for the case, that no SAN based data store was with
+ enogh free space was found."""
+
+
+ # -------------------------------------------------------------------------
+ def __init__(self, needed_bytes):
+
+ self.needed_bytes = int(needed_bytes)
+
+ # -------------------------------------------------------------------------
+ def __str__(self):
+
+ mb = float(self.needed_bytes) / 1024.0 / 1024.0
+ gb = mb / 1024.0
+
+ msg = (
+ "No SAN based datastore found with at least {m:0.0f} MiB == {g:0.1f} GiB "
+ "available space found.").format(m=mb, g=gb)
+ return msg
+
+
# =============================================================================
class CannotConnectError(HandlerError):
"""Special error class for the case, it cannot connect
"""
max_depth = 10
+ re_local_ds = re.compile(r'^local[_-]', re.IGNORECASE)
# -------------------------------------------------------------------------
def __init__(
self.config = config
self.server_instance = None
self.tpl_vm_folder = None
+ self.tpl_data_store = None
if initialized:
self.initialized = True
try:
self.ensure_vm_folder()
self.check_for_temp_tpl_vm()
+ self.select_data_store()
finally:
LOG.debug("Disconnecting from vSphere host {h}:{p} ...".format(
h=self.config.vsphere_host, p=self.config.vsphere_port))
return None
+ # -------------------------------------------------------------------------
+ def select_data_store(self):
+
+ LOG.debug((
+ "Selecting a SAN based datastore with at least {:0.1f} GiB available "
+ "space.").format(self.config.data_size_gb))
+
+ content = self.server_instance.RetrieveContent()
+ dc = self.get_obj(content, [vim.Datacenter], self.config.dc)
+
+ ds_list = []
+
+ for child in dc.datastoreFolder.childEntity:
+ self._get_data_stores(child, ds_list)
+
+ if not len(ds_list):
+ raise NoDatastoreFoundError(self.config.data_size)
+
+ LOG.debug("Found {} usable datastores.".format(len(ds_list)))
+ self.tpl_data_store = random.choice(ds_list)
+ LOG.info("Using datastore {!r} for volume of temporary VM to create.".format(
+ self.tpl_data_store.summary.name))
+
+ # -------------------------------------------------------------------------
+ def _get_data_stores(self, child, ds_list, depth=1):
+
+ if hasattr(child, 'childEntity'):
+ if depth > self.max_depth:
+ return
+ for sub_child in child.childEntity:
+ self._get_data_stores(sub_child, ds_list, depth + 1)
+ return
+
+ if isinstance(child, vim.Datastore):
+ #if not child.summary.multipleHostAccess:
+ if self.re_local_ds.match(child.summary.name):
+ if self.verbose > 2:
+ LOG.debug("Datastore {!r} seems to be local.".format(child.summary.name))
+ return
+ free_bytes = child.summary.freeSpace
+ free_gbytes = float(free_bytes) / 1024.0 / 1024.0 / 1024.0
+ if free_bytes >= self.config.data_size:
+ if self.verbose > 2:
+ LOG.debug("Found datastore {n!r} with {f:0.1f} GiB free space.".format(
+ n=child.summary.name, f=free_gbytes))
+ ds_list.append(child)
+ return
+
+ LOG.debug("Datastore {n!r} has too less space ({f:0.1f} GiB available).".format(
+ n=child.summary.name, f=free_gbytes))
+
+ return
+
# =============================================================================