Package: cloudtower-sdk
Cloudtower Python SDKPython 环境下的 Cloudtower SDK，适用于 2.7 与 3.4 以上版本。源码地址下载地址通用指南安装whlpipinstallcloudtower_sdk-2.14.2-py2.py3-none-any.whltar.gztarxvzfcloudtower-sdk-2.14.2.tar.gzcdcloudtower-sdk-2.14.2
pythonsetup.pyinstallgit 源码安装git clone https://github.com/smartxworks/cloudtower-python-sdk.git
cd cloudtower-python-sdk
python setup.py installgit pip 安装pipinstallgit+https://github.com/smartxworks/cloudtower-python-sdk.gitpypi 安装pipinstallcloudtower-sdk使用创建实例创建ApiClient实例fromcloudtower.configurationimportConfigurationfromcloudtowerimportApiClient# 配置 operation-api endpointconfiguration=Configuration(host="http://192.168.96.133/v2/api")client=ApiClient(configuration)如果需要使用 https，可以安装证书，或者忽略证书验证configuration=Configuration(host="https://192.168.96.133/v2/api")configuration.verify_ssl=Falseclient=ApiClient(configuration)创建对应的 API 实例根据不同用途的操作创建相关的 API 实例，例如虚拟机相关操作需要创建一个VmApi。fromcloudtower.api.vm_apiimportVmApivm_api=VmApi(client)鉴权可以通过 utils 中封装的登陆方法来鉴权ApiClientfromcloudtower.utilsimportwait_tasks,loginconf=Configuration(host="http://api-test.dev-cloudtower.smartx.com/v2/api")api_client=ApiClient(conf)login(api_client,"your_username","your_password")# 默认使用 LOCAL 作为 usersource也可以直接将 token 应用置configuration的api_key中fromcloudtower.api.user_apiimportUserApifromcloudtower.modelsimportUserSource# 通过 UserApi 中的 login 方法来获得 token。user_api=UserApi(client)login_res=user_api.login({"username":"your_username","password":"your_password","source":UserSource.LOCAL})# 将 token 配置在 configuration.api_key["Authorization"] 中，# 这样所有使用当前 client 的 api 都会获得鉴权的 token 信息。configuration.api_key["Authorization"]=login_res.data.token发送请求获取资源vms=vm_api.get_vms({"where":{"id":"vm_id"},"first":1,})更新资源资源更新会产生相关的异步任务，当异步任务结束时，代表资源操作完成且数据已更新。start_res=vm_api.start_vm({"where":{"id":"stopped_vm_id"},})可以通过提供的工具方法同步等待异步任务结束fromcloudtower.utilsimportwait_taskstry:wait_tasks([res.task_idforresinstart_res],api_client)exceptApiExceptionase:# 处理错误else:# task完成后的回调方法参数说明参数名类型是否必须说明idslist[str]是需查询的 task 的 id 列表api_clientApiClient是查询所使用的 ApiClient 实例intervalint否轮询的间隔时间，默认为 5stimeoutint否超时时间，默认为 300sexit_on_errorbool否是否在单个 Task 出错时立即退出，否则则会等待全部 Task 都完成后再退出，默认为 False。错误说明错误码说明408超时500异步任务内部错误自定义 headercloudtower api 支持通过设置 header 中的 content-language 来设置返回信息的语言, 可选值en-US,zh-CN。默认为en-US。通过ApiClient的set_default_header方法可以通过ApiClient的set_default_header方法设置默认的 header 信息。api_client.set_default_header("content_language","en-US")alert_api=AlertApi(api_client)# 此时得到的 alerts 中的 message, solution, cause, impact 将被转换为英文描述。alerts=alert_api.get_alerts({"where":{"cluster":{"id":"cluster_id"}},"first":100},)通过设置请求的关键字参数也可以通过设置请求的关键字参数content_language来设置返回信息的语言。fromcloudtower.api.user_apiimportAlertApialert_api=AlertApi(api_client)# 此时得到的 alerts 中的 message, solution, cause, impact 将被转换为中文描述。alerts=alert_api.get_alerts({"where":{"cluster":{"id":"cluster_id"}},"first":100},content_language="zh-CN")其他发送异步请求上述请求的发送都是同步的请求，会堵塞当前进程。如果需要使用异步请求，请在对应请求的关键字参数中加上async_req=True。
通过返回结果ApplyResult.get()来获取对应的结果。vms=vm_api.get_vms({"where":{"id":"vm_id"}},async_req=True)print(vms.get()[0].name)使用完成后销毁 ApiClient 实例client.close()操作示例获取虚拟机获取所有虚拟机fromcloudtowerimportApiClient,Configuration,VmApiconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)vms=vm_api.get_vms({})分页获取虚拟机fromcloudtowerimportApiClient,Configuration,VmApiconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)vms_from_51_to_100=vm_api.get_vms({"first":50,"skip":50,})获取所有已开机虚拟机fromcloudtowerimportApiClient,Configuration,VmApi,VmStatusconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)running_vms=vm_api.get_vms({"where":{"status":VmStatus.RUNNING}},)获取名称或描述中包含特定字符串的虚拟机fromcloudtowerimportApiClient,Configuration,VmApiconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)vms_name_contains=vm_api.get_vms({"where":{"name_contains":"string"}},)获取所有 vcpu > n 的虚拟机fromcloudtowerimportApiClient,Configuration,VmApiconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)vms_has_4_more_vcpu=vm_api.get_vms({"where":{"vcpu_gt":4}},)从模版创建虚拟机仅指定 idfromcloudtower.apiimportVmApi,ContentLibraryVmTemplateApi,ClusterApifromcloudtower.utilsimportlogin,wait_tasksfromcloudtower.configurationimportConfigurationfromcloudtowerimportApiClientimportosconfiguration=Configuration(host=os.getenv("CLOUDTOWER_ENDPOINT"))client=ApiClient(configuration)login(client,os.getenv("CLOUDTOWER_USERNAME"),os.getenv("CLOUDTOWER_PASSWORD"))defcreate_vm_from_template(template_name,cluster_name,vm_name):"""通过内容库模板创建一台虚拟机，内容通过内容库模板设置:param template_name: 指定所需使用的内容库模板名称:param cluster_name: 指定虚拟机被部署的集群的集群名称:param vm_name: 虚拟机名称:return: 被创建的虚拟机"""vm_api=VmApi(client)cluster_api=ClusterApi(client)template_api=ContentLibraryVmTemplateApi(client)cluster=cluster_api.get_clusters({"where":{"name":cluster_name}})iflen(cluster)==0:raiseException("cluster not found")template=template_api.get_content_library_vm_templates({"where":{"name":template_name}})iflen(template)==0:raiseException("template not found")with_task_vms=vm_api.create_vm_from_content_library_template([{"template_id":template[0].id,"cluster_id":cluster[0].id,"name":vm_name,"is_full_copy":False}])tasks=[with_task_vm.task_idforwith_task_vminwith_task_vms]vm_ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,client)returnvm_api.get_vms({"where":{"id_in":vm_ids}})[0]配置与模板不同的虚拟盘参数fromcloudtower.apiimportVmApi,ContentLibraryVmTemplateApi,ClusterApifromcloudtower.utilsimportlogin,wait_tasksfromcloudtower.configurationimportConfigurationfromcloudtower.modelsimportBus,VmVolumeElfStoragePolicyTypefromcloudtowerimportApiClientimportosconfiguration=Configuration(host=os.getenv("CLOUDTOWER_ENDPOINT"))client=ApiClient(configuration)login(client,os.getenv("CLOUDTOWER_USERNAME"),os.getenv("CLOUDTOWER_PASSWORD"))defcreate_vm_from_template_modify_disk(template_name,cluster_name,vm_name,disk_operate):"""通过内容库模板创建一台虚拟机，配置虚拟机的磁盘:param template_name: 模板名称:param cluster_name: 集群名称:param vm_name: 虚拟机名称:param disk_operate: 磁盘操作，使用详见 create_vm_from_template_modify_disk_example 方法:return: 被创建的虚拟机"""vm_api=VmApi(client)cluster_api=ClusterApi(client)template_api=ContentLibraryVmTemplateApi(client)cluster=cluster_api.get_clusters({"where":{"name":cluster_name}})iflen(cluster)==0:raiseException("cluster not found")template=template_api.get_content_library_vm_templates({"where":{"name":template_name}})iflen(template)==0:raiseException("template not found")with_task_vms=vm_api.create_vm_from_content_library_template([{"template_id":template[0].id,"cluster_id":cluster[0].id,"name":vm_name,"is_full_copy":False,"disk_operate":disk_operate}])tasks=[with_task_vm.task_idforwith_task_vminwith_task_vms]vm_ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,client)returnvm_api.get_vms({"where":{"id_in":vm_ids}})[0]defcreate_vm_from_template_modify_disk_example():"""通过模板创建虚拟机时，如果希望对原有的磁盘进行任何修改，可以通过 disk_operate 参数进行配置disk_operate 参数的类型是 VmDiskOperate，它是一个字典，包含以下字段：- remove_disks 由于删除指定index的磁盘- modify_disks 修改现有磁盘的配置，目前仅支持修改总线，如果有其他修改可以通过，删除原有盘- new_disks 新增磁盘，类型是 VmDiskParams，它是一个字典，包含以下字段：- mount_cd_roms 挂载 cd-rom- mount_disks 挂载已有磁盘- mount_new_create_disks 挂载新磁盘"""disk_operate={"remove_disks":{"disk_index":[0]# 用于删除指定 index 的磁盘，index 从 0 开始计算，这里既是删除第一块磁盘},"new_disks":{"mount_cd_roms":[{"boot":2,# 启动顺序"content_library_image_id":""# 指定挂载内容库镜像的 id}],"mount_disks":[{"boot":3,# 启动顺序"bus":Bus.VIRTIO,# 总线类型"vm_volume_id":"cljm6x2g1405g0958tp3zkhvh"# 被挂载虚拟卷的 id}],"mount_new_create_disks":[{"boot":4,"bus":Bus.VIRTIO,"vm_volume":{"name":"test",# 新建虚拟卷的名称"size":10*1024*1024*1024,# 新建虚拟卷的大小，单位是字节"elf_storage_policy":VmVolumeElfStoragePolicyType._2_THIN_PROVISION# 存储策略}}]}}create_vm_from_template_modify_disk("template-name","cluster-name","vm-name",disk_operate)配置与模版不同的网卡参数fromcloudtower.apiimportVmApi,ContentLibraryVmTemplateApi,ClusterApifromcloudtower.utilsimportlogin,wait_tasksfromcloudtower.configurationimportConfigurationfromcloudtower.modelsimportBus,VmNicModelfromcloudtowerimportApiClientimportosconfiguration=Configuration(host=os.getenv("CLOUDTOWER_ENDPOINT"))client=ApiClient(configuration)login(client,os.getenv("CLOUDTOWER_USERNAME"),os.getenv("CLOUDTOWER_PASSWORD"))defcreate_vm_from_template_modified_nic(template_name,cluster_name,vm_name,nic_params):"""通过内容库模板创建一台虚拟机，配置虚拟机的网卡:param template_name: 模板名称:param cluster_name: 集群名称:param vm_name: 虚拟机名称:param nic_params: 磁盘操作，使用详见 create_vm_from_template_modified_nic_example 方法:return: 被创建的虚拟机"""vm_api=VmApi(client)cluster_api=ClusterApi(client)template_api=ContentLibraryVmTemplateApi(client)cluster=cluster_api.get_clusters({"where":{"name":cluster_name}})iflen(cluster)==0:raiseException("cluster not found")template=template_api.get_content_library_vm_templates({"where":{"name":template_name}})iflen(template)==0:raiseException("template not found")with_task_vms=vm_api.create_vm_from_content_library_template([{"template_id":template[0].id,"cluster_id":cluster[0].id,"name":vm_name,"is_full_copy":False,"vm_nics":nic_params}])tasks=[with_task_vm.task_idforwith_task_vminwith_task_vms]vm_ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,client)returnvm_api.get_vms({"where":{"id_in":vm_ids}})[0]defcreate_vm_from_template_modified_nic_example():"""通过内容库模板创建虚拟机时，如果不传递 vm_nics 参数，会默认使用模板的网卡配置，如果需要修改网卡配置，可以传递 vm_nics 参数，vm_nics 参数是一个列表，列表中的每个元素都是一个字典：- connect_vlan_id 网卡对应虚拟机网络的 id，并非虚拟机网络的 vlan_id- enabled 是否启用网卡- model 网卡类型，可以使用 VmNicModel 类的属性，如 VmNicModel.VIRTIO创建虚拟机时并不支持修改网卡的 ip，mac，gateway，subnet mask，如果需要配置ip，子网，网关，可以通过 cloudinit 来实现，需要模板支持 cloudinit"""nic_params=[{"connect_vlan_id":"vlan_id","enabled":True,"model":VmNicModel.VIRTIO}]create_vm_from_template_modified_nic("template_name","cluster_name","vm_name",nic_params)创建空白虚拟机简单创建fromcloudtowerimport(ApiClient,Configuration,VmApi,VmStatus,VmFirmware,Bus)fromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.create_vm([{"cluster_id":"cluster_id","name":"vm_name","ha":True,"cpu_cores":4,"cpu_sockets":4,"memory":4*1024*1024*1024,"vcpu":16,"status":VmStatus.STOPPED,"firmware":VmFirmware.BIOS,"vm_nics":[{"connect_vlan_id":"vlan_id",}],"vm_disks":{"mount_cd_roms":[{"boot":0,"index":0}],}}])[0]wait_tasks([with_task_vm.task_id],api_client)created_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})创建时配置虚拟盘CD-ROM 加载 ISOfromcloudtowerimport(ApiClient,Configuration,VmApi,VmStatus,VmFirmware,Bus)fromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.create_vm([{"cluster_id":"cluster_id","name":"vm_name","ha":True,"cpu_cores":4,"cpu_sockets":4,"memory":4*1024*1024*1024,"vcpu":16,"status":VmStatus.STOPPED,"firmware":VmFirmware.BIOS,"vm_nics":[{"connect_vlan_id":"vlan_id",}],"vm_disks":{"mount_cd_roms":[{"index":0,"boot":0,"elf_image_id":"elf_image_id"}],}}])[0]wait_tasks([with_task_vm.task_id],api_client)created_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})挂载虚拟卷为虚拟盘fromcloudtowerimport(ApiClient,Configuration,VmApi,VmStatus,VmFirmware,Bus)fromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.create_vm([{"cluster_id":"cluster_id","name":"vm_name","ha":True,"cpu_cores":4,"cpu_sockets":4,"memory":4*1024*1024*1024,"vcpu":16,"status":VmStatus.STOPPED,"firmware":VmFirmware.BIOS,"vm_nics":[{"connect_vlan_id":"vlan_id",}],"vm_disks":{"mount_disks":[{"index":0,"boot":0,"bus":Bus.VIRTIO,"vm_volume_id":"vm_volume_id","index":0,}],}}])[0]wait_tasks([with_task_vm.task_id],api_client)created_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})新增并挂载虚拟盘fromcloudtowerimport(ApiClient,Configuration,VmApi,VmStatus,VmFirmware,Bus,VmVolumeElfStoragePolicyType)fromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.create_vm([{"cluster_id":"cluster_id","name":"vm_name","ha":True,"cpu_cores":4,"cpu_sockets":4,"memory":4*1024*1024*1024,"vcpu":16,"status":VmStatus.STOPPED,"firmware":VmFirmware.BIOS,"vm_nics":[{"connect_vlan_id":"vlan_id",}],"vm_disks":{"mount_new_create_disks":[{"boot":0,"bus":Bus.VIRTIO,"vm_volume":{"elf_storage_policy":VmVolumeElfStoragePolicyType._2_THIN_PROVISION,"size":10*1024*1024*1024,"name":"new_volume_name"}}],}}])[0]wait_tasks([with_task_vm.task_id],api_client)created_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})创建时配置虚拟网卡fromcloudtowerimport(ApiClient,Configuration,VmApi,VmStatus,VmFirmware,Bus,VmNicModel,VmVolumeElfStoragePolicyType)fromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.create_vm([{"cluster_id":"cluster_id","name":"vm_name1","ha":True,"cpu_cores":4,"cpu_sockets":4,"memory":4*1024*1024*1024,"vcpu":16,"status":VmStatus.STOPPED,"firmware":VmFirmware.BIOS,"vm_nics":[{"connect_vlan_id":"vlan_id","mirror":True,"model":VmNicModel.VIRTIO}],"vm_disks":{"mount_cd_roms":[{"index":0,"boot":0,}],}}])[0]wait_tasks([with_task_vm.task_id],api_client)created_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})编辑虚拟机编辑基本信息fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.update_vm({"where":{"id":"vm_id"},"data":{"name":"new_name","description":"new_description","ha":False,"vcpu":2*2,"cpu_cores":2,"cpu_sockets":2,"memory":1*1024*1024*1024,}})[0]wait_tasks([with_task_vm.task_id],api_client)updated_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})CD-ROM 编辑添加 CD-ROMfromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.add_vm_cd_rom({"where":{"id":"vm_id"},"data":{"vm_cd_roms":[{"elf_image_id":"elf_image_id","boot":0,"index":0}]}})[0]wait_tasks([with_task_vm.task_id],api_client)updated_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})删除 CD-ROMfromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.remove_vm_cd_rom({"where":{"id":"vm_id"},"data":{"cd_rom_ids":["cd_rom_id_1","cd_rom_id_2"]}})[0]wait_tasks([with_task_vm.task_id],api_client)updated_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})虚拟卷操作添加新虚拟卷fromcloudtowerimportApiClient,Configuration,Bus,VmVolumeElfStoragePolicyType,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.add_vm_disk({"where":{"id":"vm_id"},"data":{"vm_disks":{"mount_new_create_disks":[{"vm_volume":{"elf_storage_policy":VmVolumeElfStoragePolicyType._2_THIN_PROVISION,"size":5*1024*1024*1024,"name":"new_volume_name"},"boot":1,"bus":Bus.VIRTIO,}]}}})[0]wait_tasks([with_task_vm.task_id],api_client)updated_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})挂载已存在虚拟卷为虚拟盘fromcloudtowerimportApiClient,Configuration,Bus,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.add_vm_disk({"where":{"id":"vm_id"},"data":{"vm_disks":{"mount_disks":[{"index":0,"vm_volume_id":"vm_volume_id","boot":1,"bus":Bus.VIRTIO,}]}}})[0]wait_tasks([with_task_vm.task_id],api_client)updated_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})卸载虚拟盘fromcloudtowerimportApiClient,Configuration,VmVolumeElfStoragePolicyType,Bus,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.remove_vm_disk({"where":{"id":"vm_id"},"data":{"disk_ids":["vm_disk_id_1","vm_disk_id_2"]}})[0]wait_tasks([with_task_vm.task_id],api_client)updated_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})网卡操作添加网卡fromcloudtowerimportApiClient,Configuration,VmApi,VmNicModelfromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.add_vm_nic({"where":{"id":"vm_id"},"data":{"vm_nics":[{"connect_vlan_id":"vlan_id","enabled":False,"model":VmNicModel.VIRTIO,},{"connect_vlan_id":"vlan_id_2","enabled":True,"mirror":True,"model":VmNicModel.VIRTIO,}]}})[0]wait_tasks([with_task_vm.task_id],api_client)updated_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})编辑网卡fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.update_vm_nic({"where":{"id":"vm_id"},"data":{"nic_index":0,"enabled":False,"mirror":False,"connect_vlan_id":"vlan_id"}})[0]wait_tasks([with_task_vm.task_id],api_client)updated_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})移除网卡fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.remove_vm_nic({"where":{"id":"vm_id"},"data":{"nic_index":[0,1]}})[0]wait_tasks([with_task_vm.task_id],api_client)updated_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})虚拟机迁移迁移至指定主机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.mig_rate_vm({"where":{"id":"vm_id"},"data":{"host_id":"host_id"}})[0]wait_tasks([with_task_vm.task_id],api_client)自动调度到合适的主机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.mig_rate_vm({"where":{"id":"vm_id"}})[0]wait_tasks([with_task_vm.task_id],api_client)虚拟机电源操作虚拟机开机:指定虚拟机开机，自动调度到合适的虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.start_vm({"where":{"id":"vm_id"}})[0]wait_tasks([with_task_vm.task_id],api_client)opened_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})[0]批量虚拟机开机，自动调度到合适的虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vms=vm_api.start_vm({"where":{"id_in":["vm_id_1","vm_id_2"]}})tasks=[with_task_vm.task_idforwith_task_vminwith_task_vms]ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,api_client)opened_vms=vm_api.get_vms({"where":{"id_in":ids}})开机至指定主机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.start_vm({"where":{"id":"vm_id"},"data":{"host_id":"host_id"}})[0]wait_tasks([with_task_vm.task_id],api_client)opened_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})[0]虚拟机关机指定虚拟机关机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.shut_down_vm({"where":{"id":"vm_id"}})[0]wait_tasks([with_task_vm.task_id],api_client)closed_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})[0]批量虚拟机关机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vms=vm_api.shut_down_vm({"where":{"id_in":["vm_id_1","vm_id_2"]}})tasks=[with_task_vm.task_idforwith_task_vminwith_task_vms]ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,api_client)closed_vms=vm_api.get_vms({"where":{"id_in":ids}})强制关机指定虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vm=vm_api.force_shut_down_vm({"where":{"id":"vm_id"}})[0]wait_tasks([with_task_vm.task_id],api_client)closed_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})[0]强制关机批量虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksconf=Configuration(host="http://192.168.96.133/v2/api")conf.api_key["Authorization"]="token"api_client=ApiClient(conf)vm_api=VmApi(api_client)with_task_vms=vm_api.force_shut_down_vm({"where":{"id_in":["vm_id_1","vm_id_2"]}})tasks=[with_task_vm.task_idforwith_task_vminwith_task_vms]ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,api_client)closed_vms=vm_api.get_vms({"where":{"id_in":ids}})虚拟机重启重启指定虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))vm_api=VmApi(api_client)with_task_vm=vm_api.restart_vm({"where":{"id":"vm_id"}})[0]wait_tasks([with_task_vm.task_id],api_client)restarted_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})[0]重启批量虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))vm_api=VmApi(api_client)with_task_vms=vm_api.restart_vm({"where":{"id_in":["vm_id_1","vm_id_2"]}})tasks=[with_task_vm.task_idforwith_task_vminwith_task_vms]ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,api_client)restarted_vms=vm_api.get_vms({"where":{"id_in":ids}})强制重启指定虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))vm_api=VmApi(api_client)with_task_vm=vm_api.force_restart_vm({"where":{"id":"vm_id"}})[0]wait_tasks([with_task_vm.task_id],api_client)restarted_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})[0]强制重启批量虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))vm_api=VmApi(api_client)with_task_vms=vm_api.force_restart_vm({"where":{"id_in":["vm_id_1","vm_id_2"]}})tasks=[with_task_vm.task_idforwith_task_vminwith_task_vms]ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,api_client)restarted_vms=vm_api.get_vms({"where":{"id_in":ids}})虚拟机暂停暂停指定虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))vm_api=VmApi(api_client)with_task_vm=vm_api.suspend_vm({"where":{"id":"vm_id"}})[0]wait_tasks([with_task_vm.task_id],api_client)suspended_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})[0]暂停批量虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))vm_api=VmApi(api_client)with_task_vms=vm_api.suspend_vm({"where":{"id_in":["vm_id_1","vm_id_2"]}})tasks=[with_task_vm.task_idforwith_task_vminwith_task_vms]ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,api_client)suspended_vms=vm_api.get_vms({"where":{"id_in":ids}})虚拟机恢复恢复指定虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))vm_api=VmApi(api_client)with_task_vm=vm_api.resume_vm({"where":{"id":"vm_id"}})[0]wait_tasks([with_task_vm.task_id],api_client)resumed_vm=vm_api.get_vms({"where":{"id":with_task_vm.data.id}})[0]恢复批量虚拟机fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))vm_api=VmApi(api_client)with_task_vms=vm_api.resume_vm({"where":{"id_in":["vm_id_1","vm_id_2"]}})tasks=[with_task_vm.task_idforwith_task_vminwith_task_vms]ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,api_client)resumed_vms=vm_api.get_vms({"where":{"id_in":ids}})删除虚拟机回收站移入回收站fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))vm_api=VmApi(api_client)with_task_delete_vms=vm_api.move_vm_to_recycle_bin({"where":{"id_in":["vm_id_1","vm_id_2"]}})tasks=[with_task_delete_vm.task_idforwith_task_delete_vminwith_task_delete_vms]ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,api_client)vm_moved_to_recycle_bin=vm_api.get_vms({"where":{"id_in":ids}})从回收站恢复fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))vm_api=VmApi(api_client)with_task_delete_vms=vm_api.recover_vm_from_recycle_bin({"where":{"id_in":["vm_id_1","vm_id_2"]}})tasks=[with_task_delete_vm.task_idforwith_task_delete_vminwith_task_delete_vms]ids=[with_task_vm.data.idforwith_task_vminwith_task_vms]wait_tasks(tasks,api_client)recovered_vms=vm_api.get_vms({"where":{"id_in":ids}})永久删除fromcloudtowerimportApiClient,Configuration,VmApifromcloudtower.utilsimportwait_tasksapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))vm_api=VmApi(api_client)with_task_delete_vms=vm_api.delete_vm({"where":{"id_in":["vm_id_1","vm_id_2"]}})tasks=[with_task_delete_vm.task_idforwith_task_delete_vminwith_task_delete_vms]wait_tasks(tasks,api_client)场景示例虚拟机备份fromcloudtowerimportApiClientfromcloudtower.api.vm_apiimportVmApifromcloudtower.api.vm_snapshot_apiimportVmSnapshotApifromcloudtower.api.iscsi_lun_snapshot_apiimportIscsiLunSnapshotApifromcloudtower.modelsimport(ConsistentType,VmToolsStatus)fromcloudtower.utilsimportwait_tasksdefcreate_vm_snapshot(api_client:ApiClient,target_vm_name:str,target_snapshot_name:str,consistent_type:ConsistentType):vm_api=VmApi(api_client)vm_snapshot_api=VmSnapshotApi(api_client)iscsi_lun_snapshot_api=IscsiLunSnapshotApi(api_client)# 1. 获取所需备份的虚拟机的信息，这里我们需要vm的id来构建创建snapshot的参数vm=vm_api.get_vms({"where":{"name":target_vm_name},"first":1})# vm 已安装并启动 VMTools 时，consistent_type 可以使用 FILE_SYSTEM_CONSISTENT 代表文件系统一致性快照ifvm.vm_tools_status!=VmToolsStatus.RUNNINGandconsistent_type==ConsistentType.FILE_SYSTEM_CONSISTENT:consistent_type=ConsistentType.CRASH_CONSISTENT# 2. 创建虚拟机快照snapshots_with_task=vm_snapshot_api.create_vm_snapshot({"data":[{"vm_id":vm.id,"name":target_snapshot_name,"consistent_type":consistent_type}]})# 3. 等待Task完成wait_tasks([snapshots_with_task[0].task_id],api_client)# 4. 根据返回的id查询生成的虚拟机快照snapshot=vm_snapshot_api.get_vm_snapshots({"where":{"id":snapshots_with_task.data.id}})[0]# 5. 根据返回的snapshot中的vm_disks包含了快照的虚拟盘信息# type 为 DISK 表示对应一个卷，其中会包含一个 snapshot_local_id 则表示该虚拟卷对应的lun快照的 local_id# type 为 CD-ROM则代表为被挂载的CD-ROM，不会产生lun快照lun_snapshot_ids=[]fordiskinsnapshot.vm_disks:ifdisk.type=="DISK":lun_snapshot_ids.append(disk.snapshot_local_id)lun_snapshots=iscsi_lun_snapshot_api.get_iscsi_lun_snapshots({"where":{"name_in":lun_snapshot_ids}})return{"vm_snapshot":snapshot,"lun_snapshots":lun_snapshots}Dashboard 构建定义工具方法fromfunctoolsimportreducefromdatetimeimportdatetime,timedeltafromcloudtowerimportApiClientfromcloudtower.configurationimportConfigurationfromcloudtower.modelsimportSeverityEnum,ClusterType,Hypervisor,DiskType,DiskUsageStatus,DiskHealthStatusfromcloudtower.apiimportVmApi,ClusterApi,AlertApi,HostApi,DiskApi,ClusterSettingsApi,GlobalSettingsApiapi_client=ApiClient(Configuration(host="http://192.168.96.133/v2/api"))byte_units=["B","KiB","MiB","GiB","TiB","PiB"]hz_units=["Hz","KHz","MHz","GHz","THz"]defformat_unit(base:int,units,step=1024):ifnotlen(units):raiseException("no unit provided")ifbase<=0:return"0"+units[0]forunitinunits:ifbase<step:return"{:.2f}{}".format(base,unit)base/=stepreturn"{:.2f}{}".format(base,units[-1])构建报警信息defbuild_alerts(api_client:ApiClient,cluster_ids):alert_api=AlertApi(api_client)alerts=alert_api.get_alerts({"where":{"ended":False,"cluster":{"id_in":cluster_ids},}})critial_alerts=[alertforalertinalertsifalert.severity==SeverityEnum.CRITICAL]notice_alerts=[alertforalertinalertsifalert.severity==SeverityEnum.NOTICE]info_alerts=[alertforalertinalertsifalert.severity==SeverityEnum.INFO]return{"critical":critial_alerts,"notice":notice_alerts,"info":info_alerts}构建硬盘信息这里以机械硬盘为例defbuild_hdd_info(api_client:ApiClient,cluster_ids):disk_api=DiskApi(api_client)disks=disk_api.get_disks({"where":{"host":{"cluster":{"id_in":cluster_ids}}}})hdd={"healthy":0,"warning":0,"error":0,"total":0,}fordiskindisks:ifdisk.type==DiskType.HDD:ifdisk.health_statusin[DiskHealthStatus.UNHEALTHY,DiskHealthStatus.SUBHEALTHY,DiskHealthStatus.SMART_FAILED]:hdd['error']+=1elifdisk.usage_statusin[DiskUsageStatus.UNMOUNTED,DiskUsageStatus.PARTIAL_MOUNTED]:hdd['warning']+=1else:hdd['healthy']+=1hdd['total']+=1returnhdd构建性能指标获取指定集群的 CPU 核数，CPU 频率总数，CPU 使用率，内存总量，内存使用量，存储资源总量，存储资源已使用量，存储资源失效量与存储资源可用量。defbuild_metrics(api_client:ApiClient,clusters,cluster_ids):result={}host_api=HostApi(api_client)hosts=host_api.get_hosts({"where":{"cluster":{"id_in":cluster_ids}}})cpu={"total_cpu_cores":0,"total_cpu_hz":0,"used_cpu_hz":0,}memory={"total_memory":0,"used_memory":0,}storage={"total":0,"used":0,"invalid":0,"available":0}forhostinhosts:cluster=next(clusterforclusterinclustersifcluster.id==host.cluster.id)ifcluster.hypervisor==Hypervisor.ELF:memory['total_memory']+=0ifhost.total_memory_bytesisNoneelsehost.total_memory_bytesmemory['used_memory']+=(0ifhost.running_pause_vm_memory_bytesisNoneelsehost.running_pause_vm_memory_bytes)+\(0ifhost.os_memory_bytesisNoneelsehost.os_memory_bytes)forclusterinclusters:ifcluster.type==ClusterType.SMTX_OS:cpu["total_cpu_cores"]+=0ifcluster.total_cpu_coresisNoneelsecluster.total_cpu_corescpu["total_cpu_hz"]+=0ifcluster.total_cpu_hzisNoneelsecluster.total_cpu_hzcpu["used_cpu_hz"]+=0ifcluster.used_cpu_hzisNoneelsecluster.used_cpu_hzifcluster.hypervisor==Hypervisor.VMWARE:memory["total_memory"]+=0ifcluster.total_memory_bytesisNoneelsecluster.total_memory_bytesmemory["used_memory"]+=0ifcluster.used_memory_bytesisNoneelsecluster.used_memory_bytesstorage["total"]+=0ifcluster.total_data_capacityisNoneelsecluster.total_data_capacitystorage["used"]+=0ifcluster.used_data_spaceisNoneelsecluster.used_data_spacestorage["invalid"]+=0ifcluster.failure_data_spaceisNoneelsecluster.failure_data_spaceiflen([clusterforclusterinclustersifcluster.type!=ClusterType.SMTX_ZBS])>1:cpu["cpu_usage"]="{:.2f}%".format(cpu["used_cpu_hz"]/cpu["total_cpu_hz"])cpu["total_cpu_hz"]=format_unit(cpu["total_cpu_hz"],hz_units,1000)cpu["used_cpu_hz"]=format_unit(cpu["used_cpu_hz"],hz_units,1000)result['cpu']=cpumemory["memory_usage"]="{:.2f}%".format(memory["used_memory"]/memory["total_memory"])memory["total_memory"]=format_unit(memory["total_memory"],byte_units)memory["used_memory"]=format_unit(memory["used_memory"],byte_units)result["memory"]=memorystorage["available"]=format_unit(storage["total"]-storage["used"]-storage["invalid"],byte_units)storage["total"]=format_unit(storage["total"],byte_units)storage["used"]=format_unit(storage["used"],byte_units)storage["invalid"]=format_unit(storage["invalid"],byte_units)result["storage"]=storagereturnresult构建 Dashboarddefbuild_dashboard(api_client:ApiClient,datacenter_id:str=None,cluster_id:str=None):result={}cluster_api=ClusterApi(api_client)clusters=cluster_api.get_clusters({"where":{"id":cluster_id}ifcluster_idisnotNoneelse{"datacenters_some":{"id":datacenter_id}}ifdatacenter_idisnotNoneelseNone})cluster_ids=[cluster.idforclusterinclusters]result["alerts"]=build_alerts(api_client,cluster_ids)result["hdd"]=build_hdd_info(api_client,cluster_ids)metric=build_metrics(api_client,clusters,cluster_ids)if"cpu"inmetric:result["cpu"]=metric["cpu"]if"memory"inmetric:result["memory"]=metric["memory"]if"storage"inmetric:result["storage"]=metric["storage"]returnresult