This commit is contained in:
2025-11-14 12:44:02 +03:00
parent 06336697a6
commit becbe65993
16 changed files with 3050 additions and 537 deletions

View File

@@ -56,6 +56,7 @@ class decort_kvmvm(DecortController):
comp_id=self.aparams['clone_from']['id'],
)
)
self.rg_id = self.vm_to_clone_info['rgId']
if not self.vm_to_clone_id:
self.message(
f'Check for parameter "clone_from.id" failed: '
@@ -73,7 +74,7 @@ class decort_kvmvm(DecortController):
clone_id, clone_dict, _ = self.compute_find(
comp_name=self.aparams['name'],
rg_id=self.vm_to_clone_info['rgId'],
rg_id=self.rg_id,
)
self.check_amodule_args_for_clone(
clone_id=clone_id,
@@ -389,7 +390,7 @@ class decort_kvmvm(DecortController):
Compute instance with the specified characteristics into the target Resource Group.
The target RG must exist.
"""
# the following parameters must be present: cpu, ram, image_id or image_name
# the following parameters must be present: cpu, ram, image_id
# each of the following calls will abort if argument is missing
self.check_amodule_argument('cpu')
self.check_amodule_argument('ram')
@@ -429,27 +430,15 @@ class decort_kvmvm(DecortController):
image_id, image_facts = None, None
if self.aparam_image:
# either image_name or image_id must be present
if (
self.check_amodule_argument('image_id', abort=False)
and self.amodule.params['image_id'] > 0
):
# find image by image ID and account ID
# image_find(self, image_id, image_name, account_id, rg_id=0, sepid=0, pool=""):
# image_find(self, image_id, account_id, rg_id=0, sepid=0, pool=""):
image_id, image_facts = self.image_find(
image_id=self.amodule.params['image_id'],
image_name="",
account_id=self.acc_id)
elif (
self.check_amodule_argument('image_name', abort=False)
and self.amodule.params['image_name'] != ""
):
# find image by image name and account ID
image_id, image_facts = self.image_find(
image_id=0,
image_name=self.amodule.params['image_name'],
account_id=self.acc_id,
)
if validated_bdisk_size <= image_facts['size']:
# adjust disk size to the minimum allowed by OS image, which will be used to spin off this Compute
@@ -523,26 +512,31 @@ class decort_kvmvm(DecortController):
# if we get through here, all parameters required to create new Compute instance should be at hand
# NOTE: KVM VM is created in HALTED state and must be explicitly started
self.comp_id = self.kvmvm_provision(rg_id=self.rg_id,
comp_name=self.amodule.params['name'],
cpu=self.amodule.params['cpu'], ram=self.amodule.params['ram'],
boot_disk_size=validated_bdisk_size,
image_id=image_id,
description=self.amodule.params['description'],
userdata=cloud_init_params,
sep_id=self.amodule.params['sep_id' ] if "sep_id" in self.amodule.params else None,
pool_name=self.amodule.params['pool'] if "pool" in self.amodule.params else None,
start_on_create=start_compute,
chipset=chipset,
cpu_pin=cpu_pin,
hp_backed=hp_backed,
numa_affinity=numa_affinity,
preferred_cpu_cores=self.amodule.params['preferred_cpu_cores'],
boot_mode=boot_mode,
boot_loader_type=loader_type,
network_interface_naming=network_interface_naming,
hot_resize=hot_resize,
zone_id=self.aparams['zone_id'],)
self.comp_id = self.kvmvm_provision(
rg_id=self.rg_id,
comp_name=self.amodule.params['name'],
cpu=self.amodule.params['cpu'],
ram=self.amodule.params['ram'],
boot_disk_size=validated_bdisk_size,
image_id=image_id,
description=self.amodule.params['description'],
userdata=cloud_init_params,
sep_id=self.amodule.params['sep_id' ] if "sep_id" in self.amodule.params else None,
pool_name=self.amodule.params['pool'] if "pool" in self.amodule.params else None,
start_on_create=start_compute,
chipset=chipset,
cpu_pin=cpu_pin,
hp_backed=hp_backed,
numa_affinity=numa_affinity,
preferred_cpu_cores=self.amodule.params['preferred_cpu_cores'],
boot_mode=boot_mode,
boot_loader_type=loader_type,
network_interface_naming=network_interface_naming,
hot_resize=hot_resize,
zone_id=self.aparams['zone_id'],
storage_policy_id=self.aparams['storage_policy_id'],
os_version=self.aparams['os_version'],
)
self.comp_should_exist = True
# Originally we would have had to re-read comp_info after VM was provisioned
@@ -579,7 +573,7 @@ class decort_kvmvm(DecortController):
if self.amodule.params['disks'] is not None:
self.compute_disks(
comp_dict=self.comp_info,
aparam_disks=self.amodule.params['disks'],
aparam_disks_dict=self.amodule.params['disks'],
)
self.compute_affinity(self.comp_info,
@@ -626,8 +620,7 @@ class decort_kvmvm(DecortController):
Note that this handler deletes the VM permanently together with all assigned disk resources.
"""
self.compute_delete(comp_id=self.comp_id, permanently=True)
self.comp_info['status'] = 'DESTROYED'
self.comp_should_exist = False
self.comp_id, self.comp_info, _ = self._compute_get_by_id(self.comp_id)
return
def restore(self):
@@ -676,7 +669,7 @@ class decort_kvmvm(DecortController):
if self.amodule.params['disks'] is not None:
self.compute_disks(
comp_dict=self.comp_info,
aparam_disks=self.amodule.params['disks'],
aparam_disks_dict=self.amodule.params['disks'],
)
aparam_boot = self.amodule.params['boot']
@@ -695,6 +688,59 @@ class decort_kvmvm(DecortController):
if boot_disk_new_size:
self.compute_bootdisk_size(self.comp_info, boot_disk_new_size)
boot_order = aparam_boot['order']
if (
boot_order is not None
and self.comp_info['bootOrder'] != boot_order
):
self.compute_set_boot_order(
vm_id=self.comp_id,
order=boot_order,
)
disk_redeploy = aparam_boot['disk_redeploy']
if disk_redeploy:
auto_start = False
if self.aparams['state'] is None:
if self.comp_info['techStatus'] == 'STARTED':
auto_start = True
else:
if self.aparams['state'] == 'started':
auto_start = True
disk_size = None
if (
aparam_boot is not None
and aparam_boot['disk_size'] is not None
):
disk_size = aparam_boot['disk_size']
elif self.aparams['image_id'] is not None:
_, image_facts = self.image_find(
image_id=self.aparams['image_id'],
)
disk_size = image_facts['size']
os_version = None
if (
self.aparams['image_id'] is None
or self.aparams['image_id'] == self.comp_info['imageId']
):
if self.aparams['os_version'] is None:
os_version = self.comp_info['os_version']
else:
os_version = self.aparams['os_version']
elif self.aparams['image_id'] != self.comp_info['imageId']:
os_version = self.aparams['os_version']
self.compute_disk_redeploy(
vm_id=self.comp_id,
storage_policy_id=self.aparams['storage_policy_id'],
image_id=self.aparams['image_id'],
disk_size=disk_size,
auto_start=auto_start,
os_version=os_version,
)
self.compute_resize(self.comp_info,
self.amodule.params['cpu'], self.amodule.params['ram'],
wait_for_state_change=arg_wait_cycles)
@@ -754,6 +800,28 @@ class decort_kvmvm(DecortController):
)
)
aparam_cdrom = self.aparams['cdrom']
if aparam_cdrom is not None:
mode = aparam_cdrom['mode']
image_id = aparam_cdrom['image_id']
if (
mode == 'insert'
and self.comp_info['cdImageId'] != image_id
):
self.compute_cd_insert(
vm_id=self.comp_id,
image_id=image_id,
)
elif mode == 'eject':
self.compute_cd_eject(
vm_id=self.comp_id,
)
if self.aparams['abort_cloning']:
self.compute_clone_abort(
vm_id=self.comp_id,
)
return
@property
@@ -773,6 +841,7 @@ class decort_kvmvm(DecortController):
'boot.loader_type': 'loaderType',
'network_interface_naming': 'networkInterfaceNaming',
'hot_resize': 'hotResize',
'os_version': 'os_version',
}
def get_nested_value(
@@ -814,6 +883,14 @@ class decort_kvmvm(DecortController):
)
if aparam_value is not None and aparam_value != comp_value:
# If disk_redeploy = True no need to update os_version.
# Updating os_version through compute_disk_redeploy
if (
aparam_name == 'os_version'
and self.aparams['boot'] is not None
and self.aparams['boot']['disk_redeploy']
):
continue
result_args[aparam_name.replace('.', '_')] = (
aparam_value
)
@@ -837,7 +914,6 @@ class decort_kvmvm(DecortController):
cpu="",
ram="",
disk_size=0,
data_disks=[], # IDs of attached data disks; this list can be emty
state="CHECK_MODE",
tech_status="",
account_id=0,
@@ -898,18 +974,19 @@ class decort_kvmvm(DecortController):
elif iface['connType'] == "VLAN": # This is direct external network connection
ret_dict['public_ips'].append(iface['ipAddress'])
iface['security_group_mode'] = iface.pop('enable_secgroups')
iface['security_group_ids'] = iface.pop('security_groups')
ret_dict['cpu'] = self.comp_info['cpus']
ret_dict['ram'] = self.comp_info['ram']
ret_dict['image_id'] = self.comp_info['imageId']
for ddisk in self.comp_info['disks']:
if ddisk['type'] == 'B':
ret_dict['disks'] = self.comp_info['disks']
for disk in ret_dict['disks']:
if disk['type'] == 'B':
# if it is a boot disk - store its size
ret_dict['disk_size'] = ddisk['sizeMax']
elif ddisk['type'] == 'D':
# if it is a data disk - append its ID to the list of data disks IDs
ret_dict['data_disks'].append(ddisk['id'])
ret_dict['disk_size'] = disk['sizeMax']
ret_dict['chipset'] = self.comp_info['chipset']
@@ -960,15 +1037,30 @@ class decort_kvmvm(DecortController):
self.comp_info['snapshot_merge_status']
)
ret_dict['cd_image_id'] = self.comp_info['cdImageId']
ret_dict['boot_order'] = self.comp_info['bootOrder']
ret_dict['os_version'] = self.comp_info['os_version']
ret_dict['boot_loader_metaiso'] = self.comp_info['loaderMetaIso']
if self.comp_info['loaderMetaIso'] is not None:
ret_dict['boot_loader_metaiso'] = {
'device_name': self.comp_info['loaderMetaIso']['devicename'],
'path': self.comp_info['loaderMetaIso']['path'],
}
if self.amodule.params['get_cloning_status']:
ret_dict['cloning_status'] = self.compute_get_clone_status(
vm_id=self.comp_id,
)
return ret_dict
def check_amodule_args_for_create(self):
check_errors = False
# Check for unacceptable parameters for a blank Compute
if (
self.aparams['image_id'] is not None
or self.aparams['image_name'] is not None
):
if self.aparams['image_id'] is not None:
self.aparam_image = True
for param in (
'network_interface_naming',
@@ -1017,7 +1109,7 @@ class decort_kvmvm(DecortController):
check_errors = True
self.message(
f'Check for parameter "{parameter}" failed: '
f'"image_id" or "image_name" must be specified '
f'"image_id" must be specified '
f'to set {parameter}.'
)
@@ -1029,7 +1121,7 @@ class decort_kvmvm(DecortController):
check_errors = True
self.message(
'Check for parameter "sep_id" failed: '
'"image_id" or "image_name" or "boot.disk_size" '
'"image_id" or "boot.disk_size" '
'must be specified to set sep_id.'
)
@@ -1072,6 +1164,39 @@ class decort_kvmvm(DecortController):
if self.check_aparam_networks_trunk() is False:
check_errors = True
if self.aparams['cdrom'] is not None:
check_errors = True
self.message(
'Check for parameter "cdrom" failed: '
'cdrom can be specified only for existing compute.'
)
aparam_storage_policy_id = self.aparams['storage_policy_id']
if aparam_storage_policy_id is None:
check_errors = True
self.message(
msg='Check for parameter "storage_policy_id" failed: '
'storage_policy_id must be specified when creating '
'a new compute'
)
elif (
aparam_storage_policy_id
not in self.rg_info['storage_policy_ids']
):
check_errors = True
self.message(
msg='Check for parameter "storage_policy_id" failed: '
f'RG ID {self.rg_id} does not have access to '
f'storage_policy_id {aparam_storage_policy_id}'
)
if self.aparams['abort_cloning'] is not None:
check_errors = True
self.message(
'Check for parameter "abort_cloning" failed: '
'abort_cloning can be specified only for existing compute.'
)
if check_errors:
self.exit(fail=True)
@@ -1114,6 +1239,19 @@ class decort_kvmvm(DecortController):
'unknown',
],
),
from_cdrom=dict(
type='int',
),
order=dict(
type='list',
elements='str',
choices=[
e.value for e in self.VMBootDevice
],
),
disk_redeploy=dict(
type='bool',
),
),
),
sep_id=dict(
@@ -1142,9 +1280,24 @@ class decort_kvmvm(DecortController):
],
default='update',
),
ids=dict(
objects=dict(
type='list',
elements='int',
elements='dict',
options=dict(
id=dict(
type='int',
required=True,
),
pci_slot_num_hex=dict(
type='str',
),
bus_num_hex=dict(
type='str',
),
),
required_together=[
('pci_slot_num_hex', 'bus_num_hex'),
],
),
),
),
@@ -1155,9 +1308,6 @@ class decort_kvmvm(DecortController):
image_id=dict(
type='int',
),
image_name=dict(
type='str',
),
name=dict(
type='str',
),
@@ -1190,6 +1340,16 @@ class decort_kvmvm(DecortController):
mac=dict(
type='str',
),
security_group_ids=dict(
type='list',
elements='int',
),
security_group_mode=dict(
type='bool',
),
enabled=dict(
type='bool',
),
),
required_if=[
('type', 'VINS', ('id',)),
@@ -1197,7 +1357,7 @@ class decort_kvmvm(DecortController):
('type', 'VFNIC', ('id',)),
('type', 'DPDK', ('id',)),
('type', 'TRUNK', ('id',)),
('type', 'SDN', ('id', 'mac')),
('type', 'SDN', ('id',)),
],
),
network_order_changing=dict(
@@ -1326,6 +1486,16 @@ class decort_kvmvm(DecortController):
('name', 'timestamp', 'datetime'),
],
),
sep_pool_name=dict(
type='str',
),
sep_id=dict(
type='int',
),
storage_policy_id=dict(
type='int',
requiered=True,
),
),
),
network_interface_naming=dict(
@@ -1368,6 +1538,34 @@ class decort_kvmvm(DecortController):
get_snapshot_merge_status=dict(
type='bool',
),
cdrom=dict(
type='dict',
options=dict(
mode=dict(
type='str',
choices=[
'insert',
'eject',
],
default='insert',
),
image_id=dict(
type='int',
),
),
),
storage_policy_id=dict(
type='int',
),
os_version=dict(
type='str',
),
get_cloning_status=dict(
type='bool',
),
abort_cloning=dict(
type='bool',
),
),
supports_check_mode=True,
required_one_of=[
@@ -1377,7 +1575,7 @@ class decort_kvmvm(DecortController):
'clone_from': 'name',
},
)
def check_amodule_args_for_change(self):
check_errors = False
@@ -1404,30 +1602,6 @@ class decort_kvmvm(DecortController):
aparam_boot = self.amodule.params['boot']
if aparam_boot is not None:
new_boot_disk_size = aparam_boot['disk_size']
if new_boot_disk_size is not None:
boot_disk_size = 0
for disk in self.comp_info['disks']:
if disk['type'] == 'B':
boot_disk_size = disk['sizeMax']
break
else:
if aparam_boot is None or aparam_boot['disk_id'] is None:
check_errors = True
self.message(
f'Can\'t set boot disk size for Compute '
f'{comp_id}, because it doesn\'t '
f'have a boot disk.'
)
if new_boot_disk_size < boot_disk_size:
check_errors = True
self.message(
f'New boot disk size {new_boot_disk_size} is less'
f' than current {boot_disk_size} for Compute ID '
f'{comp_id}'
)
aparam_disks = self.amodule.params['disks']
aparam_boot_disk_id = aparam_boot['disk_id']
comp_disk_ids = [disk['id'] for disk in self.comp_info['disks']]
@@ -1479,6 +1653,75 @@ class decort_kvmvm(DecortController):
f'to Compute ID {self.comp_id}.'
)
if self.check_aparam_boot_disk_redeploy() is False:
check_errors = True
new_boot_disk_size = aparam_boot['disk_size']
if new_boot_disk_size is not None:
boot_disk_size = 0
for disk in self.comp_info['disks']:
if disk['type'] == 'B':
boot_disk_size = disk['sizeMax']
break
else:
if aparam_boot is None or aparam_boot['disk_id'] is None:
check_errors = True
self.message(
f'Can\'t set boot disk size for Compute '
f'{comp_id}, because it doesn\'t '
f'have a boot disk.'
)
if new_boot_disk_size < boot_disk_size:
check_errors = True
self.message(
f'New boot disk size {new_boot_disk_size} is less'
f' than current {boot_disk_size} for Compute ID '
f'{comp_id}'
)
cd_rom_image_id = aparam_boot['from_cdrom']
if cd_rom_image_id is not None:
if not (
self.comp_info['techStatus'] == 'STOPPED'
and self.aparams['state'] == 'started'
):
check_errors = True
self.message(
f'Check for parameter "boot.from_cdrom" failed: '
f'VM ID {self.comp_id} must be stopped and "state" '
'must be "started" to boot from CD-ROM.'
)
_, image_info = self._image_get_by_id(
image_id=cd_rom_image_id,
)
if image_info is None:
check_errors = True
self.message(
'Check for parameter "boot.from_cdrom" failed: '
f'Image ID {cd_rom_image_id} not found.'
)
elif image_info['type'] != 'cdrom':
check_errors = True
self.message(
'Check for parameter "boot.from_cdrom" failed: '
f'Image ID {cd_rom_image_id} is not a cd-rom type.'
)
boot_order_list = aparam_boot['order']
if boot_order_list is not None:
boot_order_duplicates = set([
boot_dev for boot_dev in boot_order_list
if boot_order_list.count(boot_dev) > 1
])
if boot_order_duplicates:
check_errors = True
self.message(
'Check for parameter "boot.order" failed: '
'List of boot devices has duplicates: '
f'{boot_order_duplicates}.'
)
if (
not comp_info['imageId']
and self.amodule.params['state'] in (
@@ -1574,24 +1817,24 @@ class decort_kvmvm(DecortController):
'VM must be started to get console url.'
)
aparam_disks = self.aparams['disks']
if aparam_disks is not None:
aparam_disks_ids = aparam_disks['ids']
aparam_disks_dict = self.aparams['disks']
if aparam_disks_dict is not None:
aparam_disks = aparam_disks_dict.get('objects', [])
aparam_disks_ids = [disk['id'] for disk in aparam_disks]
comp_boot_disk_id = None
for comp_disk in self.comp_info['disks']:
if comp_disk['type'] == 'B':
comp_boot_disk_id = comp_disk['id']
break
disks_to_detach = []
match aparam_disks['mode']:
match aparam_disks_dict['mode']:
case 'detach' | 'delete':
disks_to_detach = aparam_disks_ids
case 'match':
comp_disk_ids = {
disk['id'] for disk in self.comp_info['disks']
}
disks = set(aparam_disks_ids)
disks_to_detach = comp_disk_ids - disks
disks_to_detach = comp_disk_ids - set(aparam_disks_ids)
if (
comp_boot_disk_id is not None
and comp_boot_disk_id in disks_to_detach
@@ -1611,6 +1854,18 @@ class decort_kvmvm(DecortController):
f'Compute ID {self.comp_id} while snapshots exist.'
)
if aparam_disks_dict['mode'] in ('delete', 'detach'):
for disk in aparam_disks:
for param, value in disk.items():
if param != 'id' and value is not None:
check_errors = True
self.message(
msg='Check for parameter "disks.objects" '
'failed: only disk id can be specified if '
'disks.mode is "delete" or "detach"'
)
break
if (
(
self.aparams['cpu'] is not None
@@ -1637,11 +1892,72 @@ class decort_kvmvm(DecortController):
aparam_networks = self.aparams['networks']
if aparam_networks is not None:
vm_networks = self.comp_info['interfaces']
if (
not vm_networks
and not self.is_vm_stopped_or_will_be_stopped
):
check_errors = True
self.message(
'Check for parameter "networks" failed: '
'VM must be stopped before attach it\'s first network.'
)
vm_networks_ids = [
network['netId'] for network in vm_networks
if network['type'] != self.VMNetType.EMPTY.value
]
aparam_networks_ids = [
network['id'] for network in aparam_networks
if network['type'] != self.VMNetType.EMPTY.value
]
new_networks = list(
set(aparam_networks_ids) - set(vm_networks_ids)
)
net_types = {net['type'] for net in aparam_networks}
if new_networks:
if not (
len(new_networks) == 1
and self.VMNetType.DPDK.value in net_types
) and not self.is_vm_stopped_or_will_be_stopped:
check_errors = True
self.message(
'Check for parameter "networks" failed: '
'VM must be stopped to attach non-DPDK network.'
)
if self.VMNetType.TRUNK.value in net_types:
if self.check_aparam_networks_trunk() is False:
check_errors = True
for network in aparam_networks:
if (
network['enabled'] is not None
and network['type'] not in [
self.VMNetType.VINS.value,
self.VMNetType.EXTNET.value,
self.VMNetType.DPDK.value,
self.VMNetType.SDN.value,
self.VMNetType.TRUNK.value,
]
):
check_errors = True
self.message(
'Check for parameter "networks.enabled" failed: '
'Can not enable or disable network '
f'ID {network['id']} and type {network['type']}.'
'Only networks of type VINS, EXTNET, DPDK, SDN, TRUNK '
'can be enabled or disabled.'
)
if self.check_aparam_cdrom() is False:
check_errors = True
if self.check_aparam_storage_policy_id() is False:
check_errors = True
if self.check_aparam_image_id() is False:
check_errors = True
if check_errors:
self.exit(fail=True)
@@ -1731,6 +2047,9 @@ class decort_kvmvm(DecortController):
snapshot_timestamp=snapshot_timestamp,
snapshot_name=snapshot_name,
snapshot_datetime=snapshot_datetime,
sep_pool_name=self.aparams['clone_from']['sep_pool_name'],
sep_id=self.aparams['clone_from']['sep_id'],
storage_policy_id=self.aparams['clone_from']['storage_policy_id'],
)
return clone_id
@@ -1812,6 +2131,130 @@ class decort_kvmvm(DecortController):
return not check_errors
def check_aparam_cdrom(self) -> bool | None:
check_errors = False
aparam_cdrom = self.aparams['cdrom']
if aparam_cdrom is not None:
mode = aparam_cdrom['mode']
if self.is_vm_stopped_or_will_be_stopped:
check_errors = True
self.message(
'Check for parameter "cdrom" failed: '
f'VM ID {self.comp_id} must be started to {mode} '
f'CD-ROM.'
)
image_id = aparam_cdrom['image_id']
match mode:
case 'insert':
if image_id is None:
check_errors = True
self.message(
'Check for parameter "cdrom.image_id" failed: '
f'cdrom.image_id must be specified '
f'if cdrom.mode is "insert".'
)
_, image_info = self._image_get_by_id(
image_id=image_id,
)
if image_info is None:
check_errors = True
self.message(
'Check for parameter "cdrom.image_id" failed: '
f'Image ID {image_id} not found.'
)
elif image_info['type'] != 'cdrom':
check_errors = True
self.message(
'Check for parameter "cdrom.image_id" failed: '
f'Image ID {image_id} is not a CD-ROM type.'
)
case 'eject':
if image_id is not None:
check_errors = True
self.message(
'Check for parameter "cdrom.image_id" failed: '
f'cdrom.image_id must not be specified '
f'if cdrom.mode is "eject".'
)
if not self.comp_info['cdImageId']:
check_errors = True
self.message(
'Check for parameter "cdrom.mode" failed: '
f'VM ID {self.comp_id} does not have CD-ROM '
'to eject.'
)
return not check_errors
def check_aparam_storage_policy_id(self) -> bool:
check_errors = False
aparam_storage_policy_id = self.aparams['storage_policy_id']
if aparam_storage_policy_id is not None:
for disk in self.comp_info['disks']:
if aparam_storage_policy_id != disk['storage_policy_id']:
check_errors = True
self.message(
msg='Check for parameter "storage_policy_id" failed: '
'storage_policy_id can not be changed for compute '
f'ID {self.comp_id} disk ID {disk['id']}'
)
return not check_errors
def check_aparam_boot_disk_redeploy(self) -> bool:
check_errors = False
disk_redeploy = self.aparams['boot']['disk_redeploy']
if disk_redeploy:
if self.aparams['storage_policy_id'] is None:
check_errors = True
self.message(
'Check for parameter "storage_policy_id" failed:'
'"storage_policy_id" must be specified to redeploy.'
)
vm_has_boot_disk = False
for disk in self.comp_info['disks']:
if disk['type'] == 'B':
vm_has_boot_disk = True
break
if not vm_has_boot_disk:
check_errors = True
self.message(
'Check for parameter "boot.redeploy" failed: '
'VM does not have boot disk to redeploy.'
)
aparam_disks = self.amodule.params['disks']
if aparam_disks is not None and aparam_disks['mode'] == 'match':
check_errors = True
self.message(
'Check for parameter "disks.mode" failed: '
'"disks.mode" must not be "match" to redeploy.'
)
return not check_errors
def check_aparam_image_id(self) -> bool:
check_errors = False
aparam_image_id = self.aparams['image_id']
if aparam_image_id is not None:
if aparam_image_id != self.comp_info['imageId']:
if (
self.aparams['boot'] is None
or self.aparams['boot']['disk_redeploy'] is None
):
check_errors = True
self.message(
'Check for parameter "image_id" failed: '
'"boot.disk_redeploy" must be set to True to change '
'VM image.'
)
return not check_errors
def find_networks_tags_intersections(
self,
trunk_networks: list,
@@ -1958,7 +2401,7 @@ def main():
amodule = subj.amodule
if subj.comp_id:
if subj.comp_info['status'] in ("DISABLED", "MIGRATING", "DELETING", "DESTROYING", "ERROR", "REDEPLOYING"):
if subj.comp_info['status'] in ("MIGRATING", "DELETING", "DESTROYING", "ERROR", "REDEPLOYING"):
# cannot do anything on the existing Compute in the listed states
subj.error() # was subj.nop()
elif subj.comp_info['status'] in ("ENABLED", "DISABLED"):