6.1.0
This commit is contained in:
@@ -1,355 +1,17 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
||||
# Copyright: (c) 2018-2023 Digital Energy Cloud Solutions LLC
|
||||
#
|
||||
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: decort_kvmvm
|
||||
short_description: Manage KVM virtual machine in DECORT cloud
|
||||
description: >
|
||||
This module can be used to create a KVM based virtual machine in Digital Energy cloud platform from a
|
||||
specified OS image, modify virtual machine's CPU and RAM allocation, change its power state, configure
|
||||
network port forwarding rules, restart guest OS and delete a virtual machine thus releasing
|
||||
corresponding cloud resources.
|
||||
version_added: "2.2"
|
||||
|
||||
requirements:
|
||||
- python >= 3.8
|
||||
- PyJWT Python module
|
||||
- requests Python module
|
||||
- netaddr Python module
|
||||
- decort_utils utility library (module)
|
||||
- DECORT cloud platform version 3.8.6 or higher
|
||||
notes:
|
||||
- Environment variables can be used to pass selected parameters to the module, see details below.
|
||||
- Specified Oauth2 provider must be trusted by the DECORT cloud controller on which JWT will be used.
|
||||
- 'Similarly, JWT supplied in I(authenticator=jwt) mode should be received from Oauth2 provider trusted by
|
||||
the DECORT cloud controller on which this JWT will be used.'
|
||||
options:
|
||||
account_id:
|
||||
description:
|
||||
- 'ID of the account in which this VM will be created (for new VMs) or is located (for already
|
||||
existing VMs). This is the alternative to I(account_name) option.'
|
||||
- If both I(account_id) and I(account_name) specified, then I(account_name) is ignored.
|
||||
- If any one of I(vm_id) or I(rg_id) specified, I(account_id) is ignored.
|
||||
required: no
|
||||
account_name:
|
||||
description:
|
||||
- 'Name of the account in which this VM will be created (for new VMs) or is located (for already
|
||||
existing VMs).'
|
||||
- This parameter is ignored if I(account_id) is specified.
|
||||
- If any one of I(vm_id) or I(rg_id) specified, I(account_name) is ignored.
|
||||
required: no
|
||||
annotation:
|
||||
description:
|
||||
- Optional text description of this VM.
|
||||
default: empty string
|
||||
required: no
|
||||
app_id:
|
||||
description:
|
||||
- 'Application ID for authenticating to the DECORT controller when I(authenticator=oauth2).'
|
||||
- 'Required if I(authenticator=oauth2).'
|
||||
- 'If not found in the playbook or command line arguments, the value will be taken from DECORT_APP_ID
|
||||
environment variable.'
|
||||
required: no
|
||||
app_secret:
|
||||
description:
|
||||
- 'Application API secret used for authenticating to the DECORT controller when I(authenticator=oauth2).'
|
||||
- This parameter is required when I(authenticator=oauth2) and ignored in other modes.
|
||||
- 'If not found in the playbook or command line arguments, the value will be taken from DECORT_APP_SECRET
|
||||
environment variable.'
|
||||
required: no
|
||||
arch:
|
||||
description:
|
||||
- Architecture of the KVM VM. DECORT supports KVM hosts based on Intel x86.
|
||||
- This parameter is used when new KVM VM is created and ignored for all other operations.
|
||||
- Module may fail if your DECORT installation does not have physical nodes of specified architecture.
|
||||
default: X86_64
|
||||
choices: [ X86_64 ]
|
||||
required: yes
|
||||
authenticator:
|
||||
description:
|
||||
- Authentication mechanism to be used when accessing DECORT controller and authorizing API call.
|
||||
default: jwt
|
||||
choices: [ jwt, oauth2, legacy ]
|
||||
required: yes
|
||||
boot_disk:
|
||||
description:
|
||||
- 'Boot disk size in GB. If this parameter is not specified for a new VM, the size of the boot disk
|
||||
will be set to the size of the OS image, which this VM is based on.'
|
||||
- Boot disk is always created in the same storage and pool, as the OS image, which this VM is based on.
|
||||
- Boot disk cannot be detached from VM.
|
||||
required: no
|
||||
controller_url:
|
||||
description:
|
||||
- URL of the DECORT controller that will be contacted to manage the VM according to the specification.
|
||||
- 'This parameter is always required regardless of the specified I(authenticator) type.'
|
||||
required: yes
|
||||
cpu:
|
||||
description:
|
||||
- Number of virtual CPUs to allocate for the VM.
|
||||
- This parameter is required for creating new VM and optional for other operations.
|
||||
- 'If you set this parameter for an existing VM, then the module will check if VM resize is necessary and do
|
||||
it accordingly. Note that resize operation on a running VM may generate errors as not all OS images support
|
||||
hot resize feature.'
|
||||
required: no
|
||||
data_disks:
|
||||
description:
|
||||
- Optional list of integer IDs of the pre-existing disks that will be attached to this VM.
|
||||
- These are additional disks (aka data disks) besides boot disk, which is created and attached automatically.
|
||||
required: no
|
||||
id:
|
||||
description:
|
||||
- ID of the KVM VM to manage.
|
||||
- 'Either I(id) or a combination of VM name I(name) and RG related parameters (either I(rg_id) or a pair of
|
||||
I(account_name) and I(rg_name) is required to manage an existing VM.'
|
||||
- 'This parameter is not required (and ignored) when creating new VM as VM ID is assigned by cloud platform
|
||||
automatically and cannot be changed afterwards. If existing VM is identified by I(id), then I(account_id),
|
||||
I(account_name), I(rg_name) or I(rg_id) parameters will be ignored.'
|
||||
required: no
|
||||
image_id:
|
||||
description:
|
||||
- ID of the OS image to use for VM provisioning.
|
||||
- 'This parameter is valid at VM creation time only and is ignored for operations on existing VMs.'
|
||||
- 'You need to know image ID, e.g. by extracting it with decort_osimage module and storing
|
||||
in a variable prior to calling decort_kvmvm.'
|
||||
- 'If both I(image_id) and I(image_name) are specified, I(image_name) will be ignored.'
|
||||
required: no
|
||||
image_name:
|
||||
description:
|
||||
- Name of the OS image to use for a new VM provisioning.
|
||||
- 'This parameter is valid at VM creation time only and is ignored for operations on existing VMs.'
|
||||
- 'The specified image name will be looked up in the target DECORT controller and error will be generated if
|
||||
no matching image is found.'
|
||||
- 'If both I(image_id) and I(image_name) are specified, I(image_name) will be ignored.'
|
||||
required: no
|
||||
jwt:
|
||||
description:
|
||||
- 'JWT (access token) for authenticating to the DECORT controller when I(authenticator=jwt).'
|
||||
- 'This parameter is required if I(authenticator=jwt) and ignored for other authentication modes.'
|
||||
- If not specified in the playbook, the value will be taken from DECORT_JWT environment variable.
|
||||
required: no
|
||||
name:
|
||||
description:
|
||||
- Name of the VM.
|
||||
- 'To manage VM by I(name) you also need to specify either I(rg_id) or a pair of I(rg_name) and I(account_name).'
|
||||
- 'If both I(name) and I(id) are specified, I(name) will be ignored and I(id) used to locate the VM.'
|
||||
required: no
|
||||
networks:
|
||||
description:
|
||||
- List of dictionaries that specifies network connections for this VM.
|
||||
- Structure of each element is as follows:
|
||||
- ' - (string) type - type of the network connection. Supported types are VINS and EXTNET.'
|
||||
- ' - (int) id - ID of the target network segment. It is ViNS ID for I(net_type=VINS) and
|
||||
external network segment ID for I(net_type=EXTNET)'
|
||||
- ' - (string) ip_addr - optional IP address to request for this connection. If not specified, the
|
||||
platform will assign valid IP address automatically.'
|
||||
- 'If you call decort_kvmvm module for an existing VM, the module will try to reconfigure existing network
|
||||
connections according to the new specification.'
|
||||
- If this parameter is not specified, the VM will have no connections to the network(s).
|
||||
required: no
|
||||
oauth2_url:
|
||||
description:
|
||||
- 'URL of the oauth2 authentication provider to use when I(authenticator=oauth2).'
|
||||
- 'This parameter is required when when I(authenticator=oauth2).'
|
||||
- If not specified in the playbook, the value will be taken from DECORT_OAUTH2_URL environment variable.
|
||||
password:
|
||||
description:
|
||||
- 'Password for authenticating to the DECORT controller when I(authenticator=legacy).'
|
||||
- 'This parameter is required if I(authenticator=legacy) and ignored in other authentication modes.'
|
||||
- If not specified in the playbook, the value will be taken from DECORT_PASSWORD environment variable.
|
||||
required: no
|
||||
ram:
|
||||
description:
|
||||
- Size of RAM in MB to allocate to the VM.
|
||||
- This parameter is required for creating new VM and optional for other operations.
|
||||
- 'If you set this parameter for an existing VM, then the module will check if VM resize is necessary and do
|
||||
it accordingly. Note that resize operation on a running VM may generate errors as not all OS images support
|
||||
hot resize feature.'
|
||||
required: no
|
||||
ssh_key:
|
||||
description:
|
||||
- 'SSH public key to be deployed on to the new VM for I(ssh_key_user). If I(ssh_key_user) is not specified,
|
||||
the key will not be deployed, and a warning is generated.'
|
||||
- This parameter is valid at VM creation time only and ignored for any operation on existing VMs.
|
||||
required: no
|
||||
ssh_key_user:
|
||||
description:
|
||||
- User for which I(ssh_key) should be deployed.
|
||||
- If I(ssh_key) is not specified, this parameter is ignored and a warning is generated.
|
||||
- This parameter is valid at VM creation time only and ignored for any operation on existing VMs.
|
||||
required: no
|
||||
user_data:
|
||||
description:
|
||||
- Cloud-init User-Data, exept ssh module
|
||||
state:
|
||||
description:
|
||||
- Specify the desired state of the virtual machine at the exit of the module.
|
||||
- 'Regardless of I(state), if VM exists and is in one of [MIGRATING, DESTROYING, ERROR] states, do nothing.'
|
||||
- 'If desired I(state=check):'
|
||||
- ' - Just check if VM exists in any state and return its current specifications.'
|
||||
- ' - If VM does not exist, fail the task.'
|
||||
- 'If desired I(state=present):'
|
||||
- ' - VM does not exist, create the VM according to the specifications and start it.'
|
||||
- ' - VM in one of [RUNNING, PAUSED, HALTED] states, attempt resize if necessary, change network if necessary.'
|
||||
- ' - VM in DELETED state, restore and start it.'
|
||||
- ' - VM in DESTROYED state, recreate the VM according to the specifications and start it.'
|
||||
- 'If desired I(state=poweredon):'
|
||||
- ' - VM does not exist, create it according to the specifications.'
|
||||
- ' - VM in RUNNING state, attempt resize if necessary, change network if necessary.'
|
||||
- ' - VM in one of [PAUSED, HALTED] states, attempt resize if necessary, change network if necessary, next
|
||||
start the VM.'
|
||||
- ' - VM in DELETED state, restore it.'
|
||||
- ' - VM in DESTROYED state, create it according to the specifications.'
|
||||
- 'If desired I(state=absent):'
|
||||
- ' - VM in one of [RUNNING, PAUSED, HALTED] states, destroy it.'
|
||||
- ' - VM in one of [DELETED, DESTROYED] states, do nothing.'
|
||||
- 'If desired I(state=paused):'
|
||||
- ' - VM in RUNNING state, pause the VM, resize if necessary, change network if necessary.'
|
||||
- ' - VM in one of [PAUSED, HALTED] states, resize if necessary, change network if necessary.'
|
||||
- ' - VM in one of [DELETED, DESTROYED] states, abort with an error.'
|
||||
- 'If desired I(state=poweredoff) or I(state=halted):'
|
||||
- ' - VM does not exist, create the VM according to the specifications and leave it in HALTED state.'
|
||||
- ' - VM in RUNNING state, stop the VM, resize if necessary, change network if necessary.'
|
||||
- ' - VM in one of [PAUSED, HALTED] states, resize if necessary, change network if necessary.'
|
||||
- ' - VM in DELETED state, abort with an error.'
|
||||
- ' - VM in DESTROYED state, recreate the VM according to the specifications and leave it in HALTED state.'
|
||||
default: present
|
||||
choices: [ present, absent, poweredon, poweredoff, halted, paused, check ]
|
||||
tags:
|
||||
description:
|
||||
- Dict of custom tags to be assigned to the VM.
|
||||
- These tags are arbitrary text that can be used for grouping or indexing the VMs by other applications.
|
||||
required: no
|
||||
user:
|
||||
description:
|
||||
- 'Name of the legacy user for authenticating to the DECORT controller when I(authenticator=legacy).'
|
||||
- 'This parameter is required when I(authenticator=legacy) and ignored for other authentication modes.'
|
||||
- If not specified in the playbook, the value will be taken from DECORT_USER environment variable.
|
||||
required: no
|
||||
rg_id:
|
||||
description:
|
||||
- ID of the Resource Group where a new VM will be deployed or an existing VM can be found.
|
||||
- 'This parameter may be required when managing VM by its I(name). If you specify I(rg_id), then
|
||||
I(account_name), I(account_id) and I(rg_name) will be ignored.'
|
||||
required: no
|
||||
rg_name:
|
||||
description:
|
||||
- Name of the RG where the VM will be deployed (for new VMs) or can be found (for existing VMs).
|
||||
- This parameter is required when managing VM by its I(name).
|
||||
- If both I(rg_id) and I(rg_name) are specified, I(rg_name) will be ignored.
|
||||
- If I(rg_name) is specified, then either I(account_name) or I(account_id) must also be set.
|
||||
required: no
|
||||
verify_ssl:
|
||||
description:
|
||||
- 'Controls SSL verification mode when making API calls to DECORT controller. Set it to False if you
|
||||
want to disable SSL certificate verification. Intended use case is when you run module in a trusted
|
||||
environment that uses self-signed certificates. Note that disabling SSL verification in any other
|
||||
scenario can lead to security issues, so please know what you are doing.'
|
||||
default: True
|
||||
required: no
|
||||
workflow_callback:
|
||||
description:
|
||||
- 'Callback URL that represents an application, which invokes this module (e.g. up-level orchestrator or
|
||||
end-user portal) and may except out-of-band updates on progress / exit status of the module run.'
|
||||
- API call at this URL will be used to relay such information to the application.
|
||||
- 'API call payload will include module-specific details about this module run and I(workflow_context).'
|
||||
required: no
|
||||
workflow_context:
|
||||
description:
|
||||
- 'Context data that will be included into the payload of the API call directed at I(workflow_callback) URL.'
|
||||
- 'This context data is expected to uniquely identify the task carried out by this module invocation so
|
||||
that up-level orchestrator could match returned information to the its internal entities.'
|
||||
required: no
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: create a VM named "SimpleVM" in the DECORT cloud along with VDC named "ANewVDC" if it does not exist yet.
|
||||
decort_kvmvm:
|
||||
annotation: "VM managed by decort_kvmvm module"
|
||||
authenticator: oauth2
|
||||
app_id: "{{ MY_APP_ID }}"
|
||||
app_secret: "{{ MY_APP_SECRET }}"
|
||||
controller_url: "https://ds1.digitalenergy.online"
|
||||
name: SimpleVM
|
||||
cpu: 2
|
||||
ram: 4096
|
||||
boot_disk: 10
|
||||
image_name: "Ubuntu 16.04 v1.1"
|
||||
data_disks:
|
||||
- {{DISK_ID}}
|
||||
state: present
|
||||
tags:
|
||||
PROJECT:Ansible
|
||||
STATUS:Test
|
||||
account_name: "Development"
|
||||
rg_name: "ANewVDC"
|
||||
delegate_to: localhost
|
||||
register: simple_vm
|
||||
- name: resize the above VM to CPU 4 and remove port forward rule for port number 80.
|
||||
decort_kvmvm:
|
||||
authenticator: jwt
|
||||
jwt: "{{ MY_JWT }}"
|
||||
controller_url: "https://ds1.digitalenergy.online"
|
||||
name: SimpleVM
|
||||
cpu: 4
|
||||
ram: 4096
|
||||
port_forwards:
|
||||
- ext_port: 21022
|
||||
int_port: 22
|
||||
proto: tcp
|
||||
state: present
|
||||
account_name: "Development"
|
||||
rg_name: "ANewVDC"
|
||||
delegate_to: localhost
|
||||
register: simple_vm
|
||||
- name: stop existing VM identified by the VM ID and down size it to CPU:RAM 1:2048 along the way.
|
||||
decort_kvmvm:
|
||||
authenticator: jwt
|
||||
jwt: "{{ MY_JWT }}"
|
||||
controller_url: "https://ds1.digitalenergy.online"
|
||||
id: "{{ TARGET_VM_ID }}"
|
||||
cpu: 1
|
||||
ram: 2048
|
||||
state: poweredoff
|
||||
delegate_to: localhost
|
||||
register: simple_vm
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
facts:
|
||||
description: facts about the virtual machine that may be useful in the playbook
|
||||
returned: always
|
||||
type: dict
|
||||
sample:
|
||||
facts:
|
||||
id: 9454
|
||||
name: TestVM
|
||||
state: RUNNING
|
||||
username: testuser
|
||||
password: Yab!tWbyPF
|
||||
int_ip: 192.168.103.253
|
||||
rg_name: SandboxVDC
|
||||
rg_id: 2883
|
||||
vdc_ext_ip: 185.193.143.151
|
||||
ext_ip: 185.193.143.106
|
||||
ext_netmask: 24
|
||||
ext_gateway: 185.193.143.1
|
||||
ext_mac: 52:54:00:00:1a:24
|
||||
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home).
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.basic import env_fallback
|
||||
from ansible.module_utils.decort_utils import *
|
||||
|
||||
|
||||
class decort_kvmvm(DecortController):
|
||||
def __init__(self, arg_amodule):
|
||||
# call superclass constructor first
|
||||
@@ -420,6 +82,37 @@ class decort_kvmvm(DecortController):
|
||||
self.comp_should_exist = True
|
||||
self.acc_id = self.comp_info['accountId']
|
||||
|
||||
check_error = False
|
||||
params_to_check = {
|
||||
'chipset': 'chipset',
|
||||
'cpu_pin': 'cpupin',
|
||||
'hp_backed': 'hpBacked',
|
||||
'numa_affinity': 'numaAffinity',
|
||||
}
|
||||
for param_name, comp_field_name in params_to_check.items():
|
||||
if (
|
||||
self.aparams[param_name] is not None
|
||||
and self.comp_info[comp_field_name] != self.aparams[param_name]
|
||||
and self.aparams['state'] not in ('halted', 'poweredoff')
|
||||
):
|
||||
self.message(
|
||||
f'Cannot change "{param_name}" for compute '
|
||||
f'{self.comp_id} if parameter "state" is not '
|
||||
f'halted or poweredoff.'
|
||||
)
|
||||
check_error = True
|
||||
|
||||
if check_error:
|
||||
self.exit(fail=True)
|
||||
|
||||
else:
|
||||
if self.aparams['chipset'] is None:
|
||||
self.message(
|
||||
'Check for parameter "chipset" failed: '
|
||||
'chipset must be specified for a new compute.'
|
||||
)
|
||||
self.exit(fail=True)
|
||||
|
||||
return
|
||||
|
||||
def check_amodule_args(self):
|
||||
@@ -441,32 +134,15 @@ class decort_kvmvm(DecortController):
|
||||
)
|
||||
self.exit(fail=True)
|
||||
|
||||
# Check for unacceptable parameters for a blank Compute
|
||||
if (
|
||||
self.aparams['image_id'] is None
|
||||
and self.aparams['image_name'] is None
|
||||
):
|
||||
for parameter in (
|
||||
'ssh_key',
|
||||
'ssh_key_user',
|
||||
'ci_user_data',
|
||||
):
|
||||
if self.aparams[parameter] is not None:
|
||||
self.message(
|
||||
f'Check for parameter "{parameter}" failed: '
|
||||
f'"image_id" or "image_name" must be specified '
|
||||
f'to set {parameter}.'
|
||||
)
|
||||
self.exit(fail=True)
|
||||
|
||||
aparam_custom_fields = self.aparams['custom_fields']
|
||||
if aparam_custom_fields is not None:
|
||||
if (
|
||||
self.aparams['sep_id'] is not None
|
||||
and self.aparams['boot_disk'] is None
|
||||
aparam_custom_fields['disable']
|
||||
and aparam_custom_fields['fields'] is not None
|
||||
):
|
||||
self.message(
|
||||
'Check for parameter "sep_id" failed: '
|
||||
'"image_id" or "image_name" or "boot_disk" '
|
||||
'must be specified to set sep_id.'
|
||||
'Check for parameter "custom_fields" failed: '
|
||||
'"fields" cannot be set if "disable" is True.'
|
||||
)
|
||||
self.exit(fail=True)
|
||||
|
||||
@@ -579,13 +255,27 @@ class decort_kvmvm(DecortController):
|
||||
cloud_init_params = self.amodule.params['ci_user_data']
|
||||
else:
|
||||
cloud_init_params = None
|
||||
# if we get through here, all parameters required to create new Compute instance should be at hand
|
||||
|
||||
match self.amodule.params['chipset'].lower():
|
||||
case 'q35':
|
||||
chipset = 'Q35'
|
||||
case 'i440fx':
|
||||
chipset = 'i440fx'
|
||||
cpu_pin = self.aparams['cpu_pin']
|
||||
if cpu_pin is None:
|
||||
cpu_pin = False
|
||||
|
||||
hp_backed = self.aparams['hp_backed']
|
||||
if hp_backed is None:
|
||||
hp_backed = False
|
||||
|
||||
numa_affinity = self.aparams['numa_affinity']
|
||||
if numa_affinity is None:
|
||||
numa_affinity = 'none'
|
||||
|
||||
if self.aparams['custom_fields'] is None:
|
||||
custom_fields_disable = True
|
||||
custom_fields_fields = None
|
||||
else:
|
||||
custom_fields_disable = self.aparams['custom_fields']['disable']
|
||||
custom_fields_fields = self.aparams['custom_fields']['fields']
|
||||
|
||||
# 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,
|
||||
@@ -593,12 +283,16 @@ class decort_kvmvm(DecortController):
|
||||
cpu=self.amodule.params['cpu'], ram=self.amodule.params['ram'],
|
||||
boot_disk=validated_bdisk_size,
|
||||
image_id=image_id,
|
||||
annotation=self.amodule.params['annotation'],
|
||||
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)
|
||||
chipset=self.amodule.params['chipset'],
|
||||
cpu_pin=cpu_pin,
|
||||
hp_backed=hp_backed,
|
||||
numa_affinity=numa_affinity,
|
||||
custom_fields=custom_fields_fields)
|
||||
self.comp_should_exist = True
|
||||
|
||||
# Originally we would have had to re-read comp_info after VM was provisioned
|
||||
@@ -713,15 +407,44 @@ class decort_kvmvm(DecortController):
|
||||
**self.compute_update_args,
|
||||
)
|
||||
|
||||
aparam_custom_fields = self.amodule.params['custom_fields']
|
||||
if aparam_custom_fields is not None:
|
||||
compute_custom_fields = self.compute_get_custom_fields(
|
||||
compute_id=self.comp_info['id'],
|
||||
)
|
||||
if aparam_custom_fields['disable']:
|
||||
if compute_custom_fields is not None:
|
||||
self.compute_disable_custom_fields(
|
||||
compute_id=self.comp_info['id'],
|
||||
)
|
||||
else:
|
||||
if compute_custom_fields != aparam_custom_fields['fields']:
|
||||
self.compute_set_custom_fields(
|
||||
compute_id=self.comp_info['id'],
|
||||
custom_fields=aparam_custom_fields['fields'],
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
@property
|
||||
def compute_update_args(self) -> dict:
|
||||
result_args = {}
|
||||
|
||||
aparam_name = self.amodule.params['name']
|
||||
if aparam_name is not None and aparam_name != self.comp_info['name']:
|
||||
result_args['name'] = aparam_name
|
||||
params_to_check = {
|
||||
'name': 'name',
|
||||
'chipset': 'chipset',
|
||||
'cpu_pin': 'cpupin',
|
||||
'hp_backed': 'hpBacked',
|
||||
'numa_affinity': 'numaAffinity',
|
||||
'description': 'desc',
|
||||
}
|
||||
for param_name, comp_field_name in params_to_check.items():
|
||||
aparam_value = self.amodule.params[param_name]
|
||||
if (
|
||||
aparam_value is not None
|
||||
and aparam_value != self.comp_info[comp_field_name]
|
||||
):
|
||||
result_args[param_name] = aparam_value
|
||||
|
||||
return result_args
|
||||
|
||||
@@ -756,6 +479,10 @@ class decort_kvmvm(DecortController):
|
||||
tags={},
|
||||
chipset="",
|
||||
interfaces=[],
|
||||
cpu_pin="",
|
||||
hp_backed="",
|
||||
numa_affinity="",
|
||||
custom_fields={},
|
||||
)
|
||||
|
||||
if check_mode or self.comp_info is None:
|
||||
@@ -812,8 +539,46 @@ class decort_kvmvm(DecortController):
|
||||
|
||||
ret_dict['interfaces'] = self.comp_info['interfaces']
|
||||
|
||||
ret_dict['cpu_pin'] = self.comp_info['cpupin']
|
||||
ret_dict['hp_backed'] = self.comp_info['hpBacked']
|
||||
ret_dict['numa_affinity'] = self.comp_info['numaAffinity']
|
||||
|
||||
ret_dict['custom_fields'] = self.compute_get_custom_fields(
|
||||
compute_id=self.comp_info['id'],
|
||||
)
|
||||
|
||||
return ret_dict
|
||||
|
||||
def check_amodule_args_for_create(self):
|
||||
# Check for unacceptable parameters for a blank Compute
|
||||
if (
|
||||
self.aparams['image_id'] is None
|
||||
and self.aparams['image_name'] is None
|
||||
):
|
||||
for parameter in (
|
||||
'ssh_key',
|
||||
'ssh_key_user',
|
||||
'ci_user_data',
|
||||
):
|
||||
if self.aparams[parameter] is not None:
|
||||
self.message(
|
||||
f'Check for parameter "{parameter}" failed: '
|
||||
f'"image_id" or "image_name" must be specified '
|
||||
f'to set {parameter}.'
|
||||
)
|
||||
self.exit(fail=True)
|
||||
|
||||
if (
|
||||
self.aparams['sep_id'] is not None
|
||||
and self.aparams['boot_disk'] is None
|
||||
):
|
||||
self.message(
|
||||
'Check for parameter "sep_id" failed: '
|
||||
'"image_id" or "image_name" or "boot_disk" '
|
||||
'must be specified to set sep_id.'
|
||||
)
|
||||
self.exit(fail=True)
|
||||
|
||||
@staticmethod
|
||||
def build_parameters():
|
||||
"""Build and return a dictionary of parameters expected by decort_kvmvm module in a form
|
||||
@@ -825,9 +590,7 @@ class decort_kvmvm(DecortController):
|
||||
return dict(
|
||||
account_id=dict(type='int', required=False, default=0),
|
||||
account_name=dict(type='str', required=False, default=''),
|
||||
annotation=dict(type='str',
|
||||
default='',
|
||||
required=False),
|
||||
description=dict(type='str', required=False),
|
||||
app_id=dict(type='str',
|
||||
required=False,
|
||||
fallback=(env_fallback, ['DECORT_APP_ID'])),
|
||||
@@ -917,10 +680,52 @@ class decort_kvmvm(DecortController):
|
||||
workflow_context=dict(type='str', required=False),
|
||||
chipset=dict(
|
||||
type='str',
|
||||
default='i440fx',
|
||||
choices=['Q35', 'q35', 'I440FX', 'i440fx']
|
||||
choices=['Q35', 'i440fx']
|
||||
),
|
||||
cpu_pin=dict(
|
||||
type='bool',
|
||||
),
|
||||
hp_backed=dict(
|
||||
type='bool',
|
||||
),
|
||||
numa_affinity=dict(
|
||||
type='str',
|
||||
choices=['strict', 'loose', 'none'],
|
||||
),
|
||||
custom_fields=dict(
|
||||
type='dict',
|
||||
options=dict(
|
||||
fields=dict(
|
||||
type='dict',
|
||||
),
|
||||
disable=dict(
|
||||
type='bool',
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
def check_amodule_args_for_change(self):
|
||||
new_boot_disk_size = self.amodule.params['boot_disk']
|
||||
if new_boot_disk_size is not None:
|
||||
for disk in self.comp_info['disks']:
|
||||
if disk['type'] == 'B':
|
||||
boot_disk_size = disk['sizeMax']
|
||||
break
|
||||
else:
|
||||
self.message(
|
||||
f'Can\'t set boot disk size for Compute '
|
||||
f'{self.comp_info["id"]}, because it doesn\'t have a '
|
||||
f'boot disk.'
|
||||
)
|
||||
self.exit(fail=True)
|
||||
if new_boot_disk_size < boot_disk_size:
|
||||
self.message(
|
||||
f'New boot disk size {new_boot_disk_size} is less than '
|
||||
f'current {boot_disk_size} for Compute ID '
|
||||
f'{self.comp_info["id"]}'
|
||||
)
|
||||
self.exit(fail=True)
|
||||
|
||||
# Workflow digest:
|
||||
# 1) authenticate to DECORT controller & validate authentication by issuing API call - done when creating DECSController
|
||||
@@ -980,6 +785,8 @@ def main():
|
||||
pass
|
||||
|
||||
if subj.comp_id:
|
||||
subj.check_amodule_args_for_change()
|
||||
|
||||
if subj.comp_info['status'] in ("DISABLED", "MIGRATING", "DELETING", "DESTROYING", "ERROR", "REDEPLOYING"):
|
||||
# cannot do anything on the existing Compute in the listed states
|
||||
subj.error() # was subj.nop()
|
||||
@@ -1011,6 +818,8 @@ def main():
|
||||
elif amodule.params['state'] == 'paused':
|
||||
subj.error()
|
||||
else:
|
||||
subj.check_amodule_args_for_create()
|
||||
|
||||
# Preexisting Compute of specified identity was not found.
|
||||
# If requested state is 'absent' - nothing to do
|
||||
if amodule.params['state'] == 'absent':
|
||||
|
||||
Reference in New Issue
Block a user