def __init__(self, host, login, passwd): """ Initializes the SDK """ self._host = host self._username = login self._password = passwd self._sessionID = None self._check_session = True self._cache = ObjectCache() self._cache.setduration(weeks=1) self._client = Client('https://%s/sdk/vimService?wsdl' % host, cache=self._cache, cachingpolicy=1) self._client.set_options(location='https://%s/sdk' % host, plugins=[ValueExtender()]) service_reference = self._build_property('ServiceInstance') self._serviceContent = self._client.service.RetrieveServiceContent( service_reference) # In case of an ESXi host, this would be 'HostAgent' self._is_vcenter = self._serviceContent.about.apiType == 'VirtualCenter' if not self._is_vcenter: # pylint: disable=line-too-long self._login() self._esxHost = self._get_object( self._serviceContent.rootFolder, prop_type='HostSystem', traversal={ 'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': { 'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'ComputeResourceTravelSpec', # noqa 'type': 'ComputeResource', 'path': 'host' } } } }, properties=['name']).obj_identifier # pylint: enable=line-too-long else: self._esxHost = self._get_vcenter_hosts( )[0].obj_identifier # TODO?
def __init__(self, host, login, passwd): """ Initializes the SDK """ self._host = host self._username = login self._password = passwd self._sessionID = None self._check_session = True self._cache = ObjectCache() self._cache.setduration(weeks=1) self._client = Client('https://{0}/sdk/vimService?wsdl'.format(host), cache=self._cache, cachingpolicy=1) self._client.set_options(location='https://{0}/sdk'.format(host), plugins=[ValueExtender()]) service_reference = self._build_property('ServiceInstance') self._serviceContent = self._client.service.RetrieveServiceContent( service_reference) # In case of an ESXi host, this would be 'HostAgent' self.is_vcenter = self._serviceContent.about.apiType == 'VirtualCenter' if not self.is_vcenter: self._login() self._esxHost = self._get_object( self._serviceContent.rootFolder, prop_type='HostSystem', traversal={ 'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': { 'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'ComputeResourceTravelSpec', 'type': 'ComputeResource', 'path': 'host' } } } }, properties=['name']).obj_identifier else: # @TODO: We need to extend all calls to specify the ESXi host where the action needs to be executed. # We cannot just assume an ESXi host here, as this is important for certain calls like creating a VM. self._esxHost = None
def _setup(self): plugings = [] cache_conf = NoCache() if Configuration.debug: if Configuration.log_file is not None: logging.basicConfig(filename=Configuration.log_file, level=Configuration.log_level, format=utils.get_log_format()) else: logging.basicConfig(level=Configuration.log_level, format=utils.get_log_format()) if Configuration.log_level == logging.DEBUG and Configuration.environment == constants.PRODUCTION_ENV: raise LogException plugings.append(LogPlugin()) s = requests.Session() s.mount('file://', FileAdapter()) if Configuration.proxy_url: s.proxies = utils.get_builded_proxy_url(Configuration.proxy_url, Configuration.proxy_port) if Configuration.proxy_user: s.auth= HTTPProxyAuth(Configuration.proxy_user, Configuration.proxy_pass) if Configuration.certificate and Configuration.c_key: s.cert=(Configuration.certificate, Configuration.c_key) else: s.verify = Configuration.certificate t = RequestsTransport(s, timeout=Configuration.timeout) if Configuration.cache: cache_conf = ObjectCache(location=Configuration.cache_location, seconds=Configuration.cache_duration) self._client = client.Client(Configuration.get_wsdl().strip(), plugins=plugings, transport=t, cache=cache_conf)
def __init__(self, name, url, verbose=True, cache=False): """.. rubric:: Constructor :param str name: a name e.g. Kegg, Reactome, ... :param str url: the URL of the WSDL service :param bool verbose: prints informative messages The :attr:`serv` give access to all WSDL functionalities of the service. The :attr:`methods` is an alias to self.serv.methods and returns the list of functionalities. """ super(WSDLService, self).__init__(name, url, verbose=verbose) self.logging.info("Initialising %s service (WSDL)" % self.name) self.CACHING = cache try: #: attribute to access to the methods provided by this WSDL service from suds.client import Client from suds.cache import ObjectCache oc = ObjectCache(self.settings.user_config_dir, days=0) if self.CACHING is True: self.suds = Client(self.url, cache=oc, cachingpolicy=1) else: self.suds = Client(self.url) # reference to the service self.serv = self.suds.service self._update_settings() except Exception: self.logging.error("Could not connect to the service %s " % self.url) raise Exception
def get_client(hostname, wsdl_name, username='******', password='******', cachedir=None, verify=False, timeout=90, port=443): """Returns and instance of suds.client.Client. A separate client is used for each iControl WSDL/Namespace (e.g. "LocalLB.Pool"). This function allows any suds exceptions to propagate up to the caller. @param hostname: The IP address or hostname of the BIGIP. @param wsdl_name: The iControl namespace (e.g. "LocalLB.Pool") @param username: The admin username on the BIGIP. @param password: The admin password on the BIGIP. @param cachedir: The directory to cache wsdls in. None indicates that caching should be disabled. @param verify: When True, performs SSL certificate validation in Python / urllib2 versions that support it (v2.7.9 and newer) @param timeout: The time to wait (in seconds) before timing out the connection to the URL """ url = 'https://%s:%s/iControl/iControlPortal.cgi?WSDL=%s' % ( hostname, port, wsdl_name) imp = Import('http://schemas.xmlsoap.org/soap/encoding/') imp.filter.add('urn:iControl') if cachedir is not None: cachedir = ObjectCache(location=os.path.expanduser(cachedir), days=1) doctor = ImportDoctor(imp) if verify: client = Client(url, doctor=doctor, username=username, password=password, cache=cachedir, timeout=timeout) else: transport = HTTPSTransportNoVerify(username=username, password=password, timeout=timeout) client = Client(url, doctor=doctor, username=username, password=password, cache=cachedir, transport=transport, timeout=timeout) # Without this, subsequent requests will use the actual hostname of the # BIGIP, which is often times invalid. client.set_options(location=url.split('?')[0]) client.factory.separator('_') return client
def __init__(self, xaddr, user, passwd, url, cache_location='/tmp/suds', cache_duration=None, encrypt=True, daemon=False, ws_client=None): if not os.path.isfile(url): raise ONVIFError('%s doesn`t exist!' % url) # Create cache object # NOTE: if cache_location is specified, # onvif must has the permission to access it. cache = ObjectCache(location=cache_location) # cache_duration: cache will expire in `cache_duration` days if cache_duration is not None: cache.setduration(days=cache_duration) # Convert pathname to url self.url = urlparse.urljoin('file:', urllib.pathname2url(url)) self.xaddr = xaddr # Create soap client if not ws_client: self.ws_client = Client(url=self.url, location=self.xaddr, cache=cache) else: self.ws_client = ws_client self.ws_client.set_options(location=self.xaddr) # Set soap header for authentication self.user = user self.passwd = passwd # Indicate wether password digest is needed self.encrypt = encrypt self.daemon = daemon self.set_wsse() # Method to create type instance of service method defined in WSDL self.create_type = self.ws_client.factory.create
def _get_client(wsdl_url, suds_cache=("default",), suds_timeout=None, user_cache=False): """ Open and re-use (persist) a suds.client.Client instance _suds_client throughout the session, to minimize WOF server impact and improve performance. _suds_client is global in scope. Parameters ---------- wsdl_url : str URL of a service's web service definition language (WSDL) description. All WaterOneFlow services publish a WSDL description and this url is the entry point to the service. suds_cache : ``None`` or tuple suds client local cache duration for WSDL description and client object. Pass a cache duration tuple like ('days', 3) to set a custom duration. Duration may be in months, weeks, days, hours, or seconds. If unspecified, the suds default (1 day) will be used. Use ``None`` to turn off caching. suds_timeout : int or float suds SOAP URL open timeout (seconds). If unspecified, the suds default (90 seconds) will be used. user_cache : bool If False (default), use the system temp location to store cache WSDL and other files. Use the default user ulmo directory if True. Returns ------- _suds_client : suds Client Newly or previously instantiated (reused) suds Client object. """ global _suds_client # Handle new or changed client request (create new client) if _suds_client is None or _suds_client.wsdl.url != wsdl_url or not suds_timeout is None: if user_cache: cache_dir = os.path.join(util.get_ulmo_dir(), 'suds') util.mkdir_if_doesnt_exist(cache_dir) _suds_client = suds.client.Client(wsdl_url, cache=ObjectCache(location=cache_dir)) else: _suds_client = suds.client.Client(wsdl_url) if suds_cache is None: _suds_client.set_options(cache=None) else: cache = _suds_client.options.cache # could add some error catching ... if suds_cache[0] == "default": cache.setduration(days=1) else: cache.setduration(**dict([suds_cache])) if not suds_timeout is None: _suds_client.set_options(timeout=suds_timeout) return _suds_client
def get_ewsclient(): ews_domain, ews_user, ews_pass = \ map(os.environ.get, ('EWS_DOMAIN', 'EWS_USER', 'EWS_PASS')) transport = WindowsHttpAuthenticated(username=ews_user, password=ews_pass) uri = "https://%s/EWS/Services.wsdl" % ews_domain # Long cache to avoid w3c xml.xsd lifetime issue: client = Client(uri, transport=transport, cache=ObjectCache(weeks=52), plugins=[ewsclient.AddService()]) return client
def __init__(self, use_local_wsdl=False, suds_debug=False): if use_local_wsdl: wsdl = os.path.join(os.path.dirname(__file__), 'harmony.wsdl') url = 'file://' + wsdl cache = None else: url = 'https://congruity.sourceforge.io/congruity/harmony.wsdl' cache = ObjectCache(hours=4) if suds_debug: logging.basicConfig(level=logging.INFO) logging.getLogger('suds.transport').setLevel(logging.DEBUG) self.client = Client(url, cache=cache, plugins=[MHPlugin()])
def __init__(self): merchant_settings = getattr(settings, "MERCHANT_SETTINGS") if not merchant_settings or not merchant_settings.get("paylane"): raise GatewayNotConfigured("The '%s' gateway is not correctly " "configured." % self.display_name) paylane_settings = merchant_settings["paylane"] wsdl = paylane_settings.get('WSDL', 'https://direct.paylane.com/wsdl/production/Direct.wsdl') wsdl_cache = paylane_settings.get('SUDS_CACHE_DIR', '/tmp/suds') username = paylane_settings.get('USERNAME', '') password = paylane_settings.get('PASSWORD', '') self.client = Client(wsdl, username=username, password=password, cache=ObjectCache(location=wsdl_cache, days=15))
def __init__(self, username, password, debug=False): # suds has schema cache by default, here you can set manually oc = ObjectCache() oc.setduration(days=1) oc.setlocation("./cache") self.debug = debug if debug: logging.getLogger("suds.server").setLevel(logging.DEBUG) logging.getLogger("suds.client").setLevel(logging.DEBUG) logging.getLogger("suds.transport").setLevel(logging.DEBUG) else: logging.getLogger("suds.client").setLevel(logging.CRITICAL) # hide soap faults try: self.client = suds.client.Client(url=self.url, username=username, password=password, cache=None) except suds.transport.TransportError as (err): raise Exception( "Authentication error: Invalid username or password." if err.httpcode == 401 else "Unknown initialization error: %s" % str(err) )
def __init__(self, host, login, passwd): """ Initializes the SDK """ self._logger = LogHandler.get('extensions', name='vmware sdk') self._host = host self._username = login self._password = passwd self._sessionID = None self._check_session = True self._cache = ObjectCache() self._cache.setduration(weeks=1) self._client = Client('https://{0}/sdk/vimService?wsdl'.format(host), cache=self._cache, cachingpolicy=1) self._client.set_options(location='https://{0}/sdk'.format(host), plugins=[ValueExtender()]) service_reference = self._build_property('ServiceInstance') self._serviceContent = self._client.service.RetrieveServiceContent( service_reference ) # In case of an ESXi host, this would be 'HostAgent' self.is_vcenter = self._serviceContent.about.apiType == 'VirtualCenter' if not self.is_vcenter: self._login() self._esxHost = self._get_object( self._serviceContent.rootFolder, prop_type='HostSystem', traversal={'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': {'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'ComputeResourceTravelSpec', 'type': 'ComputeResource', 'path': 'host'}}}}, properties=['name'] ).obj_identifier else: # @TODO: We need to extend all calls to specify the ESXi host where the action needs to be executed. # We cannot just assume an ESXi host here, as this is important for certain calls like creating a VM. self._esxHost = None
def __init__(self, host, login, passwd): """ Initializes the SDK """ self._host = host self._username = login self._password = passwd self._sessionID = None self._check_session = True self._cache = ObjectCache() self._cache.setduration(weeks=1) self._client = Client('https://%s/sdk/vimService?wsdl' % host, cache=self._cache, cachingpolicy=1) self._client.set_options(location='https://%s/sdk' % host, plugins=[ValueExtender()]) service_reference = self._build_property('ServiceInstance') self._serviceContent = self._client.service.RetrieveServiceContent( service_reference) # In case of an ESXi host, this would be 'HostAgent' self._is_vcenter = self._serviceContent.about.apiType == 'VirtualCenter' if not self._is_vcenter: # pylint: disable=line-too-long self._login() self._esxHost = self._get_object( self._serviceContent.rootFolder, prop_type='HostSystem', traversal={'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': {'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'ComputeResourceTravelSpec', # noqa 'type': 'ComputeResource', 'path': 'host'}}}}, properties=['name'] ).obj_identifier # pylint: enable=line-too-long else: self._esxHost = None
def get_services(bbox=None, user_cache=False): """Retrieves a list of services. Parameters ---------- bbox : ``None`` or 4-tuple Optional argument for a bounding box that covers the area you want to look for services in. This should be a tuple containing (min_longitude, min_latitude, max_longitude, and max_latitude) with these values in decimal degrees. If not provided then the full set of services will be queried from HIS Central. user_cache : bool If False (default), use the system temp location to store cache WSDL and other files. Use the default user ulmo directory if True. Returns ------- services_dicts : list A list of dicts that each contain information on an individual service. """ if user_cache: cache_dir = os.path.join(util.get_ulmo_dir(), 'suds') util.mkdir_if_doesnt_exist(cache_dir) suds_client = suds.client.Client(HIS_CENTRAL_WSDL_URL, cache=ObjectCache(location=cache_dir)) else: suds_client = suds.client.Client(HIS_CENTRAL_WSDL_URL) if bbox is None: services = suds_client.service.GetWaterOneFlowServiceInfo() else: x_min, y_min, x_max, y_max = bbox services = suds_client.service.GetServicesInBox2( xmin=x_min, ymin=y_min, xmax=x_max, ymax=y_max) services = [ _service_dict(service_info) for service_info in services.ServiceInfo ] return services
def get_client(hostname, wsdl_name, username='******', password='******', cachedir=None): """Returns and instance of suds.client.Client. A separate client is used for each iControl WSDL/Namespace (e.g. "LocalLB.Pool"). This function allows any suds exceptions to propagate up to the caller. @param hostname: The IP address or hostname of the BIGIP. @param wsdl_name: The iControl namespace (e.g. "LocalLB.Pool") @param username: The admin username on the BIGIP. @param password: The admin password on the BIGIP. @param cachedir: The directory to cache wsdls in. None indicates that caching should be disabled. """ url = 'https://%s/iControl/iControlPortal.cgi?WSDL=%s' % (hostname, wsdl_name) imp = Import('http://schemas.xmlsoap.org/soap/encoding/') imp.filter.add('urn:iControl') if cachedir is not None: cachedir = ObjectCache(location=os.path.expanduser(cachedir), days=1) doctor = ImportDoctor(imp) client = Client(url, doctor=doctor, username=username, password=password, cache=cachedir) # Without this, subsequent requests will use the actual hostname of the # BIGIP, which is often times invalid. client.set_options(location=url.split('?')[0]) client.factory.separator('_') return client
def __init__(self, service, version, authorization_data=None, environment='production', **suds_options): """ Initializes a new instance of this class. :param service: The service name. :type service: str :param authorization_data: (optional) The authorization data, if not provided, cannot call operations on service :type authorization_data: AuthorizationData or None :param environment: (optional) The environment name, can only be 'production' or 'sandbox', the default is 'production' :type environment: str :param version: to specify the service version :param suds_options: The suds options need to pass to suds client """ self._input_service = service self._input_environment = environment self._authorization_data = authorization_data self._refresh_oauth_tokens_automatically = True self._version = ServiceClient._format_version(version) # TODO This is a temp fix for set default suds temp folder with user info, suds development branch has already fixed it. if 'cache' not in suds_options: location = path.join(gettempdir(), 'suds', getuser()) suds_options['cache'] = ObjectCache(location, days=1) # set cachingpolicy to 1 to reuse WSDL cache files, otherwise will only reuse XML files if 'cachingpolicy' not in suds_options: suds_options['cachingpolicy'] = 1 self._options = suds_options self._service = ServiceClient._format_service(service) self._environment = ServiceClient._format_environment(environment) self.hp = HeaderPlugin() suds_options['plugins'] = [self.hp] self._soap_client = Client(self.service_url, **suds_options)
def __init__(self, url, **kwargs): """ @param url: The URL for the WSDL. @type url: str @param kwargs: keyword arguments. @see: L{Options} """ options = Options() options.transport = HttpAuthenticated() self.options = options options.cache = ObjectCache(days=1) self.set_options(**kwargs) reader = DefinitionsReader(options, Definitions) self.wsdl = reader.open(url) plugins = PluginContainer(options.plugins) plugins.init.initialized(wsdl=self.wsdl) self.factory = Factory(self.wsdl) self.service = ServiceSelector(self, self.wsdl.services) self.sd = [] for s in self.wsdl.services: sd = ServiceDefinition(self.wsdl, s) self.sd.append(sd) self.messages = dict(tx=None, rx=None)
class Sdk(object): """ This class contains all SDK related methods """ def __init__(self, host, login, passwd): """ Initializes the SDK """ self._host = host self._username = login self._password = passwd self._sessionID = None self._check_session = True self._cache = ObjectCache() self._cache.setduration(weeks=1) self._client = Client('https://{0}/sdk/vimService?wsdl'.format(host), cache=self._cache, cachingpolicy=1) self._client.set_options(location='https://{0}/sdk'.format(host), plugins=[ValueExtender()]) service_reference = self._build_property('ServiceInstance') self._serviceContent = self._client.service.RetrieveServiceContent( service_reference) # In case of an ESXi host, this would be 'HostAgent' self.is_vcenter = self._serviceContent.about.apiType == 'VirtualCenter' if not self.is_vcenter: self._login() self._esxHost = self._get_object( self._serviceContent.rootFolder, prop_type='HostSystem', traversal={ 'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': { 'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'ComputeResourceTravelSpec', 'type': 'ComputeResource', 'path': 'host' } } } }, properties=['name']).obj_identifier else: # @TODO: We need to extend all calls to specify the ESXi host where the action needs to be executed. # We cannot just assume an ESXi host here, as this is important for certain calls like creating a VM. self._esxHost = None @authenticated(force=True) def _get_vcenter_hosts(self): """ reload vCenter info (host name and summary) """ if not self.is_vcenter: raise RuntimeError('Must be connected to a vCenter Server API.') return self._get_object(self._serviceContent.rootFolder, prop_type='HostSystem', traversal={ 'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': { 'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'ComputeResourceTravelSpec', 'type': 'ComputeResource', 'path': 'host' } } } }, properties=[ 'name', 'summary.runtime', 'config.virtualNicManagerInfo.netConfig' ], as_list=True) def get_host_status_by_ip(self, host_ip): """ Return host status by ip, from vcenter info Must be connected to a vcenter server api """ host = self._get_host_info_by_ip(host_ip) return host.summary.runtime.powerState def get_host_status_by_pk(self, pk): """ Return host status by pk, from vcenter info Must be connected to a vcenter server api """ host = self._get_host_info_by_pk(pk) return host.summary.runtime.powerState def get_host_primary_key(self, host_ip): """ Return host primary key, based on current ip Must be connected to a vcenter server api """ host = self._get_host_info_by_ip(host_ip) return host.obj_identifier.value def _get_host_info_by_ip(self, host_ip): """ Return HostSystem object by ip, from vcenter info Must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() for host in datacenter_info: for nic in host.config.virtualNicManagerInfo.netConfig.VirtualNicManagerNetConfig: if nic.nicType == 'management': for vnic in nic.candidateVnic: if vnic.spec.ip.ipAddress == host_ip: return host raise RuntimeError( 'Host with ip {0} not found in datacenter info'.format(host_ip)) def _get_host_info_by_pk(self, pk): """ Return HostSystem object by pk, from vcenter info Must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() for host in datacenter_info: if host.obj_identifier.value == pk: return host def get_hosts(self): """ Gets a neutral list of all hosts available """ host_data = self._get_vcenter_hosts() host_data = [] if host_data is None else host_data hosts = {} for host in host_data: ips = [] for nic in host.config.virtualNicManagerInfo.netConfig.VirtualNicManagerNetConfig: if nic.nicType == 'management': for vnic in nic.candidateVnic: ips.append(vnic.spec.ip.ipAddress) hosts[host.obj_identifier.value] = {'name': host.name, 'ips': ips} return hosts def test_connection(self): """ Tests the connection """ self._login() return True def list_hosts_in_datacenter(self): """ return a list of registered host names in vCenter must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() return [host.name for host in datacenter_info] def validate_result(self, result, message=None): """ Validates a given result. Returning True if the task succeeded, raising an error if not """ if hasattr(result, '_type') and result._type == 'Task': return self.validate_result(self.get_task_info(result), message) elif hasattr(result, 'info'): if result.info.state == 'success': return True elif result.info.state == 'error': error = result.info.error.localizedMessage raise Exception(( '{0}: {1}'.format(message, error)) if message else error) raise Exception(('{0}: {1}'.format(message, 'Unexpected result') ) if message else 'Unexpected result') @authenticated() def get_task_info(self, task): """ Loads the task details """ return self._get_object(task) @authenticated() def get_vm_ip_information(self): """ Get the IP information for all vms on a given esxi host """ esxhost = self._validate_host(None) configuration = [] for vm in self._get_object( esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm' }, properties=['name', 'guest.net', 'config.files'], as_list=True): vmi = { 'id': str(vm.obj_identifier.value), 'vmxpath': str(vm.config.files.vmPathName), 'name': str(vm.name), 'net': [] } if vm.guest.net: for net in vm.guest.net[0]: vmi['net'].append({ 'mac': str(net.macAddress), 'ipaddresses': [str(i.ipAddress) for i in net.ipConfig.ipAddress] }) configuration.append(vmi) return configuration @authenticated() def exists(self, name=None, key=None): """ Checks whether a vm with a given name or key exists on a given esxi host """ esxhost = self._validate_host(self._esxHost) if name is not None or key is not None: try: if name is not None: vms = [ vm for vm in self._get_object( esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm' }, properties=['name'], as_list=True) if vm.name == name ] if len(vms) == 0: return None else: return vms[0].obj_identifier if key is not None: return self._get_object(Sdk._build_property( 'VirtualMachine', key), properties=['name']).obj_identifier except: return None else: raise Exception('A name or key should be passed.') @authenticated() def get_vm(self, key): """ Retreives a vm object, based on its key """ vmid = self.exists(key=key) if vmid is None: raise RuntimeError( 'Virtual Machine with key {} could not be found.'.format(key)) vm = self._get_object(vmid) return vm @authenticated() def get_vm_device_info(self, key): """ Return a vm config, based on its key """ vm = self.get_vm(key) filename = vm.config.files.vmPathName regex = '\[([^\]]+)\]\s(.+)' match = re.search(regex, filename) disks = self._get_vmachine_vdisks(vm) return { 'file_name': match.group(2), 'host_name': vm.name, 'vpool_name': match.group(1), 'disks': disks } @authenticated() def get_all_vms(self): """ Get all vMachines on all esxhosts registered to this vCenter :return: list """ if not self.is_vcenter: raise RuntimeError('Must be connected to a vCenter Server API.') hosts = self._get_vcenter_hosts() guests = [] for host in hosts: esxhost = self._validate_host(host.obj_identifier) vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm' }, properties=['name', 'config'], as_list=True) for vm in vms: guests.append({ 'id': vm.obj_identifier.value, 'name': vm.name, 'instance_name': vm.name }) return guests def _get_vmachine_vdisks(self, vm_object): disks = [] regex = '\[([^\]]+)\]\s(.+)' disk_type = type(self._client.factory.create('ns0:VirtualDisk')) for device in vm_object.config.hardware.device: if isinstance(device, disk_type): backingfile = device.backing.fileName match = re.search(regex, backingfile) if match: disks.append({ 'filename': match.group(2), 'datastore': match.group(1), 'name': device.deviceInfo.label }) return disks @authenticated() def get_all_vdisks(self): """ Get all vDisks on all esxhosts registered to this vCenter # similar to cinder.volumes.list() :return: list """ if not self.is_vcenter: raise RuntimeError('Must be connected to a vCenter Server API.') hosts = self._get_vcenter_hosts() disks = [] for host in hosts: esxhost = self._validate_host(host.obj_identifier) vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm' }, properties=['name', 'config'], as_list=True) for vm in vms: disks.extend(self._get_vmachine_vdisks(vm)) return disks @authenticated() def get_vms(self, ip, mountpoint): """ Get all vMachines using a given nfs share """ esxhost = self._validate_host(None) datastore = self.get_datastore(ip, mountpoint) filtered_vms = [] vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm' }, properties=['name', 'config'], as_list=True) for vm in vms: mapping = self._get_vm_datastore_mapping(vm) if datastore.name in mapping: filtered_vms.append(vm) return filtered_vms @authenticated() def set_disk_mode(self, vmid, disks, mode, wait=True): """ Sets the disk mode for a set of disks """ config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.deviceChange = [] disk_type = type(self._client.factory.create('ns0:VirtualDisk')) vmid = self.exists(key=vmid) vm = self._get_object(vmid) for device in vm.config.hardware.devices: if type(device) == disk_type and hasattr( device, 'backing') and device.backing.fileName in disks: backing = self._client.factory.create( 'ns0:VirtualDiskFlatVer2BackingInfo') backing.diskMode = mode device = self._client.factory.create('ns0:VirtualDisk') device.backing = backing disk_spec = self._client.factory.create( 'ns0:VirtualDeviceConfigSpec') disk_spec.operation = 'edit' disk_spec.fileOperation = None disk_spec.device = device config.deviceChange.append(disk_spec) task = self._client.service.ReconfigVM_Task(vm.obj_identifier, config) if wait: self.wait_for_task(task) return task @staticmethod def _create_disk(factory, key, disk, unit, datastore): """ Creates a disk spec for a given backing device Example for parameter disk: {'name': diskname, 'backingdevice': 'disk-flat.vmdk'} """ device_info = factory.create('ns0:Description') device_info.label = disk['name'] device_info.summary = 'Disk {0}'.format(disk['name']) backing = factory.create('ns0:VirtualDiskFlatVer2BackingInfo') backing.diskMode = 'persistent' backing.fileName = '[{0}] {1}'.format(datastore.name, disk['backingdevice']) backing.thinProvisioned = True device = factory.create('ns0:VirtualDisk') device.controllerKey = key device.key = -200 - unit device.unitNumber = unit device.deviceInfo = device_info device.backing = backing disk_spec = factory.create('ns0:VirtualDeviceConfigSpec') disk_spec.operation = 'add' disk_spec.fileOperation = None disk_spec.device = device return disk_spec @staticmethod def _create_file_info(factory, datastore): """ Creates a file info object """ file_info = factory.create('ns0:VirtualMachineFileInfo') file_info.vmPathName = '[{0}]'.format(datastore) return file_info @staticmethod def _create_nic(factory, device_type, device_label, device_summary, network, unit): """ Creates a NIC spec """ device_info = factory.create('ns0:Description') device_info.label = device_label device_info.summary = device_summary backing = factory.create('ns0:VirtualEthernetCardNetworkBackingInfo') backing.deviceName = network device = factory.create('ns0:{0}'.format(device_type)) device.addressType = 'Generated' device.wakeOnLanEnabled = True device.controllerKey = 100 # PCI Controller device.key = -300 - unit device.unitNumber = unit device.backing = backing device.deviceInfo = device_info nic_spec = factory.create('ns0:VirtualDeviceConfigSpec') nic_spec.operation = 'add' nic_spec.fileOperation = None nic_spec.device = device return nic_spec def _create_disk_controller(self, factory, key): """ Create a disk controller """ device_info = self._client.factory.create('ns0:Description') device_info.label = 'SCSI controller 0' device_info.summary = 'LSI Logic SAS' controller = factory.create('ns0:VirtualLsiLogicSASController') controller.busNumber = 0 controller.key = key controller.sharedBus = 'noSharing' controller.deviceInfo = device_info controller_spec = factory.create('ns0:VirtualDeviceConfigSpec') controller_spec.operation = 'add' controller_spec.fileOperation = None controller_spec.device = controller return controller_spec @staticmethod def _create_option_value(factory, key, value): """ Create option values """ option = factory.create('ns0:OptionValue') option.key = key option.value = value return option @authenticated() def copy_file(self, source, destination, wait=True): """ Copies a file on the datastore """ task = self._client.service.CopyDatastoreFile_Task( _this=self._serviceContent.fileManager, sourceName=source, destinationName=destination) if wait: self.wait_for_task(task) return task @authenticated() def create_vm_from_template(self, name, source_vm, disks, ip, mountpoint, wait=True): """ Create a vm based on an existing vtemplate on specified tgt hypervisor Raises RuntimeError if datastore is not available at (ip, mountpoint) """ esxhost = self._validate_host(None) host_data = self._get_host_data(esxhost) datastore = self.get_datastore(ip, mountpoint) # Build basic config information config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.name = name config.numCPUs = source_vm.config.hardware.numCPU config.memoryMB = source_vm.config.hardware.memoryMB config.guestId = source_vm.config.guestId config.deviceChange = [] config.extraConfig = [] config.files = Sdk._create_file_info(self._client.factory, datastore.name) disk_controller_key = -101 config.deviceChange.append( self._create_disk_controller(self._client.factory, disk_controller_key)) # Add disk devices for disk in disks: config.deviceChange.append( Sdk._create_disk(self._client.factory, disk_controller_key, disk, disks.index(disk), datastore)) # Add network nw_type = type( self._client.factory.create( 'ns0:VirtualEthernetCardNetworkBackingInfo')) for device in source_vm.config.hardware.device: if hasattr(device, 'backing') and type(device.backing) == nw_type: config.deviceChange.append( Sdk._create_nic(self._client.factory, device.__class__.__name__, device.deviceInfo.label, device.deviceInfo.summary, device.backing.deviceName, device.unitNumber)) # Copy additional properties extraconfigstoskip = ['nvram'] for item in source_vm.config.extraConfig: if item.key not in extraconfigstoskip: config.extraConfig.append( Sdk._create_option_value(self._client.factory, item.key, item.value)) task = self._client.service.CreateVM_Task( host_data['folder'], config=config, pool=host_data['resourcePool'], host=host_data['host']) if wait: self.wait_for_task(task) return task @authenticated() def clone_vm(self, vmid, name, disks, wait=True): """ Clone a existing VM configuration @param vmid: unique id of the vm @param name: name of the clone vm @param disks: list of disks to use in vm configuration @param wait: wait for task to complete or not (True/False) """ esxhost = self._validate_host(None) host_data = self._get_host_data(esxhost) source_vm_object = self.exists(key=vmid) if not source_vm_object: raise Exception('VM with key reference {0} not found'.format(vmid)) source_vm = self._get_object(source_vm_object) datastore = self._get_object(source_vm.datastore[0][0]) # Build basic config information config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.name = name config.numCPUs = source_vm.config.hardware.numCPU config.memoryMB = source_vm.config.hardware.memoryMB config.guestId = source_vm.config.guestId config.deviceChange = [] config.extraConfig = [] config.files = Sdk._create_file_info(self._client.factory, datastore.name) disk_controller_key = -101 config.deviceChange.append( self._create_disk_controller(self._client.factory, disk_controller_key)) # Add disk devices for disk in disks: config.deviceChange.append( Sdk._create_disk(self._client.factory, disk_controller_key, disk, disks.index(disk), datastore)) self.copy_file( '[{0}] {1}.vmdk'.format( datastore.name, disk['name'].split('_')[-1].replace('-clone', '')), '[{0}] {1}'.format(datastore.name, disk['backingdevice'])) # Add network nw_type = type( self._client.factory.create( 'ns0:VirtualEthernetCardNetworkBackingInfo')) for device in source_vm.config.hardware.device: if hasattr(device, 'backing') and type(device.backing) == nw_type: config.deviceChange.append( Sdk._create_nic(self._client.factory, device.__class__.__name__, device.deviceInfo.label, device.deviceInfo.summary, device.backing.deviceName, device.unitNumber)) # Copy additional properties extraconfigstoskip = ['nvram'] for item in source_vm.config.extraConfig: if item.key not in extraconfigstoskip: config.extraConfig.append( Sdk._create_option_value(self._client.factory, item.key, item.value)) task = self._client.service.CreateVM_Task( host_data['folder'], config=config, pool=host_data['resourcePool'], host=host_data['host']) if wait: self.wait_for_task(task) return task @authenticated() def get_datastore(self, ip, mountpoint, host=None): """ @param ip : hypervisor ip to query for datastore presence @param mountpoint: nfs mountpoint on hypervisor @rtype: sdk datastore object @return: object when found else None """ datastore = None if host is None: host = self._esxHost esxhost = self._validate_host(host) host_system = self._get_object(esxhost, properties=['datastore']) for store in host_system.datastore[0]: store = self._get_object(store) if not store.summary.accessible: logger.warning( 'Datastore {0} is not accessible, skipping'.format( store.name)) if hasattr(store.info, 'nas'): if store.info.nas.remoteHost == ip and store.info.nas.remotePath == mountpoint: datastore = store return datastore @authenticated() def is_datastore_available(self, ip, mountpoint): """ @param ip : hypervisor ip to query for datastore presence @param mountpoint: nfs mountpoint on hypervisor @rtype: boolean @return: True | False """ if self.get_datastore(ip, mountpoint): return True else: return False def make_agnostic_config(self, vm_object, host=None): regex = '\[([^\]]+)\]\s(.+)' match = re.search(regex, vm_object.config.files.vmPathName) if host is None: host = self._esxHost esxhost = self._validate_host(host) config = { 'name': vm_object.config.name, 'id': vm_object.obj_identifier.value, 'backing': { 'filename': match.group(2), 'datastore': match.group(1) }, 'disks': [], 'datastores': {} } for device in vm_object.config.hardware.device: if device.__class__.__name__ == 'VirtualDisk': if device.backing is not None and device.backing.fileName is not None: backingfile = device.backing.fileName match = re.search(regex, backingfile) if match: filename = match.group(2) backingfile = filename.replace('.vmdk', '-flat.vmdk') backingfile = '/{0}'.format(backingfile.strip('/')) config['disks'].append({ 'filename': filename, 'backingfilename': backingfile, 'datastore': match.group(1), 'name': device.deviceInfo.label, 'order': device.unitNumber }) host_system = self._get_object(esxhost, properties=['datastore']) for store in host_system.datastore[0]: store = self._get_object(store) if hasattr(store.info, 'nas'): config['datastores'][store.info.name] = '{}:{}'.format( store.info.nas.remoteHost, store.info.nas.remotePath) return config @authenticated() def delete_vm(self, vmid, storagedriver_mountpoint, storagedriver_storage_ip, devicename, wait=False): """ Delete a given vm """ machine = None task = None if vmid: try: machine = Sdk._build_property('VirtualMachine', vmid) except Exception as ex: logger.error( 'SDK domain retrieve failed by vmid: {}'.format(ex)) elif storagedriver_mountpoint and storagedriver_storage_ip and devicename: try: machine_info = self.get_nfs_datastore_object( storagedriver_storage_ip, storagedriver_mountpoint, devicename)[0] machine = Sdk._build_property( 'VirtualMachine', machine_info.obj_identifier.value) except Exception as ex: logger.error( 'SDK domain retrieve failed by nfs datastore info: {}'. format(ex)) if machine: task = self._client.service.Destroy_Task(machine) if wait: self.wait_for_task(task) if storagedriver_mountpoint and devicename: vmx_path = os.path.join(storagedriver_mountpoint, devicename) if os.path.exists(vmx_path): dir_name = os.path.dirname(vmx_path) logger.debug('Removing leftover files in {0}'.format(dir_name)) try: shutil.rmtree(dir_name) logger.debug('Removed dir tree {}'.format(dir_name)) except Exception as exception: logger.error( 'Failed to remove dir tree {0}. Reason: {1}'.format( dir_name, str(exception))) return task @authenticated() def get_power_state(self, vmid): """ Get the power state of a given vm """ return self._get_object(Sdk._build_property('VirtualMachine', vmid), properties=['runtime.powerState' ]).runtime.powerState @authenticated() def mount_nfs_datastore(self, name, remote_host, remote_path): """ Mounts a given NFS export as a datastore """ esxhost = self._validate_host(None) host = self._get_object(esxhost, properties=[ 'datastore', 'name', 'configManager', 'configManager.datastoreSystem' ]) for store in host.datastore[0]: store = self._get_object(store) if hasattr(store.info, 'nas'): if store.info.name == name: if store.info.nas.remoteHost == remote_host and store.info.nas.remotePath == remote_path: # We'll remove this store, as it's identical to the once we'll add, # forcing a refresh self._client.service.RemoveDatastore( host.configManager.datastoreSystem, store.obj_identifier) break else: raise RuntimeError( 'A datastore {0} already exists, pointing to {1}:{2}' .format(name, store.info.nas.remoteHost, store.info.nas.remotePath)) spec = self._client.factory.create('ns0:HostNasVolumeSpec') spec.accessMode = 'readWrite' spec.localPath = name spec.remoteHost = remote_host spec.remotePath = remote_path spec.type = 'nfs' return self._client.service.CreateNasDatastore( host.configManager.datastoreSystem, spec) @authenticated() def wait_for_task(self, task): """ Wait for a task to be completed """ state = self.get_task_info(task).info.state while state in ['running', 'queued']: sleep(1) state = self.get_task_info(task).info.state @authenticated() def get_nfs_datastore_object(self, ip, mountpoint, filename, host=None): """ ip : "10.130.12.200", string mountpoint: "/srv/volumefs", string filename: "cfovs001/vhd0(-flat).vmdk" identify nfs datastore on this esx host based on ip and mount check if filename is present on datastore if file is .vmdk return VirtualDisk object for corresponding virtual disk if file is .vmx return VirtualMachineConfigInfo for corresponding vm @rtype: tuple @return: A tuple. First item: vm config, second item: Device if a vmdk was given """ filename = filename.replace( '-flat.vmdk', '.vmdk') # Support both -flat.vmdk and .vmdk if not filename.endswith('.vmdk') and not filename.endswith('.vmx'): raise ValueError('Unexpected filetype') if host is None: host = self._esxHost esxhost = self._validate_host(host) datastore = self.get_datastore(ip, mountpoint, host=esxhost) if not datastore: raise RuntimeError('Could not find datastore') vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm' }, properties=['name', 'config'], as_list=True) if not vms: raise RuntimeError('No vMachines found') for vm in vms: mapping = self._get_vm_datastore_mapping(vm) if datastore.name in mapping: if filename in mapping[datastore.name]: return vm, mapping[datastore.name][filename] raise RuntimeError( 'Could not locate given file on the given datastore') def file_exists(self, ip, mountpoint, filename): try: self.get_nfs_datastore_object(ip, mountpoint, filename) return True except Exception, ex: logger.debug('File does not exist: {0}'.format(ex)) return False
from odoo.tools import float_round, DEFAULT_SERVER_DATE_FORMAT from odoo.tools.float_utils import float_compare, float_repr from odoo.tools.translate import _ from odoo.exceptions import UserError from base64 import b64decode import os _logger = logging.getLogger(__name__) try: from suds.client import Client from suds.wsse import Security from .wsse.suds import WssePlugin from suds.transport.https import HttpTransport from suds.cache import ObjectCache cache_path = "/tmp/{0}-suds".format(os.getuid()) cache = ObjectCache(cache_path) except Exception as e: _logger.warning("No Load suds or wsse: %s" % str(e)) URLS = { 'integ': 'https://webpay3gint.transbank.cl/WSWebpayTransaction/cxf/WSWebpayService?wsdl', 'test': 'https://webpay3gint.transbank.cl/WSWebpayTransaction/cxf/WSWebpayService?wsdl', 'prod': 'https://webpay3g.transbank.cl/WSWebpayTransaction/cxf/WSWebpayService?wsdl', } class PaymentAcquirerWebpay(models.Model): _inherit = 'payment.acquirer'
class Sdk(object): """ This class contains all SDK related methods """ def __init__(self, host, login, passwd): """ Initializes the SDK """ self._host = host self._username = login self._password = passwd self._sessionID = None self._check_session = True self._cache = ObjectCache() self._cache.setduration(weeks=1) self._client = Client('https://%s/sdk/vimService?wsdl' % host, cache=self._cache, cachingpolicy=1) self._client.set_options(location='https://%s/sdk' % host, plugins=[ValueExtender()]) service_reference = self._build_property('ServiceInstance') self._serviceContent = self._client.service.RetrieveServiceContent( service_reference) # In case of an ESXi host, this would be 'HostAgent' self._is_vcenter = self._serviceContent.about.apiType == 'VirtualCenter' if not self._is_vcenter: # pylint: disable=line-too-long self._login() self._esxHost = self._get_object( self._serviceContent.rootFolder, prop_type='HostSystem', traversal={ 'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': { 'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'ComputeResourceTravelSpec', # noqa 'type': 'ComputeResource', 'path': 'host' } } } }, properties=['name']).obj_identifier # pylint: enable=line-too-long else: self._esxHost = None @authenticated(force=True) def _get_vcenter_hosts(self): """ reload vCenter info (host name and summary) """ if not self._is_vcenter: raise RuntimeError('Must be connected to a vCenter Server API.') datacenter_info = self._get_object( self._serviceContent.rootFolder, prop_type='HostSystem', traversal={ 'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': { 'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': { 'name': 'ComputeResourceTravelSpec', # noqa 'type': 'ComputeResource', 'path': 'host' } } } }, properties=[ 'name', 'summary.runtime', 'config.virtualNicManagerInfo.netConfig' ]) return datacenter_info def get_host_status_by_ip(self, host_ip): """ Return host status by ip, from vcenter info Must be connected to a vcenter server api """ host = self._get_host_info_by_ip(host_ip) return host.summary.runtime.powerState def get_host_status_by_pk(self, pk): """ Return host status by pk, from vcenter info Must be connected to a vcenter server api """ host = self._get_host_info_by_pk(pk) return host.summary.runtime.powerState def get_host_primary_key(self, host_ip): """ Return host primary key, based on current ip Must be connected to a vcenter server api """ host = self._get_host_info_by_ip(host_ip) return host.obj_identifier.value def _get_host_info_by_ip(self, host_ip): """ Return HostSystem object by ip, from vcenter info Must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() for host in datacenter_info: for nic in host.config.virtualNicManagerInfo.netConfig.VirtualNicManagerNetConfig: if nic.nicType == 'management': for vnic in nic.candidateVnic: if vnic.spec.ip.ipAddress == host_ip: return host raise RuntimeError( 'Host with ip {0} not found in datacenter info'.format(host_ip)) def _get_host_info_by_pk(self, pk): """ Return HostSystem object by pk, from vcenter info Must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() for host in datacenter_info: if host.obj_identifier.value == pk: return host def get_hosts(self): """ Gets a neutral list of all hosts available """ host_data = self._get_vcenter_hosts() host_data = [] if host_data is None else host_data hosts = {} for host in host_data: ips = [] for nic in host.config.virtualNicManagerInfo.netConfig.VirtualNicManagerNetConfig: if nic.nicType == 'management': for vnic in nic.candidateVnic: ips.append(vnic.spec.ip.ipAddress) hosts[host.obj_identifier.value] = {'name': host.name, 'ips': ips} return hosts def test_connection(self): """ Tests the connection """ self._login() return True def list_hosts_in_datacenter(self): """ return a list of registered host names in vCenter must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() return [host.name for host in datacenter_info] def validate_result(self, result, message=None): """ Validates a given result. Returning True if the task succeeded, raising an error if not """ if hasattr(result, '_type') and result._type == 'Task': return self.validate_result(self.get_task_info(result), message) elif hasattr(result, 'info'): if result.info.state == 'success': return True elif result.info.state == 'error': error = result.info.error.localizedMessage raise Exception(('%s: %s' % (message, error)) if message else error) raise Exception(('%s: %s' % (message, 'Unexpected result') ) if message else 'Unexpected result') @authenticated() def get_task_info(self, task): """ Loads the task details """ return self._get_object(task) @authenticated() def get_vm_ip_information(self): """ Get the IP information for all vms on a given esxi host """ esxhost = self._validate_host(None) configuration = [] for vm in self._get_object( esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm' }, properties=['name', 'guest.net', 'config.files']): vmi = { 'id': str(vm.obj_identifier.value), 'vmxpath': str(vm.config.files.vmPathName), 'name': str(vm.name), 'net': [] } if vm.guest.net: for net in vm.guest.net[0]: vmi['net'].append({ 'mac': str(net.macAddress), 'ipaddresses': [str(i.ipAddress) for i in net.ipConfig.ipAddress] }) configuration.append(vmi) return configuration @authenticated() def exists(self, name=None, key=None): """ Checks whether a vm with a given name or key exists on a given esxi host """ esxhost = self._validate_host(None) if name is not None or key is not None: try: if name is not None: vms = [ vm for vm in self._get_object( esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm' }, properties=['name']) if vm.name == name ] if len(vms) == 0: return None else: return vms[0].obj_identifier if key is not None: return self._get_object(self._build_property( 'VirtualMachine', key), properties=['name']).obj_identifier except: return None else: raise Exception('A name or key should be passed.') @authenticated() def get_vm(self, key): """ Retreives a vm object, based on its key """ vmid = self.exists(key=key) if vmid is None: raise RuntimeError( 'Virtual Machine with key {} could not be found.'.format(key)) vm = self._get_object(vmid) return vm @authenticated() def get_vms(self, ip, mountpoint): """ Get all vMachines using a given nfs share """ esxhost = self._validate_host(None) datastore = self.get_datastore(ip, mountpoint) filtered_vms = [] vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm' }, properties=['name', 'config']) for vm in vms: mapping = self._get_vm_datastore_mapping(vm) if datastore.name in mapping: filtered_vms.append(vm) return filtered_vms @authenticated() def set_disk_mode(self, vmid, disks, mode, wait=True): """ Sets the disk mode for a set of disks """ config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.deviceChange = [] disk_type = type(self._client.factory.create('ns0:VirtualDisk')) vmid = self.exists(key=vmid) vm = self._get_object(vmid) for device in vm.config.hardware.devices: if type(device) == disk_type and hasattr(device, 'backing') \ and device.backing.fileName in disks: backing = self._client.factory.create( 'ns0:VirtualDiskFlatVer2BackingInfo') backing.diskMode = mode device = self._client.factory.create('ns0:VirtualDisk') device.backing = backing diskSpec = self._client.factory.create( 'ns0:VirtualDeviceConfigSpec') diskSpec.operation = 'edit' diskSpec.fileOperation = None diskSpec.device = device config.deviceChange.append(diskSpec) task = self._client.service.ReconfigVM_Task(vm.obj_identifier, config) if wait: self.wait_for_task(task) return task def _create_disk(self, factory, key, disk, unit, datastore): """ Creates a disk spec for a given backing device Example for parameter disk: {'name': diskname, 'backingdevice': 'disk-flat.vmdk'} """ deviceInfo = factory.create('ns0:Description') deviceInfo.label = disk['name'] deviceInfo.summary = 'Disk %s' % disk['name'] backing = factory.create('ns0:VirtualDiskFlatVer2BackingInfo') backing.diskMode = 'persistent' backing.fileName = '[%s] %s' % (datastore.name, disk['backingdevice']) backing.thinProvisioned = True device = factory.create('ns0:VirtualDisk') device.controllerKey = key device.key = -200 - unit device.unitNumber = unit device.deviceInfo = deviceInfo device.backing = backing diskSpec = factory.create('ns0:VirtualDeviceConfigSpec') diskSpec.operation = 'add' diskSpec.fileOperation = None diskSpec.device = device return diskSpec def _create_file_info(self, factory, datastore): """ Creates a file info object """ fileInfo = factory.create('ns0:VirtualMachineFileInfo') fileInfo.vmPathName = '[%s]' % datastore return fileInfo def _create_nic(self, factory, device_type, device_label, device_summary, network, unit): """ Creates a NIC spec """ deviceInfo = factory.create('ns0:Description') deviceInfo.label = device_label deviceInfo.summary = device_summary backing = factory.create('ns0:VirtualEthernetCardNetworkBackingInfo') backing.deviceName = network device = factory.create('ns0:%s' % device_type) device.addressType = 'Generated' device.wakeOnLanEnabled = True device.controllerKey = 100 # PCI Controller device.key = -300 - unit device.unitNumber = unit device.backing = backing device.deviceInfo = deviceInfo nicSpec = factory.create('ns0:VirtualDeviceConfigSpec') nicSpec.operation = 'add' nicSpec.fileOperation = None nicSpec.device = device return nicSpec def _create_disk_controller(self, factory, key): """ Create a disk controller """ deviceInfo = self._client.factory.create('ns0:Description') deviceInfo.label = 'SCSI controller 0' deviceInfo.summary = 'LSI Logic SAS' controller = factory.create('ns0:VirtualLsiLogicSASController') controller.busNumber = 0 controller.key = key controller.sharedBus = 'noSharing' controller.deviceInfo = deviceInfo controllerSpec = factory.create('ns0:VirtualDeviceConfigSpec') controllerSpec.operation = 'add' controllerSpec.fileOperation = None controllerSpec.device = controller return controllerSpec def _create_option_value(self, factory, key, value): """ Create option values """ option = factory.create('ns0:OptionValue') option.key = key option.value = value return option @authenticated() def copy_file(self, source, destination, wait=True): """ Copies a file on the datastore """ task = self._client.service.CopyDatastoreFile_Task( _this=self._serviceContent.fileManager, sourceName=source, destinationName=destination) if wait: self.wait_for_task(task) return task @authenticated() def create_vm_from_template(self, name, source_vm, disks, ip, mountpoint, wait=True): """ Create a vm based on an existing vtemplate on specified tgt hypervisor Raises RuntimeError if datastore is not available at (ip, mountpoint) """ esxhost = self._validate_host(None) host_data = self._get_host_data(esxhost) datastore = self.get_datastore(ip, mountpoint) # Build basic config information config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.name = name config.numCPUs = source_vm.config.hardware.numCPU config.memoryMB = source_vm.config.hardware.memoryMB config.guestId = source_vm.config.guestId config.deviceChange = [] config.extraConfig = [] config.files = self._create_file_info(self._client.factory, datastore.name) disk_controller_key = -101 config.deviceChange.append( self._create_disk_controller(self._client.factory, disk_controller_key)) # Add disk devices for disk in disks: config.deviceChange.append( self._create_disk(self._client.factory, disk_controller_key, disk, disks.index(disk), datastore)) # Add network nw_type = type( self._client.factory.create( 'ns0:VirtualEthernetCardNetworkBackingInfo')) for device in source_vm.config.hardware.device: if hasattr(device, 'backing') and type(device.backing) == nw_type: config.deviceChange.append( self._create_nic(self._client.factory, device.__class__.__name__, device.deviceInfo.label, device.deviceInfo.summary, device.backing.deviceName, device.unitNumber)) # Copy additional properties extraconfigstoskip = ['nvram'] for item in source_vm.config.extraConfig: if not item.key in extraconfigstoskip: config.extraConfig.append( self._create_option_value(self._client.factory, item.key, item.value)) task = self._client.service.CreateVM_Task( host_data['folder'], config=config, pool=host_data['resourcePool'], host=host_data['host']) if wait: self.wait_for_task(task) return task @authenticated() def clone_vm(self, vmid, name, disks, wait=True): """ Clone a existing VM configuration @param vmid: unique id of the vm @param name: name of the clone vm @param disks: list of disks to use in vm configuration @param kvmport: kvm port for the clone vm @param esxhost: esx host identifier on which to clone the vm @param wait: wait for task to complete or not (True/False) """ esxhost = self._validate_host(None) host_data = self._get_host_data(esxhost) source_vm_object = self.exists(key=vmid) if not source_vm_object: raise Exception('VM with key reference %s not found' % vmid) source_vm = self._get_object(source_vm_object) datastore = self._get_object(source_vm.datastore[0][0]) # Build basic config information config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.name = name config.numCPUs = source_vm.config.hardware.numCPU config.memoryMB = source_vm.config.hardware.memoryMB config.guestId = source_vm.config.guestId config.deviceChange = [] config.extraConfig = [] config.files = self._create_file_info(self._client.factory, datastore.name) disk_controller_key = -101 config.deviceChange.append( self._create_disk_controller(self._client.factory, disk_controller_key)) # Add disk devices for disk in disks: config.deviceChange.append( self._create_disk(self._client.factory, disk_controller_key, disk, disks.index(disk), datastore)) self.copy_file( '[{0}] {1}'.format( datastore.name, '%s.vmdk' % disk['name'].split('_')[-1].replace('-clone', '')), '[{0}] {1}'.format(datastore.name, disk['backingdevice'])) # Add network nw_type = type( self._client.factory.create( 'ns0:VirtualEthernetCardNetworkBackingInfo')) for device in source_vm.config.hardware.device: if hasattr(device, 'backing') and type(device.backing) == nw_type: config.deviceChange.append( self._create_nic(self._client.factory, device.__class__.__name__, device.deviceInfo.label, device.deviceInfo.summary, device.backing.deviceName, device.unitNumber)) # Copy additional properties extraconfigstoskip = ['nvram'] for item in source_vm.config.extraConfig: if not item.key in extraconfigstoskip: config.extraConfig.append( self._create_option_value(self._client.factory, item.key, item.value)) task = self._client.service.CreateVM_Task( host_data['folder'], config=config, pool=host_data['resourcePool'], host=host_data['host']) if wait: self.wait_for_task(task) return task @authenticated() def get_vm(self, key): vmid = self.exists(key=key) if vmid is None: raise RuntimeError( 'Virtual Machine with key {} could not be found.'.format(key)) vm = self._get_object(vmid) return vm @authenticated() def get_datastore(self, ip, mountpoint): """ @param ip : hypervisor ip to query for datastore presence @param mountpoint: nfs mountpoint on hypervisor @rtype: sdk datastore object @return: object when found else None """ datastore = None esxhost = self._validate_host(None) host_system = self._get_object(esxhost, properties=['datastore']) for store in host_system.datastore[0]: store = self._get_object(store) if not store.summary.accessible: raise RuntimeError( 'Datastore {0} is not accessible at mountpoint {1}'.format( store.name, mountpoint)) if hasattr(store.info, 'nas'): if store.info.nas.remoteHost == ip and store.info.nas.remotePath == mountpoint: datastore = store return datastore @authenticated() def is_datastore_available(self, ip, mountpoint): """ @param ip : hypervisor ip to query for datastore presence @param mountpoint: nfs mountpoint on hypervisor @rtype: boolean @return: True | False """ if self.get_datastore(ip, mountpoint): return True else: return False def make_agnostic_config(self, vm_object): regex = '\[([^\]]+)\]\s(.+)' match = re.search(regex, vm_object.config.files.vmPathName) esxhost = self._validate_host(None) config = { 'name': vm_object.config.name, 'id': vm_object.obj_identifier.value, 'backing': { 'filename': match.group(2), 'datastore': match.group(1) }, 'disks': [], 'datastores': {} } for device in vm_object.config.hardware.device: if device.__class__.__name__ == 'VirtualDisk': if device.backing is not None and \ device.backing.fileName is not None: backingfile = device.backing.fileName match = re.search(regex, backingfile) if match: filename = match.group(2) backingfile = filename.replace('.vmdk', '-flat.vmdk') config['disks'].append({ 'filename': filename, 'backingfilename': backingfile, 'datastore': match.group(1), 'name': device.deviceInfo.label, 'order': device.unitNumber }) host_system = self._get_object(esxhost, properties=['datastore']) for store in host_system.datastore[0]: store = self._get_object(store) if hasattr(store.info, 'nas'): config['datastores'][store.info.name] = '{}:{}'.format( store.info.nas.remoteHost, store.info.nas.remotePath) return config @authenticated() def delete_vm(self, vmid, storagedriver_mountpoint, storagedriver_storage_ip, devicename, wait=False): """ Delete a given vm """ machine = None if vmid: try: machine = self._build_property('VirtualMachine', vmid) except Exception as ex: logger.error( 'SDK domain retrieve failed by vmid: {}'.format(ex)) elif storagedriver_mountpoint and storagedriver_storage_ip and devicename: try: machine_info = self.get_nfs_datastore_object( storagedriver_storage_ip, storagedriver_mountpoint, devicename)[0] machine = self._build_property( 'VirtualMachine', machine_info.obj_identifier.value) except Exception as ex: logger.error( 'SDK domain retrieve failed by nfs datastore info: {}'. format(ex)) if machine: task = self._client.service.Destroy_Task(machine) if wait: self.wait_for_task(task) if storagedriver_mountpoint and devicename: vmx_path = os.path.join(storagedriver_mountpoint, devicename) if os.path.exists(vmx_path): dir_name = os.path.dirname(vmx_path) logger.debug('Removing leftover files in {0}'.format(dir_name)) try: shutil.rmtree(dir_name) logger.debug('Removed dir tree {}'.format(dir_name)) except Exception as exception: logger.error( 'Failed to remove dir tree {0}. Reason: {1}'.format( dir_name, str(exception))) return task @authenticated() def get_power_state(self, vmid): """ Get the power state of a given vm """ return self._get_object(self._build_property('VirtualMachine', vmid), properties=['runtime.powerState' ]).runtime.powerState @authenticated() def mount_nfs_datastore(self, name, remote_host, remote_path): """ Mounts a given NFS export as a datastore """ esxhost = self._validate_host(None) host = self._get_object(esxhost, properties=[ 'datastore', 'name', 'configManager', 'configManager.datastoreSystem' ]) for store in host.datastore[0]: store = self._get_object(store) if hasattr(store.info, 'nas'): if store.info.name == name: if store.info.nas.remoteHost == remote_host and \ store.info.nas.remotePath == remote_path: # We'll remove this store, as it's identical to the once we'll add, # forcing a refresh self._client.service.RemoveDatastore( host.configManager.datastoreSystem, store.obj_identifier) break else: raise RuntimeError( 'A datastore {0} already exists, pointing to {1}:{2}' .format(name, store.info.nas.remoteHost, store.info.nas.remotePath)) spec = self._client.factory.create('ns0:HostNasVolumeSpec') spec.accessMode = 'readWrite' spec.localPath = name spec.remoteHost = remote_host spec.remotePath = remote_path spec.type = 'nfs' return self._client.service.CreateNasDatastore( host.configManager.datastoreSystem, spec) @authenticated() def wait_for_task(self, task): """ Wait for a task to be completed """ state = self.get_task_info(task).info.state while state in ['running', 'queued']: sleep(1) state = self.get_task_info(task).info.state @authenticated() def get_nfs_datastore_object(self, ip, mountpoint, filename): """ ip : "10.130.12.200", string mountpoint: "/srv/volumefs", string filename: "cfovs001/vhd0(-flat).vmdk" identify nfs datastore on this esx host based on ip and mount check if filename is present on datastore if file is .vmdk return VirtualDisk object for corresponding virtual disk if file is .vmx return VirtualMachineConfigInfo for corresponding vm @rtype: tuple @return: A tuple. First item: vm config, second item: Device if a vmdk was given """ filename = filename.replace( '-flat.vmdk', '.vmdk') # Support both -flat.vmdk and .vmdk if not filename.endswith('.vmdk') and not filename.endswith('.vmx'): raise ValueError('Unexpected filetype') esxhost = self._validate_host(None) datastore = self.get_datastore(ip, mountpoint) if not datastore: raise RuntimeError('Could not find datastore') vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm' }, properties=['name', 'config']) if not vms: raise RuntimeError('No vMachines found') for vm in vms: mapping = self._get_vm_datastore_mapping(vm) if datastore.name in mapping: if filename in mapping[datastore.name]: return vm, mapping[datastore.name][filename] raise RuntimeError( 'Could not locate given file on the given datastore') def _get_vm_datastore_mapping(self, vm): """ Creates a datastore mapping for a vm's devices Structure {<datastore name>: {<backing filename>: <device>, <backing filename>: <device>}, <datastore name>: {<backing filename>: <device>}} Example {'datastore A': {'/machine1/machine1.vmx': <device>, '/machine1/disk1.vmdk': <device>}, 'datastore B': {'/machine1/disk2.vmdk': <device>}} """ def extract_names(backingfile, given_mapping, metadata=None): match = re.search('\[([^\]]+)\]\s(.+)', backingfile) if match: datastore_name = match.group(1) filename = match.group(2) if datastore_name not in mapping: given_mapping[datastore_name] = {} given_mapping[datastore_name][filename] = metadata return given_mapping virtual_disk_type = self._client.factory.create('ns0:VirtualDisk') flat_type = self._client.factory.create( 'ns0:VirtualDiskFlatVer2BackingInfo') mapping = {} for device in vm.config.hardware.device: if isinstance(device, type(virtual_disk_type)): if device.backing is not None and isinstance( device.backing, type(flat_type)): mapping = extract_names(device.backing.fileName, mapping, device) mapping = extract_names(vm.config.files.vmPathName, mapping) return mapping def _get_host_data(self, esxhost): """ Get host data for a given esxhost """ hostobject = self._get_object( esxhost, properties=['parent', 'datastore', 'network']) datastore = self._get_object(hostobject.datastore[0][0], properties=['info']).info computeresource = self._get_object( hostobject.parent, properties=['resourcePool', 'parent']) datacenter = self._get_object(computeresource.parent, properties=['parent']).parent vm_folder = self._get_object(datacenter, properties=['vmFolder']).vmFolder return { 'host': esxhost, 'computeResource': computeresource, 'resourcePool': computeresource.resourcePool, 'datacenter': datacenter, 'folder': vm_folder, 'datastore': datastore, 'network': hostobject.network[0] } def _get_host_iqn_mapping(self, esxhost, rescan=False): """ Get the IQN mapping for a given esx host, optionally rescanning the host """ # pylint: disable=line-too-long regex = re.compile( '^key-vim.host.PlugStoreTopology.Path-iqn.+?,(?P<iqn>iqn.*?),t,1-(?P<eui>eui.+)$' ) # noqa # pylint: enable=line-too-long hostobject = self._get_object( esxhost, properties=['configManager.storageSystem']) stg_ssystem = self._get_object( hostobject.configManager.storageSystem, properties=[ 'storageDeviceInfo', 'storageDeviceInfo.plugStoreTopology.device' ]) if rescan: # Force a rescan of the vmfs self._client.service.RescanVmfs(stg_ssystem.obj_identifier) stg_ssystem = self._get_object( hostobject.configManager.storageSystem, properties=[ 'storageDeviceInfo', 'storageDeviceInfo.plugStoreTopology.device' ]) device_info_mapping = {} for disk in stg_ssystem.storageDeviceInfo.scsiLun: device_info_mapping[disk.key] = disk.uuid iqn_mapping = {} for device in stg_ssystem.storageDeviceInfo.plugStoreTopology\ .device.HostPlugStoreTopologyDevice: for path in device.path: match = regex.search(path) if match: groups = match.groupdict() iqn_mapping[groups['iqn']] = { 'eui': groups['eui'], 'lun': device.lun, 'uuid': device_info_mapping[device.lun] } return iqn_mapping def _get_object(self, key_object, prop_type=None, traversal=None, properties=None): """ Gets an object based on a given set of query parameters. Only the requested properties will be loaded. If no properties are specified, all will be loaded """ object_spec = self._client.factory.create('ns0:ObjectSpec') object_spec.obj = key_object property_spec = self._client.factory.create('ns0:PropertySpec') property_spec.type = key_object._type if prop_type is None else prop_type if properties is None: property_spec.all = True else: property_spec.all = False property_spec.pathSet = properties if traversal is not None: select_set_ptr = object_spec while True: select_set_ptr.selectSet = self._client.factory.create( 'ns0:TraversalSpec') select_set_ptr.selectSet.name = traversal['name'] select_set_ptr.selectSet.type = traversal['type'] select_set_ptr.selectSet.path = traversal['path'] if 'traversal' in traversal: traversal = traversal['traversal'] select_set_ptr = select_set_ptr.selectSet else: break property_filter_spec = self._client.factory.create( 'ns0:PropertyFilterSpec') property_filter_spec.objectSet = [object_spec] property_filter_spec.propSet = [property_spec] found_objects = self._client.service.RetrieveProperties( self._serviceContent.propertyCollector, [property_filter_spec]) if len(found_objects) > 0: for item in found_objects: item.obj_identifier = item.obj del item.obj if hasattr(item, 'missingSet'): for missing_item in item.missingSet: if missing_item.fault.fault.__class__.__name__ == 'NotAuthenticated': raise NotAuthenticatedException() for propSet in item.propSet: if '.' in propSet.name: working_item = item path = str(propSet.name).split('.') part_counter = 0 for part in path: part_counter += 1 if part_counter < len(path): if not part in working_item.__dict__: setattr(working_item, part, type(part, (), {})()) working_item = working_item.__dict__[part] else: setattr(working_item, part, propSet.val) else: setattr(item, propSet.name, propSet.val) del item.propSet if len(found_objects) == 1: return found_objects[0] else: return found_objects return None def _build_property(self, property_name, value=None): """ Create a property object with given name and value """ new_property = Property(property_name) new_property._type = property_name if value is not None: new_property.value = value return new_property def _validate_host(self, host): """ Validates wheteher a given host is valid """ if host is None: if self._is_vcenter: raise Exception( 'A HostSystem reference is mandatory for a vCenter Server') else: return self._esxHost else: if hasattr(host, '_type') and host._type == 'HostSystem': return self._get_object(host, properties=['name']).obj_identifier else: return self._get_object(self._build_property( 'HostSystem', host), properties=['name']).obj_identifier def _login(self): """ Executes a logout (to make sure we're logged out), and logs in again """ self._logout() self._sessionID = self._client.service.Login( self._serviceContent.sessionManager, self._username, self._password, None).key def _logout(self): """ Logs out the current session """ try: self._client.service.Logout(self._serviceContent.sessionManager) except: pass
def build_object_cache(self): cache = ObjectCache() cache.setduration(seconds=config.get('soap.client_timeout')) cache.setlocation(config.get('soap.cache_location')) return cache
def activate_cache(self): oc = ObjectCache() oc.setduration(days=365)
def clear_suds_cache(wsdl): for type in ("wsdl", "document"): cacheId = Reader(Options()).mangle(wsdl, type) DocumentCache().purge(cacheId) ObjectCache().purge(cacheId) FileCache().purge(cacheId)
class Sdk(object): """ This class contains all SDK related methods """ def __init__(self, host, login, passwd): """ Initializes the SDK """ self._host = host self._username = login self._password = passwd self._sessionID = None self._check_session = True self._cache = ObjectCache() self._cache.setduration(weeks=1) self._client = Client('https://%s/sdk/vimService?wsdl' % host, cache=self._cache, cachingpolicy=1) self._client.set_options(location='https://%s/sdk' % host, plugins=[ValueExtender()]) service_reference = self._build_property('ServiceInstance') self._serviceContent = self._client.service.RetrieveServiceContent( service_reference) # In case of an ESXi host, this would be 'HostAgent' self._is_vcenter = self._serviceContent.about.apiType == 'VirtualCenter' if not self._is_vcenter: # pylint: disable=line-too-long self._login() self._esxHost = self._get_object( self._serviceContent.rootFolder, prop_type='HostSystem', traversal={'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': {'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'ComputeResourceTravelSpec', # noqa 'type': 'ComputeResource', 'path': 'host'}}}}, properties=['name'] ).obj_identifier # pylint: enable=line-too-long else: self._esxHost = None @authenticated(force=True) def _get_vcenter_hosts(self): """ reload vCenter info (host name and summary) """ if not self._is_vcenter: raise RuntimeError('Must be connected to a vCenter Server API.') datacenter_info = self._get_object( self._serviceContent.rootFolder, prop_type='HostSystem', traversal={'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': {'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'ComputeResourceTravelSpec', # noqa 'type': 'ComputeResource', 'path': 'host'}}}}, properties=['name', 'summary.runtime', 'config.virtualNicManagerInfo.netConfig'] ) return datacenter_info def get_host_status_by_ip(self, host_ip): """ Return host status by ip, from vcenter info Must be connected to a vcenter server api """ host = self._get_host_info_by_ip(host_ip) return host.summary.runtime.powerState def get_host_status_by_pk(self, pk): """ Return host status by pk, from vcenter info Must be connected to a vcenter server api """ host = self._get_host_info_by_pk(pk) return host.summary.runtime.powerState def get_host_primary_key(self, host_ip): """ Return host primary key, based on current ip Must be connected to a vcenter server api """ host = self._get_host_info_by_ip(host_ip) return host.obj_identifier.value def _get_host_info_by_ip(self, host_ip): """ Return HostSystem object by ip, from vcenter info Must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() for host in datacenter_info: for nic in host.config.virtualNicManagerInfo.netConfig.VirtualNicManagerNetConfig: if nic.nicType == 'management': for vnic in nic.candidateVnic: if vnic.spec.ip.ipAddress == host_ip: return host raise RuntimeError('Host with ip {0} not found in datacenter info'.format(host_ip)) def _get_host_info_by_pk(self, pk): """ Return HostSystem object by pk, from vcenter info Must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() for host in datacenter_info: if host.obj_identifier.value == pk: return host def get_hosts(self): """ Gets a neutral list of all hosts available """ host_data = self._get_vcenter_hosts() host_data = [] if host_data is None else host_data hosts = {} for host in host_data: ips = [] for nic in host.config.virtualNicManagerInfo.netConfig.VirtualNicManagerNetConfig: if nic.nicType == 'management': for vnic in nic.candidateVnic: ips.append(vnic.spec.ip.ipAddress) hosts[host.obj_identifier.value] = {'name': host.name, 'ips': ips} return hosts def test_connection(self): """ Tests the connection """ self._login() return True def list_hosts_in_datacenter(self): """ return a list of registered host names in vCenter must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() return [host.name for host in datacenter_info] def validate_result(self, result, message=None): """ Validates a given result. Returning True if the task succeeded, raising an error if not """ if hasattr(result, '_type') and result._type == 'Task': return self.validate_result(self.get_task_info(result), message) elif hasattr(result, 'info'): if result.info.state == 'success': return True elif result.info.state == 'error': error = result.info.error.localizedMessage raise Exception(('%s: %s' % (message, error)) if message else error) raise Exception(('%s: %s' % (message, 'Unexpected result')) if message else 'Unexpected result') @authenticated() def get_task_info(self, task): """ Loads the task details """ return self._get_object(task) @authenticated() def get_vm_ip_information(self): """ Get the IP information for all vms on a given esxi host """ esxhost = self._validate_host(None) configuration = [] for vm in self._get_object(esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm'}, properties=['name', 'guest.net', 'config.files']): vmi = {'id': str(vm.obj_identifier.value), 'vmxpath': str(vm.config.files.vmPathName), 'name': str(vm.name), 'net': []} if vm.guest.net: for net in vm.guest.net[0]: vmi['net'].append({'mac': str(net.macAddress), 'ipaddresses': [str(i.ipAddress) for i in net.ipConfig.ipAddress]}) configuration.append(vmi) return configuration @authenticated() def exists(self, name=None, key=None): """ Checks whether a vm with a given name or key exists on a given esxi host """ esxhost = self._validate_host(None) if name is not None or key is not None: try: if name is not None: vms = [vm for vm in self._get_object(esxhost, prop_type='VirtualMachine', traversal={'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm'}, properties=['name']) if vm.name == name] if len(vms) == 0: return None else: return vms[0].obj_identifier if key is not None: return self._get_object( self._build_property('VirtualMachine', key), properties=['name']).obj_identifier except: return None else: raise Exception('A name or key should be passed.') @authenticated() def get_vm(self, key): """ Retreives a vm object, based on its key """ vmid = self.exists(key=key) if vmid is None: raise RuntimeError('Virtual Machine with key {} could not be found.'.format(key)) vm = self._get_object(vmid) return vm @authenticated() def get_vms(self, ip, mountpoint): """ Get all vMachines using a given nfs share """ esxhost = self._validate_host(None) datastore = self.get_datastore(ip, mountpoint) filtered_vms = [] vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm'}, properties=['name', 'config']) for vm in vms: mapping = self._get_vm_datastore_mapping(vm) if datastore.name in mapping: filtered_vms.append(vm) return filtered_vms @authenticated() def set_disk_mode(self, vmid, disks, mode, wait=True): """ Sets the disk mode for a set of disks """ config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.deviceChange = [] disk_type = type(self._client.factory.create('ns0:VirtualDisk')) vmid = self.exists(key=vmid) vm = self._get_object(vmid) for device in vm.config.hardware.devices: if type(device) == disk_type and hasattr(device, 'backing') \ and device.backing.fileName in disks: backing = self._client.factory.create( 'ns0:VirtualDiskFlatVer2BackingInfo') backing.diskMode = mode device = self._client.factory.create('ns0:VirtualDisk') device.backing = backing diskSpec = self._client.factory.create( 'ns0:VirtualDeviceConfigSpec') diskSpec.operation = 'edit' diskSpec.fileOperation = None diskSpec.device = device config.deviceChange.append(diskSpec) task = self._client.service.ReconfigVM_Task(vm.obj_identifier, config) if wait: self.wait_for_task(task) return task def _create_disk(self, factory, key, disk, unit, datastore): """ Creates a disk spec for a given backing device Example for parameter disk: {'name': diskname, 'backingdevice': 'disk-flat.vmdk'} """ deviceInfo = factory.create('ns0:Description') deviceInfo.label = disk['name'] deviceInfo.summary = 'Disk %s' % disk['name'] backing = factory.create('ns0:VirtualDiskFlatVer2BackingInfo') backing.diskMode = 'persistent' backing.fileName = '[%s] %s' % (datastore.name, disk['backingdevice']) backing.thinProvisioned = True device = factory.create('ns0:VirtualDisk') device.controllerKey = key device.key = -200 - unit device.unitNumber = unit device.deviceInfo = deviceInfo device.backing = backing diskSpec = factory.create('ns0:VirtualDeviceConfigSpec') diskSpec.operation = 'add' diskSpec.fileOperation = None diskSpec.device = device return diskSpec def _create_file_info(self, factory, datastore): """ Creates a file info object """ fileInfo = factory.create('ns0:VirtualMachineFileInfo') fileInfo.vmPathName = '[%s]' % datastore return fileInfo def _create_nic(self, factory, device_type, device_label, device_summary, network, unit): """ Creates a NIC spec """ deviceInfo = factory.create('ns0:Description') deviceInfo.label = device_label deviceInfo.summary = device_summary backing = factory.create('ns0:VirtualEthernetCardNetworkBackingInfo') backing.deviceName = network device = factory.create('ns0:%s' % device_type) device.addressType = 'Generated' device.wakeOnLanEnabled = True device.controllerKey = 100 # PCI Controller device.key = -300 - unit device.unitNumber = unit device.backing = backing device.deviceInfo = deviceInfo nicSpec = factory.create('ns0:VirtualDeviceConfigSpec') nicSpec.operation = 'add' nicSpec.fileOperation = None nicSpec.device = device return nicSpec def _create_disk_controller(self, factory, key): """ Create a disk controller """ deviceInfo = self._client.factory.create('ns0:Description') deviceInfo.label = 'SCSI controller 0' deviceInfo.summary = 'LSI Logic SAS' controller = factory.create('ns0:VirtualLsiLogicSASController') controller.busNumber = 0 controller.key = key controller.sharedBus = 'noSharing' controller.deviceInfo = deviceInfo controllerSpec = factory.create('ns0:VirtualDeviceConfigSpec') controllerSpec.operation = 'add' controllerSpec.fileOperation = None controllerSpec.device = controller return controllerSpec def _create_option_value(self, factory, key, value): """ Create option values """ option = factory.create('ns0:OptionValue') option.key = key option.value = value return option @authenticated() def copy_file(self, source, destination, wait=True): """ Copies a file on the datastore """ task = self._client.service.CopyDatastoreFile_Task( _this=self._serviceContent.fileManager, sourceName=source, destinationName=destination) if wait: self.wait_for_task(task) return task @authenticated() def create_vm_from_template(self, name, source_vm, disks, ip, mountpoint, wait=True): """ Create a vm based on an existing vtemplate on specified tgt hypervisor Raises RuntimeError if datastore is not available at (ip, mountpoint) """ esxhost = self._validate_host(None) host_data = self._get_host_data(esxhost) datastore = self.get_datastore(ip, mountpoint) # Build basic config information config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.name = name config.numCPUs = source_vm.config.hardware.numCPU config.memoryMB = source_vm.config.hardware.memoryMB config.guestId = source_vm.config.guestId config.deviceChange = [] config.extraConfig = [] config.files = self._create_file_info(self._client.factory, datastore.name) disk_controller_key = -101 config.deviceChange.append( self._create_disk_controller(self._client.factory, disk_controller_key)) # Add disk devices for disk in disks: config.deviceChange.append( self._create_disk(self._client.factory, disk_controller_key, disk, disks.index(disk), datastore)) # Add network nw_type = type(self._client.factory.create('ns0:VirtualEthernetCardNetworkBackingInfo')) for device in source_vm.config.hardware.device: if hasattr(device, 'backing') and type(device.backing) == nw_type: config.deviceChange.append( self._create_nic(self._client.factory, device.__class__.__name__, device.deviceInfo.label, device.deviceInfo.summary, device.backing.deviceName, device.unitNumber)) # Copy additional properties extraconfigstoskip = ['nvram'] for item in source_vm.config.extraConfig: if not item.key in extraconfigstoskip: config.extraConfig.append( self._create_option_value(self._client.factory, item.key, item.value)) task = self._client.service.CreateVM_Task(host_data['folder'], config=config, pool=host_data['resourcePool'], host=host_data['host']) if wait: self.wait_for_task(task) return task @authenticated() def clone_vm(self, vmid, name, disks, wait=True): """ Clone a existing VM configuration @param vmid: unique id of the vm @param name: name of the clone vm @param disks: list of disks to use in vm configuration @param kvmport: kvm port for the clone vm @param esxhost: esx host identifier on which to clone the vm @param wait: wait for task to complete or not (True/False) """ esxhost = self._validate_host(None) host_data = self._get_host_data(esxhost) source_vm_object = self.exists(key=vmid) if not source_vm_object: raise Exception('VM with key reference %s not found' % vmid) source_vm = self._get_object(source_vm_object) datastore = self._get_object(source_vm.datastore[0][0]) # Build basic config information config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.name = name config.numCPUs = source_vm.config.hardware.numCPU config.memoryMB = source_vm.config.hardware.memoryMB config.guestId = source_vm.config.guestId config.deviceChange = [] config.extraConfig = [] config.files = self._create_file_info( self._client.factory, datastore.name) disk_controller_key = -101 config.deviceChange.append( self._create_disk_controller(self._client.factory, disk_controller_key)) # Add disk devices for disk in disks: config.deviceChange.append( self._create_disk(self._client.factory, disk_controller_key, disk, disks.index(disk), datastore)) self.copy_file( '[{0}] {1}'.format(datastore.name, '%s.vmdk' % disk['name'].split('_')[-1].replace('-clone', '')), '[{0}] {1}'.format(datastore.name, disk['backingdevice'])) # Add network nw_type = type(self._client.factory.create( 'ns0:VirtualEthernetCardNetworkBackingInfo')) for device in source_vm.config.hardware.device: if hasattr(device, 'backing') and type(device.backing) == nw_type: config.deviceChange.append( self._create_nic(self._client.factory, device.__class__.__name__, device.deviceInfo.label, device.deviceInfo.summary, device.backing.deviceName, device.unitNumber)) # Copy additional properties extraconfigstoskip = ['nvram'] for item in source_vm.config.extraConfig: if not item.key in extraconfigstoskip: config.extraConfig.append( self._create_option_value(self._client.factory, item.key, item.value)) task = self._client.service.CreateVM_Task(host_data['folder'], config=config, pool=host_data['resourcePool'], host=host_data['host']) if wait: self.wait_for_task(task) return task @authenticated() def get_vm(self, key): vmid = self.exists(key=key) if vmid is None: raise RuntimeError('Virtual Machine with key {} could not be found.'.format(key)) vm = self._get_object(vmid) return vm @authenticated() def get_datastore(self, ip, mountpoint): """ @param ip : hypervisor ip to query for datastore presence @param mountpoint: nfs mountpoint on hypervisor @rtype: sdk datastore object @return: object when found else None """ datastore = None esxhost = self._validate_host(None) host_system = self._get_object(esxhost, properties=['datastore']) for store in host_system.datastore[0]: store = self._get_object(store) if not store.summary.accessible: raise RuntimeError('Datastore {0} is not accessible at mountpoint {1}'.format(store.name, mountpoint)) if hasattr(store.info, 'nas'): if store.info.nas.remoteHost == ip and store.info.nas.remotePath == mountpoint: datastore = store return datastore @authenticated() def is_datastore_available(self, ip, mountpoint): """ @param ip : hypervisor ip to query for datastore presence @param mountpoint: nfs mountpoint on hypervisor @rtype: boolean @return: True | False """ if self.get_datastore(ip, mountpoint): return True else: return False def make_agnostic_config(self, vm_object): regex = '\[([^\]]+)\]\s(.+)' match = re.search(regex, vm_object.config.files.vmPathName) esxhost = self._validate_host(None) config = {'name': vm_object.config.name, 'id': vm_object.obj_identifier.value, 'backing': {'filename': match.group(2), 'datastore': match.group(1)}, 'disks': [], 'datastores': {}} for device in vm_object.config.hardware.device: if device.__class__.__name__ == 'VirtualDisk': if device.backing is not None and \ device.backing.fileName is not None: backingfile = device.backing.fileName match = re.search(regex, backingfile) if match: filename = match.group(2) backingfile = filename.replace('.vmdk', '-flat.vmdk') config['disks'].append({'filename': filename, 'backingfilename': backingfile, 'datastore': match.group(1), 'name': device.deviceInfo.label, 'order': device.unitNumber}) host_system = self._get_object(esxhost, properties=['datastore']) for store in host_system.datastore[0]: store = self._get_object(store) if hasattr(store.info, 'nas'): config['datastores'][store.info.name] = '{}:{}'.format(store.info.nas.remoteHost, store.info.nas.remotePath) return config @authenticated() def delete_vm(self, vmid, storagedriver_mountpoint, storagedriver_storage_ip, devicename, wait=False): """ Delete a given vm """ machine = None if vmid: try: machine = self._build_property('VirtualMachine', vmid) except Exception as ex: logger.error('SDK domain retrieve failed by vmid: {}'.format(ex)) elif storagedriver_mountpoint and storagedriver_storage_ip and devicename: try: machine_info = self.get_nfs_datastore_object(storagedriver_storage_ip, storagedriver_mountpoint, devicename)[0] machine = self._build_property('VirtualMachine', machine_info.obj_identifier.value) except Exception as ex: logger.error('SDK domain retrieve failed by nfs datastore info: {}'.format(ex)) if machine: task = self._client.service.Destroy_Task(machine) if wait: self.wait_for_task(task) if storagedriver_mountpoint and devicename: vmx_path = os.path.join(storagedriver_mountpoint, devicename) if os.path.exists(vmx_path): dir_name = os.path.dirname(vmx_path) logger.debug('Removing leftover files in {0}'.format(dir_name)) try: shutil.rmtree(dir_name) logger.debug('Removed dir tree {}'.format(dir_name)) except Exception as exception: logger.error('Failed to remove dir tree {0}. Reason: {1}'.format(dir_name, str(exception))) return task @authenticated() def get_power_state(self, vmid): """ Get the power state of a given vm """ return self._get_object(self._build_property('VirtualMachine', vmid), properties=['runtime.powerState']).runtime.powerState @authenticated() def mount_nfs_datastore(self, name, remote_host, remote_path): """ Mounts a given NFS export as a datastore """ esxhost = self._validate_host(None) host = self._get_object(esxhost, properties=['datastore', 'name', 'configManager', 'configManager.datastoreSystem']) for store in host.datastore[0]: store = self._get_object(store) if hasattr(store.info, 'nas'): if store.info.name == name: if store.info.nas.remoteHost == remote_host and \ store.info.nas.remotePath == remote_path: # We'll remove this store, as it's identical to the once we'll add, # forcing a refresh self._client.service.RemoveDatastore(host.configManager.datastoreSystem, store.obj_identifier) break else: raise RuntimeError('A datastore {0} already exists, pointing to {1}:{2}'.format( name, store.info.nas.remoteHost, store.info.nas.remotePath )) spec = self._client.factory.create('ns0:HostNasVolumeSpec') spec.accessMode = 'readWrite' spec.localPath = name spec.remoteHost = remote_host spec.remotePath = remote_path spec.type = 'nfs' return self._client.service.CreateNasDatastore(host.configManager.datastoreSystem, spec) @authenticated() def wait_for_task(self, task): """ Wait for a task to be completed """ state = self.get_task_info(task).info.state while state in ['running', 'queued']: sleep(1) state = self.get_task_info(task).info.state @authenticated() def get_nfs_datastore_object(self, ip, mountpoint, filename): """ ip : "10.130.12.200", string mountpoint: "/srv/volumefs", string filename: "cfovs001/vhd0(-flat).vmdk" identify nfs datastore on this esx host based on ip and mount check if filename is present on datastore if file is .vmdk return VirtualDisk object for corresponding virtual disk if file is .vmx return VirtualMachineConfigInfo for corresponding vm @rtype: tuple @return: A tuple. First item: vm config, second item: Device if a vmdk was given """ filename = filename.replace('-flat.vmdk', '.vmdk') # Support both -flat.vmdk and .vmdk if not filename.endswith('.vmdk') and not filename.endswith('.vmx'): raise ValueError('Unexpected filetype') esxhost = self._validate_host(None) datastore = self.get_datastore(ip, mountpoint) if not datastore: raise RuntimeError('Could not find datastore') vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm'}, properties=['name', 'config']) if not vms: raise RuntimeError('No vMachines found') for vm in vms: mapping = self._get_vm_datastore_mapping(vm) if datastore.name in mapping: if filename in mapping[datastore.name]: return vm, mapping[datastore.name][filename] raise RuntimeError('Could not locate given file on the given datastore') def _get_vm_datastore_mapping(self, vm): """ Creates a datastore mapping for a vm's devices Structure {<datastore name>: {<backing filename>: <device>, <backing filename>: <device>}, <datastore name>: {<backing filename>: <device>}} Example {'datastore A': {'/machine1/machine1.vmx': <device>, '/machine1/disk1.vmdk': <device>}, 'datastore B': {'/machine1/disk2.vmdk': <device>}} """ def extract_names(backingfile, given_mapping, metadata=None): match = re.search('\[([^\]]+)\]\s(.+)', backingfile) if match: datastore_name = match.group(1) filename = match.group(2) if datastore_name not in mapping: given_mapping[datastore_name] = {} given_mapping[datastore_name][filename] = metadata return given_mapping virtual_disk_type = self._client.factory.create('ns0:VirtualDisk') flat_type = self._client.factory.create('ns0:VirtualDiskFlatVer2BackingInfo') mapping = {} for device in vm.config.hardware.device: if isinstance(device, type(virtual_disk_type)): if device.backing is not None and isinstance(device.backing, type(flat_type)): mapping = extract_names(device.backing.fileName, mapping, device) mapping = extract_names(vm.config.files.vmPathName, mapping) return mapping def _get_host_data(self, esxhost): """ Get host data for a given esxhost """ hostobject = self._get_object( esxhost, properties=['parent', 'datastore', 'network']) datastore = self._get_object( hostobject.datastore[0][0], properties=['info']).info computeresource = self._get_object( hostobject.parent, properties=['resourcePool', 'parent']) datacenter = self._get_object( computeresource.parent, properties=['parent']).parent vm_folder = self._get_object( datacenter, properties=['vmFolder']).vmFolder return {'host': esxhost, 'computeResource': computeresource, 'resourcePool': computeresource.resourcePool, 'datacenter': datacenter, 'folder': vm_folder, 'datastore': datastore, 'network': hostobject.network[0]} def _get_host_iqn_mapping(self, esxhost, rescan=False): """ Get the IQN mapping for a given esx host, optionally rescanning the host """ # pylint: disable=line-too-long regex = re.compile('^key-vim.host.PlugStoreTopology.Path-iqn.+?,(?P<iqn>iqn.*?),t,1-(?P<eui>eui.+)$') # noqa # pylint: enable=line-too-long hostobject = self._get_object( esxhost, properties=['configManager.storageSystem']) stg_ssystem = self._get_object(hostobject.configManager.storageSystem, properties=['storageDeviceInfo', 'storageDeviceInfo.plugStoreTopology.device']) if rescan: # Force a rescan of the vmfs self._client.service.RescanVmfs(stg_ssystem.obj_identifier) stg_ssystem = self._get_object( hostobject.configManager.storageSystem, properties=['storageDeviceInfo', 'storageDeviceInfo.plugStoreTopology.device']) device_info_mapping = {} for disk in stg_ssystem.storageDeviceInfo.scsiLun: device_info_mapping[disk.key] = disk.uuid iqn_mapping = {} for device in stg_ssystem.storageDeviceInfo.plugStoreTopology\ .device.HostPlugStoreTopologyDevice: for path in device.path: match = regex.search(path) if match: groups = match.groupdict() iqn_mapping[groups['iqn']] = {'eui': groups['eui'], 'lun': device.lun, 'uuid': device_info_mapping[device.lun]} return iqn_mapping def _get_object(self, key_object, prop_type=None, traversal=None, properties=None): """ Gets an object based on a given set of query parameters. Only the requested properties will be loaded. If no properties are specified, all will be loaded """ object_spec = self._client.factory.create('ns0:ObjectSpec') object_spec.obj = key_object property_spec = self._client.factory.create('ns0:PropertySpec') property_spec.type = key_object._type if prop_type is None else prop_type if properties is None: property_spec.all = True else: property_spec.all = False property_spec.pathSet = properties if traversal is not None: select_set_ptr = object_spec while True: select_set_ptr.selectSet = self._client.factory.create( 'ns0:TraversalSpec') select_set_ptr.selectSet.name = traversal['name'] select_set_ptr.selectSet.type = traversal['type'] select_set_ptr.selectSet.path = traversal['path'] if 'traversal' in traversal: traversal = traversal['traversal'] select_set_ptr = select_set_ptr.selectSet else: break property_filter_spec = self._client.factory.create( 'ns0:PropertyFilterSpec') property_filter_spec.objectSet = [object_spec] property_filter_spec.propSet = [property_spec] found_objects = self._client.service.RetrieveProperties( self._serviceContent.propertyCollector, [property_filter_spec] ) if len(found_objects) > 0: for item in found_objects: item.obj_identifier = item.obj del item.obj if hasattr(item, 'missingSet'): for missing_item in item.missingSet: if missing_item.fault.fault.__class__.__name__ == 'NotAuthenticated': raise NotAuthenticatedException() for propSet in item.propSet: if '.' in propSet.name: working_item = item path = str(propSet.name).split('.') part_counter = 0 for part in path: part_counter += 1 if part_counter < len(path): if not part in working_item.__dict__: setattr(working_item, part, type(part, (), {})()) working_item = working_item.__dict__[part] else: setattr(working_item, part, propSet.val) else: setattr(item, propSet.name, propSet.val) del item.propSet if len(found_objects) == 1: return found_objects[0] else: return found_objects return None def _build_property(self, property_name, value=None): """ Create a property object with given name and value """ new_property = Property(property_name) new_property._type = property_name if value is not None: new_property.value = value return new_property def _validate_host(self, host): """ Validates wheteher a given host is valid """ if host is None: if self._is_vcenter: raise Exception( 'A HostSystem reference is mandatory for a vCenter Server') else: return self._esxHost else: if hasattr(host, '_type') and host._type == 'HostSystem': return self._get_object(host, properties=['name']).obj_identifier else: return self._get_object( self._build_property('HostSystem', host), properties=['name']).obj_identifier def _login(self): """ Executes a logout (to make sure we're logged out), and logs in again """ self._logout() self._sessionID = self._client.service.Login( self._serviceContent.sessionManager, self._username, self._password, None ).key def _logout(self): """ Logs out the current session """ try: self._client.service.Logout(self._serviceContent.sessionManager) except: pass
class Sdk(object): """ This class contains all SDK related methods """ def __init__(self, host, login, passwd): """ Initializes the SDK """ self._host = host self._username = login self._password = passwd self._sessionID = None self._check_session = True self._cache = ObjectCache() self._cache.setduration(weeks=1) self._client = Client('https://{0}/sdk/vimService?wsdl'.format(host), cache=self._cache, cachingpolicy=1) self._client.set_options(location='https://{0}/sdk'.format(host), plugins=[ValueExtender()]) service_reference = self._build_property('ServiceInstance') self._serviceContent = self._client.service.RetrieveServiceContent( service_reference ) # In case of an ESXi host, this would be 'HostAgent' self.is_vcenter = self._serviceContent.about.apiType == 'VirtualCenter' if not self.is_vcenter: self._login() self._esxHost = self._get_object( self._serviceContent.rootFolder, prop_type='HostSystem', traversal={'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': {'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'ComputeResourceTravelSpec', 'type': 'ComputeResource', 'path': 'host'}}}}, properties=['name'] ).obj_identifier else: # @TODO: We need to extend all calls to specify the ESXi host where the action needs to be executed. # We cannot just assume an ESXi host here, as this is important for certain calls like creating a VM. self._esxHost = None @authenticated(force=True) def _get_vcenter_hosts(self): """ reload vCenter info (host name and summary) """ if not self.is_vcenter: raise RuntimeError('Must be connected to a vCenter Server API.') return self._get_object( self._serviceContent.rootFolder, prop_type='HostSystem', traversal={'name': 'FolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'DatacenterTraversalSpec', 'type': 'Datacenter', 'path': 'hostFolder', 'traversal': {'name': 'DFolderTraversalSpec', 'type': 'Folder', 'path': 'childEntity', 'traversal': {'name': 'ComputeResourceTravelSpec', 'type': 'ComputeResource', 'path': 'host'}}}}, properties=['name', 'summary.runtime', 'config.virtualNicManagerInfo.netConfig'], as_list=True ) def get_host_status_by_ip(self, host_ip): """ Return host status by ip, from vcenter info Must be connected to a vcenter server api """ host = self._get_host_info_by_ip(host_ip) return host.summary.runtime.powerState def get_host_status_by_pk(self, pk): """ Return host status by pk, from vcenter info Must be connected to a vcenter server api """ host = self._get_host_info_by_pk(pk) return host.summary.runtime.powerState def get_host_primary_key(self, host_ip): """ Return host primary key, based on current ip Must be connected to a vcenter server api """ host = self._get_host_info_by_ip(host_ip) return host.obj_identifier.value def _get_host_info_by_ip(self, host_ip): """ Return HostSystem object by ip, from vcenter info Must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() for host in datacenter_info: for nic in host.config.virtualNicManagerInfo.netConfig.VirtualNicManagerNetConfig: if nic.nicType == 'management': for vnic in nic.candidateVnic: if vnic.spec.ip.ipAddress == host_ip: return host raise RuntimeError('Host with ip {0} not found in datacenter info'.format(host_ip)) def _get_host_info_by_pk(self, pk): """ Return HostSystem object by pk, from vcenter info Must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() for host in datacenter_info: if host.obj_identifier.value == pk: return host def get_hosts(self): """ Gets a neutral list of all hosts available """ host_data = self._get_vcenter_hosts() host_data = [] if host_data is None else host_data hosts = {} for host in host_data: ips = [] for nic in host.config.virtualNicManagerInfo.netConfig.VirtualNicManagerNetConfig: if nic.nicType == 'management': for vnic in nic.candidateVnic: ips.append(vnic.spec.ip.ipAddress) hosts[host.obj_identifier.value] = {'name': host.name, 'ips': ips} return hosts def test_connection(self): """ Tests the connection """ self._login() return True def list_hosts_in_datacenter(self): """ return a list of registered host names in vCenter must be connected to a vcenter server api """ datacenter_info = self._get_vcenter_hosts() return [host.name for host in datacenter_info] def validate_result(self, result, message=None): """ Validates a given result. Returning True if the task succeeded, raising an error if not """ if hasattr(result, '_type') and result._type == 'Task': return self.validate_result(self.get_task_info(result), message) elif hasattr(result, 'info'): if result.info.state == 'success': return True elif result.info.state == 'error': error = result.info.error.localizedMessage raise Exception(('{0}: {1}'.format(message, error)) if message else error) raise Exception(('{0}: {1}'.format(message, 'Unexpected result')) if message else 'Unexpected result') @authenticated() def get_task_info(self, task): """ Loads the task details """ return self._get_object(task) @authenticated() def get_vm_ip_information(self): """ Get the IP information for all vms on a given esxi host """ esxhost = self._validate_host(None) configuration = [] for vm in self._get_object(esxhost, prop_type='VirtualMachine', traversal={ 'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm'}, properties=['name', 'guest.net', 'config.files'], as_list=True): vmi = {'id': str(vm.obj_identifier.value), 'vmxpath': str(vm.config.files.vmPathName), 'name': str(vm.name), 'net': []} if vm.guest.net: for net in vm.guest.net[0]: vmi['net'].append({'mac': str(net.macAddress), 'ipaddresses': [str(i.ipAddress) for i in net.ipConfig.ipAddress]}) configuration.append(vmi) return configuration @authenticated() def exists(self, name=None, key=None): """ Checks whether a vm with a given name or key exists on a given esxi host """ esxhost = self._validate_host(self._esxHost) if name is not None or key is not None: try: if name is not None: vms = [vm for vm in self._get_object(esxhost, prop_type='VirtualMachine', traversal={'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm'}, properties=['name'], as_list=True) if vm.name == name] if len(vms) == 0: return None else: return vms[0].obj_identifier if key is not None: return self._get_object( Sdk._build_property('VirtualMachine', key), properties=['name'] ).obj_identifier except: return None else: raise Exception('A name or key should be passed.') @authenticated() def get_vm(self, key): """ Retreives a vm object, based on its key """ vmid = self.exists(key=key) if vmid is None: raise RuntimeError('Virtual Machine with key {} could not be found.'.format(key)) vm = self._get_object(vmid) return vm @authenticated() def get_vm_device_info(self, key): """ Return a vm config, based on its key """ vm = self.get_vm(key) filename = vm.config.files.vmPathName regex = '\[([^\]]+)\]\s(.+)' match = re.search(regex, filename) disks = self._get_vmachine_vdisks(vm) return {'file_name': match.group(2), 'host_name': vm.name, 'vpool_name': match.group(1), 'disks': disks} @authenticated() def get_all_vms(self): """ Get all vMachines on all esxhosts registered to this vCenter :return: list """ if not self.is_vcenter: raise RuntimeError('Must be connected to a vCenter Server API.') hosts = self._get_vcenter_hosts() guests = [] for host in hosts: esxhost = self._validate_host(host.obj_identifier) vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm'}, properties=['name', 'config'], as_list=True) for vm in vms: guests.append({'id': vm.obj_identifier.value, 'name': vm.name, 'instance_name': vm.name}) return guests def _get_vmachine_vdisks(self, vm_object): disks = [] regex = '\[([^\]]+)\]\s(.+)' disk_type = type(self._client.factory.create('ns0:VirtualDisk')) for device in vm_object.config.hardware.device: if isinstance(device, disk_type): backingfile = device.backing.fileName match = re.search(regex, backingfile) if match: disks.append({'filename': match.group(2), 'datastore': match.group(1), 'name': device.deviceInfo.label}) return disks @authenticated() def get_all_vdisks(self): """ Get all vDisks on all esxhosts registered to this vCenter # similar to cinder.volumes.list() :return: list """ if not self.is_vcenter: raise RuntimeError('Must be connected to a vCenter Server API.') hosts = self._get_vcenter_hosts() disks = [] for host in hosts: esxhost = self._validate_host(host.obj_identifier) vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm'}, properties=['name', 'config'], as_list=True) for vm in vms: disks.extend(self._get_vmachine_vdisks(vm)) return disks @authenticated() def get_vms(self, ip, mountpoint): """ Get all vMachines using a given nfs share """ esxhost = self._validate_host(None) datastore = self.get_datastore(ip, mountpoint) filtered_vms = [] vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm'}, properties=['name', 'config'], as_list=True) for vm in vms: mapping = self._get_vm_datastore_mapping(vm) if datastore.name in mapping: filtered_vms.append(vm) return filtered_vms @authenticated() def set_disk_mode(self, vmid, disks, mode, wait=True): """ Sets the disk mode for a set of disks """ config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.deviceChange = [] disk_type = type(self._client.factory.create('ns0:VirtualDisk')) vmid = self.exists(key=vmid) vm = self._get_object(vmid) for device in vm.config.hardware.devices: if type(device) == disk_type and hasattr(device, 'backing') and device.backing.fileName in disks: backing = self._client.factory.create('ns0:VirtualDiskFlatVer2BackingInfo') backing.diskMode = mode device = self._client.factory.create('ns0:VirtualDisk') device.backing = backing disk_spec = self._client.factory.create('ns0:VirtualDeviceConfigSpec') disk_spec.operation = 'edit' disk_spec.fileOperation = None disk_spec.device = device config.deviceChange.append(disk_spec) task = self._client.service.ReconfigVM_Task(vm.obj_identifier, config) if wait: self.wait_for_task(task) return task @staticmethod def _create_disk(factory, key, disk, unit, datastore): """ Creates a disk spec for a given backing device Example for parameter disk: {'name': diskname, 'backingdevice': 'disk-flat.vmdk'} """ device_info = factory.create('ns0:Description') device_info.label = disk['name'] device_info.summary = 'Disk {0}'.format(disk['name']) backing = factory.create('ns0:VirtualDiskFlatVer2BackingInfo') backing.diskMode = 'persistent' backing.fileName = '[{0}] {1}'.format(datastore.name, disk['backingdevice']) backing.thinProvisioned = True device = factory.create('ns0:VirtualDisk') device.controllerKey = key device.key = -200 - unit device.unitNumber = unit device.deviceInfo = device_info device.backing = backing disk_spec = factory.create('ns0:VirtualDeviceConfigSpec') disk_spec.operation = 'add' disk_spec.fileOperation = None disk_spec.device = device return disk_spec @staticmethod def _create_file_info(factory, datastore): """ Creates a file info object """ file_info = factory.create('ns0:VirtualMachineFileInfo') file_info.vmPathName = '[{0}]'.format(datastore) return file_info @staticmethod def _create_nic(factory, device_type, device_label, device_summary, network, unit): """ Creates a NIC spec """ device_info = factory.create('ns0:Description') device_info.label = device_label device_info.summary = device_summary backing = factory.create('ns0:VirtualEthernetCardNetworkBackingInfo') backing.deviceName = network device = factory.create('ns0:{0}'.format(device_type)) device.addressType = 'Generated' device.wakeOnLanEnabled = True device.controllerKey = 100 # PCI Controller device.key = -300 - unit device.unitNumber = unit device.backing = backing device.deviceInfo = device_info nic_spec = factory.create('ns0:VirtualDeviceConfigSpec') nic_spec.operation = 'add' nic_spec.fileOperation = None nic_spec.device = device return nic_spec def _create_disk_controller(self, factory, key): """ Create a disk controller """ device_info = self._client.factory.create('ns0:Description') device_info.label = 'SCSI controller 0' device_info.summary = 'LSI Logic SAS' controller = factory.create('ns0:VirtualLsiLogicSASController') controller.busNumber = 0 controller.key = key controller.sharedBus = 'noSharing' controller.deviceInfo = device_info controller_spec = factory.create('ns0:VirtualDeviceConfigSpec') controller_spec.operation = 'add' controller_spec.fileOperation = None controller_spec.device = controller return controller_spec @staticmethod def _create_option_value(factory, key, value): """ Create option values """ option = factory.create('ns0:OptionValue') option.key = key option.value = value return option @authenticated() def copy_file(self, source, destination, wait=True): """ Copies a file on the datastore """ task = self._client.service.CopyDatastoreFile_Task( _this=self._serviceContent.fileManager, sourceName=source, destinationName=destination ) if wait: self.wait_for_task(task) return task @authenticated() def create_vm_from_template(self, name, source_vm, disks, ip, mountpoint, wait=True): """ Create a vm based on an existing vtemplate on specified tgt hypervisor Raises RuntimeError if datastore is not available at (ip, mountpoint) """ esxhost = self._validate_host(None) host_data = self._get_host_data(esxhost) datastore = self.get_datastore(ip, mountpoint) # Build basic config information config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.name = name config.numCPUs = source_vm.config.hardware.numCPU config.memoryMB = source_vm.config.hardware.memoryMB config.guestId = source_vm.config.guestId config.deviceChange = [] config.extraConfig = [] config.files = Sdk._create_file_info(self._client.factory, datastore.name) disk_controller_key = -101 config.deviceChange.append( self._create_disk_controller(self._client.factory, disk_controller_key)) # Add disk devices for disk in disks: config.deviceChange.append( Sdk._create_disk(self._client.factory, disk_controller_key, disk, disks.index(disk), datastore)) # Add network nw_type = type(self._client.factory.create('ns0:VirtualEthernetCardNetworkBackingInfo')) for device in source_vm.config.hardware.device: if hasattr(device, 'backing') and type(device.backing) == nw_type: config.deviceChange.append( Sdk._create_nic(self._client.factory, device.__class__.__name__, device.deviceInfo.label, device.deviceInfo.summary, device.backing.deviceName, device.unitNumber)) # Copy additional properties extraconfigstoskip = ['nvram'] for item in source_vm.config.extraConfig: if item.key not in extraconfigstoskip: config.extraConfig.append( Sdk._create_option_value(self._client.factory, item.key, item.value)) task = self._client.service.CreateVM_Task(host_data['folder'], config=config, pool=host_data['resourcePool'], host=host_data['host']) if wait: self.wait_for_task(task) return task @authenticated() def clone_vm(self, vmid, name, disks, wait=True): """ Clone a existing VM configuration @param vmid: unique id of the vm @param name: name of the clone vm @param disks: list of disks to use in vm configuration @param wait: wait for task to complete or not (True/False) """ esxhost = self._validate_host(None) host_data = self._get_host_data(esxhost) source_vm_object = self.exists(key=vmid) if not source_vm_object: raise Exception('VM with key reference {0} not found'.format(vmid)) source_vm = self._get_object(source_vm_object) datastore = self._get_object(source_vm.datastore[0][0]) # Build basic config information config = self._client.factory.create('ns0:VirtualMachineConfigSpec') config.name = name config.numCPUs = source_vm.config.hardware.numCPU config.memoryMB = source_vm.config.hardware.memoryMB config.guestId = source_vm.config.guestId config.deviceChange = [] config.extraConfig = [] config.files = Sdk._create_file_info(self._client.factory, datastore.name) disk_controller_key = -101 config.deviceChange.append( self._create_disk_controller(self._client.factory, disk_controller_key)) # Add disk devices for disk in disks: config.deviceChange.append( Sdk._create_disk(self._client.factory, disk_controller_key, disk, disks.index(disk), datastore)) self.copy_file( '[{0}] {1}.vmdk'.format(datastore.name, disk['name'].split('_')[-1].replace('-clone', '')), '[{0}] {1}'.format(datastore.name, disk['backingdevice']) ) # Add network nw_type = type(self._client.factory.create('ns0:VirtualEthernetCardNetworkBackingInfo')) for device in source_vm.config.hardware.device: if hasattr(device, 'backing') and type(device.backing) == nw_type: config.deviceChange.append( Sdk._create_nic(self._client.factory, device.__class__.__name__, device.deviceInfo.label, device.deviceInfo.summary, device.backing.deviceName, device.unitNumber)) # Copy additional properties extraconfigstoskip = ['nvram'] for item in source_vm.config.extraConfig: if item.key not in extraconfigstoskip: config.extraConfig.append( Sdk._create_option_value(self._client.factory, item.key, item.value) ) task = self._client.service.CreateVM_Task(host_data['folder'], config=config, pool=host_data['resourcePool'], host=host_data['host']) if wait: self.wait_for_task(task) return task @authenticated() def get_datastore(self, ip, mountpoint, host=None): """ @param ip : hypervisor ip to query for datastore presence @param mountpoint: nfs mountpoint on hypervisor @rtype: sdk datastore object @return: object when found else None """ datastore = None if host is None: host = self._esxHost esxhost = self._validate_host(host) host_system = self._get_object(esxhost, properties=['datastore']) for store in host_system.datastore[0]: store = self._get_object(store) if not store.summary.accessible: logger.warning('Datastore {0} is not accessible, skipping'.format(store.name)) if hasattr(store.info, 'nas'): if store.info.nas.remoteHost == ip and store.info.nas.remotePath == mountpoint: datastore = store return datastore @authenticated() def is_datastore_available(self, ip, mountpoint): """ @param ip : hypervisor ip to query for datastore presence @param mountpoint: nfs mountpoint on hypervisor @rtype: boolean @return: True | False """ if self.get_datastore(ip, mountpoint): return True else: return False def make_agnostic_config(self, vm_object, host=None): regex = '\[([^\]]+)\]\s(.+)' match = re.search(regex, vm_object.config.files.vmPathName) if host is None: host = self._esxHost esxhost = self._validate_host(host) config = {'name': vm_object.config.name, 'id': vm_object.obj_identifier.value, 'backing': {'filename': match.group(2), 'datastore': match.group(1)}, 'disks': [], 'datastores': {}} for device in vm_object.config.hardware.device: if device.__class__.__name__ == 'VirtualDisk': if device.backing is not None and device.backing.fileName is not None: backingfile = device.backing.fileName match = re.search(regex, backingfile) if match: filename = match.group(2) backingfile = filename.replace('.vmdk', '-flat.vmdk') backingfile = '/{0}'.format(backingfile.strip('/')) config['disks'].append({'filename': filename, 'backingfilename': backingfile, 'datastore': match.group(1), 'name': device.deviceInfo.label, 'order': device.unitNumber}) host_system = self._get_object(esxhost, properties=['datastore']) for store in host_system.datastore[0]: store = self._get_object(store) if hasattr(store.info, 'nas'): config['datastores'][store.info.name] = '{}:{}'.format(store.info.nas.remoteHost, store.info.nas.remotePath) return config @authenticated() def delete_vm(self, vmid, storagedriver_mountpoint, storagedriver_storage_ip, devicename, wait=False): """ Delete a given vm """ machine = None task = None if vmid: try: machine = Sdk._build_property('VirtualMachine', vmid) except Exception as ex: logger.error('SDK domain retrieve failed by vmid: {}'.format(ex)) elif storagedriver_mountpoint and storagedriver_storage_ip and devicename: try: machine_info = self.get_nfs_datastore_object(storagedriver_storage_ip, storagedriver_mountpoint, devicename)[0] machine = Sdk._build_property('VirtualMachine', machine_info.obj_identifier.value) except Exception as ex: logger.error('SDK domain retrieve failed by nfs datastore info: {}'.format(ex)) if machine: task = self._client.service.Destroy_Task(machine) if wait: self.wait_for_task(task) if storagedriver_mountpoint and devicename: vmx_path = os.path.join(storagedriver_mountpoint, devicename) if os.path.exists(vmx_path): dir_name = os.path.dirname(vmx_path) logger.debug('Removing leftover files in {0}'.format(dir_name)) try: shutil.rmtree(dir_name) logger.debug('Removed dir tree {}'.format(dir_name)) except Exception as exception: logger.error('Failed to remove dir tree {0}. Reason: {1}'.format(dir_name, str(exception))) return task @authenticated() def get_power_state(self, vmid): """ Get the power state of a given vm """ return self._get_object(Sdk._build_property('VirtualMachine', vmid), properties=['runtime.powerState']).runtime.powerState @authenticated() def mount_nfs_datastore(self, name, remote_host, remote_path): """ Mounts a given NFS export as a datastore """ esxhost = self._validate_host(None) host = self._get_object(esxhost, properties=['datastore', 'name', 'configManager', 'configManager.datastoreSystem']) for store in host.datastore[0]: store = self._get_object(store) if hasattr(store.info, 'nas'): if store.info.name == name: if store.info.nas.remoteHost == remote_host and store.info.nas.remotePath == remote_path: # We'll remove this store, as it's identical to the once we'll add, # forcing a refresh self._client.service.RemoveDatastore(host.configManager.datastoreSystem, store.obj_identifier) break else: raise RuntimeError('A datastore {0} already exists, pointing to {1}:{2}'.format( name, store.info.nas.remoteHost, store.info.nas.remotePath )) spec = self._client.factory.create('ns0:HostNasVolumeSpec') spec.accessMode = 'readWrite' spec.localPath = name spec.remoteHost = remote_host spec.remotePath = remote_path spec.type = 'nfs' return self._client.service.CreateNasDatastore(host.configManager.datastoreSystem, spec) @authenticated() def wait_for_task(self, task): """ Wait for a task to be completed """ state = self.get_task_info(task).info.state while state in ['running', 'queued']: sleep(1) state = self.get_task_info(task).info.state @authenticated() def get_nfs_datastore_object(self, ip, mountpoint, filename, host=None): """ ip : "10.130.12.200", string mountpoint: "/srv/volumefs", string filename: "cfovs001/vhd0(-flat).vmdk" identify nfs datastore on this esx host based on ip and mount check if filename is present on datastore if file is .vmdk return VirtualDisk object for corresponding virtual disk if file is .vmx return VirtualMachineConfigInfo for corresponding vm @rtype: tuple @return: A tuple. First item: vm config, second item: Device if a vmdk was given """ filename = filename.replace('-flat.vmdk', '.vmdk') # Support both -flat.vmdk and .vmdk if not filename.endswith('.vmdk') and not filename.endswith('.vmx'): raise ValueError('Unexpected filetype') if host is None: host = self._esxHost esxhost = self._validate_host(host) datastore = self.get_datastore(ip, mountpoint, host=esxhost) if not datastore: raise RuntimeError('Could not find datastore') vms = self._get_object(esxhost, prop_type='VirtualMachine', traversal={'name': 'HostSystemTraversalSpec', 'type': 'HostSystem', 'path': 'vm'}, properties=['name', 'config'], as_list=True) if not vms: raise RuntimeError('No vMachines found') for vm in vms: mapping = self._get_vm_datastore_mapping(vm) if datastore.name in mapping: if filename in mapping[datastore.name]: return vm, mapping[datastore.name][filename] raise RuntimeError('Could not locate given file on the given datastore') def file_exists(self, ip, mountpoint, filename): try: self.get_nfs_datastore_object(ip, mountpoint, filename) return True except Exception, ex: logger.debug('File does not exist: {0}'.format(ex)) return False
def __init__(self, hostname=None, username=None, password=None, wsdls=None, directory=None, fromurl=False, debug=False, proto='https', sessions=False, cache=None, **kwargs): self.hostname = hostname self.username = username self.password = password self.directory = directory self.sessions = sessions self.fromurl = fromurl self.proto = proto self.debug = debug self.kw = kwargs self.sessionisset = False # Setup the object cache if cache: self.cache = cache else: self.cache = ObjectCache(days=30) if self.debug == True: self._set_trace_logging() location = '{protocol}://{hostname}{uri}'.format( protocol=self.proto, hostname=self.hostname, uri=ICONTROL_URI) if self.sessions: '''This if block forces System.Session into index 0 in the wsdl list.''' if SESSION_WSDL in wsdls: self.wsdls = [ x for x in wsdls if not x.startswith('System.Session') ] self.wsdls.insert(0, SESSION_WSDL) else: self.wsdls = wsdls self.wsdls.insert(0, SESSION_WSDL) else: self.wsdls = wsdls self.clients = self._get_clients() for client in self.clients: self._set_module_attributes(client) self._set_interface_attributes(client) self._set_interface_sudsclient(client) self._set_type_factory(client) self._set_interface_methods(client) client.factory.separator('_') client.set_options(location=location, cache=self.cache) if self.sessions: if self.sessionisset: pass else: self.sessionid = self.get_sessionid() self.set_sessionid(self.sessionid.__str__(), client)
def get_cache(configname): return ObjectCache(get_cache_path(configname))