def createProfiles(self, profile_info, nw_id=None): """ @summary: 创建指定网络的配置集 @param profile_info: XML文件 输入说明: 1)配置集名称只能由数字、字母、-、_组成 2)名称和网络id是必须的,网络名称无效 @param nw_id:指定网络id @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式) @note: 有两种使用情况 1)nw_id可以通过外部传参,此时xml文件中network id为变量 <vnic_profile> <name>abc#</name> <description>shelled</description> <network id="%s"/> <port_mirroring>false</port_mirroring> </vnic_profile> 2)nw_id为空,此时xml文件中需为network id赋值 <vnic_profile> <name>abc#</name> <description>shelled</description> <network id="字符串"/> <port_mirroring>false</port_mirroring> </vnic_profile> """ api_url = self.base_url method = "POST" if nw_id: r = HttpClient.sendRequest(method=method, api_url=api_url, data=(profile_info % nw_id)) else: r = HttpClient.sendRequest(method=method, api_url=api_url, data=profile_info) return {"status_code": r.status_code, "result": xmltodict.parse(r.text)}
def attachStorageDomainToDC(self, dc_name, sd_name=None, data=None): ''' @summary: 将存储域附加到数据中心 @param dc_name: 数据中心名称 @param sd_name: 存储域名称(可选参数,若不指定,则必须按规则在data中指定相应参数) @param data: 存储域的xml数据(可选参数,若提供了sd_name,则不需要提供该参数;若未提供sd_name,则需提供相应的xml字符串) @return: 字典,(1)status_code:请求返回状态码;(2)result:请求返回的内容。 ''' api_url = '%s/%s/storagedomains' % ( self.base_url, self.getDataCenterIdByName(dc_name)) method = 'POST' if sd_name: data = '''<storage_domain><name>%s</name></storage_domain>''' % sd_name r = HttpClient.sendRequest(method=method, api_url=api_url, data=data) elif data: r = HttpClient.sendRequest(method=method, api_url=api_url, data=data) else: raise Exception(u'至少需要提供storage_name或xml数据来完成分离操作。') return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def updateTemplateNic(self,temp_name,nic_name,update_data,proid=None): ''' @summary:编辑某个模板的网络接口 @param temp_name:模板名称 @param nic_name:网络接口名称 @param update_data:网络接口配置信息 ,xml @param proid: 配置集id 1)proid为空,即通过xml文件中定义vnic_profile_id值 <nic> <name>nic2</name> <vnic_profile id="6f1bff46-d0aa-49d2-9206-0bc9a4adf6aa"/> <interface>VirtIO</interface> <linked>false</linked> <plugged>false</plugged> </nic> 2)proid非空,即通过外部传参设置vnic_profile_id <nic> <name>nic2</name> <vnic_profile id="%s"/> <interface>VirtIO</interface> <linked>false</linked> <plugged>false</plugged> </nic> @return:字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容 ''' temp_id = self.getTemplateIdByName(temp_name) nic_id = self.getNicIdByName(temp_name, nic_name) api_url='%s/%s/nics/%s' % (self.base_url,temp_id,nic_id) method = 'PUT' if proid: r = HttpClient.sendRequest(method=method, api_url=api_url,data=(update_data %proid)) else: r = HttpClient.sendRequest(method=method, api_url=api_url,data=update_data) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def createTemplateNic(self,temp_name,nic_data,proid=None): ''' @summary:为模板创建网络接口 @param temp_name:模板名称 @param nic_data:网络接口配置信息,xml文件 @param proid:配置集id 参数传递有两种情况: 1)proid为空,即通过xml文件中定义vnic_profile_id值 <nic> <name>nic4</name> <vnic_profile id="6f1bff46-d0aa-49d2-9206-0bc9a4adf6aa"/> </nic> 2)proid非空,即通过外部传参设置vnic_profile_id <nic> <name>nic4</name> <vnic_profile id="%s"/> </nic> 网络接口输入说明: 1)接口名称是必须的,其余是可选的 2)配置集必须设置id 异常情况说明: 1)接口名称重复(409) 2)id设置错误(400) 3)对象不存在(404) @return:字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容 ''' temp_id = self.getTemplateIdByName(temp_name) api_url = '%s/%s/nics' % (self.base_url,temp_id) method = 'POST' if proid: r = HttpClient.sendRequest(method=method, api_url=api_url,data=(nic_data %proid)) else: r = HttpClient.sendRequest(method=method, api_url=api_url,data=nic_data ) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def createTemplate(self, temp_info,vm_id=None,disk_id=None,sd_id=None): ''' @summary: 创建模板 @param temp_info: XML形式的集群信息,调用接口时需要传递此xml数据 @note: 有三种使用情况 1)vm_id可以通过外部传参,此时xml文件中vm id为变量 <template> <name>template-osvtest1</name> <vm id="%s"/> </template> 2)nw_id为空,此时xml文件中需为vm id赋值 <template> <name>template-osvtest1</name> <vm id="4fbca0c3-e2b7-4cf0-a680-ea43d5a0e778"/> </template> 3)vm_id、disk_id、sd_id均通过外部传参 <template> <name>template-osvtest1</name> <vm id="%s"> <disks> <disk id="%s"> <storage_domains> <storage_domain id="%s"/> </storage_domains> </disk> </disks> </vm> </template> 创建模板的测试数据说明: 1)测试数据最小集: 模板名称和虚拟机id,且模板名称唯一且虚拟机状态为down,创建成功并返回代码202(异步) 3)虚拟机状态非down,创建失败并返回代码409 4)其他参数: <permissions> <clone>true</clone> ;是否复制虚拟机权限 </permissions> ************************************************* <vm id="91fab0d3-5ee0-4d81-9e4e-342327d0e362"> <disks> <disk id="7aa205f0-f292-415b-8bf4-91c009e573d1"> <storage_domains> <storage_domain id="ae2d5d54-38d5-41a2-835b-1c966c199855"/> </storage_domains> </disk> </disks> </vm> ;为虚拟机的某个磁盘指定存放的存储域 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式) ''' api_url = self.base_url method = 'POST' if not vm_id and not disk_id and not sd_id: r = HttpClient.sendRequest(method=method, api_url=api_url, data=temp_info) if vm_id and not disk_id and not sd_id: r = HttpClient.sendRequest(method=method, api_url=api_url, data=(temp_info %vm_id)) if vm_id and disk_id and sd_id: r=HttpClient.sendRequest(method=method, api_url=api_url, data=(temp_info %(vm_id,disk_id,sd_id))) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def main(): parseE = ParseExcel() parseE.loadWorkBook(file_path) sheetObj = parseE.getSheetByName(u"API") activeList = parseE.getColumn(sheetObj, API_active) for idx, cell in enumerate(activeList[1:], 2): if cell.value == "y": # 需要执行的接口所在行的行对象 rowObj = parseE.getRow(sheetObj, idx) apiName = rowObj[API_apiName - 1].value requestUrl = rowObj[API_requestUrl - 1].value requestMethod = rowObj[API_requestMethod - 1].value paramsType = rowObj[API_paramsType - 1].value apiTestCaseFileName = rowObj[API_apiTestCaseFileName - 1].value # 下一步读用例sheet表,准备执行测试用例 caseSheetObj = parseE.getSheetByName(apiTestCaseFileName) caseActiveObj = parseE.getColumn(caseSheetObj, CASE_active) for c_idx, col in enumerate(caseActiveObj[1:], 2): if col.value == "y": # 说明此case行需要执行 caseRowObj = parseE.getRow(caseSheetObj, c_idx) requestData = caseRowObj[CASE_requestData - 1].value relyData = caseRowObj[CASE_relyData - 1].value dataStore = caseRowObj[CASE_dataStore - 1].value if relyData: # 发送接口请求之前,先做依赖数据的处理 requestData = "%s" %GetKey.get(eval(requestData), eval(relyData)) # 拼接接口请求参数,发送接口请求 httpC = HttpClient() print requestMethod, requestUrl, paramsType, requestData response = httpC.request(requestMethod = requestMethod, requestUrl = requestUrl, paramsType = paramsType, requestData = requestData ) responseData = response.json() # 存储依赖数据 if dataStore: RelyDataStore.do(eval(dataStore),apiName, c_idx - 1, eval (requestData),responseData) # 比对结果 else: print "用例被忽略执行" else: print "接口被设置忽略执行"
def delStorageDomain(self, sd_name, xml_del_option, host_name=None): ''' @summary: 删除存储域(包括删除、销毁) @param sd_name: 存储域名称 @param host_name: 关联的主机名称(如果不提供,则必须在xml_del_option中指定) @param xml_del_option: XML格式的删除选项信息;如下: <storage_domain> <host> <name>node2</name> </host> <format>true</format> <destroy>true</destroy> <async>false</async> </storage_domain> @attention: (1) <host>字段是必须提供的;(2)<destroy>字段表示销毁操作,销毁时不需要另外指定<format>字段; (3)<format>字段表示是否格式化域,在进行删除操作时必须指定该字段;(4)<async>表示是否异步返回。 @attention: (1)Maintenance状态可以销毁;(2)游离状态可以删除。 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容。 ''' sd_id = self.getStorageDomainIdByName(sd_name) api_url = '%s/%s' % (self.base_url, sd_id) method = 'DELETE' if host_name: xml_del_option = xml_del_option % host_name r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_del_option) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def attachNicWithNetwork(self, host_name, nic_name, network_name): ''' @summary: 将虚拟化主机网卡与逻辑网络绑定(附加) @param host_name: 虚拟化主机名称 @param nic_name: 虚拟化主机网络接口名称 @param xml_network_info: network的XML信息(需提供network的name或id),如: <action> <network id="id"/> </action> @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容 @todo: 其功能只是将逻辑网络与物理网卡绑定,至于具体的配置需要调用其他接口? ''' host_id = self.getHostIdByName(host_name) nic_id = self.getHostNicIdByName(host_name, nic_name) api_url = '%s/%s/%s/%s/attach' % (self.base_url, host_id, self.sub_url, nic_id) method = 'POST' xml_network_info = ''' <action> <network> <name>%s</name> </network> </action> ''' % network_name r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_network_info) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def setupNetworks(self, host_name, xml_networks_info): ''' @summary: 对虚拟化主机上的多个网络接口进行配置 @param xml_networks_info: 虚拟化主机网络配置信息,如: <action> <host_nics> <host_nic id="41561e1c-c653-4b45-b9c9-126630e8e3b9"> <name>em1</name> <network id="00000000-0000-0000-0000-000000000009"/> <boot_protocol>dhcp</boot_protocol> </host_nic> <host_nic id="3c3f442f-948b-4cdc-9a48-89bb0593cfbd"> <name>em2</name> <network id="00000000-0000-0000-0000-000000000010"/> <ip address="10.35.1.247" netmask="255.255.254.0" gateway="10.35.1.254"/> <boot_protocol>static</boot_protocol> </host_nic> <checkConnectivity>true</checkConnectivity> <connectivityTimeout>60</connectivityTimeout> <force>false</force> </host_nics> </action> @attention: 没有指定的nic是否直接设置为空? @return: ''' host_id = self.getHostIdByName(host_name) api_url = '%s/%s/%s/setupnetworks' % (self.base_url, host_id, self.sub_url) method = 'POST' r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_networks_info) print r.text return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def iscsiLogin(self, host_name, xml_target_info): ''' @summary: ISCSI存储登陆(挂载) @param host_name: 主机名称 @param xml_target_info: 要登录的ISCSI存储信息,至少包括ip、target_name等信息,举例如下: <action> <iscsi> <address>mysan.exam ple.com </address> <target>iqn.2009-08.com .exam...</target> <username>jimmy</username> <password>s3kr37</password> </iscsi> </action> @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式,host挂载的target信息) ''' host_id = self.getHostIdByName(host_name) api_url = '%s/%s/iscsilogin' % (self.base_url, host_id) method = 'POST' r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_target_info) return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def detachNicFromNetwork(self, host_name, nic_name, network_name): ''' @summary: 解决虚拟化主机网卡与逻辑网络的绑定(分离) @param host_name: 虚拟化主机名称 @param nic_name: 虚拟化主机网络接口名称 @param network_name: 逻辑网络名称 @attention: 通过接口调用时,要求主机处于维护状态才能进行detach操作,与UI不一致,原因不明确 @return: ''' host_id = self.getHostIdByName(host_name) nic_id = self.getHostNicIdByName(host_name, nic_name) api_url = '%s/%s/%s/%s/detach' % (self.base_url, host_id, self.sub_url, nic_id) method = 'POST' xml_network_info = ''' <action> <network> <name>%s</name> </network> </action> ''' % network_name r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_network_info) print r.text return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def exportTemplateDisk(self, temp_name, disk_name, export_data): ''' @summary: 导出某个模板的某个磁盘 @param temp_name:模板名称 @param disk_name:磁盘名称 @param export_data:导出配置,xml文件 <action> <storage_domain> <name>Data2-ISCSI</name> </storage_domain> <async>false</async> </action> @return:字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容 @bug: 执行失败 ''' temp_id = self.getTemplateIdByName(temp_name) disk_id = self.getDiskIdByName(temp_name, disk_name) api_url = '%s/%s/disks/%s/export' % (self.base_url, temp_id, disk_id) method = 'POST' r = HttpClient.sendRequest(method=method, api_url=api_url, data=export_data) r.raise_for_status() return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def updateNetworkOfCluster(self, cluster_name, nw_name, data): ''' @summary: 更新附加到集群的网络信息 @param cluster_name: 集群名称 @param nw_name: 网络名称 @param data:更新的信息,xml文件 <network> <display>false</display> <usages> <usage>VM</usage> <usage>DISPLAY</usage> </usages> </network> @return: 字典,(1)status_code:请求返回状态码;(2)result:请求返回的内容。 ''' cluster_id = self.getClusterIdByName(cluster_name) dc_id = self.getClusterInfo( cluster_name)['result']['cluster']['data_center']['@id'] dc_name = DataCenterAPIs().getDataCenterNameById(dc_id) nw_id = NetworkAPIs().getNetworkIdByName(nw_name, dc_name) method = 'PUT' api_url = '%s/%s/networks/%s' % (self.base_url, cluster_id, nw_id) r = HttpClient.sendRequest(method=method, api_url=api_url, data=data) #r.raise_for_status() return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def deleteTemplateDisk(self, temp_name, disk_name, delete_data): ''' @summary: 删除某个模板的某个磁盘 @param temp_name:模板名称 @param disk_name:磁盘名称 @param delete_data:删除配置,xml <action> <storage_domain> <id>631cd328-55a5-4e70-9e5d-d86471de8ce7</id> </storage_domain> <async>false</async> <force>true</force> </action> @return:字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容 @bug: 执行失败 ''' temp_id = self.getTemplateIdByName(temp_name) disk_id = self.getDiskIdByName(temp_name, disk_name) api_url = '%s/%s/disks/%s' % (self.base_url, temp_id, disk_id) method = 'DELETE' r = HttpClient.sendRequest(method=method, api_url=api_url, data=delete_data) return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def importStorageDomain(self, xml_sd_info): ''' @summary: 导入被销毁的ISO/Export域 @attention: 该接口只能完成导入域操作,导入之后的存储域处于游离状态,需要调用其他接口将其附加到某个数据中心。 @param xml_sd_info: XML格式的待导入的存储域信息,如: <storage_domain> <type>iso</type> <storage> <type>nfs</type> <address>10.1.167.2</address> <path>/storage/iso</path> </storage> <host> <name>node2</name> </host> </storage_domain> @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容。 ''' api_url = self.base_url method = 'POST' r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_sd_info) return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def delStorageDomain(self, sd_name, xml_del_option, host_name=None): ''' @summary: 删除存储域(包括删除、销毁) @param sd_name: 存储域名称 @param host_name: 关联的主机名称(如果不提供,则必须在xml_del_option中指定) @param xml_del_option: XML格式的删除选项信息;如下: <storage_domain> <host> <name>node2</name> </host> <format>true</format> </storage_domain> @change: 对于data域,必须有host和format选项;其他类型数据域则只需有host; @attention: (1)Maintenance状态可以销毁;(2)游离状态可以删除。 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容。 ''' sd_id = self.getStorageDomainIdByName(sd_name) api_url = '%s/%s' % (self.base_url, sd_id) method = 'DELETE' if host_name: xml_del_option = xml_del_option % host_name r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_del_option) return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def createCluster(self, cluster_info): ''' @summary: 创建集群 @param cluster_info: XML形式的集群信息,调用接口时需要传递此xml数据 创建集群时集群名称、cpuid和数据中心为必需,其余为可选; 1)内存优化 <memory_policy> <overcommit percent="150"/> ;100,150,200,默认为200 <transparent_hugepages> <enabled>true</enabled> ;默认false </transparent_hugepages> </memory_policy> 2)cpu线程 <threads_as_cores>false</threads_as_cores> ;默认为false 3)弹性策略 <error_handling> <on_error>migrate_highly_available</on_error>;包括migrate,migrate_highly_available,do_not_migrate,默认为migrate </error_handling> 4)集群策略 <scheduling_policy> <policy>power_saving</policy> ;包括none(默认),power_saving,evenly_distributed三种,其中none无需输入,evenly_distributed需要输入high和duration两个参数 <thresholds low="20" high="80" duration="120"/> </scheduling_policy> 5)其他 <virt_service>true</virt_service> <gluster_service>false</gluster_service> <tunnel_migration>false</tunnel_migration> <trusted_service>false</trusted_service> ;若设置true,前提是配置服务,否则创建失败 <ballooning_enabled>false</ballooning_enabled> @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式) ''' api_url = self.base_url method = 'POST' r = HttpClient.sendRequest(method=method, api_url=api_url, data=cluster_info) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def updateHostNic(self, host_name, nic_name, xml_nic_info): ''' @summary: 更新虚拟化主机网络接口信息 @param host_name: 虚拟化主机名称 @param nic_name: 虚拟化主机网络接口名称 @param xml_nic_info: 要修改的网络接口信息,如: <host_nic> <boot_protocol>static</boot_protocol> <ip address="192.168.0.1" netmask="255.255.255.0" gateway="192.168.1.1"/> </host_nic> @return: @attention: 通过验证,目前暂未完成明白该接口实现的功能 ''' host_id = self.getHostIdByName(host_name) nic_id = self.getHostNicIdByName(host_name, nic_name) api_url = '%s/%s/%s/%s' % (self.base_url, host_id, self.sub_url, nic_id) method = 'PUT' r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_nic_info) return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def delStorageDomain(self, sd_name, xml_del_option, host_name=None): ''' @summary: 删除存储域(包括删除、销毁) @param sd_name: 存储域名称 @param host_name: 关联的主机名称(如果不提供,则必须在xml_del_option中指定) @param xml_del_option: XML格式的删除选项信息;如下: <storage_domain> <host> <name>node2</name> </host> <format>true</format> <destroy>true</destroy> <async>false</async> </storage_domain> @attention: (1) <host>字段是必须提供的;(2)<destroy>字段表示销毁操作,销毁时不需要另外指定<format>字段; (3)<format>字段表示是否格式化域,在进行删除操作时必须指定该字段;(4)<async>表示是否异步返回。 @attention: (1)Maintenance状态可以销毁;(2)游离状态可以删除。 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容。 ''' sd_id = self.getStorageDomainIdByName(sd_name) api_url = '%s/%s' % (self.base_url, sd_id) method = 'DELETE' if host_name: xml_del_option = xml_del_option % host_name r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_del_option) return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def importVmFromExportStorage(self, es_name, vm_name, xml_import_vm_info): ''' @summary: 从Export域导入虚拟机 @param es_name: Export域名称 @param vm_name: 待导入的VM名称 @param xml_import_vm_info: XML格式的导入虚拟机的设置信息,如下: (1) 进行最普通的导入虚拟机操作,只需要指定cluster、storage_domain即可,其中<async>设定是否异步,<collapse_snapshot>如果不指定,则缺省值为false(导入的虚拟机带有原来的快照): <action> <cluster> <name>Default</name> </cluster> <async>false</async> <storage_domain> <name>Data2-ISCSI</name> </storage_domain> (2) 其他几个参数的意义,举例如下: (a)<clone>:是否克隆,若克隆则必须设定<collapse_snapshot>为true; (b)<collapse_snapshot>:是否去掉快照: <action> <cluster> <name>Default</name> </cluster> <async>false</async> <storage_domain> <name>data</name> </storage_domain> <clone>true</clone> <vm> <name>new</name> <snapshots> <collapse_snapshots>true</collapse_snapshots> </snapshots> </vm> </action> (3) 导入VM时,若需要更改磁盘的分配策略和存储域,则需要在上述<vm>下增加如下字段: <disks> <disk id=""> <storage_domains> <storage_domain id=""/> <sparse></sparse> <format></format> </storage_domains> </disk> </disks> @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(操作结果等信息)。 @todo: xml_info中的第(3)未验证 ''' es_id = self.getStorageDomainIdByName(es_name) vm_id = self.getVmIdByNameFromExportStorage(es_name, vm_name) api_url = '%s/%s/%s/%s/import' % (self.base_url, es_id, self.sub_url_vms, vm_id) method = 'POST' r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_import_vm_info) return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def createDisk(self, disk_info,sd_id=None): ''' @summary: 创建磁盘 @param disk_info: XML形式的集群信息,调用接口时需要传递此xml数据 磁盘大小、存储域、interface、format参数是必需的(不能设置type字段) 异常情况说明: 1)存储域不存在:404 2)缺少参数或参数错误:400 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式) ''' api_url = self.base_url method = 'POST' if sd_id: r = HttpClient.sendRequest(method=method, api_url=api_url, data=(disk_info %sd_id)) else: r = HttpClient.sendRequest(method=method, api_url=api_url, data=disk_info) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getStorageConnectionInfo(self, sc_id): ''' @summary: 获得Storage Connection的信息 ''' api_url = '%s/%s' % (self.base_url, sc_id) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getHostsList(self): ''' @summary: 获取全部虚拟化主机列表 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式)。 ''' api_url = self.base_url method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getDataCentersList(self): ''' @summary: 获取全部数据中心列表 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式)。 ''' api_url = self.base_url method = "GET" r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def attachStorageDomainToDC(self, dc_name, sd_name=None, data=None): ''' @summary: 将存储域附加到数据中心 @param dc_name: 数据中心名称 @param sd_name: 存储域名称(可选参数,若不指定,则必须按规则在data中指定相应参数) @param data: 存储域的xml数据(可选参数,若提供了sd_name,则不需要提供该参数;若未提供sd_name,则需提供相应的xml字符串) @return: 字典,(1)status_code:请求返回状态码;(2)result:请求返回的内容。 ''' api_url = '%s/%s/storagedomains' % (self.base_url, self.getDataCenterIdByName(dc_name)) method = 'POST' if sd_name: data = '''<storage_domain><name>%s</name></storage_domain>''' % sd_name r = HttpClient.sendRequest(method=method, api_url=api_url, data=data) elif data: r = HttpClient.sendRequest(method=method, api_url=api_url, data=data) else: raise Exception(u'至少需要提供storage_name或xml数据来完成分离操作。') return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getProfilesList(self): """ @summary: 获取全部配置集列表 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式)。 """ api_url = self.base_url method = "GET" r = HttpClient.sendRequest(method=method, api_url=api_url) return {"status_code": r.status_code, "result": xmltodict.parse(r.text)}
def getStorageConnectionsList(self): ''' @summary: 获得全部storage connection的列表 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式)。 ''' api_url = self.base_url method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def updateStorageDomain(self, sd_name, xml_update_info): ''' @summary: 更新存储域信息 @param xml_update_info: XML格式的待更新存储域信息,通过该接口可以编辑NFS、ISCSC和FC类型存储域,如下: (1) 编辑NFS类型存储域(NFS类型存储域只能编辑名称、描述等字段): <storage_domain> <name>data-new</name> <description>aaa</description> </storage_domain> (2) 编辑ISCSI/FC类型存储域(编辑名称、描述) <storage_domain> <name>Data2-ISCSI</name> <description>bbb</description> <storage> <type>iscsi</type> <logical_unit id="35005907f57002df5"/> <override_luns>true</override_luns> </storage> </storage_domain> (3) 编辑ISCSI/FC类型存储域(添加LUN,前提是主机已经登陆该Target) <storage_domain> <host> <name>node2</name> </host> <storage> <type>iscsi</type> <logical_unit id="35005907f57002df5"/> <override_luns>true</override_luns> </storage> </storage_domain> (4) 编辑ISCSI/FC类型存储域(添加LUN,前提是主机未登录该Target) <storage_domain> <host> <name>node2</name> </host> <storage> <type>iscsi</type> <logical_unit id="35005907f57002df5"> <address>10.1.161.61</address> <port>3260</port> <target>iqn.2012-07.com.lenovoemc:ix12.px12-TI3111.wangyy</target> <serial>SLENOVO_LIFELINE-DISK</serial> <vendor_id>LENOVO</vendor_id> <product_id>LIFELINE-DISK</product_id> <lun_mapping>1</lun_mapping> </logical_unit> <override_luns>true</override_luns> </storage> </storage_domain> @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容。 ''' sd_id = self.getStorageDomainIdByName(sd_name) api_url = '%s/%s' % (self.base_url, sd_id) method = 'PUT' r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_update_info) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def createHost(self, xml_host_info): ''' @summary: 创建虚拟化主机 @param xml_host_info: XML形式的虚拟化主机信息,用于创建主机: @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式的新建主机信息) ''' api_url = self.base_url method = 'POST' r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_host_info) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def delDiskFromDataStorage(self, ds_name, disk_name=None, disk_id=None): ''' @summary: 从Data存储域中删除指定的磁盘 @todo: 问题同上 ''' ds_id = self.getStorageDomainIdByName(ds_name) api_url = '%s/%s/%s/%s' % (self.base_url, ds_id, self.sub_url, disk_id) method = 'DELETE' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getDisksList(self): ''' @summary: 获取全部磁盘列表 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式)。 ''' api_url = self.base_url method = "GET" r = HttpClient.sendRequest(method=method, api_url=api_url) r.raise_for_status() return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getStaticsofDisk(self,disk_id): ''' @summary: 获取磁盘的统计信息 @param disk_id: 磁盘id @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容。 ''' api_url = '%s/%s/statistics' % (self.base_url, disk_id) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getDCStorageDomainsList(self, dc_name): ''' @summary: 获取指定数据中心的存储域列表 @param dc_name: 数据中心名称 @return: 字典,(1)status_code:请求返回状态码;(2)result:请求返回的内容。 ''' api_url = '%s/%s/storagedomains' % (self.base_url, self.getDataCenterIdByName(dc_name)) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getHostStoragesList(self, host_name): ''' @summary: 获取主机可用的iSCSI或FC存储域 @param host_name: 虚拟化主机名称 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(主机可用的iSCSI或FC存储) ''' host_id = self.getHostIdByName(host_name) api_url = '%s/%s/%s' % (self.base_url, host_id, self.sub_url) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getTemplateNameById(self, temp_id): ''' @summary: 根据模板id获取名称 @param temp_id: 模板id @return: 模板名称 ''' api_url = '%s/%s' % (self.base_url,temp_id) method = "GET" r = HttpClient.sendRequest(method=method, api_url=api_url) if r.status_code==200: return xmltodict.parse(r.text)['template']['name']
def getDisksListFromDataStorage(self, ds_name): ''' @summary: 从指定的Data存储域中获取磁盘列表 @param ds_name: Data存储域名称 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(存储域中磁盘列表)。 ''' ds_id = self.getStorageDomainIdByName(ds_name) api_url = '%s/%s/%s' % (self.base_url, ds_id, self.sub_url) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getDataCenterNameById(self, dc_id): ''' @summary: 根据数据中心的id返回其名称 @param dc_id: 数据中心id @return: 数据中心名称 ''' api_url = '%s/%s' % (self.base_url, dc_id) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) if r.status_code == 200: return xmltodict.parse(r.text)['data_center']['name']
def getTemplateNameById(self, temp_id): ''' @summary: 根据模板id获取名称 @param temp_id: 模板id @return: 模板名称 ''' api_url = '%s/%s' % (self.base_url, temp_id) method = "GET" r = HttpClient.sendRequest(method=method, api_url=api_url) if r.status_code == 200: return xmltodict.parse(r.text)['template']['name']
def getClusterNameById(self, cluster_id): ''' @summary: 根据集群id获取名称 @param dc_id: 集群id @return: 集群名称 ''' api_url = '%s/%s' % (self.base_url, cluster_id) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) if r.status_code==200: return xmltodict.parse(r.text)['cluster']['name']
def getDiskInfo(self,disk_id): ''' @summary: 根据磁盘id,获取磁盘详细信息 @param disk_id: 磁盘id @return: 字典:(1)status_code:请求返回码;(2)result:dict形式的数据中心信息 ''' api_url = '%s/%s' % (self.base_url, disk_id) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getStorageConnectionInfo(self, sc_id): ''' @summary: 获得Storage Connection的信息 ''' api_url = '%s/%s' % (self.base_url, sc_id) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def delTemplate(self, temp_name,version_name=None): ''' @summary: 删除模板 @param temp_name: 模板名称 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容。 ''' temp_id = self.getTemplateIdByName(temp_name,version_name) api_url = '%s/%s' % (self.base_url, temp_id) method = 'DELETE' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getTemplateDiskList(self,temp_name): ''' @summary: 获得某个模板的磁盘列表 @param temp_name:模板名称 @return:字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容 ''' temp_id = self.getTemplateIdByName(temp_name) api_url = '%s/%s/disks' % (self.base_url, temp_id) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getDCClustersList(self, dc_name): ''' @summary: 获取数据中心的集群列表 @param dc_name: 数据中心名称 @return: 字典,(1)status_code:请求返回状态码;(2)result:请求返回的内容(数据中心的集群列表)。 ''' dc_id = self.getDataCenterIdByName(dc_name) api_url = '%s/%s/clusters' % (self.base_url, dc_id) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getHostStatistics(self, host_name): ''' @summary: 获取虚拟化主机统计信息(包括memory、swap、cpu) @param host_name: 虚拟化主机名称 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式,包括操作结果) ''' host_id = self.getHostIdByName(host_name) api_url = '%s/%s/statistics' % (self.base_url, host_id) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getTemplatesListFromExportStorage(self, es_name): ''' @summary: 获取Export域中的模板列表 @param es_name: Export域名称 @return: @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(模板列表)。 ''' es_id = self.getStorageDomainIdByName(es_name) api_url = '%s/%s/%s' % (self.base_url, es_id, self.sub_url_templates) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getFilesListFromISOStorage(self, is_name): ''' @summary: 从ISO域获取文件列表 @param is_name: ISO域名称 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(ISO域中文件列表)。 ''' is_id = self.getStorageDomainIdByName(is_name) api_url = '%s/%s/%s' % (self.base_url, is_id, self.sub_url) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def getDataCenterNameById(self, dc_id): ''' @summary: 根据数据中心的id返回其名称 @param dc_id: 数据中心id @return: 数据中心名称 ''' api_url = '%s/%s' % (self.base_url, dc_id) method = 'GET' r = HttpClient.sendRequest(method=method, api_url=api_url) if r.status_code==200: return xmltodict.parse(r.text)['data_center']['name']
def updateTemplateNic(self, temp_name, nic_name, update_data, proid=None): ''' @summary:编辑某个模板的网络接口 @param temp_name:模板名称 @param nic_name:网络接口名称 @param update_data:网络接口配置信息 ,xml @param proid: 配置集id 1)proid为空,即通过xml文件中定义vnic_profile_id值 <nic> <name>nic2</name> <vnic_profile id="6f1bff46-d0aa-49d2-9206-0bc9a4adf6aa"/> <interface>VirtIO</interface> <linked>false</linked> <plugged>false</plugged> </nic> 2)proid非空,即通过外部传参设置vnic_profile_id <nic> <name>nic2</name> <vnic_profile id="%s"/> <interface>VirtIO</interface> <linked>false</linked> <plugged>false</plugged> </nic> @return:字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容 ''' temp_id = self.getTemplateIdByName(temp_name) nic_id = self.getNicIdByName(temp_name, nic_name) api_url = '%s/%s/nics/%s' % (self.base_url, temp_id, nic_id) method = 'PUT' if proid: r = HttpClient.sendRequest(method=method, api_url=api_url, data=(update_data % proid)) else: r = HttpClient.sendRequest(method=method, api_url=api_url, data=update_data) return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def createTemplateNic(self, temp_name, nic_data, proid=None): ''' @summary:为模板创建网络接口 @param temp_name:模板名称 @param nic_data:网络接口配置信息,xml文件 @param proid:配置集id 参数传递有两种情况: 1)proid为空,即通过xml文件中定义vnic_profile_id值 <nic> <name>nic4</name> <vnic_profile id="6f1bff46-d0aa-49d2-9206-0bc9a4adf6aa"/> </nic> 2)proid非空,即通过外部传参设置vnic_profile_id <nic> <name>nic4</name> <vnic_profile id="%s"/> </nic> 网络接口输入说明: 1)接口名称是必须的,其余是可选的 2)配置集必须设置id 异常情况说明: 1)接口名称重复(409) 2)id设置错误(400) 3)对象不存在(404) @return:字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容 ''' temp_id = self.getTemplateIdByName(temp_name) api_url = '%s/%s/nics' % (self.base_url, temp_id) method = 'POST' if proid: r = HttpClient.sendRequest(method=method, api_url=api_url, data=(nic_data % proid)) else: r = HttpClient.sendRequest(method=method, api_url=api_url, data=nic_data) return { 'status_code': r.status_code, 'result': xmltodict.parse(r.text) }
def commitNetConfig(self, host_name, xml_action='<action/>'): ''' @summary: 提交保存虚拟化主机网络配置 @param host_name: 虚拟化主机名称 @param xml_action: XML格式的action,向服务器发送POST请求时需要传输的数据,取值只能是'<action/>' @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式,包括操作结果) ''' host_id = self.getHostIdByName(host_name) api_url = '%s/%s/commitnetconfig' % (self.base_url, host_id) method = 'POST' r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_action) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}
def iscsiDiscoverByHost(self, host_name, xml_iscsi_info): ''' @summary: ISCSI存储发现 @param host_name: 主机名称 @param xml_iscsi_info: iSCSI目标地址、端口等信息 @return: 字典,包括:(1)status_code:http请求返回码;(2)result:请求返回的内容(dict格式,包括target列表) ''' host_id = self.getHostIdByName(host_name) api_url = '%s/%s/iscsidiscover' % (self.base_url, host_id) method = 'POST' r = HttpClient.sendRequest(method=method, api_url=api_url, data=xml_iscsi_info) return {'status_code':r.status_code, 'result':xmltodict.parse(r.text)}