10.0.0
This commit is contained in:
@@ -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"):
|
||||
|
||||
Reference in New Issue
Block a user