Skip to content

Commit b3c996a

Browse files
committed
chore: misc update
- bump version to v2.9.1 - update create vm from template to content library api
1 parent 0ef3262 commit b3c996a

File tree

10 files changed

+602
-128
lines changed

10 files changed

+602
-128
lines changed

README.md

Lines changed: 234 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -320,144 +320,260 @@ vms_has_4_more_vcpu = vm_api.get_vms(
320320
#### 仅指定 id
321321

322322
```python
323-
from cloudtower import ApiClient, Configuration, VmApi
324-
from cloudtower.utils import wait_tasks
323+
from cloudtower.api import VmApi, ContentLibraryVmTemplateApi, ClusterApi
324+
from cloudtower.utils import login, wait_tasks
325+
from cloudtower.configuration import Configuration
326+
from cloudtower import ApiClient
327+
import os
325328

326-
conf = Configuration(host="http://192.168.96.133/v2/api")
327-
conf.api_key["Authorization"] = "token"
328-
api_client = ApiClient(conf)
329-
vm_api = VmApi(api_client)
330329

331-
with_task_vms = vm_api.create_vm_from_template([
332-
{
333-
"template_id": "template_id",
334-
"cluster_id": "cluster_id",
335-
"name": "vm_name",
336-
"is_full_copy": False
337-
}
338-
])
339-
tasks = [with_task_vm.task_id for with_task_vm in with_task_vms]
340-
vm_ids = [
341-
with_task_vm.data.id for with_task_vm in with_task_vms]
342-
wait_tasks(tasks, api_client)
343-
created_vms = vm_api.get_vms({
344-
"where": {
345-
"id_in": vm_ids
346-
}
347-
})
330+
configuration = Configuration(host=os.getenv("CLOUDTOWER_ENDPOINT"))
331+
client = ApiClient(configuration)
332+
333+
login(client, os.getenv("CLOUDTOWER_USERNAME"), os.getenv("CLOUDTOWER_PASSWORD"))
334+
335+
336+
def create_vm_from_template(template_name, cluster_name, vm_name):
337+
"""
338+
通过内容库模板创建一台虚拟机,内容通过内容库模板设置
339+
:param template_name: 指定所需使用的内容库模板名称
340+
:param cluster_name: 指定虚拟机被部署的集群的集群名称
341+
:param vm_name: 虚拟机名称
342+
:return: 被创建的虚拟机
343+
"""
344+
vm_api = VmApi(client)
345+
cluster_api = ClusterApi(client)
346+
template_api = ContentLibraryVmTemplateApi(client)
347+
348+
cluster = cluster_api.get_clusters({
349+
"where": {
350+
"name": cluster_name
351+
}
352+
})
353+
if len(cluster) == 0:
354+
raise Exception("cluster not found")
355+
356+
template = template_api.get_content_library_vm_templates({
357+
"where": {
358+
"name": template_name
359+
}
360+
})
361+
if len(template) == 0:
362+
raise Exception("template not found")
363+
364+
with_task_vms = vm_api.create_vm_from_content_library_template([
365+
{
366+
"template_id": template[0].id,
367+
"cluster_id": cluster[0].id,
368+
"name": vm_name,
369+
"is_full_copy": False
370+
}
371+
])
372+
tasks = [with_task_vm.task_id for with_task_vm in with_task_vms]
373+
vm_ids = [
374+
with_task_vm.data.id for with_task_vm in with_task_vms]
375+
wait_tasks(tasks, client)
376+
return vm_api.get_vms({
377+
"where": {
378+
"id_in": vm_ids
379+
}
380+
})[0]
348381
```
349382

350383
#### 配置与模板不同的虚拟盘参数
351384

352385
```python
353-
from cloudtower import (
354-
ApiClient,
355-
Configuration,
356-
VmApi,
357-
VmCreateVmFromTemplateParamsDiskOperateModifyDisks,
358-
VmDiskParams,
359-
Bus,
360-
VmVolumeElfStoragePolicyType
361-
)
362-
from cloudtower.utils import wait_tasks
386+
from cloudtower.api import VmApi, ContentLibraryVmTemplateApi, ClusterApi
387+
from cloudtower.utils import login, wait_tasks
388+
from cloudtower.configuration import Configuration
389+
from cloudtower.models import Bus, VmVolumeElfStoragePolicyType
390+
from cloudtower import ApiClient
391+
import os
363392

364-
conf = Configuration(host="http://192.168.96.133/v2/api")
365-
conf.api_key["Authorization"] = "token"
366-
api_client = ApiClient(conf)
367-
vm_api = VmApi(api_client)
368-
with_task_vms = vm_api.create_vm_from_template([
369-
{
370-
"template_id": "template_id",
371-
"cluster_id": "cluster_id",
372-
"name": "vm_name",
373-
"is_full_copy": False,
374-
"disk_operate": {
375-
"remove_disks": {
376-
"disk_index": [2, 3]
377-
},
378-
"modify_disks": [
393+
394+
configuration = Configuration(host=os.getenv("CLOUDTOWER_ENDPOINT"))
395+
client = ApiClient(configuration)
396+
397+
login(client, os.getenv("CLOUDTOWER_USERNAME"), os.getenv("CLOUDTOWER_PASSWORD"))
398+
399+
400+
def create_vm_from_template_modify_disk(template_name, cluster_name, vm_name, disk_operate):
401+
"""
402+
通过内容库模板创建一台虚拟机,配置虚拟机的磁盘
403+
:param template_name: 模板名称
404+
:param cluster_name: 集群名称
405+
:param vm_name: 虚拟机名称
406+
:param disk_operate: 磁盘操作,使用详见 create_vm_from_template_modify_disk_example 方法
407+
:return: 被创建的虚拟机
408+
"""
409+
vm_api = VmApi(client)
410+
cluster_api = ClusterApi(client)
411+
template_api = ContentLibraryVmTemplateApi(client)
412+
413+
cluster = cluster_api.get_clusters({
414+
"where": {
415+
"name": cluster_name
416+
}
417+
})
418+
if len(cluster) == 0:
419+
raise Exception("cluster not found")
420+
421+
template = template_api.get_content_library_vm_templates({
422+
"where": {
423+
"name": template_name
424+
}
425+
})
426+
if len(template) == 0:
427+
raise Exception("template not found")
428+
429+
with_task_vms = vm_api.create_vm_from_content_library_template([
430+
{
431+
"template_id": template[0].id,
432+
"cluster_id": cluster[0].id,
433+
"name": vm_name,
434+
"is_full_copy": False,
435+
"disk_operate": disk_operate
436+
}
437+
])
438+
tasks = [with_task_vm.task_id for with_task_vm in with_task_vms]
439+
vm_ids = [
440+
with_task_vm.data.id for with_task_vm in with_task_vms]
441+
wait_tasks(tasks, client)
442+
return vm_api.get_vms({
443+
"where": {
444+
"id_in": vm_ids
445+
}
446+
})[0]
447+
448+
449+
def create_vm_from_template_modify_disk_example():
450+
"""
451+
通过模板创建虚拟机时,如果希望对原有的磁盘进行任何修改,可以通过 disk_operate 参数进行配置
452+
disk_operate 参数的类型是 VmDiskOperate,它是一个字典,包含以下字段:
453+
- remove_disks 由于删除指定index的磁盘
454+
- modify_disks 修改现有磁盘的配置,目前仅支持修改总线,如果有其他修改可以通过,删除原有盘
455+
- new_disks 新增磁盘,类型是 VmDiskParams,它是一个字典,包含以下字段:
456+
- mount_cd_roms 挂载 cd-rom
457+
- mount_disks 挂载已有磁盘
458+
- mount_new_create_disks 挂载新磁盘
459+
"""
460+
disk_operate = {
461+
"remove_disks": {
462+
"disk_index": [0] # 用于删除指定 index 的磁盘,index 从 0 开始计算,这里既是删除第一块磁盘
463+
},
464+
"new_disks": {
465+
"mount_cd_roms": [
379466
{
380-
"disk_index": 0,
381-
"vm_volume_id": "vm_volume_id"
467+
"boot": 2, # 启动顺序
468+
"content_library_image_id": "" # 指定挂载内容库镜像的 id
382469
}
383470
],
384-
"new_disks": {
385-
"mount_cd_roms": [
386-
{
387-
"index": 2,
388-
"boot": 0,
389-
"elf_image_id": "elf_image_id"
390-
}
391-
],
392-
"mount_disks": [
393-
{
394-
"index": 3,
395-
"bus": Bus.VIRTIO,
396-
"boot": 1,
397-
"vm_volume_id": "vm_volume_id"
398-
}
399-
],
400-
"mount_new_create_disks": [
401-
{
402-
"vm_volume": {
403-
"elf_storage_policy": VmVolumeElfStoragePolicyType._2_THIN_PROVISION,
404-
"size": 4*1024*1024*1024,
405-
"name": "disk_name",
406-
},
407-
"bus": Bus.IDE,
408-
"boot": 3,
471+
"mount_disks": [
472+
{
473+
"boot": 3, # 启动顺序
474+
"bus": Bus.VIRTIO, # 总线类型
475+
"vm_volume_id": "cljm6x2g1405g0958tp3zkhvh" # 被挂载虚拟卷的 id
476+
}
477+
],
478+
"mount_new_create_disks": [
479+
{
480+
"boot": 4,
481+
"bus": Bus.VIRTIO,
482+
"vm_volume": {
483+
"name": "test", # 新建虚拟卷的名称
484+
"size": 10 * 1024 * 1024 * 1024, # 新建虚拟卷的大小,单位是字节
485+
"elf_storage_policy": VmVolumeElfStoragePolicyType._2_THIN_PROVISION # 存储策略
409486
}
410-
]
411-
}
487+
}
488+
]
412489
}
413490
}
414-
])
415-
416-
tasks = [with_task_vm.task_id for with_task_vm in with_task_vms]
417-
vm_ids = [
418-
with_task_vm.data.id for with_task_vm in with_task_vms]
419-
wait_tasks(tasks, api_client)
420-
created_vms = vm_api.get_vms({
421-
"where": {
422-
"id_in": vm_ids
423-
}
424-
})
491+
create_vm_from_template_modify_disk("template-name", "cluster-name", "vm-name", disk_operate)
425492
```
426493

427494
#### 配置与模版不同的网卡参数
428495

429496
```python
430-
from cloudtower import ApiClient, Configuration, VmApi, VmNicModel
431-
from cloudtower.utils import wait_tasks
497+
from cloudtower.api import VmApi, ContentLibraryVmTemplateApi, ClusterApi
498+
from cloudtower.utils import login, wait_tasks
499+
from cloudtower.configuration import Configuration
500+
from cloudtower.models import Bus, VmNicModel
501+
from cloudtower import ApiClient
502+
import os
432503

433-
conf = Configuration(host="http://192.168.96.133/v2/api")
434-
conf.api_key["Authorization"] = "token"
435-
api_client = ApiClient(conf)
436-
vm_api = VmApi(api_client)
437-
with_task_vms = vm_api.create_vm_from_template([
438-
{
439-
"template_id": "template_id",
440-
"cluster_id": "cluster_id",
441-
"name": "vm_name",
442-
"is_full_copy": False,
443-
"vm_nics": [
444-
{
445-
"connect_vlan_id": "vlan_id",
446-
"enabled": True,
447-
"model": VmNicModel.E1000
448-
}
449-
]
450-
}
451-
])
452-
tasks = [with_task_vm.task_id for with_task_vm in with_task_vms]
453-
vm_ids = [
454-
with_task_vm.data.id for with_task_vm in with_task_vms]
455-
wait_tasks(tasks, api_client)
456-
created_vms = vm_api.get_vms({
457-
"where": {
458-
"id_in": vm_ids
459-
}
460-
})
504+
505+
configuration = Configuration(host=os.getenv("CLOUDTOWER_ENDPOINT"))
506+
client = ApiClient(configuration)
507+
508+
login(client, os.getenv("CLOUDTOWER_USERNAME"), os.getenv("CLOUDTOWER_PASSWORD"))
509+
510+
511+
def create_vm_from_template_modified_nic(template_name, cluster_name, vm_name, nic_params):
512+
"""
513+
通过内容库模板创建一台虚拟机,配置虚拟机的网卡
514+
:param template_name: 模板名称
515+
:param cluster_name: 集群名称
516+
:param vm_name: 虚拟机名称
517+
:param nic_params: 磁盘操作,使用详见 create_vm_from_template_modified_nic_example 方法
518+
:return: 被创建的虚拟机
519+
"""
520+
vm_api = VmApi(client)
521+
cluster_api = ClusterApi(client)
522+
template_api = ContentLibraryVmTemplateApi(client)
523+
524+
cluster = cluster_api.get_clusters({
525+
"where": {
526+
"name": cluster_name
527+
}
528+
})
529+
if len(cluster) == 0:
530+
raise Exception("cluster not found")
531+
532+
template = template_api.get_content_library_vm_templates({
533+
"where": {
534+
"name": template_name
535+
}
536+
})
537+
if len(template) == 0:
538+
raise Exception("template not found")
539+
540+
with_task_vms = vm_api.create_vm_from_content_library_template([
541+
{
542+
"template_id": template[0].id,
543+
"cluster_id": cluster[0].id,
544+
"name": vm_name,
545+
"is_full_copy": False,
546+
"vm_nics": nic_params
547+
}
548+
])
549+
tasks = [with_task_vm.task_id for with_task_vm in with_task_vms]
550+
vm_ids = [
551+
with_task_vm.data.id for with_task_vm in with_task_vms]
552+
wait_tasks(tasks, client)
553+
return vm_api.get_vms({
554+
"where": {
555+
"id_in": vm_ids
556+
}
557+
})[0]
558+
559+
560+
def create_vm_from_template_modified_nic_example():
561+
"""
562+
通过内容库模板创建虚拟机时,如果不传递 vm_nics 参数,会默认使用模板的网卡配置,如果需要修改网卡配置,可以传递 vm_nics 参数,
563+
vm_nics 参数是一个列表,列表中的每个元素都是一个字典:
564+
- connect_vlan_id 网卡对应虚拟机网络的 id,并非虚拟机网络的 vlan_id
565+
- enabled 是否启用网卡
566+
- model 网卡类型,可以使用 VmNicModel 类的属性,如 VmNicModel.VIRTIO
567+
创建虚拟机时并不支持修改网卡的 ip,mac,gateway,subnet mask,如果需要配置ip,子网,网关,可以通过 cloudinit 来实现,需要模板支持 cloudinit
568+
"""
569+
nic_params = [
570+
{
571+
"connect_vlan_id": "vlan_id",
572+
"enabled": True,
573+
"model": VmNicModel.VIRTIO
574+
}
575+
]
576+
create_vm_from_template_modified_nic("template_name", "cluster_name", "vm_name", nic_params)
461577
```
462578

463579
### 创建空白虚拟机

0 commit comments

Comments
 (0)