Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36773c7bb3 | ||
|
|
3d9917b8a7 | ||
|
|
a166ce1c8d | ||
|
|
e81bf1ca16 | ||
|
|
2c95c6ef0c | ||
|
|
18067b82b7 | ||
|
|
bc317d1438 | ||
|
|
e17c8be53a | ||
|
|
2014863c37 | ||
|
|
4b57777a2c |
@@ -1,12 +1,12 @@
|
|||||||
# decort-ansible
|
# decort-ansible
|
||||||
Ansible modules for Digital Energy Orchestration Technology (DECORT) platform v3.4.2 and above
|
Ansible modules for Digital Energy Orchestration Technology (DECORT) platform v3.6.1 and above.
|
||||||
|
|
||||||
Note that this module may produce unreliable results when used with older DECORT API versions.
|
Note that this module may produce unreliable results when used with older DECORT API versions.
|
||||||
|
|
||||||
Requirements:
|
Requirements:
|
||||||
* Ansible 2.7 or higher
|
* Ansible 2.7 or higher
|
||||||
* Python 2.6 or higher
|
* Python 2.6 or higher
|
||||||
* PyJWT Python module
|
* PyJWT 1.7.1 Python module
|
||||||
* requests Python module
|
* requests Python module
|
||||||
* netaddr Python module
|
* netaddr Python module
|
||||||
* DECORT cloud platform version 3.4.2 or higher
|
* DECORT cloud platform version 3.5.0 or higher
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
#
|
#
|
||||||
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
||||||
# Copyright: (c) 2018-2020 Digital Energy Cloud Solutions LLC
|
# Copyright: (c) 2018-2021 Digital Energy Cloud Solutions LLC
|
||||||
#
|
#
|
||||||
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||||
#
|
#
|
||||||
@@ -30,7 +30,7 @@ requirements:
|
|||||||
- requests Python module
|
- requests Python module
|
||||||
- netaddr Python module
|
- netaddr Python module
|
||||||
- decort_utils utility library (module)
|
- decort_utils utility library (module)
|
||||||
- DECORT cloud platform version 3.4.2 or higher
|
- DECORT cloud platform version 3.6.1 or higher
|
||||||
notes:
|
notes:
|
||||||
- Environment variables can be used to pass selected parameters to the module, see details below.
|
- 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.
|
- Specified Oauth2 provider must be trusted by the DECORT cloud controller on which JWT will be used.
|
||||||
@@ -139,7 +139,7 @@ options:
|
|||||||
description:
|
description:
|
||||||
- Name of the pool where to place new disk. Once disk is created, its pool cannot be changed.
|
- Name of the pool where to place new disk. Once disk is created, its pool cannot be changed.
|
||||||
- This parameter is used when creating new disk and igonred for all other operations.
|
- This parameter is used when creating new disk and igonred for all other operations.
|
||||||
default: default
|
default: empty string
|
||||||
required: no
|
required: no
|
||||||
sep_id:
|
sep_id:
|
||||||
description:
|
description:
|
||||||
@@ -209,7 +209,6 @@ EXAMPLES = '''
|
|||||||
controller_url: "https://cloud.digitalenergy.online"
|
controller_url: "https://cloud.digitalenergy.online"
|
||||||
name: "MyDataDisk01"
|
name: "MyDataDisk01"
|
||||||
sep_id: 1
|
sep_id: 1
|
||||||
pool: "default"
|
|
||||||
size: 50
|
size: 50
|
||||||
account_name: "MyAccount"
|
account_name: "MyAccount"
|
||||||
state: present
|
state: present
|
||||||
@@ -275,7 +274,7 @@ def decort_disk_package_facts(disk_facts, check_mode=False):
|
|||||||
ret_dict['size'] = disk_facts['sizeMax']
|
ret_dict['size'] = disk_facts['sizeMax']
|
||||||
ret_dict['state'] = disk_facts['status']
|
ret_dict['state'] = disk_facts['status']
|
||||||
ret_dict['account_id'] = disk_facts['accountId']
|
ret_dict['account_id'] = disk_facts['accountId']
|
||||||
ret_dict['sep_id'] = disk_facts['sepid']
|
ret_dict['sep_id'] = disk_facts['sepId']
|
||||||
ret_dict['pool'] = disk_facts['pool']
|
ret_dict['pool'] = disk_facts['pool']
|
||||||
ret_dict['attached_to'] = disk_facts['vmid']
|
ret_dict['attached_to'] = disk_facts['vmid']
|
||||||
ret_dict['gid'] = disk_facts['gid']
|
ret_dict['gid'] = disk_facts['gid']
|
||||||
@@ -316,7 +315,7 @@ def decort_disk_parameters():
|
|||||||
fallback=(env_fallback, ['DECORT_PASSWORD']),
|
fallback=(env_fallback, ['DECORT_PASSWORD']),
|
||||||
no_log=True),
|
no_log=True),
|
||||||
place_with=dict(type='int', required=False, default=0),
|
place_with=dict(type='int', required=False, default=0),
|
||||||
pool=dict(type='str', required=False, default='default'),
|
pool=dict(type='str', required=False, default=''),
|
||||||
sep_id=dict(type='int', required=False, default=0),
|
sep_id=dict(type='int', required=False, default=0),
|
||||||
size=dict(type='int', required=False),
|
size=dict(type='int', required=False),
|
||||||
state=dict(type='str',
|
state=dict(type='str',
|
||||||
@@ -402,7 +401,7 @@ def main():
|
|||||||
|
|
||||||
disk_should_exist = False
|
disk_should_exist = False
|
||||||
target_sep_id = 0
|
target_sep_id = 0
|
||||||
target_pool = "default"
|
# target_pool = ""
|
||||||
|
|
||||||
if disk_id:
|
if disk_id:
|
||||||
disk_should_exist = True
|
disk_should_exist = True
|
||||||
@@ -455,10 +454,10 @@ def main():
|
|||||||
# request to place this disk on the same SEP as the specified OS image
|
# request to place this disk on the same SEP as the specified OS image
|
||||||
# validate specified OS image and assign SEP ID accordingly
|
# validate specified OS image and assign SEP ID accordingly
|
||||||
image_id, image_facts = decon.image_find(amodule.params['place_with'], "", 0)
|
image_id, image_facts = decon.image_find(amodule.params['place_with'], "", 0)
|
||||||
target_sep_id = image_facts['sepid']
|
target_sep_id = image_facts['sepId']
|
||||||
else:
|
else:
|
||||||
# no new SEP ID is explicitly specified, and no place_with option - use sep_id from the disk_facts
|
# no new SEP ID is explicitly specified, and no place_with option - use sepId from the disk_facts
|
||||||
target_sep_id = disk_facts['sepid']
|
target_sep_id = disk_facts['sepId']
|
||||||
disk_id = decon.disk_provision(disk_name=disk_facts['name'], # as this disk was found, its name is in the facts
|
disk_id = decon.disk_provision(disk_name=disk_facts['name'], # as this disk was found, its name is in the facts
|
||||||
size=amodule.params['size'],
|
size=amodule.params['size'],
|
||||||
account_id=validated_acc_id,
|
account_id=validated_acc_id,
|
||||||
@@ -496,7 +495,7 @@ def main():
|
|||||||
# request to place this disk on the same SEP as the specified OS image
|
# request to place this disk on the same SEP as the specified OS image
|
||||||
# validate specified OS image and assign SEP ID accordingly
|
# validate specified OS image and assign SEP ID accordingly
|
||||||
image_id, image_facts = decon.image_find(amodule.params['place_with'], "", 0)
|
image_id, image_facts = decon.image_find(amodule.params['place_with'], "", 0)
|
||||||
target_sep_id = image_facts['sepid']
|
target_sep_id = image_facts['sepId']
|
||||||
else:
|
else:
|
||||||
# no SEP ID is explicitly specified, and no place_with option - we do not know where
|
# no SEP ID is explicitly specified, and no place_with option - we do not know where
|
||||||
# to place the new disk - fail the module
|
# to place the new disk - fail the module
|
||||||
@@ -509,7 +508,7 @@ def main():
|
|||||||
size=amodule.params['size'],
|
size=amodule.params['size'],
|
||||||
account_id=validated_acc_id,
|
account_id=validated_acc_id,
|
||||||
sep_id=target_sep_id,
|
sep_id=target_sep_id,
|
||||||
pool=amodule.params['pool'],
|
pool_name=amodule.params['pool'],
|
||||||
desc=amodule.params['annotation'],
|
desc=amodule.params['annotation'],
|
||||||
location="")
|
location="")
|
||||||
disk_should_exist = True
|
disk_should_exist = True
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
#
|
#
|
||||||
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
||||||
# Copyright: (c) 2018-2020 Digital Energy Cloud Solutions LLC
|
# Copyright: (c) 2018-2021 Digital Energy Cloud Solutions LLC
|
||||||
#
|
#
|
||||||
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||||
#
|
#
|
||||||
@@ -32,7 +32,7 @@ requirements:
|
|||||||
- PyJWT module
|
- PyJWT module
|
||||||
- requests module
|
- requests module
|
||||||
- decort_utils utility library (module)
|
- decort_utils utility library (module)
|
||||||
- DECORT cloud platform version 3.4.2 or higher
|
- DECORT cloud platform version 3.6.1 or higher
|
||||||
options:
|
options:
|
||||||
app_id:
|
app_id:
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
#
|
#
|
||||||
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
||||||
# Copyright: (c) 2018-2020 Digital Energy Cloud Solutions LLC
|
# Copyright: (c) 2018-2021 Digital Energy Cloud Solutions LLC
|
||||||
#
|
#
|
||||||
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||||
#
|
#
|
||||||
@@ -32,7 +32,7 @@ requirements:
|
|||||||
- requests Python module
|
- requests Python module
|
||||||
- netaddr Python module
|
- netaddr Python module
|
||||||
- decort_utils utility library (module)
|
- decort_utils utility library (module)
|
||||||
- DECORT cloud platform version 3.4.2 or higher
|
- DECORT cloud platform version 3.6.1 or higher
|
||||||
notes:
|
notes:
|
||||||
- Environment variables can be used to pass selected parameters to the module, see details below.
|
- 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.
|
- Specified Oauth2 provider must be trusted by the DECORT cloud controller on which JWT will be used.
|
||||||
@@ -77,8 +77,8 @@ options:
|
|||||||
- Architecture of the KVM VM. DECORT supports KVM hosts based on Intel x86 and IBM PowerPC hardware.
|
- Architecture of the KVM VM. DECORT supports KVM hosts based on Intel x86 and IBM PowerPC hardware.
|
||||||
- This parameter is used when new KVM VM is created and ignored for all other operations.
|
- 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.
|
- Module may fail if your DECORT installation does not have physical nodes of specified architecture.
|
||||||
default: KVM_X86
|
default: X86_64
|
||||||
choices: [ KVM_X86, KVM_PPC ]
|
choices: [ X86_64, PPC64_LE ]
|
||||||
required: yes
|
required: yes
|
||||||
authenticator:
|
authenticator:
|
||||||
description:
|
description:
|
||||||
@@ -439,8 +439,8 @@ class decort_kvmvm(DecortController):
|
|||||||
check_state=False)
|
check_state=False)
|
||||||
|
|
||||||
if self.comp_id:
|
if self.comp_id:
|
||||||
if self.comp_info['status'] != 'DESTROYED' and self.comp_info['arch'] not in ["KVM_X86", "KVM_PPC"]:
|
if self.comp_info['status'] != 'DESTROYED' and self.comp_info['arch'] not in ["X86_64", "PPC64_LE"]:
|
||||||
# If we found a Compute in a non-DESTROYED state and it is not of type KVM_*, abort the module
|
# If we found a Compute in a non-DESTROYED state and it is not of type valid arch, abort the module
|
||||||
self.result['failed'] = True
|
self.result['failed'] = True
|
||||||
self.result['msg'] = ("Compute ID {} architecture '{}' is not supported by "
|
self.result['msg'] = ("Compute ID {} architecture '{}' is not supported by "
|
||||||
"decort_kvmvm module.").format(self.comp_id,
|
"decort_kvmvm module.").format(self.comp_id,
|
||||||
@@ -500,7 +500,7 @@ class decort_kvmvm(DecortController):
|
|||||||
self.check_amodule_argument('cpu')
|
self.check_amodule_argument('cpu')
|
||||||
self.check_amodule_argument('ram')
|
self.check_amodule_argument('ram')
|
||||||
|
|
||||||
if self.amodule.params['arch'] not in ["KVM_X86", "KVM_PPC"]:
|
if self.amodule.params['arch'] not in ["X86_64", "PPC64_LE"]:
|
||||||
self.result['failed'] = True
|
self.result['failed'] = True
|
||||||
self.result['msg'] = ("Unsupported architecture '{}' is specified for "
|
self.result['msg'] = ("Unsupported architecture '{}' is specified for "
|
||||||
"KVM VM create.").format(self.amodule.params['arch'])
|
"KVM VM create.").format(self.amodule.params['arch'])
|
||||||
@@ -743,7 +743,7 @@ class decort_kvmvm(DecortController):
|
|||||||
required=False,
|
required=False,
|
||||||
fallback=(env_fallback, ['DECORT_APP_SECRET']),
|
fallback=(env_fallback, ['DECORT_APP_SECRET']),
|
||||||
no_log=True),
|
no_log=True),
|
||||||
arch=dict(type='str', choices=['KVM_X86', 'KVM_PPC'], default='KVM_X86'),
|
arch=dict(type='str', choices=['X86_64', 'PPC64_LE'], default='X86_64'),
|
||||||
authenticator=dict(type='str',
|
authenticator=dict(type='str',
|
||||||
required=True,
|
required=True,
|
||||||
choices=['legacy', 'oauth2', 'jwt']),
|
choices=['legacy', 'oauth2', 'jwt']),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
#
|
#
|
||||||
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
||||||
# Copyright: (c) 2018-2020 Digital Energy Cloud Solutions LLC
|
# Copyright: (c) 2018-2021 Digital Energy Cloud Solutions LLC
|
||||||
#
|
#
|
||||||
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||||
#
|
#
|
||||||
@@ -33,7 +33,7 @@ requirements:
|
|||||||
- requests Python module
|
- requests Python module
|
||||||
- netaddr Python module
|
- netaddr Python module
|
||||||
- decort_utils utility library (module)
|
- decort_utils utility library (module)
|
||||||
- DECORT cloud platform version 3.4.2 or higher.
|
- DECORT cloud platform version 3.6.1 or higher.
|
||||||
notes:
|
notes:
|
||||||
- Environment variables can be used to pass selected parameters to the module, see details below.
|
- 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.
|
- Specified Oauth2 provider must be trusted by the DECORT cloud controller on which JWT will be used.
|
||||||
@@ -203,7 +203,7 @@ def decort_osimage_package_facts(arg_osimage_facts, arg_check_mode=False):
|
|||||||
ret_dict['size'] = arg_osimage_facts['size']
|
ret_dict['size'] = arg_osimage_facts['size']
|
||||||
ret_dict['type'] = arg_osimage_facts['type']
|
ret_dict['type'] = arg_osimage_facts['type']
|
||||||
# ret_dict['arch'] = arg_osimage_facts['architecture']
|
# ret_dict['arch'] = arg_osimage_facts['architecture']
|
||||||
ret_dict['sep_id'] = arg_osimage_facts['sepid']
|
ret_dict['sep_id'] = arg_osimage_facts['sepId']
|
||||||
ret_dict['pool'] = arg_osimage_facts['pool']
|
ret_dict['pool'] = arg_osimage_facts['pool']
|
||||||
ret_dict['state'] = arg_osimage_facts['status']
|
ret_dict['state'] = arg_osimage_facts['status']
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
#
|
#
|
||||||
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
||||||
# Copyright: (c) 2018-2020 Digital Energy Cloud Solutions LLC
|
# Copyright: (c) 2018-2021 Digital Energy Cloud Solutions LLC
|
||||||
#
|
#
|
||||||
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||||
#
|
#
|
||||||
@@ -30,7 +30,7 @@ requirements:
|
|||||||
- requests Python module
|
- requests Python module
|
||||||
- netaddr Python module
|
- netaddr Python module
|
||||||
- decort_utils utility library (module)
|
- decort_utils utility library (module)
|
||||||
- DECORT cloud platform version 3.4.2 or higher
|
- DECORT cloud platform version 3.6.1 or higher
|
||||||
notes:
|
notes:
|
||||||
- Environment variables can be used to pass selected parameters to the module, see details below.
|
- 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.
|
- Specified Oauth2 provider must be trusted by the DECORT cloud controller on which JWT will be used.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
#
|
#
|
||||||
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
||||||
# Copyright: (c) 2018-2020 Digital Energy Cloud Solutions LLC
|
# Copyright: (c) 2018-2021 Digital Energy Cloud Solutions LLC
|
||||||
#
|
#
|
||||||
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||||
#
|
#
|
||||||
@@ -30,7 +30,7 @@ requirements:
|
|||||||
- requests Python module
|
- requests Python module
|
||||||
- netaddr Python module
|
- netaddr Python module
|
||||||
- decort_utils utility library (module)
|
- decort_utils utility library (module)
|
||||||
- DECORT cloud platform version 3.4.2 or higher
|
- DECORT cloud platform version 3.6.1 or higher
|
||||||
notes:
|
notes:
|
||||||
- Environment variables can be used to pass selected parameters to the module, see details below.
|
- 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.
|
- Specified Oauth2 provider must be trusted by the DECORT cloud controller on which JWT will be used.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
#
|
#
|
||||||
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
||||||
# Copyright: (c) 2018-2020 Digital Energy Cloud Solutions LLC
|
# Copyright: (c) 2018-2021 Digital Energy Cloud Solutions LLC
|
||||||
#
|
#
|
||||||
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||||
#
|
#
|
||||||
@@ -30,7 +30,7 @@ requirements:
|
|||||||
- requests Python module
|
- requests Python module
|
||||||
- netaddr Python module
|
- netaddr Python module
|
||||||
- decort_utils utility library (module)
|
- decort_utils utility library (module)
|
||||||
- DECORT cloud platform version 3.4.2 or higher
|
- DECORT cloud platform version 3.6.1 or higher
|
||||||
notes:
|
notes:
|
||||||
- Environment variables can be used to pass selected parameters to the module, see details below.
|
- 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.
|
- Specified Oauth2 provider must be trusted by the DECORT cloud controller on which JWT will be used.
|
||||||
@@ -273,7 +273,7 @@ def decort_vins_package_facts(arg_vins_facts, arg_check_mode=False):
|
|||||||
ret_dict['name'] = arg_vins_facts['name']
|
ret_dict['name'] = arg_vins_facts['name']
|
||||||
ret_dict['state'] = arg_vins_facts['status']
|
ret_dict['state'] = arg_vins_facts['status']
|
||||||
ret_dict['account_id'] = arg_vins_facts['accountId']
|
ret_dict['account_id'] = arg_vins_facts['accountId']
|
||||||
ret_dict['rg_id'] = arg_vins_facts['rgid']
|
ret_dict['rg_id'] = arg_vins_facts['rgId']
|
||||||
ret_dict['int_net_addr'] = arg_vins_facts['network']
|
ret_dict['int_net_addr'] = arg_vins_facts['network']
|
||||||
ret_dict['gid'] = arg_vins_facts['gid']
|
ret_dict['gid'] = arg_vins_facts['gid']
|
||||||
|
|
||||||
@@ -385,7 +385,7 @@ def main():
|
|||||||
decon.fail_json(**decon.result)
|
decon.fail_json(**decon.result)
|
||||||
vins_level="ID"
|
vins_level="ID"
|
||||||
validated_acc_id = vins_facts['accountId']
|
validated_acc_id = vins_facts['accountId']
|
||||||
validated_rg_id = vins_facts['rgid']
|
validated_rg_id = vins_facts['rgId']
|
||||||
elif amodule.params['rg_id']:
|
elif amodule.params['rg_id']:
|
||||||
# expect ViNS @ RG level in the RG with specified ID
|
# expect ViNS @ RG level in the RG with specified ID
|
||||||
vins_level="RG"
|
vins_level="RG"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
# Digital Enegry Cloud Orchestration Technology (DECORT) modules for Ansible
|
||||||
# Copyright: (c) 2018-2020 Digital Energy Cloud Solutions LLC
|
# Copyright: (c) 2018-2021 Digital Energy Cloud Solutions LLC
|
||||||
#
|
#
|
||||||
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
# Apache License 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.txt)
|
||||||
#
|
#
|
||||||
@@ -28,7 +28,7 @@ Requirements:
|
|||||||
- PyJWT Python module
|
- PyJWT Python module
|
||||||
- requests Python module
|
- requests Python module
|
||||||
- netaddr Python module
|
- netaddr Python module
|
||||||
- DECORT cloud platform version 3.4.2 or higher
|
- DECORT cloud platform version 3.6.1 or higher
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
@@ -272,7 +272,7 @@ class DecortController(object):
|
|||||||
# never be executed
|
# never be executed
|
||||||
return False
|
return False
|
||||||
|
|
||||||
req_url = self.controller_url + "/restmachine/cloudapi/accounts/list"
|
req_url = self.controller_url + "/restmachine/cloudapi/account/list"
|
||||||
req_header = dict(Authorization="bearer {}".format(arg_jwt),)
|
req_header = dict(Authorization="bearer {}".format(arg_jwt),)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -316,7 +316,7 @@ class DecortController(object):
|
|||||||
self.amodule.fail_json(**self.result)
|
self.amodule.fail_json(**self.result)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
req_url = self.controller_url + "/restmachine/cloudapi/users/authenticate"
|
req_url = self.controller_url + "/restmachine/cloudapi/user/authenticate"
|
||||||
req_data = dict(username=self.user,
|
req_data = dict(username=self.user,
|
||||||
password=self.password,)
|
password=self.password,)
|
||||||
|
|
||||||
@@ -518,8 +518,11 @@ class DecortController(object):
|
|||||||
#
|
#
|
||||||
# then all values when entering this method will be of type string. We need to
|
# then all values when entering this method will be of type string. We need to
|
||||||
# explicitly cast int type on all of them.
|
# explicitly cast int type on all of them.
|
||||||
|
if new_data_disks is not None:
|
||||||
for idx, repair in enumerate(new_data_disks):
|
for idx, repair in enumerate(new_data_disks):
|
||||||
new_data_disks[idx] = int(repair)
|
new_data_disks[idx] = int(repair)
|
||||||
|
else:
|
||||||
|
new_data_disks = []
|
||||||
|
|
||||||
for disk in comp_dict['disks']:
|
for disk in comp_dict['disks']:
|
||||||
if disk['type'] == 'B':
|
if disk['type'] == 'B':
|
||||||
@@ -766,8 +769,8 @@ class DecortController(object):
|
|||||||
|
|
||||||
@param (int) rg_id: ID of the RG where the VM will be provisioned.
|
@param (int) rg_id: ID of the RG where the VM will be provisioned.
|
||||||
@param (string) comp_name: that specifies the name of the VM.
|
@param (string) comp_name: that specifies the name of the VM.
|
||||||
@param (string) arch: hardware architecture of KVM VM. Supported values are: "KVM_X86" for Intel x86
|
@param (string) arch: hardware architecture of KVM VM. Supported values are: "X86_64" for Intel x86
|
||||||
and "KVM_PPC" for IBM PowerPC.
|
and "PPC64_LE" for IBM PowerPC.
|
||||||
@param (int) cpu: how many virtual CPUs to allocate.
|
@param (int) cpu: how many virtual CPUs to allocate.
|
||||||
@param (int) ram: volume of RAM in MB to allocate (i.e. pass 4096 to allocate 4GB RAM).
|
@param (int) ram: volume of RAM in MB to allocate (i.e. pass 4096 to allocate 4GB RAM).
|
||||||
@param (int) boot_disk: boot disk size in GB.
|
@param (int) boot_disk: boot disk size in GB.
|
||||||
@@ -789,9 +792,9 @@ class DecortController(object):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
api_url=""
|
api_url=""
|
||||||
if arch == "KVM_X86":
|
if arch == "X86_64":
|
||||||
api_url = "/restmachine/cloudapi/kvmx86/create"
|
api_url = "/restmachine/cloudapi/kvmx86/create"
|
||||||
elif arch == "KVM_PPC":
|
elif arch == "PPC64_LE":
|
||||||
api_url = "/restmachine/cloudapi/kvmppc/create"
|
api_url = "/restmachine/cloudapi/kvmppc/create"
|
||||||
else:
|
else:
|
||||||
self.result['failed'] = True
|
self.result['failed'] = True
|
||||||
@@ -864,19 +867,28 @@ class DecortController(object):
|
|||||||
api_params = dict(accountId = comp_dict['accountId'])
|
api_params = dict(accountId = comp_dict['accountId'])
|
||||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/vins/search", api_params)
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/vins/search", api_params)
|
||||||
vins_list = json.loads(api_resp.content.decode('utf8'))
|
vins_list = json.loads(api_resp.content.decode('utf8'))
|
||||||
if not len(vins_list):
|
#
|
||||||
self.result['failed'] = True
|
# We should not fail the module if ViNS list is empty - it is not an error, as in case of
|
||||||
self.result['msg'] = ("compute_networks() cannot obtain VINS list for Account ID {}, "
|
# API failure "decort_api_call" will abort the module execution on its own. Hence the
|
||||||
"Compute ID {}.").format(comp_dict['accountId'], comp_dict['id'])
|
# following code fragment is commented out
|
||||||
return
|
#
|
||||||
|
# if not len(vins_list):
|
||||||
|
# self.result['failed'] = True
|
||||||
|
# self.result['msg'] = ("compute_networks() cannot obtain VINS list for Account ID {}, "
|
||||||
|
# "Compute ID {}.").format(comp_dict['accountId'], comp_dict['id'])
|
||||||
|
# return
|
||||||
|
|
||||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/externalnetwork/list", api_params)
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/extnet/list", api_params)
|
||||||
extnet_list = json.loads(api_resp.content.decode('utf8')) # list of dicts: "name" holds "NET_ADDR/NETMASK", "id" is ID
|
extnet_list = json.loads(api_resp.content.decode('utf8')) # list of dicts: "name" holds "NET_ADDR/NETMASK", "id" is ID
|
||||||
if not len(vins_list):
|
#
|
||||||
self.result['failed'] = True
|
# Empty extnet_list does not constitute error condition, so we should not fail the module in
|
||||||
self.result['msg'] = ("compute_networks() cannot obtain External networks list for Account ID {}, "
|
# this case. Therefore the following code fragment is commented out.
|
||||||
"Compute ID {}.").format(comp_dict['accountId'], comp_dict['id'])
|
#
|
||||||
return
|
# if not len(extnet_list):
|
||||||
|
# self.result['failed'] = True
|
||||||
|
# self.result['msg'] = ("compute_networks() cannot obtain External networks list for Account ID {}, "
|
||||||
|
# "Compute ID {}.").format(comp_dict['accountId'], comp_dict['id'])
|
||||||
|
# return
|
||||||
|
|
||||||
# Prepare the lists of network interfaces for the compute instance:
|
# Prepare the lists of network interfaces for the compute instance:
|
||||||
vins_iface_list = [] # will contain dict(id=<int>, ipAddress=<str>, mac=<str>) for ifaces connected to ViNS(es)
|
vins_iface_list = [] # will contain dict(id=<int>, ipAddress=<str>, mac=<str>) for ifaces connected to ViNS(es)
|
||||||
@@ -902,6 +914,19 @@ class DecortController(object):
|
|||||||
mac=iface['mac'])
|
mac=iface['mac'])
|
||||||
enet_iface_list.append(iface_data)
|
enet_iface_list.append(iface_data)
|
||||||
|
|
||||||
|
# If at this point compt_dict["interfaces"] lists some interfaces, but neither vins_iface_list
|
||||||
|
# nor enet_iface_list contain any members, it means that none of the ViNS or Ext Nets currently
|
||||||
|
# available to us match existing interfaces of the Compute instance.
|
||||||
|
# This is abnormal condition and we should not proceed any further.
|
||||||
|
if len(comp_dict['interfaces']) and (not len(vins_iface_list) and not len(enet_iface_list)):
|
||||||
|
self.result['failed'] = True
|
||||||
|
self.result['msg'] = ("compute_networks() no match between {} interface(s) of Compute ID {}"
|
||||||
|
"and available {} ViNS(es) or {} ExtNet(s).").format(len(comp_dict['interfaces']),
|
||||||
|
comp_dict['id'],
|
||||||
|
len(vins_list),
|
||||||
|
len(extnet_list))
|
||||||
|
return
|
||||||
|
|
||||||
vins_id_list = [ rec['id'] for rec in vins_iface_list ]
|
vins_id_list = [ rec['id'] for rec in vins_iface_list ]
|
||||||
|
|
||||||
enet_id_list = [ rec['id'] for rec in enet_iface_list ]
|
enet_id_list = [ rec['id'] for rec in enet_iface_list ]
|
||||||
@@ -1165,11 +1190,11 @@ class DecortController(object):
|
|||||||
# OS image manipulation methods
|
# OS image manipulation methods
|
||||||
###################################
|
###################################
|
||||||
def _image_get_by_id(self, image_id):
|
def _image_get_by_id(self, image_id):
|
||||||
# TODO: update once cloudapi/images/get is implemented, see ticket #2963
|
# TODO: update once cloudapi/image/get is implemented, see ticket #2963
|
||||||
|
|
||||||
api_params = dict(imageId=image_id,
|
api_params = dict(imageId=image_id,
|
||||||
showAll=False)
|
showAll=False)
|
||||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/images/get", api_params)
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/image/get", api_params)
|
||||||
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||||
ret_image_dict = json.loads(api_resp.content.decode('utf8'))
|
ret_image_dict = json.loads(api_resp.content.decode('utf8'))
|
||||||
|
|
||||||
@@ -1204,7 +1229,7 @@ class DecortController(object):
|
|||||||
if image_id > 0:
|
if image_id > 0:
|
||||||
ret_image_id, ret_image_dict = self._image_get_by_id(image_id)
|
ret_image_id, ret_image_dict = self._image_get_by_id(image_id)
|
||||||
if ( ret_image_id and
|
if ( ret_image_id and
|
||||||
(sepid == 0 or sepid == ret_image_dict['sepid']) and
|
(sepid == 0 or sepid == ret_image_dict['sepId']) and
|
||||||
(pool == "" or pool == ret_image_dict['pool']) ):
|
(pool == "" or pool == ret_image_dict['pool']) ):
|
||||||
return ret_image_id, ret_image_dict
|
return ret_image_id, ret_image_dict
|
||||||
else:
|
else:
|
||||||
@@ -1218,7 +1243,7 @@ class DecortController(object):
|
|||||||
validated_acc_id = rg_facts['accountId']
|
validated_acc_id = rg_facts['accountId']
|
||||||
|
|
||||||
api_params = dict(accountId=validated_acc_id)
|
api_params = dict(accountId=validated_acc_id)
|
||||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/images/list", api_params)
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/image/list", api_params)
|
||||||
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
# On success the above call will return here. On error it will abort execution by calling fail_json.
|
||||||
images_list = json.loads(api_resp.content.decode('utf8'))
|
images_list = json.loads(api_resp.content.decode('utf8'))
|
||||||
for image_record in images_list:
|
for image_record in images_list:
|
||||||
@@ -1228,7 +1253,7 @@ class DecortController(object):
|
|||||||
return image_record['id'], image_record
|
return image_record['id'], image_record
|
||||||
# if positive SEP ID and/or non-emtpy pool name are passed, match by them
|
# if positive SEP ID and/or non-emtpy pool name are passed, match by them
|
||||||
full_match = True
|
full_match = True
|
||||||
if sepid > 0 and sepid != image_record['sepid']:
|
if sepid > 0 and sepid != image_record['sepId']:
|
||||||
full_match = False
|
full_match = False
|
||||||
if pool != "" and pool != image_record['pool']:
|
if pool != "" and pool != image_record['pool']:
|
||||||
full_match = False
|
full_match = False
|
||||||
@@ -1355,12 +1380,12 @@ class DecortController(object):
|
|||||||
self.amodule.fail_json(**self.result)
|
self.amodule.fail_json(**self.result)
|
||||||
# try to locate RG by name - start with getting all RGs IDs within the specified account
|
# try to locate RG by name - start with getting all RGs IDs within the specified account
|
||||||
api_params['accountId'] = arg_account_id
|
api_params['accountId'] = arg_account_id
|
||||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/accounts/get", api_params)
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/account/listRG", api_params)
|
||||||
if api_resp.status_code == 200:
|
if api_resp.status_code == 200:
|
||||||
account_specs = json.loads(api_resp.content.decode('utf8'))
|
account_specs = json.loads(api_resp.content.decode('utf8'))
|
||||||
api_params.pop('accountId')
|
api_params.pop('accountId')
|
||||||
for rg_id in account_specs['rgs']:
|
for rg_item in account_specs:
|
||||||
got_id, got_specs = self._rg_get_by_id(rg_id)
|
got_id, got_specs = self._rg_get_by_id(rg_item['id'])
|
||||||
if got_id and got_specs['name'] == arg_rg_name:
|
if got_id and got_specs['name'] == arg_rg_name:
|
||||||
# name matches
|
# name matches
|
||||||
if not arg_check_state or got_specs['status'] not in RG_INVALID_STATES:
|
if not arg_check_state or got_specs['status'] not in RG_INVALID_STATES:
|
||||||
@@ -1608,12 +1633,12 @@ class DecortController(object):
|
|||||||
|
|
||||||
if account_name == "":
|
if account_name == "":
|
||||||
api_params['accountId'] = account_id
|
api_params['accountId'] = account_id
|
||||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/accounts/get", api_params)
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/account/get", api_params)
|
||||||
if api_resp.status_code == 200:
|
if api_resp.status_code == 200:
|
||||||
account_details = json.loads(api_resp.content.decode('utf8'))
|
account_details = json.loads(api_resp.content.decode('utf8'))
|
||||||
return account_details['id'], account_details
|
return account_details['id'], account_details
|
||||||
else:
|
else:
|
||||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/accounts/list", api_params)
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/account/list", api_params)
|
||||||
if api_resp.status_code == 200:
|
if api_resp.status_code == 200:
|
||||||
# Parse response to see if a account matching arg_account_name is found in the output
|
# Parse response to see if a account matching arg_account_name is found in the output
|
||||||
# If it is found, assign its ID to the return variable and copy dictionary with the facts
|
# If it is found, assign its ID to the return variable and copy dictionary with the facts
|
||||||
@@ -1623,7 +1648,7 @@ class DecortController(object):
|
|||||||
# get detailed information about the account from "accounts/get" call as
|
# get detailed information about the account from "accounts/get" call as
|
||||||
# "accounts/list" does not return all necessary fields
|
# "accounts/list" does not return all necessary fields
|
||||||
api_params['accountId'] = runner['id']
|
api_params['accountId'] = runner['id']
|
||||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/accounts/get", api_params)
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/account/get", api_params)
|
||||||
if api_resp.status_code == 200:
|
if api_resp.status_code == 200:
|
||||||
account_details = json.loads(api_resp.content.decode('utf8'))
|
account_details = json.loads(api_resp.content.decode('utf8'))
|
||||||
return account_details['id'], account_details
|
return account_details['id'], account_details
|
||||||
@@ -2122,7 +2147,7 @@ class DecortController(object):
|
|||||||
"was requested.").format(vins_dict['id'],vins_dict['name'])
|
"was requested.").format(vins_dict['id'],vins_dict['name'])
|
||||||
return
|
return
|
||||||
|
|
||||||
if not vins_dict['rgid']:
|
if not vins_dict['rgId']:
|
||||||
# this ViNS exists at account level - no updates are possible
|
# this ViNS exists at account level - no updates are possible
|
||||||
self.result['warning'] = ("vins_update(): no update is possible for ViNS ID {} "
|
self.result['warning'] = ("vins_update(): no update is possible for ViNS ID {} "
|
||||||
"as it exists at account level.").format(vins_dict['id'])
|
"as it exists at account level.").format(vins_dict['id'])
|
||||||
@@ -2301,7 +2326,7 @@ class DecortController(object):
|
|||||||
|
|
||||||
return 0, None
|
return 0, None
|
||||||
|
|
||||||
def disk_provision(self, disk_name, size, account_id, sep_id, pool="default", desc="", location=""):
|
def disk_provision(self, disk_name, size, account_id, sep_id, pool_name="", desc="", location=""):
|
||||||
"""Provision Disk according to the specified arguments.
|
"""Provision Disk according to the specified arguments.
|
||||||
Note that disks created by this method will be of type 'D' (data disks).
|
Note that disks created by this method will be of type 'D' (data disks).
|
||||||
If critical error occurs the embedded call to API function will abort further execution
|
If critical error occurs the embedded call to API function will abort further execution
|
||||||
@@ -2336,11 +2361,12 @@ class DecortController(object):
|
|||||||
api_params = dict(accountId=account_id,
|
api_params = dict(accountId=account_id,
|
||||||
gid=target_gid,
|
gid=target_gid,
|
||||||
name=disk_name,
|
name=disk_name,
|
||||||
description=desc,
|
desc=desc,
|
||||||
size=size,
|
size=size,
|
||||||
type='D',
|
type='D',
|
||||||
sep_id=sep_id,
|
sepId=sep_id,)
|
||||||
pool=pool,)
|
if pool_name != "":
|
||||||
|
api_params['pool'] = pool_name
|
||||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/disks/create", api_params)
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/disks/create", api_params)
|
||||||
if api_resp.status_code == 200:
|
if api_resp.status_code == 200:
|
||||||
ret_disk_id = json.loads(api_resp.content.decode('utf8'))
|
ret_disk_id = json.loads(api_resp.content.decode('utf8'))
|
||||||
|
|||||||
Reference in New Issue
Block a user