def get_version(self): """ Gets the major version from the Rhevm server """ try: headers = dict() headers['Version'] = '3' response = requests.get(urlparse.urljoin(self.url, 'api'), auth=self.auth, headers=headers, verify=False) if response.status_code == 404 and 'ovirt-engine' not in self.url: response = requests.get(urlparse.urljoin( self.url, 'ovirt-engine/api'), auth=self.auth, headers=headers, verify=False) response.raise_for_status() except requests.RequestException as e: raise virt.VirtError("Unable to connect to RHEV-M server: %s" % str(e)) try: api = ElementTree.fromstring(response.content) except Exception as e: self.logger.debug("Invalid xml file: %s" % response) raise virt.VirtError("Invalid XML file returned from RHEV-M: %s" % str(e)) version = api.find('.//version') if version is not None: major = version.attrib['major'] self.major_version = major else: self.logger.info("Could not determine version")
def createFilter(self): oSpec = self.objectSpec() oSpec.obj = self.sc.rootFolder oSpec.selectSet = self.buildFullTraversal() pfs = self.propertyFilterSpec() pfs.objectSet = [oSpec] pfs.propSet = [ self.createPropertySpec("VirtualMachine", ["config.uuid", "runtime.powerState"]), self.createPropertySpec("ClusterComputeResource", ["name"]), self.createPropertySpec("HostSystem", [ "name", "vm", "hardware.systemInfo.uuid", "hardware.cpuInfo.numCpuPackages", "parent", "config.product.name", "config.product.version", "config.network.dnsConfig.hostName", "config.network.dnsConfig.domainName" ]) ] try: return self.client.service.CreateFilter( _this=self.sc.propertyCollector, spec=pfs, partialUpdates=0) except requests.RequestException as e: raise virt.VirtError(str(e))
def login(self): """ Log into ESX """ kwargs = {'transport': RequestsTransport()} # Connect to the vCenter server if self.config['simplified_vim']: wsdl = 'file://%s/vimServiceMinimal.wsdl' % os.path.dirname( os.path.abspath(__file__)) kwargs['cache'] = None else: wsdl = self.url + '/sdk/vimService.wsdl' try: self.client = suds.client.Client(wsdl, location="%s/sdk" % self.url, **kwargs) except requests.RequestException as e: raise virt.VirtError(str(e)) self.client.set_options(timeout=self.MAX_WAIT_TIME) # Get Meta Object Reference to ServiceInstance which is the root object of the inventory self.moRef = suds.sudsobject.Property('ServiceInstance') self.moRef._type = 'ServiceInstance' # pylint: disable=W0212 # Service Content object defines properties of the ServiceInstance object try: self.sc = self.client.service.RetrieveServiceContent( _this=self.moRef) except requests.RequestException as e: raise virt.VirtError(str(e)) # Login to server using given credentials try: # Don't log message containing password logging.getLogger('suds.client').setLevel(logging.CRITICAL) self.client.service.Login(_this=self.sc.sessionManager, userName=self.username, password=self.password) logging.getLogger('suds.client').setLevel(logging.ERROR) except requests.RequestException as e: raise virt.VirtError(str(e)) except suds.WebFault as e: self.logger.exception("Unable to login to ESX") raise virt.VirtError(str(e))
def get_version(self): """ Gets the major version from the Rhevm server """ try: # If we are talking to a Rhev4 system, we need to specifically request # the Rhev 3 version of the api. To minimize code impact, we do this # by setting a 'Version' header, as outlined in Rhev 4's "Version 3 # REST API Guide" headers = dict() headers['Version'] = '3' # We will store the api_base that seems to work and use that for future requests response = requests.get(urllib.parse.urljoin( self.url, self.api_base), auth=self.auth, headers=headers, verify=False) if response.status_code == 404: # this would happen if the api_base is not correct. early version 3 API. self.api_base = 'api' response = requests.get(urllib.parse.urljoin( self.url, self.api_base), auth=self.auth, headers=headers, verify=False) response.raise_for_status() except requests.RequestException as e: raise virt.VirtError("Unable to connect to RHEV-M server: %s" % str(e)) try: api = ElementTree.fromstring(response.content) except Exception as e: self.logger.debug("Invalid xml file: %s" % response) raise virt.VirtError("Invalid XML file returned from RHEV-M: %s" % str(e)) version = api.find('.//version') if version is not None: major = version.attrib['major'] self.major_version = major else: self.logger.info("Could not determine version")
def get_xml(self, url): """ Call RHEV-M server, retrieve XML and parse it. """ response = self.get(url) try: return ElementTree.fromstring(response) except Exception as e: self.logger.debug("Invalid xml file: %s" % response) raise virt.VirtError("Invalid XML file returned from RHEV-M: %s" % str(e))
def get(self, url): """ Call RHEV-M server and retrieve what's on given url. """ try: response = requests.get(url, auth=self.auth, verify=False) response.raise_for_status() except requests.RequestException as e: raise virt.VirtError("Unable to connect to RHEV-M server: %s" % str(e)) # FIXME: other errors return response.content
def login(self, url=None): """ Login to server using given credentials. """ url = url or self.url try: # Don't log message containing password self.session = XenAPI.Session( url, transport=RequestsXmlrpcTransport(url)) self.session.xenapi.login_with_password(self.username, self.password) self.logger.debug("XEN pool login successful with user %s" % self.username) except NewMaster as nm: url = nm.new_master() if "://" not in url: url = '%s://%s' % (self.url.partition(":")[0], url) self.logger.debug("Switching to new master: %s", url) return self.login(url) except requests.ConnectionError as e: raise virt.VirtError(str(e)) except Exception as e: self.logger.exception("Unable to login to XENserver %s" % self.url) raise virt.VirtError(str(e))
def get(self, url): """ Call RHEV-M server and retrieve what's on given url. """ headers = dict() try: if self.major_version == '4': headers['Version'] = '3' response = requests.get(url, auth=self.auth, verify=False, headers=headers) response.raise_for_status() except requests.RequestException as e: raise virt.VirtError("Unable to connect to RHEV-M server: %s" % str(e)) # FIXME: other errors return response.content
def get(self, url): """ Call RHEV-M server and retrieve what's on given url. """ try: if self.major_version == '4': # If we are talking to a Rhev4 system, we need to specifically request # the Rhev 3 version of the api. To minimize code impact, we do this # by setting a 'Version' header, as outlined in Rhev 4's "Version 3 # REST API Guide" headers = dict() headers['Version'] = '3' response = requests.get(url, auth=self.auth, verify=False, headers=headers) else: response = requests.get(url, auth=self.auth, verify=False) response.raise_for_status() except requests.RequestException as e: raise virt.VirtError("Unable to connect to RHEV-M server: %s" % str(e)) # FIXME: other errors return response.content
def getHostGuestMapping(self): guests = [] connection = self.connect() hypervsoap = HyperVSoap(self.url, connection, self.logger) uuid = None if not self.useNewApi: try: # SettingType == 3 means current setting, 5 is snapshot - we don't want snapshots uuid = hypervsoap.Enumerate( "select BIOSGUID, ElementName " "from Msvm_VirtualSystemSettingData " "where SettingType = 3", "root/virtualization") except HyperVCallFailed: self.logger.debug( "Unable to enumerate using root/virtualization namespace, " "trying root/virtualization/v2 namespace") self.useNewApi = True if self.useNewApi: # Filter out Planned VMs and snapshots, see # http://msdn.microsoft.com/en-us/library/hh850257%28v=vs.85%29.aspx uuid = hypervsoap.Enumerate( "select BIOSGUID, ElementName " "from Msvm_VirtualSystemSettingData " "where VirtualSystemType = 'Microsoft:Hyper-V:System:Realized'", "root/virtualization/v2") # Get guest states guest_states = hypervsoap.Invoke_GetSummaryInformation( "root/virtualization/v2" if self. useNewApi else "root/virtualization") vmmsVersion = self.getVmmsVersion(hypervsoap) for instance in hypervsoap.Pull(uuid): try: uuid = instance["BIOSGUID"] except KeyError: self.logger.warning("Guest without BIOSGUID found, ignoring") continue try: elementName = instance["ElementName"] except KeyError: self.logger.warning("Guest %s is missing ElementName", uuid) continue try: state = guest_states[elementName] except KeyError: self.logger.warning("Unknown state for guest %s", elementName) state = virt.Guest.STATE_UNKNOWN guests.append(virt.Guest(HyperV.decodeWinUUID(uuid), self, state)) # Get the hostname hostname = None socket_count = None data = hypervsoap.Enumerate( "select DNSHostName, NumberOfProcessors from Win32_ComputerSystem", "root/cimv2") for instance in hypervsoap.Pull(data, "root/cimv2"): hostname = instance["DNSHostName"] socket_count = instance["NumberOfProcessors"] if self.config.hypervisor_id == 'uuid': uuid = hypervsoap.Enumerate( "select UUID from Win32_ComputerSystemProduct", "root/cimv2") host = None for instance in hypervsoap.Pull(uuid, "root/cimv2"): host = HyperV.decodeWinUUID(instance["UUID"]) elif self.config.hypervisor_id == 'hostname': host = hostname else: raise virt.VirtError( 'Invalid option %s for hypervisor_id, use one of: uuid, or hostname' % self.config.hypervisor_id) facts = { virt.Hypervisor.CPU_SOCKET_FACT: str(socket_count), virt.Hypervisor.HYPERVISOR_TYPE_FACT: 'hyperv', virt.Hypervisor.HYPERVISOR_VERSION_FACT: vmmsVersion, } hypervisor = virt.Hypervisor(hypervisorId=host, name=hostname, guestIds=guests, facts=facts) return {'hypervisors': [hypervisor]}
def getHostGuestMapping(self): """ Returns dictionary containing a list of virt.Hypervisors Each virt.Hypervisor contains the hypervisor ID as well as a list of virt.Guest {'hypervisors': [Hypervisor1, ...] } """ mapping = {} hosts = {} clusters = set() clusters_xml = self.get_xml(self.clusters_url) hosts_xml = self.get_xml(self.hosts_url) vms_xml = self.get_xml(self.vms_url) # Save ids of clusters that are "virt_service" for cluster in clusters_xml.findall('cluster'): cluster_id = cluster.get('id') virt_service = cluster.find('virt_service').text if virt_service.lower() == 'true': clusters.add(cluster_id) for host in hosts_xml.findall('host'): id = host.get('id') # Check if host is in cluster that is "virt_service" host_cluster = host.find('cluster') host_cluster_id = host_cluster.get('id') if host_cluster_id not in clusters: # Skip the host if it's cluster is not "virt_service" self.logger.debug( 'Cluster of host %s is not virt_service, skipped', id) continue if self.config.hypervisor_id == 'uuid': host_id = id elif self.config.hypervisor_id == 'hwuuid': try: host_id = host.find('hardware_information').find( 'uuid').text except AttributeError: self.logger.warn("Host %s doesn't have hardware uuid", id) continue elif self.config.hypervisor_id == 'hostname': host_id = host.find('name').text else: raise virt.VirtError( 'Invalid option %s for hypervisor_id, use one of: uuid, hwuuid, or hostname' % self.config.hypervisor_id) sockets = host.find('cpu').find('topology').get('sockets') if not sockets: sockets = host.find('cpu').find('topology').find( 'sockets').text facts = { virt.Hypervisor.CPU_SOCKET_FACT: sockets, virt.Hypervisor.HYPERVISOR_TYPE_FACT: 'qemu', } try: version = host.find('version').get('full_version') if version: facts[virt.Hypervisor.HYPERVISOR_VERSION_FACT] = version except AttributeError: pass hosts[id] = virt.Hypervisor(hypervisorId=host_id, name=host.find('name').text, facts=facts) mapping[id] = [] for vm in vms_xml.findall('vm'): guest_id = vm.get('id') host = vm.find('host') if host is None: # Guest don't have any host continue host_id = host.get('id') if host_id not in mapping.keys(): self.logger.warning( "Guest %s claims that it belongs to host %s which doesn't exist", guest_id, host_id) continue try: status = vm.find('status') try: state_text = status.find('state').text.lower() except AttributeError: # RHEVM 4.0 reports the state differently state_text = status.text.lower() state = RHEVM_STATE_TO_GUEST_STATE.get( state_text, virt.Guest.STATE_UNKNOWN) except AttributeError: self.logger.warning("Guest %s doesn't report any status", guest_id) state = virt.Guest.STATE_UNKNOWN hosts[host_id].guestIds.append(virt.Guest(guest_id, self, state)) return {'hypervisors': hosts.values()}
def getHostGuestMapping(self): mapping = {'hypervisors': []} for host_id, host in self.hosts.items(): parent = host['parent'].value if self.config.exclude_host_parents is not None and parent in self.config.exclude_host_parents: self.logger.debug( "Skipping host '%s' because its parent '%s' is excluded", host_id, parent) continue if self.config.filter_host_parents is not None and parent not in self.config.filter_host_parents: self.logger.debug( "Skipping host '%s' because its parent '%s' is not included", host_id, parent) continue guests = [] try: if self.config.hypervisor_id == 'uuid': uuid = host['hardware.systemInfo.uuid'] elif self.config.hypervisor_id == 'hwuuid': uuid = host_id elif self.config.hypervisor_id == 'hostname': uuid = host['config.network.dnsConfig.hostName'] domain_name = host['config.network.dnsConfig.domainName'] if domain_name: uuid = '{0}.{1}'.format(uuid, domain_name) else: raise virt.VirtError( 'Invalid option %s for hypervisor_id, use one of: uuid, hwuuid, or hostname' % self.config.hypervisor_id) except KeyError: self.logger.debug( "Host '%s' doesn't have hypervisor_id property", host_id) continue if host['vm']: for vm_id in host['vm'].ManagedObjectReference: if vm_id.value not in self.vms: self.logger.debug( "Host '%s' references non-existing guest '%s'", host_id, vm_id.value) continue vm = self.vms[vm_id.value] if 'config.uuid' not in vm: self.logger.debug( "Guest '%s' doesn't have 'config.uuid' property", vm_id.value) continue if not vm['config.uuid'].strip(): self.logger.debug( "Guest '%s' has empty 'config.uuid' property", vm_id.value) continue state = virt.Guest.STATE_UNKNOWN try: if vm['runtime.powerState'] == 'poweredOn': state = virt.Guest.STATE_RUNNING elif vm['runtime.powerState'] == 'suspended': state = virt.Guest.STATE_PAUSED elif vm['runtime.powerState'] == 'poweredOff': state = virt.Guest.STATE_SHUTOFF except KeyError: self.logger.debug( "Guest '%s' doesn't have 'runtime.powerState' property", vm_id.value) guests.append(virt.Guest(vm['config.uuid'], self, state)) try: name = host['config.network.dnsConfig.hostName'] domain_name = host['config.network.dnsConfig.domainName'] if domain_name: name = '{0}.{1}'.format(name, domain_name) except KeyError: self.logger.debug("Unable to determine hostname for host '%s'", uuid) name = '' facts = { virt.Hypervisor.CPU_SOCKET_FACT: str(host['hardware.cpuInfo.numCpuPackages']), virt.Hypervisor.HYPERVISOR_TYPE_FACT: host.get('config.product.name', 'vmware'), } version = host.get('config.product.version', None) if version: facts[virt.Hypervisor.HYPERVISOR_VERSION_FACT] = version mapping['hypervisors'].append( virt.Hypervisor(hypervisorId=uuid, guestIds=guests, name=name, facts=facts)) return mapping
def _send(self, method, url, **kwargs): """This private method acting as proxy for all http methods. Args: method (str): The http method type. url (str): The URL to for the Request kwargs (dict): Keyword args to be passed to the requests call. retries (int): The retry count in case of HTTP errors. Except the codes in the list NO_RETRY_HTTP_CODES. Returns: Response (requests.Response): The response object. """ kwargs['verify'] = kwargs.get('verify', False) if 'timeout' not in kwargs: kwargs['timeout'] = self._timeout if 'data' not in kwargs: body = {} kwargs['data'] = json.dumps(body) content_dict = {'content-type': 'application/json'} kwargs.setdefault('headers', {}) kwargs['headers'].update(content_dict) func = getattr(self._session, method) response = None retries = kwargs.pop("retries", None) retry_interval = kwargs.pop("retry_interval", self._retry_interval) retry_count = retries if retries else self._retries for ii in range(retry_count): try: response = func(url, **kwargs) if self._internal_debug: self._logger.debug("%s method The request url sent: %s" % (method.upper(), response.request.url)) self._logger.debug('Response status: %d' % response.status_code) self._logger.debug('Response: %s' % json.dumps(response.json(), indent=4)) except (ConnectionError, ReadTimeout) as e: self._logger.warning("Request failed with error: %s" % e) if ii != retry_count - 1: time.sleep(retry_interval) continue finally: self._session.close() if response.ok: return response if response.status_code in [401, 403]: raise virt.VirtError( 'HTTP Auth Failed %s %s. \n res: response: %s' % (method, url, response)) elif response.status_code == 409: raise virt.VirtError( 'HTTP conflict with the current state of the ' 'target resource %s %s. \n res: %s' % (method, url, response)) elif response.status_code in self.NO_RETRY_HTTP_CODES: break if ii != retry_count - 1: time.sleep(retry_interval) if response is not None: msg = 'HTTP %s %s failed: ' % (method, url) if hasattr(response, "text") and response.text: msg = "\n".join([msg, response.text]).encode('utf-8') self._logger.error(msg) else: self._logger.error("Failed to make the HTTP request (%s, %s)" % (method, url))
def getHostGuestMapping(self): assert hasattr(self, 'session'), "Login was not called" hosts = self.session.xenapi.host.get_all() mapping = { 'hypervisors': [], } for host in hosts: record = self.session.xenapi.host.get_record(host) guests = [] for resident in self.session.xenapi.host.get_resident_VMs(host): vm = self.session.xenapi.VM.get_record(resident) uuid = vm['uuid'] if vm.get('is_control_domain', False): if uuid not in self.ignored_guests: self.ignored_guests.add(uuid) self.logger.debug("Control Domain %s is ignored", uuid) continue if vm.get('is_a_snapshot', False) or vm.get( 'is_a_template', False): if uuid not in self.ignored_guests: self.ignored_guests.add(uuid) self.logger.debug( "Guest %s is snapshot or template, ignoring", uuid) continue if vm['power_state'] == 'Running': state = virt.Guest.STATE_RUNNING elif vm['power_state'] == 'Suspended': state = virt.Guest.STATE_PAUSED elif vm['power_state'] == 'Paused': state = virt.Guest.STATE_PAUSED elif vm['power_state'] == 'Halted': state = virt.Guest.STATE_SHUTOFF else: state = virt.Guest.STATE_UNKNOWN guests.append(virt.Guest(uuid=uuid, virt=self, state=state)) facts = {} sockets = record.get('cpu_info', {}).get('socket_count') if sockets is not None: facts[virt.Hypervisor.CPU_SOCKET_FACT] = str(sockets) brand = record.get('software_version', {}).get('product_brand') if brand: facts[virt.Hypervisor.HYPERVISOR_TYPE_FACT] = brand version = record.get('software_version', {}).get('product_version') if version: facts[virt.Hypervisor.HYPERVISOR_VERSION_FACT] = version if self.config.hypervisor_id == 'uuid': uuid = record["uuid"] elif self.config.hypervisor_id == 'hwuuid': uuid = record["cpu_info"]['features'] elif self.config.hypervisor_id == 'hostname': uuid = record["hostname"] else: raise virt.VirtError( 'Invalid option %s for hypervisor_id, use one of: uuid, hwuuid, or hostname' % self.config.hypervisor_id) mapping['hypervisors'].append( virt.Hypervisor(hypervisorId=uuid, guestIds=guests, name=record["hostname"], facts=facts)) return mapping