9.0.0
This commit is contained in:
@@ -18,6 +18,9 @@ DefaultT = TypeVar('DefaultT')
|
||||
|
||||
|
||||
class decort_kvmvm(DecortController):
|
||||
is_vm_stopped_or_will_be_stopped: None | bool = None
|
||||
guest_agent_exec_result: None | str = None
|
||||
|
||||
def __init__(self):
|
||||
# call superclass constructor first
|
||||
super(decort_kvmvm, self).__init__(AnsibleModule(**self.amodule_init_args))
|
||||
@@ -31,20 +34,22 @@ class decort_kvmvm(DecortController):
|
||||
# This following flag is used to avoid extra (and unnecessary) get of compute details prior to
|
||||
# packaging facts before the module completes. As ""
|
||||
self.skip_final_get = False
|
||||
self.force_final_get = False
|
||||
self.comp_id = 0
|
||||
self.comp_info = None
|
||||
self.acc_id = 0
|
||||
self.rg_id = 0
|
||||
self.aparam_image = None
|
||||
|
||||
|
||||
validated_acc_id =0
|
||||
validated_acc_id = 0
|
||||
validated_rg_id = 0
|
||||
validated_rg_facts = None
|
||||
|
||||
self.vm_to_clone_id = 0
|
||||
self.vm_to_clone_info = None
|
||||
|
||||
if self.aparams['get_snapshot_merge_status']:
|
||||
self.force_final_get = True
|
||||
|
||||
if arg_amodule.params['clone_from'] is not None:
|
||||
self.vm_to_clone_id, self.vm_to_clone_info, _ = (
|
||||
self._compute_get_by_id(
|
||||
@@ -101,7 +106,7 @@ class decort_kvmvm(DecortController):
|
||||
|
||||
if not comp_id: # manage Compute by name -> need RG identity
|
||||
if not arg_amodule.params['rg_id']: # RG ID is not set -> locate RG by name -> need account ID
|
||||
validated_acc_id, _ = self.account_find(arg_amodule.params['account_name'],
|
||||
validated_acc_id, self._acc_info = self.account_find(arg_amodule.params['account_name'],
|
||||
arg_amodule.params['account_id'])
|
||||
if not validated_acc_id:
|
||||
self.result['failed'] = True
|
||||
@@ -142,6 +147,7 @@ class decort_kvmvm(DecortController):
|
||||
if self.comp_id:
|
||||
self.comp_should_exist = True
|
||||
self.acc_id = self.comp_info['accountId']
|
||||
self.rg_id = self.comp_info['rgId']
|
||||
self.check_amodule_args_for_change()
|
||||
else:
|
||||
if self.amodule.params['state'] != 'absent':
|
||||
@@ -186,18 +192,82 @@ class decort_kvmvm(DecortController):
|
||||
'to a DPDK network.'
|
||||
)
|
||||
for net in aparam_nets:
|
||||
# MTU for non-DPDK networks
|
||||
net_type = net['type']
|
||||
|
||||
if (
|
||||
net['type'] != self.VMNetType.DPDK.value
|
||||
and net['mtu'] is not None
|
||||
net['type'] not in (
|
||||
self.VMNetType.SDN.value,
|
||||
self.VMNetType.EMPTY.value,
|
||||
)
|
||||
and not isinstance(net['id'], int)
|
||||
):
|
||||
check_error = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed:'
|
||||
' MTU can be specifed only for DPDK network'
|
||||
' (remove parameter "mtu" for network'
|
||||
f' {net["type"]} with ID {net["id"]}).'
|
||||
'Check for parameter "networks" failed: '
|
||||
'Type of parameter "id" must be integer for '
|
||||
f'{net["type"]} network type'
|
||||
)
|
||||
|
||||
# MTU
|
||||
net_mtu = net['mtu']
|
||||
if net_mtu is not None:
|
||||
mtu_net_types = (
|
||||
self.VMNetType.DPDK.value,
|
||||
self.VMNetType.EXTNET.value,
|
||||
)
|
||||
|
||||
# Allowed network types for set MTU
|
||||
if net_type not in mtu_net_types:
|
||||
check_error = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed:'
|
||||
' MTU can be specifed'
|
||||
' only for DPDK or EXTNET network'
|
||||
' (remove parameter "mtu" for network'
|
||||
f' {net["type"]} with ID {net["id"]}).'
|
||||
)
|
||||
|
||||
# Maximum MTU
|
||||
MAX_MTU = 9216
|
||||
if net_type in mtu_net_types and net_mtu > MAX_MTU:
|
||||
check_error = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed:'
|
||||
f' MTU must be no more than {MAX_MTU}'
|
||||
' (change value for parameter "mtu" for network'
|
||||
f' {net["type"]} with ID {net["id"]}).'
|
||||
)
|
||||
|
||||
# EXTNET minimum MTU
|
||||
EXTNET_MIN_MTU = 1500
|
||||
if (
|
||||
net_type == self.VMNetType.EXTNET.value
|
||||
and net_mtu < EXTNET_MIN_MTU
|
||||
):
|
||||
check_error = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed:'
|
||||
f' MTU for {self.VMNetType.EXTNET.value} network'
|
||||
f' must be at least {EXTNET_MIN_MTU}'
|
||||
' (change value for parameter "mtu" for network'
|
||||
f' {net["type"]} with ID {net["id"]}).'
|
||||
)
|
||||
|
||||
# DPDK minimum MTU
|
||||
DPDK_MIN_MTU = 1
|
||||
if (
|
||||
net_type == self.VMNetType.DPDK.value
|
||||
and net_mtu < DPDK_MIN_MTU
|
||||
):
|
||||
check_error = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed:'
|
||||
f' MTU for {self.VMNetType.DPDK.value} network'
|
||||
f' must be at least {DPDK_MIN_MTU}'
|
||||
' (change value for parameter "mtu" for network'
|
||||
f' {net["type"]} with ID {net["id"]}).'
|
||||
)
|
||||
|
||||
# MAC address
|
||||
if net['mac'] is not None:
|
||||
if net['type'] == self.VMNetType.EMPTY.value:
|
||||
@@ -220,7 +290,20 @@ class decort_kvmvm(DecortController):
|
||||
'specified in quotes and in the format '
|
||||
'"XX:XX:XX:XX:XX:XX".'
|
||||
)
|
||||
|
||||
if self.VMNetType.SDN.value in net_types:
|
||||
if not net_types.issubset(
|
||||
{
|
||||
self.VMNetType.SDN.value,
|
||||
self.VMNetType.EMPTY.value,
|
||||
self.VMNetType.VFNIC.value,
|
||||
}
|
||||
):
|
||||
check_error = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed: '
|
||||
'a compute can be connected to a SDN network and '
|
||||
'only to VFNIC, EMPTY networks at the same time.'
|
||||
)
|
||||
aparam_custom_fields = self.aparams['custom_fields']
|
||||
if aparam_custom_fields is not None:
|
||||
if (
|
||||
@@ -458,7 +541,8 @@ class decort_kvmvm(DecortController):
|
||||
boot_mode=boot_mode,
|
||||
boot_loader_type=loader_type,
|
||||
network_interface_naming=network_interface_naming,
|
||||
hot_resize=hot_resize,)
|
||||
hot_resize=hot_resize,
|
||||
zone_id=self.aparams['zone_id'],)
|
||||
self.comp_should_exist = True
|
||||
|
||||
# Originally we would have had to re-read comp_info after VM was provisioned
|
||||
@@ -636,6 +720,40 @@ class decort_kvmvm(DecortController):
|
||||
custom_fields=aparam_custom_fields['fields'],
|
||||
)
|
||||
|
||||
aparam_zone_id = self.aparams['zone_id']
|
||||
if aparam_zone_id is not None and aparam_zone_id != self.comp_info['zoneId']:
|
||||
self.compute_migrate_to_zone(
|
||||
compute_id=self.comp_id,
|
||||
zone_id=aparam_zone_id,
|
||||
)
|
||||
|
||||
aparam_guest_agent = self.aparams['guest_agent']
|
||||
if aparam_guest_agent is not None:
|
||||
if aparam_guest_agent['enabled'] is not None:
|
||||
if (
|
||||
aparam_guest_agent['enabled']
|
||||
and not self.comp_info['qemu_guest']['enabled']
|
||||
):
|
||||
self.compute_guest_agent_enable(vm_id=self.comp_id)
|
||||
elif (
|
||||
aparam_guest_agent['enabled'] is False
|
||||
and self.comp_info['qemu_guest']['enabled']
|
||||
):
|
||||
self.compute_guest_agent_disable(vm_id=self.comp_id)
|
||||
|
||||
if aparam_guest_agent['update_available_commands']:
|
||||
self.compute_guest_agent_feature_update(vm_id=self.comp_id)
|
||||
|
||||
aparam_guest_agent_exec = aparam_guest_agent['exec']
|
||||
if aparam_guest_agent_exec is not None:
|
||||
self.guest_agent_exec_result = (
|
||||
self.compute_guest_agent_execute(
|
||||
vm_id=self.comp_id,
|
||||
cmd=aparam_guest_agent_exec['cmd'],
|
||||
args=aparam_guest_agent_exec['args'],
|
||||
)
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
@property
|
||||
@@ -779,7 +897,7 @@ class decort_kvmvm(DecortController):
|
||||
# If it does - save public IP address of GW VNF in ret_dict['nat_ip']
|
||||
elif iface['connType'] == "VLAN": # This is direct external network connection
|
||||
ret_dict['public_ips'].append(iface['ipAddress'])
|
||||
|
||||
|
||||
ret_dict['cpu'] = self.comp_info['cpus']
|
||||
ret_dict['ram'] = self.comp_info['ram']
|
||||
|
||||
@@ -830,6 +948,18 @@ class decort_kvmvm(DecortController):
|
||||
ret_dict['affinity_rules'] = self.comp_info['affinityRules']
|
||||
ret_dict['anti_affinity_rules'] = self.comp_info['antiAffinityRules']
|
||||
|
||||
ret_dict['zone_id'] = self.comp_info['zoneId']
|
||||
|
||||
ret_dict['guest_agent'] = self.comp_info['qemu_guest']
|
||||
|
||||
if self.guest_agent_exec_result:
|
||||
ret_dict['guest_agent']['exec_result'] = self.guest_agent_exec_result # noqa: E501
|
||||
|
||||
if self.amodule.params['get_snapshot_merge_status']:
|
||||
ret_dict['snapshot_merge_status'] = (
|
||||
self.comp_info['snapshot_merge_status']
|
||||
)
|
||||
|
||||
return ret_dict
|
||||
|
||||
def check_amodule_args_for_create(self):
|
||||
@@ -918,6 +1048,30 @@ class decort_kvmvm(DecortController):
|
||||
' to a DPDK network.'
|
||||
)
|
||||
|
||||
if self.check_aparam_zone_id() is False:
|
||||
check_errors = True
|
||||
|
||||
if self.aparams['guest_agent'] is not None:
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter "guest_agent" failed: '
|
||||
'guest_agent can be specified only for existing VM.'
|
||||
)
|
||||
|
||||
if self.aparams['get_snapshot_merge_status']:
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter "get_snapshot_merge_status" failed: '
|
||||
'snapshot merge status can be retrieved only for existing VM.'
|
||||
)
|
||||
|
||||
aparam_networks = self.aparams['networks']
|
||||
if aparam_networks is not None:
|
||||
net_types = {net['type'] for net in aparam_networks}
|
||||
if self.VMNetType.TRUNK.value in net_types:
|
||||
if self.check_aparam_networks_trunk() is False:
|
||||
check_errors = True
|
||||
|
||||
if check_errors:
|
||||
self.exit(fail=True)
|
||||
|
||||
@@ -1019,11 +1173,13 @@ class decort_kvmvm(DecortController):
|
||||
'EXTNET',
|
||||
'VFNIC',
|
||||
'DPDK',
|
||||
'TRUNK',
|
||||
'SDN',
|
||||
'EMPTY',
|
||||
],
|
||||
),
|
||||
id=dict(
|
||||
type='int',
|
||||
type='raw',
|
||||
),
|
||||
ip_addr=dict(
|
||||
type='str',
|
||||
@@ -1040,6 +1196,8 @@ class decort_kvmvm(DecortController):
|
||||
('type', 'EXTNET', ('id',)),
|
||||
('type', 'VFNIC', ('id',)),
|
||||
('type', 'DPDK', ('id',)),
|
||||
('type', 'TRUNK', ('id',)),
|
||||
('type', 'SDN', ('id', 'mac')),
|
||||
],
|
||||
),
|
||||
network_order_changing=dict(
|
||||
@@ -1180,6 +1338,36 @@ class decort_kvmvm(DecortController):
|
||||
hot_resize=dict(
|
||||
type='bool',
|
||||
),
|
||||
zone_id=dict(
|
||||
type='int',
|
||||
),
|
||||
guest_agent=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
enabled=dict(
|
||||
type='bool',
|
||||
),
|
||||
exec=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
cmd=dict(
|
||||
type='str',
|
||||
required=True,
|
||||
),
|
||||
args=dict(
|
||||
type='dict',
|
||||
default={},
|
||||
),
|
||||
),
|
||||
),
|
||||
update_available_commands=dict(
|
||||
type='bool',
|
||||
),
|
||||
),
|
||||
),
|
||||
get_snapshot_merge_status=dict(
|
||||
type='bool',
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
required_one_of=[
|
||||
@@ -1196,6 +1384,24 @@ class decort_kvmvm(DecortController):
|
||||
comp_info = self.vm_to_clone_info or self.comp_info
|
||||
comp_id = comp_info['id']
|
||||
|
||||
self.is_vm_stopped_or_will_be_stopped = (
|
||||
(
|
||||
comp_info['techStatus'] == 'STOPPED'
|
||||
and (
|
||||
self.amodule.params['state'] is None
|
||||
or self.amodule.params['state'] in (
|
||||
'halted', 'poweredoff', 'present', 'stopped',
|
||||
)
|
||||
)
|
||||
)
|
||||
or (
|
||||
comp_info['techStatus'] != 'STOPPED'
|
||||
and self.amodule.params['state'] in (
|
||||
'halted', 'poweredoff', 'stopped',
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
aparam_boot = self.amodule.params['boot']
|
||||
if aparam_boot is not None:
|
||||
new_boot_disk_size = aparam_boot['disk_size']
|
||||
@@ -1285,26 +1491,8 @@ class decort_kvmvm(DecortController):
|
||||
'state for a blank Compute can not be "started" or "paused".'
|
||||
)
|
||||
|
||||
is_vm_stopped_or_will_be_stopped = (
|
||||
(
|
||||
comp_info['techStatus'] == 'STOPPED'
|
||||
and (
|
||||
self.amodule.params['state'] is None
|
||||
or self.amodule.params['state'] in (
|
||||
'halted', 'poweredoff', 'present', 'stopped',
|
||||
)
|
||||
)
|
||||
)
|
||||
or (
|
||||
comp_info['techStatus'] != 'STOPPED'
|
||||
and self.amodule.params['state'] in (
|
||||
'halted', 'poweredoff', 'stopped',
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if self.amodule.params['rollback_to'] is not None:
|
||||
if not is_vm_stopped_or_will_be_stopped:
|
||||
if not self.is_vm_stopped_or_will_be_stopped:
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter "rollback_to" failed: '
|
||||
@@ -1334,7 +1522,7 @@ class decort_kvmvm(DecortController):
|
||||
if (
|
||||
self.aparams[param_name] is not None
|
||||
and comp_info[comp_field_name] != self.aparams[param_name]
|
||||
and not is_vm_stopped_or_will_be_stopped
|
||||
and not self.is_vm_stopped_or_will_be_stopped
|
||||
):
|
||||
check_errors = True
|
||||
self.message(
|
||||
@@ -1343,7 +1531,7 @@ class decort_kvmvm(DecortController):
|
||||
)
|
||||
|
||||
if self.aparams['preferred_cpu_cores'] is not None:
|
||||
if not is_vm_stopped_or_will_be_stopped:
|
||||
if not self.is_vm_stopped_or_will_be_stopped:
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter "preferred_cpu_cores" failed: '
|
||||
@@ -1407,7 +1595,7 @@ class decort_kvmvm(DecortController):
|
||||
if (
|
||||
comp_boot_disk_id is not None
|
||||
and comp_boot_disk_id in disks_to_detach
|
||||
and not is_vm_stopped_or_will_be_stopped
|
||||
and not self.is_vm_stopped_or_will_be_stopped
|
||||
):
|
||||
check_errors = True
|
||||
self.message(
|
||||
@@ -1438,6 +1626,22 @@ class decort_kvmvm(DecortController):
|
||||
'Hot resize must be enabled to change CPU or RAM.'
|
||||
)
|
||||
|
||||
if self.check_aparam_zone_id() is False:
|
||||
check_errors = True
|
||||
|
||||
if self.check_aparam_guest_agent() is False:
|
||||
check_errors = True
|
||||
|
||||
if self.check_aparam_get_snapshot_merge_status() is False:
|
||||
check_errors = True
|
||||
|
||||
aparam_networks = self.aparams['networks']
|
||||
if aparam_networks is not None:
|
||||
net_types = {net['type'] for net in aparam_networks}
|
||||
if self.VMNetType.TRUNK.value in net_types:
|
||||
if self.check_aparam_networks_trunk() is False:
|
||||
check_errors = True
|
||||
|
||||
if check_errors:
|
||||
self.exit(fail=True)
|
||||
|
||||
@@ -1530,6 +1734,211 @@ class decort_kvmvm(DecortController):
|
||||
)
|
||||
return clone_id
|
||||
|
||||
def check_aparam_guest_agent(self) -> bool:
|
||||
check_errors = False
|
||||
aparam_guest_agent = self.aparams['guest_agent']
|
||||
if aparam_guest_agent:
|
||||
if self.is_vm_stopped_or_will_be_stopped:
|
||||
if aparam_guest_agent['update_available_commands']:
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter '
|
||||
'"guest_agent.update_available_commands" failed: '
|
||||
f'VM ID {self.comp_id} must be started to update '
|
||||
'available commands.'
|
||||
)
|
||||
|
||||
is_guest_agent_enabled_or_will_be_enabled = (
|
||||
(
|
||||
self.comp_info['qemu_guest']['enabled']
|
||||
and aparam_guest_agent['enabled'] is not False
|
||||
)
|
||||
or (
|
||||
self.comp_info['qemu_guest']['enabled'] is False
|
||||
and aparam_guest_agent['enabled']
|
||||
)
|
||||
)
|
||||
|
||||
aparam_guest_agent_exec = aparam_guest_agent['exec']
|
||||
if aparam_guest_agent_exec is not None:
|
||||
if self.is_vm_stopped_or_will_be_stopped:
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter "guest_agent.exec" failed: '
|
||||
f'VM ID {self.comp_id} must be started '
|
||||
'to execute commands.'
|
||||
)
|
||||
|
||||
if not is_guest_agent_enabled_or_will_be_enabled:
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter "guest_agent.exec" failed: '
|
||||
f'Guest agent for VM ID {self.comp_id} must be enabled'
|
||||
' to execute commands.'
|
||||
)
|
||||
|
||||
aparam_exec_cmd = aparam_guest_agent_exec['cmd']
|
||||
available_commands = (
|
||||
self.comp_info['qemu_guest']['enabled_agent_features']
|
||||
)
|
||||
if aparam_exec_cmd not in available_commands:
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter "guest_agent.exec.cmd" failed: '
|
||||
f'Command "{aparam_exec_cmd}" is not '
|
||||
f'available for VM ID {self.comp_id}.'
|
||||
)
|
||||
|
||||
return not check_errors
|
||||
|
||||
def check_aparam_get_snapshot_merge_status(self) -> bool | None:
|
||||
check_errors = False
|
||||
if self.aparams['get_snapshot_merge_status']:
|
||||
vm_has_shared_sep_disk = False
|
||||
vm_disk_ids = [disk['id'] for disk in self.comp_info['disks']]
|
||||
for disk_id in vm_disk_ids:
|
||||
_, disk_info = self._disk_get_by_id(disk_id=disk_id)
|
||||
if disk_info['sepType'] == 'SHARED':
|
||||
vm_has_shared_sep_disk = True
|
||||
break
|
||||
|
||||
if not vm_has_shared_sep_disk:
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter "get_snapshot_merge_status" failed: '
|
||||
f'VM ID {self.comp_id} must have at least one disk with '
|
||||
'SEP type SHARED to retrieve snapshot merge status.'
|
||||
)
|
||||
|
||||
return not check_errors
|
||||
|
||||
def find_networks_tags_intersections(
|
||||
self,
|
||||
trunk_networks: list,
|
||||
extnet_networks: list,
|
||||
) -> bool:
|
||||
has_intersections = False
|
||||
|
||||
def parse_trunk_tags(trunk_tags_string: str):
|
||||
trunk_tags = set()
|
||||
for part in trunk_tags_string.split(','):
|
||||
if '-' in part:
|
||||
start, end = part.split('-')
|
||||
trunk_tags.update(range(int(start), int(end) + 1))
|
||||
else:
|
||||
trunk_tags.add(int(part))
|
||||
return trunk_tags
|
||||
|
||||
trunk_tags_dicts = []
|
||||
for trunk_network in trunk_networks:
|
||||
trunk_tags_dicts.append({
|
||||
'id': trunk_network['id'],
|
||||
'tags_str': trunk_network['trunkTags'],
|
||||
'tags': parse_trunk_tags(
|
||||
trunk_tags_string=trunk_network['trunkTags']
|
||||
),
|
||||
'native_vlan_id': trunk_network['nativeVlanId'],
|
||||
})
|
||||
|
||||
# find for trunk tags intersections with other networks
|
||||
for i in range(len(trunk_tags_dicts)):
|
||||
for j in range(i + 1, len(trunk_tags_dicts)):
|
||||
intersection = (
|
||||
trunk_tags_dicts[i]['tags']
|
||||
& trunk_tags_dicts[j]['tags']
|
||||
)
|
||||
if intersection:
|
||||
has_intersections = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed: '
|
||||
f'Trunk tags {trunk_tags_dicts[i]["tags_str"]} '
|
||||
f'of trunk ID {trunk_tags_dicts[i]["id"]} '
|
||||
f'overlaps with trunk tags '
|
||||
f'{trunk_tags_dicts[j]["tags_str"]} of trunk ID '
|
||||
f'{trunk_tags_dicts[j]["id"]}'
|
||||
)
|
||||
for extnet in extnet_networks:
|
||||
if extnet['vlanId'] in trunk_tags_dicts[i]['tags']:
|
||||
has_intersections = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed: '
|
||||
f'Trunk tags {trunk_tags_dicts[i]["tags_str"]} '
|
||||
f'of trunk ID {trunk_tags_dicts[i]["id"]} '
|
||||
f'overlaps with tag {extnet["vlanId"]} of extnet ID '
|
||||
f'{extnet["id"]}'
|
||||
)
|
||||
if extnet['vlanId'] == trunk_tags_dicts[i]['native_vlan_id']:
|
||||
has_intersections = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed: '
|
||||
f'Trunk native vlan ID '
|
||||
f'{trunk_tags_dicts[i]["native_vlan_id"]} of trunk ID '
|
||||
f'{trunk_tags_dicts[i]["id"]} '
|
||||
f'overlaps with vlan ID {extnet["vlanId"]} of extnet '
|
||||
f'ID {extnet["id"]}'
|
||||
)
|
||||
|
||||
return has_intersections
|
||||
|
||||
def check_aparam_networks_trunk(self) -> bool | None:
|
||||
check_errors = False
|
||||
|
||||
# check if account has vm feature “trunk”
|
||||
if not self.check_account_vm_features(vm_feature=self.VMFeature.trunk):
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed: '
|
||||
f'Account ID {self.acc_id} must have feature "trunk" to use '
|
||||
'trunk type networks '
|
||||
)
|
||||
# check if rg has vm feature “trunk”
|
||||
if not self.check_rg_vm_features(vm_feature=self.VMFeature.trunk):
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed: '
|
||||
f'RG ID {self.rg_id} must have feature "trunk" to use '
|
||||
'trunk type networks '
|
||||
)
|
||||
|
||||
aparam_trunk_networks = []
|
||||
aparam_extnet_networks = []
|
||||
for net in self.aparams['networks']:
|
||||
if net['type'] == self.VMNetType.TRUNK.value:
|
||||
aparam_trunk_networks.append(net)
|
||||
elif net['type'] == self.VMNetType.EXTNET.value:
|
||||
aparam_extnet_networks.append(net)
|
||||
|
||||
trunk_networks_info = []
|
||||
# check that account has access to all specified trunks
|
||||
for trunk_network in aparam_trunk_networks:
|
||||
trunk_info = self.trunk_get(id=trunk_network['id'])
|
||||
trunk_networks_info.append(trunk_info)
|
||||
if (
|
||||
trunk_info['accountIds'] is None
|
||||
or self.acc_id not in trunk_info['accountIds']
|
||||
):
|
||||
check_errors = True
|
||||
self.message(
|
||||
'Check for parameter "networks" failed: '
|
||||
f'Account ID {self.acc_id} does not have access to '
|
||||
f'trunk ID {trunk_info['id']}'
|
||||
)
|
||||
|
||||
extnet_networks_info = []
|
||||
for extnet_network in aparam_extnet_networks:
|
||||
extnet_networks_info.append(
|
||||
self.extnet_get(id=extnet_network['id'])
|
||||
)
|
||||
# check that trunk tags do not overlap with each other
|
||||
# and with extnets vlan id
|
||||
if self.find_networks_tags_intersections(
|
||||
trunk_networks=trunk_networks_info,
|
||||
extnet_networks=extnet_networks_info,
|
||||
):
|
||||
check_errors = True
|
||||
|
||||
return not check_errors
|
||||
|
||||
# Workflow digest:
|
||||
# 1) authenticate to DECORT controller & validate authentication by issuing API call - done when creating DECSController
|
||||
# 2) check if the VM with the specified id or rg_name:name exists
|
||||
@@ -1617,12 +2026,16 @@ def main():
|
||||
# prepare Compute facts to be returned as part of decon.result and then call exit_json(...)
|
||||
rg_facts = None
|
||||
if subj.comp_should_exist:
|
||||
if subj.result['changed'] and not subj.skip_final_get:
|
||||
if (
|
||||
(subj.result['changed'] and not subj.skip_final_get)
|
||||
or subj.force_final_get
|
||||
):
|
||||
# There were changes to the Compute - refresh Compute facts.
|
||||
_, subj.comp_info, _ = subj.compute_find(
|
||||
comp_id=subj.comp_id,
|
||||
need_custom_fields=True,
|
||||
need_console_url=amodule.params['get_console_url'],
|
||||
need_snapshot_merge_status=amodule.params['get_snapshot_merge_status'], # noqa: E501
|
||||
)
|
||||
#
|
||||
# We no longer need to re-read RG facts, as all network info is now available inside
|
||||
|
||||
Reference in New Issue
Block a user