def describeVdcMyCloud(self, vdc): res = self.connection.request(get_url_path(vdc.id)) elms = res.object.findall(fixxpath( res.object, "ResourceEntities/ResourceEntity") ) vapps = [ (i.get('name'), i.get('href')) for i in elms if i.get('type') == 'application/vnd.vmware.vcloud.vApp+xml' and i.get('name') ] nodes = [] for vapp_name, vapp_href in vapps: try: res = self.connection.request( get_url_path(vapp_href), headers={'Content-Type': 'application/vnd.vmware.vcloud.vApp+xml'} ) nodes.append(self._to_node(res.object)) except Exception: self.logger.error(traceback.format_exc()) raise return nodes
def _del_vm_disk(self, vm, disk_id): #ディスクIDが指定されていない場合は何もしない if disk_id is None: return rasd_ns = '{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData}' # virtualHardwareSection/disks 取得 res = self.requestLoop('%s/virtualHardwareSection/disks' % get_url_path(vm["id"])) for item in res.object.findall(fixxpath(res.object, 'Item')): if item.find('%sHostResource' % rasd_ns) is not None: name = item.find('%sInstanceID' % rasd_ns).text if str(name) == str(disk_id): res.object.remove(item) self.logger.info(ET.tostring(res.object)) res = self.requestLoop( '%s/virtualHardwareSection/disks' % get_url_path(vm["id"]), data=ET.tostring(res.object), method='PUT', headers={'Content-Type': 'application/vnd.vmware.vcloud.rasditemslist+xml'} ) self._wait_for_task_completion(res.object.get('href'))
def _perform_power_operation_vm(self, node, vm, operation): res = self.requestLoop( '%s/power/action/%s' % (get_url_path(vm["id"]), operation), method='POST') self._wait_for_task_completion(res.object.get('href'), self.connectionCls.timeout) res = self.requestLoop(get_url_path(node.id)) return self._to_node(res.object)
def _wait_for_task_completion(self, task_href): #VCloud_1_5_NodeDriver._wait_for_task_completion(self, task_href, timeout = self.timeout) start_time = time.time() res = self.connection.request(get_url_path(task_href)) status = res.object.get('status') retry = 0 while status != 'success': if status == 'error': if retry > self.RETRY_MAX: # Get error reason from the response body error_elem = res.object.find(fixxpath(res.object, 'Error')) error_msg = "Unknown error" if error_elem is not None: error_msg = error_elem.get('message') raise Exception("Error status returned by task %s.: %s" % (task_href, error_msg)) else: retry = retry +1 if status == 'canceled': raise Exception("Canceled status returned by task %s." % task_href) if (time.time() - start_time >= self.timeout): raise Exception("Timeout (%s sec) while waiting for task %s." % (self.timeout, task_href)) time.sleep(5) res = self.connection.request(get_url_path(task_href)) status = res.object.get('status')
def _wait_for_task_completion(self, task_href, timeout=6000): import time from sys import stdout start_time = time.time() res = self.connection.request(get_url_path(task_href)) status = res.object.get('status') while status != 'success': if status == 'error': # Get error reason from the response body error_elem = res.object.find(fixxpath(res.object, 'Error')) error_msg = "Unknown error" if error_elem is not None: error_msg = error_elem.get('message') raise Exception("Error status returned by task %s.: %s" % (task_href, error_msg)) if status == 'canceled': raise Exception("Canceled status returned by task %s." % task_href) if (time.time() - start_time >= timeout): raise Exception("Timeout (%s sec) while waiting for task %s." % (timeout, task_href)) stdout.write('.') stdout.flush() time.sleep(5) res = self.connection.request(get_url_path(task_href)) status = res.object.get('status')
def _wait_for_task_completion(self, task_href, timeout=6000): import time from sys import stdout start_time = time.time() res = self.connection.request(get_url_path(task_href)) status = res.object.get('status') while status != 'success': if status == 'error': # Get error reason from the response body error_elem = res.object.find(fixxpath(res.object, 'Error')) error_msg = "Unknown error" if error_elem is not None: error_msg = error_elem.get('message') raise Exception("Error status returned by task %s.: %s" % (task_href, error_msg)) if status == 'canceled': raise Exception("Canceled status returned by task %s." % task_href) if time.time() - start_time >= timeout: raise Exception("Timeout (%s sec) while waiting for task %s." % (timeout, task_href)) stdout.write('.') stdout.flush() time.sleep(5) res = self.connection.request(get_url_path(task_href)) status = res.object.get('status')
def ex_deploy_vm(self, node, vm): deploy_xml = ET.Element('DeployVAppParams', {'powerOn': 'true', 'xmlns': 'http://www.vmware.com/vcloud/v1.5'}) res = self.requestLoop('%s/action/deploy' % get_url_path(vm["id"]), data=ET.tostring(deploy_xml), method='POST', headers={'Content-Type': 'application/vnd.vmware.vcloud.deployVAppParams+xml'} ) self._wait_for_task_completion(res.object.get('href')) res = self.requestLoop(get_url_path(node.id)) return self._to_node(res.object)
def describeVdcNetwork(self): vdc = self.getUseVdc() res = self.requestLoop(get_url_path(vdc.id)).object #VDCネットワーク vdcnetworks = [] for vdcnetworkconfig in res.findall(fixxpath(res, 'AvailableNetworks/Network')): name = vdcnetworkconfig.get('name') href = vdcnetworkconfig.get('href') res2 = self.requestLoop(get_url_path(href)).object vdcnetworks.append(self._makePccVAppNetwork(res2, name, href)) return vdcnetworks
def describeStorageProfile(self, vdc, sp_Name): res = self.requestLoop(get_url_path(vdc.id)).object for storageprofile in res.findall(fixxpath(res, 'VdcStorageProfiles/VdcStorageProfile')): if storageprofile.get('name') == sp_Name: return PccStorageProfile(storageprofile.get('name'), storageprofile.get('href')) return None
def post_config(self, gateway, timeout=DEFAULT_TASK_COMPLETION_TIMEOUT, cancel_after_timeout=False): '''Despatch updated Edge Gateway configuration :param gateway: new configuration to posted to the Edge Gateway ''' update_uri = self._get_edgegateway_update_uri(gateway) gateway_service_config_xml = ET.tostring( gateway.configuration.edge_gateway_service_configuration._elem) res = self.driver.connection.request(get_url_path(update_uri), method='POST', data=gateway_service_config_xml) if res.status < 200 or res.status >= 300: log.error('Error sending Edge Gateway configuration to %r: %r:', update_uri, ET.tostring(res.object)) response = et_utils.obj_from_elem_walker(res.object) self.driver._wait_for_task_completion(response.href, timeout=timeout) if cancel_after_timeout: log.info('Task cancelled following timeout') return response
def _change_vm_ipmode(self, vapp_or_vm_id, vm_ipmode): if vm_ipmode[0] is 'MANUAL': vm_ipmode, ip_address, network = vm_ipmode else: vm_ipmode, network = vm_ipmode vms = self._get_vm_elements(vapp_or_vm_id) for vm in vms: res = self.connection.request( '%s/networkConnectionSection' % get_url_path(vm.get('href'))) net_conns = res.object.findall( fixxpath(res.object, 'NetworkConnection')) for c in net_conns: # TODO: What if we want a network other than 'default' # Can we pull the network out of the vm/vapp? c.attrib['network'] = network c.find(fixxpath(c, 'IpAddressAllocationMode')).text = vm_ipmode c.find(fixxpath(c, 'IsConnected')).text = "true" if vm_ipmode == 'MANUAL': # This is quite hacky. We probably don't want the same IP on # each interface etc. # We might not have an IP node ip = c.find(fixxpath(c, 'IpAddress')) if ip is None: ip = ET.SubElement(c, fixxpath(c, 'IpAddress')) # The order of the IpAddress element matter. Has to be after this :( conIdx = c.find(fixxpath(c, 'NetworkConnectionIndex')) c.remove(ip) c.insert(c.index(conIdx)+1, ip) ip.text = ip_address headers = { 'Content-Type': 'application/vnd.vmware.vcloud.networkConnectionSection+xml' } res = self.connection.request( '%s/networkConnectionSection' % get_url_path(vm.get('href')), data=ET.tostring(res.object), method='PUT', headers=headers ) self._wait_for_task_completion(res.object.get('href'))
def _add_vm_disk(self, vm, vm_disk): #ディスクが存在しない場合は何もしない if vm_disk is None: return rasd_ns = '{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData}' # virtualHardwareSection/disks 取得 res = self.requestLoop('%s/virtualHardwareSection/disks' % get_url_path(vm["id"])) existing_ids = [] new_disk = None #既存ディスク情報のチェック for item in res.object.findall(fixxpath(res.object, 'Item')): for elem in item: if elem.tag == '%sInstanceID' % rasd_ns: existing_ids.append(int(elem.text)) if item.find('%sHostResource' % rasd_ns) is not None: new_disk = item #追加するディスク情報 new_disk = copy.deepcopy(new_disk) for elem in new_disk: #不要なパラメータを消す if elem.tag in ['%sAddressOnParent' % rasd_ns, '%sParent' % rasd_ns]: new_disk.remove(elem) disk_id = max(existing_ids) + 1 diskName = 'Hard Disk ' + str(disk_id) #new_disk.find('%sAddressOnParent' % rasd_ns).text = str(vm_disk["UNIT_NO"]) new_disk.find('%sInstanceID' % rasd_ns).text = str(disk_id) new_disk.find('%sElementName' % rasd_ns).text = diskName new_disk.find('%sHostResource' % rasd_ns).set(fixxpath(new_disk, 'capacity'), str(int(vm_disk["SIZE"]) * 1024)) res.object.append(new_disk) self.logger.info(ET.tostring(res.object)) res = self.requestLoop( '%s/virtualHardwareSection/disks' % get_url_path(vm["id"]), data=ET.tostring(res.object), method='PUT', headers={'Content-Type': 'application/vnd.vmware.vcloud.rasditemslist+xml'} ) self._wait_for_task_completion(res.object.get('href')) return disk_id
def getVdcStorageprofiles(self, vdc): res = self.requestLoop(get_url_path(vdc.id)).object #ストレージプロファイル storageprofiles = {} for storageprofile in res.findall(fixxpath(res, 'VdcStorageProfiles/VdcStorageProfile')): storageprofiles[storageprofile.get('name')] = PccStorageProfile(storageprofile.get('name'), storageprofile.get('href')) return storageprofiles
def ex_edit_vm(self, vm_harf, **kwargs): storageProfile = kwargs.get('storageProfile') res = self.requestLoop(get_url_path(vm_harf)) #ストレージの変更 if storageProfile is not None: res.object.find(fixxpath(res.object, "StorageProfile")).set('name', storageProfile.name) res.object.find(fixxpath(res.object, "StorageProfile")).set('href', storageProfile.href) self.logger.info(ET.tostring(res.object)) ress = self.requestLoop(get_url_path(vm_harf), data=ET.tostring(res.object), method='PUT', headers={'Content-Type': 'application/vnd.vmware.vcloud.vm+xml'} ) self._wait_for_task_completion(ress.object.get('href'))
def _get_elems(self, uri, xpath): '''Get XML elements from a given URI and XPath search over returned XML content ''' res = self.driver.connection.request(get_url_path(uri)) if xpath.startswith('{'): return res.object.findall(xpath) else: return res.object.findall(fixxpath(res.object, xpath))
def _change_vm_ipmode(self, vapp_or_vm_id, vm_ipmode): from IPython import embed embed() if type(vm_ipmode) is not tuple or vm_ipmode[0] is not 'MANUAL': return super(ImprovedVCloud_5_1_Driver, self)._change_vm_ipmode(vapp_or_vm_id, vm_ipmode) vm_ipmode, ip_address = vm_ipmode vms = self._get_vm_elements(vapp_or_vm_id) for vm in vms: res = self.connection.request('%s/networkConnectionSection' % get_url_path(vm.get('href'))) net_conns = res.object.findall( fixxpath(res.object, 'NetworkConnection')) for c in net_conns: # TODO: What if we want a network other than 'default' # c.attrib['network'] = 'Default' c.find(fixxpath(c, 'IpAddressAllocationMode')).text = vm_ipmode c.find(fixxpath(c, 'IsConnected')).text = "true" # This is quite hacky. We probably don't want the same IP on # each interface etc. # We might not have an IP node ip = c.find(fixxpath(c, 'IpAddress')) if ip is None: ip = ET.SubElement(c, fixxpath(c, 'IpAddress')) # The order of the IpAddress element matter. Has to be after this :( conIdx = c.find(fixxpath(c, 'NetworkConnectionIndex')) c.remove(ip) c.insert(c.index(conIdx) + 1, ip) ip.text = ip_address headers = { 'Content-Type': 'application/vnd.vmware.vcloud.networkConnectionSection+xml' } res = self.connection.request('%s/networkConnectionSection' % get_url_path(vm.get('href')), data=ET.tostring(res.object), method='PUT', headers=headers) self._wait_for_task_completion(res.object.get('href'))
def _get_edgegateway_from_uri(self, edgegateway_rec_uri): res = self.driver.connection.request(get_url_path(edgegateway_rec_uri)) _log_etree_elem(res.object) gateway = et_utils.obj_from_elem_walker(res.object) # Augment gateway object with explicit reference to ElementTree elem #gateway._elem = res.object return gateway
def _get_edgegateway_rec(self, edgegateway_uri): res = self.driver.connection.request(get_url_path(edgegateway_uri)) _log_etree_elem(res.object) edgegateway_rec_elems = res.object.findall(fixxpath(res.object, "EdgeGatewayRecord")) edgegateway_recs = [] for edgegateway_rec_elem in edgegateway_rec_elems: edgegateway_recs.append(self._et_class_walker(edgegateway_rec_elem)) return edgegateway_recs
def describeVappNetwork(self, vapp): vappnetworks = [] res = self.requestLoop(get_url_path(vapp.id)).object for networkconfig in res.findall(fixxpath(res, 'NetworkConfigSection/NetworkConfig')): name = networkconfig.get('networkName') #未設定用NW「'none'」は無視する if name == 'none': continue vappnetworks.append(self._makePccVAppNetwork(networkconfig, name)) return vappnetworks
def _add_vapp_nw(self, vapp, newNetwork): rasd_ns = "{http://www.vmware.com/vcloud/v1.5}" res = self.requestLoop('%s/networkConfigSection' % get_url_path(vapp.id)) network_config = ET.SubElement(res.object, "%sNetworkConfig" % rasd_ns) # Don't set a custom vApp VM network name network_config.set('networkName', newNetwork["NETWORK_NAME"]) configuration = ET.SubElement(network_config, '%sConfiguration' % rasd_ns) for vdcnet in self.networks: if vdcnet.get('name') == newNetwork["NETWORK_NAME"]: ET.SubElement(configuration, '%sParentNetwork' % rasd_ns, {'href': vdcnet.get('href')}) ET.SubElement(configuration, '%sFenceMode' % rasd_ns).text = "bridged" self.logger.info(ET.tostring(res.object)) #変更を行った場合のみ通信する res = self.requestLoop( '%s/networkConfigSection' % get_url_path(vapp.id), data=ET.tostring(res.object), method='PUT', headers={'Content-Type': 'application/vnd.vmware.vcloud.networkConfigSection+xml'} ) self._wait_for_task_completion(res.object.get('href'))
def _get_edgegateway_from_uri(self, edgegateway_rec_uri): res = self.driver.connection.request(get_url_path(edgegateway_rec_uri)) _log_etree_elem(res.object) gateway_iface_elems = res.object.findall(fixxpath(res.object, "GatewayInterface")) gateway = self._et_class_walker(res.object) # Augment gateway object with explicit reference to ElementTree elem gateway._elem = res.object return gateway
def get_edgegateway_recs(self, edgegateway_uri): '''Retrieve Edge Gateway Records from the Edge Gateway query URI ''' res = self.driver.connection.request(get_url_path(edgegateway_uri)) _log_etree_elem(res.object) edgegateway_rec_elems = res.object.findall( fixxpath(res.object, self.__class__.EDGE_GATEWAY_REC_TAG)) edgegateway_recs = [et_utils.obj_from_elem_walker(edgegateway_rec_elem) for edgegateway_rec_elem in edgegateway_rec_elems] return edgegateway_recs
def createMyCloud(self, vdc, name, defNetworks): try: vappName = vdc.name + "-" + name vapp_href = self._compose_MyCloud(vdc, vappName, defNetworks) res = self.requestLoop(get_url_path(vapp_href)) node = self._to_node(res.object) #実行ログ self.logger.info(None, "IPROCESS-100701", [name]) return node except Exception: self.logger.error(traceback.format_exc()) raise IaasException("EPROCESS-000801", [name,])
def _get_elems(self, uri, xpath): '''Helper method - Get XML elements from a given URI and XPath search over returned XML content :var uri: URI to retrieve XML response from :var xpath: XPath to search returned XML content with. It can contain the {} delimited namespace or else the default vCloud one is assumed :return: ElementTree Element contain search results ''' res = self.driver.connection.request(get_url_path(uri)) _log_etree_elem(res.object) if xpath.startswith(et_utils.NS_START_DELIM): return res.object.findall(xpath) else: return res.object.findall(fixxpath(res.object, xpath))
def ex_undeploy_vm(self, node, vm): undeploy_xml = ET.Element('UndeployVAppParams', {'xmlns': 'http://www.vmware.com/vcloud/v1.5'}) undeploy_power_action_xml = ET.SubElement(undeploy_xml, 'UndeployPowerAction') undeploy_power_action_xml.text = 'shutdown' try: res = self.requestLoop('%s/action/undeploy' % get_url_path(vm["id"]), data=ET.tostring(undeploy_xml), method='POST', headers={'Content-Type': 'application/vnd.vmware.vcloud.undeployVAppParams+xml'} ) self._wait_for_task_completion(res.object.get('href')) except Exception: undeploy_power_action_xml.text = 'powerOff' res = self.requestLoop( '%s/action/undeploy' % get_url_path(vm["id"]), data=ET.tostring(undeploy_xml), method='POST', headers={'Content-Type': 'application/vnd.vmware.vcloud.undeployVAppParams+xml'} ) self._wait_for_task_completion(res.object.get('href')) res = self.requestLoop(get_url_path(node.id)) return self._to_node(res.object)
def describeVolumes(self, vm): rasd_ns = '{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData}' # Get virtualHardwareSection/disks section res = self.requestLoop('%s/virtualHardwareSection/disks' % get_url_path(vm["id"])) disks =[] for item in res.object.findall(fixxpath(res.object, 'Item')): if item.find('%sHostResource' % rasd_ns) is not None: name = item.find('%sInstanceID' % rasd_ns).text size = item.find('%sHostResource' % rasd_ns).get(fixxpath(item, 'capacity')) busType = item.find('%sHostResource' % rasd_ns).get(fixxpath(item, 'busType')) unitNo = item.find('%sAddressOnParent' % rasd_ns).text disks.append(PccVMDisk(name, size, busType, unitNo)) return disks
def _del_vm(self, node, vm_harf): del_xml = RecomposeVAppXML_DEL_VM( name=node.name, vm_harf=vm_harf ) self.logger.info(del_xml.tostring()) # Instantiate VM and get identifier. res = self.requestLoop( '%s/action/recomposeVApp ' % get_url_path(node.id), data=del_xml.tostring(), method='POST', headers={'Content-Type': 'application/vnd.vmware.vcloud.recomposeVAppParams+xml'} ) task_href = res.object.get('href') self._wait_for_task_completion(task_href)
def createMyCloudByTemplate(self, vdc, name, template_name, defNetworks): #vAppテンプレートを名称から特定 template = None templates = self.list_images() for temp in templates: if template_name == temp.name: template = temp.id try: vappName = vdc + "-" + name vapp_href = self._instantiate_MyCloud(vdc, vappName, template, defNetworks) res = self.requestLoop(get_url_path(vapp_href)) node = self._to_node(res.object) return node except Exception: self.logger.error(traceback.format_exc()) raise IaasException("EPROCESS-000801", [name,])
def describeVMNetwork(self, vm): res = self.requestLoop('%s/networkConnectionSection' % get_url_path(vm["id"])) print ET.tostring(res.object) primary_index = res.object.find(fixxpath(res.object, 'PrimaryNetworkConnectionIndex')).text net_conns = res.object.findall(fixxpath(res.object, 'NetworkConnection')) retNetworks = [] for item in net_conns: name = item.get('network') ipMode = item.find(fixxpath(item, 'IpAddressAllocationMode')).text ipAddress = item.find(fixxpath(item, 'IpAddress')).text index = item.find(fixxpath(item, 'NetworkConnectionIndex')).text isPrimary = False if index == primary_index: isPrimary = True retNetworks.append(PccVMNetwork(name, ipAddress, ipMode, index, isPrimary)) return retNetworks
def _compose_MyCloud(self, vdc, name, useNetworks): compose_xml = ComposeVAppXML( name=name, useNetworks=useNetworks ) self.logger.info(compose_xml.tostring()) # Instantiate VM and get identifier. res = self.requestLoop( '%s/action/composeVApp' % get_url_path(vdc.id), data=compose_xml.tostring(), method='POST', headers={'Content-Type': 'application/vnd.vmware.vcloud.composeVAppParams+xml'} ) vapp_href = res.object.get('href') task_href = res.object.find(fixxpath(res.object, "Tasks/Task")).get('href') self._wait_for_task_completion(task_href) return vapp_href
def _instantiate_MyCloud(self, name, template, networks): instantiate_xml = InstantiateVAppXML( name=name, template=template, networks=networks ) # Instantiate VM and get identifier. res = self.requestLoop( '%s/action/instantiateVAppTemplate' % get_url_path(self.vdc.id), data=instantiate_xml.tostring(), method='POST', headers={'Content-Type': 'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml'} ) vapp_href = res.object.get('href') task_href = res.object.find(fixxpath(res.object, "Tasks/Task")).get('href') self._wait_for_task_completion(task_href) return vapp_href
def createInstances(self, node, **kwargs): image = kwargs['image'] vm_name = kwargs['vm_name'] vm_storage = kwargs['vm_storage'] vm_networks = kwargs.get('vm_networks') vm_fqdn = kwargs.get('fqdn') try: self._add_vm(node, image, vm_name, vm_fqdn, vm_storage, vm_networks) res = self.requestLoop(get_url_path(node.id)) #実行ログ self.logger.info(None, "IPROCESS-100703", [vm_name,]) return self._to_node(res.object) except Exception: self.logger.error(traceback.format_exc()) raise IaasException("EPROCESS-000803", [vm_name,])
def ex_set_metadata_entries(self, node, **kwargs): from xml.etree import ElementTree as ET """ :param node: node :type node: :class:`Node` :param key: metadata key to be set :type key: ``str`` :param value: metadata value to be set :type value: ``str`` :rtype: ``None`` """ metadata_elem = ET.Element( 'Metadata', { 'xmlns': "http://www.vmware.com/vcloud/v1.5", 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance" }) for key, value in kwargs.items(): entry = ET.SubElement(metadata_elem, 'MetadataEntry') key_elem = ET.SubElement(entry, 'Key') key_elem.text = key value_elem = ET.SubElement(entry, 'Value') value_elem.text = value # send it back to the server res = self.connection.request( '%s/metadata' % get_url_path(node.id), data=ET.tostring(metadata_elem), headers={ 'Content-Type': 'application/vnd.vmware.vcloud.metadata+xml' }, method='POST') self._wait_for_task_completion(res.object.get('href'))