跳到主要内容

常见问题

为何部分资源的 id 一直在变化

在 CloudTower 中虚拟盘和虚拟网卡是一种虚拟资源,并没有对应的实体,表示的是两类资源的连接关系,例如虚拟盘就是指的虚拟机和虚拟盘或者虚拟光驱的连接关系。 而这类资源由于无法在更新,同步时判断唯一性,所以每次更新,同步时都会将原有的虚拟资源删除,并重建,继而导致 id 的不稳定。 此类资源在 query 时请尽量避免使用 id 的形式进行查询,而是使用一些其他条件来完成对资源的精确查询。 例如对于虚拟卷类型的虚拟盘,可以用虚拟机的 id 和对应虚拟卷的 id 来查找,这两个资源的 id 是稳定的,查找出来的虚拟盘也是稳定的

// VmDiskWhereInput
{
"where": {
"vm": {
"id": "vm_id"
},
"vm_volume": {
"id": "volume_id"
}
}
}

对于虚拟网卡,可以辅助以 mac 地址

// VmNicWhereInput
{
"where": {
"vm": {
"id": "vm_id"
},
"mac_address": "aa:bb:cc:dd:ee:ff"
}
}

connect_vlan_id

这个参数和 vlan id 有歧义,在参数中 connect_vlan_id 并不是指的 0~4095 的 vlan id,而是说需要使用的 vlan 的 cuid

配置网络

在创建时配置网络的唯一途径是通过 cloudinit,需要以创建时使用已经预装了 cloudinit 的虚拟机模板创建虚拟机。 这时可以通过 cloudinit 的配置文件来配置网卡的网络,例如配置静态 ip,配置网关,配置 dns 等等。

// VmCreateVmFromContentLibraryTemplateParams[]
[
{
"template_id": "template_id",
"cluster_id": "cluster_id",
"name": "vm_name",
"is_full_copy": false,
"cloud_init": {
"nameservers": ["114.114.114.114"],
"networks": [
{
"ip_address": "192.168.20.1", // 静态IP
"netmask": "255.255.240.0", // 子网
"nic_index": 0,
"type": "IPV4",
"routes": [
{
"gateway": "192.168.16.1", // 默认网关
"network": "0.0.0.0",
"netmask": "0.0.0.0"
}
]
}
]
}
}
]

对于运行中的虚拟机,修改静态 IP,子网,网关等需要在虚拟机系统内安装 VmTools,并确保其在运行状态后,调用 /update-vm-nic-basic-info 来更新网络的配置。

// VmUpdateNicBasicInfoParams
{
"where":{
"vm":{
"id":"vm_id"
},
"mac_address":"aa:bb:cc:dd:ee:ff"
},
"data":{
"ip_address":"192.168.1.2",
"subnet_mask":"255.255.255.0",
"gateway":"192.168.1.1"
}
}

ResourceLockedError

虽然 cloudtower api 对外表现的形式是命令式的 api,实际上对集群进行操作的时候,会将命令式的 api 转化为声明式的 api,这样当重复操作一些资源的时候,可能会产生脏数据的冲突。 假设有一个请求 A 希望将虚拟机原有的卷由 10GB 扩容为 20GB,另一个请求 B 希望额外为同一个虚拟机挂载一块大小为 10GB 的新卷。

由于 cloudtower api 会需要额外对请求进行处理,就有可能出现 A,B请求读取原数据时获取了一致的数据,分别分封装了自己的请求,此时声明式的数据中并不会包含另一个请求的更改。下发时,如果某个请求先被接收,占用了资源,在没有释放资源前,另一个请求如果被接收到,则会因为资源被抢占而失败。 但是如果当后一个请求在释放资源后才被接收到,先发生的请求的结果会被后发生的请求覆盖,从而产生预料之外的副作用以及脏数据。

因此我们在 3.3.0 及以后的 cloudtower api 中实现了一个额外的资源锁的机制,以避免此类情况发生。当接收状态码为 400 的返回值:

{
"path":"/remove-vm-disk",
"status":400,
"message":"Resource [VM-clny8ylbd19q0958o3avqavm] locked",
"props": {
"locked_resources": [
{
"id": "clny8ylbd19q0958o3avqavm",
"type": "VM"
}
]
},
"code":"ResourceLocked"
}

可以根据 code 为 ResourceLocked 来判断此类错误,此时可以通过 props.locked_resources 来获取被锁定的资源的信息, type 可以获取被锁定的资源类型,目前包括虚拟机(VM)以及虚拟卷(VM_VOLUME),id 则代表对应资源的 id。

可以通过查询对应资源的 api 对资源进行查询,可以通过查看资源的 entityAsyncStatus 来确定资源是否仍被锁定,当 entityAsyncStatus 为 null 时则代表资源目前允许被操作,其他值则代表资源正在进行更改,需要等待更改完成后才能进行操作。