Fixing initial bugs in Disk and KvmVM modules, adjusting utility module accordingly
This commit is contained in:
@@ -78,20 +78,20 @@ options:
|
|||||||
- URL of the DECORT controller that will be contacted to manage the RG according to the specification.
|
- URL of the DECORT controller that will be contacted to manage the RG according to the specification.
|
||||||
- 'This parameter is always required regardless of the specified I(authenticator) type.'
|
- 'This parameter is always required regardless of the specified I(authenticator) type.'
|
||||||
required: yes
|
required: yes
|
||||||
disk_id:
|
id:
|
||||||
description:
|
description:
|
||||||
- `ID of the disk to manage. If I(disk_id) is specified it is assumed, that this disk already
|
- `ID of the disk to manage. If I(id) is specified it is assumed, that this disk already
|
||||||
exists. In other words, you cannot create new disk by specifying its ID, use I(disk_name)
|
exists. In other words, you cannot create new disk by specifying its ID, use I(name)
|
||||||
when creating new disk.`
|
when creating new disk.`
|
||||||
- `If non-zero I(disk_id) is specified, then I(disk_name), I(account_id) and I(account_name)
|
- `If non-zero I(id) is specified, then I(name), I(account_id) and I(account_name)
|
||||||
are ignored.`
|
are ignored.`
|
||||||
default: 0
|
default: 0
|
||||||
required: no
|
required: no
|
||||||
disk_name:
|
name:
|
||||||
description:
|
description:
|
||||||
- `Name of the disk to manage. To manage disk by name you also need to specify either
|
- `Name of the disk to manage. To manage disk by name you also need to specify either
|
||||||
I(account_id) or I(account_name).`
|
I(account_id) or I(account_name).`
|
||||||
- If non-zero I(disk_id) is specified, I(disk_name) is ignored.
|
- If non-zero I(id) is specified, I(name) is ignored.
|
||||||
- `Note that the platform does not enforce uniqueness of disk names, so if more than one
|
- `Note that the platform does not enforce uniqueness of disk names, so if more than one
|
||||||
disk with this name exists under the specified account, module will return the first
|
disk with this name exists under the specified account, module will return the first
|
||||||
occurence.`
|
occurence.`
|
||||||
@@ -206,7 +206,7 @@ EXAMPLES = '''
|
|||||||
app_id: "{{ MY_APP_ID }}"
|
app_id: "{{ MY_APP_ID }}"
|
||||||
app_secret: "{{ MY_APP_SECRET }}"
|
app_secret: "{{ MY_APP_SECRET }}"
|
||||||
controller_url: "https://cloud.digitalenergy.online"
|
controller_url: "https://cloud.digitalenergy.online"
|
||||||
disk_name: "MyDataDisk01"
|
name: "MyDataDisk01"
|
||||||
sep_id: 1
|
sep_id: 1
|
||||||
pool: "default"
|
pool: "default"
|
||||||
size: 50
|
size: 50
|
||||||
@@ -288,7 +288,7 @@ def decort_disk_parameters():
|
|||||||
return dict(
|
return dict(
|
||||||
account_id=dict(type='int', required=False, default=0),
|
account_id=dict(type='int', required=False, default=0),
|
||||||
account_name=dict(type='str', required=False, default=''),
|
account_name=dict(type='str', required=False, default=''),
|
||||||
annotation=dict(type='str', required=False, default=''),
|
annotation=dict(type='str', required=False, default='Disk by decort_disk'),
|
||||||
app_id=dict(type='str',
|
app_id=dict(type='str',
|
||||||
required=False,
|
required=False,
|
||||||
fallback=(env_fallback, ['DECORT_APP_ID'])),
|
fallback=(env_fallback, ['DECORT_APP_ID'])),
|
||||||
@@ -300,8 +300,8 @@ def decort_disk_parameters():
|
|||||||
required=True,
|
required=True,
|
||||||
choices=['legacy', 'oauth2', 'jwt']),
|
choices=['legacy', 'oauth2', 'jwt']),
|
||||||
controller_url=dict(type='str', required=True),
|
controller_url=dict(type='str', required=True),
|
||||||
disk_id=dict(type='int', required=False, default=0),
|
id=dict(type='int', required=False, default=0),
|
||||||
disk_name=dict(type='str', required=False),
|
name=dict(type='str', required=False),
|
||||||
force_detach=dict(type='bool', required=False, default=False),
|
force_detach=dict(type='bool', required=False, default=False),
|
||||||
jwt=dict(type='str',
|
jwt=dict(type='str',
|
||||||
required=False,
|
required=False,
|
||||||
@@ -352,18 +352,18 @@ def main():
|
|||||||
validated_acc_id = 0
|
validated_acc_id = 0
|
||||||
acc_facts = None # will hold Account facts
|
acc_facts = None # will hold Account facts
|
||||||
|
|
||||||
if amodule.params['disk_id']:
|
if amodule.params['id']:
|
||||||
# expect existing Disk with the specified ID
|
# expect existing Disk with the specified ID
|
||||||
# This call to disk_find will abort the module if no Disk with such ID is present
|
# This call to disk_find will abort the module if no Disk with such ID is present
|
||||||
disk_id, disk_facts = decon.disk_find(amodule.params['disk_id'])
|
disk_id, disk_facts = decon.disk_find(amodule.params['id'])
|
||||||
if not disk_id:
|
if not disk_id:
|
||||||
decon.result['failed'] = True
|
decon.result['failed'] = True
|
||||||
decon.result['msg'] = "Specified Disk ID {} not found.".format(amodule.params['disk_id'])
|
decon.result['msg'] = "Specified Disk ID {} not found.".format(amodule.params['id'])
|
||||||
amodule.fail_json(**decon.result)
|
amodule.fail_json(**decon.result)
|
||||||
validated_acc_id =disk_facts['accountId']
|
validated_acc_id =disk_facts['accountId']
|
||||||
elif (amodule.params['account_id'] or amodule.params['account_name'] != "") and amodule.params['disk_name'] != "":
|
elif (amodule.params['account_id'] or amodule.params['account_name'] != "") and amodule.params['name'] != "":
|
||||||
# Make sure disk name is specified, if not - fail the module
|
# Make sure disk name is specified, if not - fail the module
|
||||||
if amodule.params['disk_name'] == "":
|
if amodule.params['name'] == "":
|
||||||
decon.result['failed'] = True
|
decon.result['failed'] = True
|
||||||
decon.result['msg'] = ("Cannot manage disk if both ID is 0 and disk name is empty.")
|
decon.result['msg'] = ("Cannot manage disk if both ID is 0 and disk name is empty.")
|
||||||
amodule.fail_json(**decon.result)
|
amodule.fail_json(**decon.result)
|
||||||
@@ -375,7 +375,7 @@ def main():
|
|||||||
"or non-existent account specified.")
|
"or non-existent account specified.")
|
||||||
amodule.fail_json(**decon.result)
|
amodule.fail_json(**decon.result)
|
||||||
# This call to disk_find may return disk_id=0 if no Disk with this name found in
|
# This call to disk_find may return disk_id=0 if no Disk with this name found in
|
||||||
disk_id, disk_facts = decon.disk_find(disk_id=0, disk_name=amodule.params['disk_name'],
|
disk_id, disk_facts = decon.disk_find(disk_id=0, disk_name=amodule.params['name'],
|
||||||
account_id=validated_acc_id,
|
account_id=validated_acc_id,
|
||||||
check_state=False)
|
check_state=False)
|
||||||
else:
|
else:
|
||||||
@@ -384,7 +384,7 @@ def main():
|
|||||||
decon.result['failed'] = True
|
decon.result['failed'] = True
|
||||||
if amodule.params['account_id'] == 0 and amodule.params['account_name'] == "":
|
if amodule.params['account_id'] == 0 and amodule.params['account_name'] == "":
|
||||||
decon.result['msg'] = "Cannot find Disk by name when account name is empty and account ID is 0."
|
decon.result['msg'] = "Cannot find Disk by name when account name is empty and account ID is 0."
|
||||||
if amodule.params['disk_name'] == "":
|
if amodule.params['name'] == "":
|
||||||
decon.result['msg'] = "Cannot find Disk by empty name."
|
decon.result['msg'] = "Cannot find Disk by empty name."
|
||||||
amodule.fail_json(**decon.result)
|
amodule.fail_json(**decon.result)
|
||||||
|
|
||||||
@@ -400,6 +400,8 @@ def main():
|
|||||||
#
|
#
|
||||||
|
|
||||||
disk_should_exist = False
|
disk_should_exist = False
|
||||||
|
target_sep_id = 0
|
||||||
|
target_pool = "default"
|
||||||
|
|
||||||
if disk_id:
|
if disk_id:
|
||||||
disk_should_exist = True
|
disk_should_exist = True
|
||||||
@@ -451,8 +453,8 @@ def main():
|
|||||||
elif decon.check_amodule_argument('place_with', False) and amodule.params['place_with'] > 0:
|
elif decon.check_amodule_argument('place_with', False) and amodule.params['place_with'] > 0:
|
||||||
# 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()
|
image_id, image_facts = decon.image_find(amodule.params['place_with'], "", 0)
|
||||||
pass
|
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 sep_id from the disk_facts
|
||||||
target_sep_id = disk_facts['sepid']
|
target_sep_id = disk_facts['sepid']
|
||||||
@@ -480,14 +482,29 @@ def main():
|
|||||||
decon.result['failed'] = False
|
decon.result['failed'] = False
|
||||||
decon.result['changed'] = False
|
decon.result['changed'] = False
|
||||||
decon.result['msg'] = ("Nothing to do as target state 'absent' was requested for "
|
decon.result['msg'] = ("Nothing to do as target state 'absent' was requested for "
|
||||||
"non-existent Disk name '{}'").format(amodule.params['disk_name'])
|
"non-existent Disk name '{}'").format(amodule.params['name'])
|
||||||
elif amodule.params['state'] == 'present':
|
elif amodule.params['state'] == 'present':
|
||||||
decon.check_amodule_argument('disk_name')
|
decon.check_amodule_argument('name') # if disk name not specified, fail the module
|
||||||
# as we already have account ID, we can create Disk and get disk_id on success
|
decon.check_amodule_argument('size') # if disk size not specified, fail the module
|
||||||
#
|
|
||||||
# TODO: implement SEP ID selction logic
|
# as we already have account ID, we can create Disk and get disk id on success
|
||||||
#
|
if decon.check_amodule_argument('sep_id', False) and amodule.params['sep_id'] > 0:
|
||||||
disk_id = decon.disk_provision(disk_name=disk_facts['name'], # as this disk was found, its name is in the facts
|
# non-zero sep_id is explicitly passed in module arguments
|
||||||
|
target_sep_id = amodule.params['sep_id']
|
||||||
|
elif decon.check_amodule_argument('place_with', False) and amodule.params['place_with'] > 0:
|
||||||
|
# request to place this disk on the same SEP as the specified OS image
|
||||||
|
# validate specified OS image and assign SEP ID accordingly
|
||||||
|
image_id, image_facts = decon.image_find(amodule.params['place_with'], "", 0)
|
||||||
|
target_sep_id = image_facts['sepid']
|
||||||
|
else:
|
||||||
|
# no SEP ID is explicitly specified, and no place_with option - we do not know where
|
||||||
|
# to place the new disk - fail the module
|
||||||
|
decon.result['failed'] = True
|
||||||
|
decon.result['msg'] = ("Cannot create new Disk name '{}': no SEP ID specified and "
|
||||||
|
"no 'place_with' option used.").format(amodule.params['name'])
|
||||||
|
amodule.fail_json(**decon.result)
|
||||||
|
|
||||||
|
disk_id = decon.disk_provision(disk_name=amodule.params['name'],
|
||||||
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,
|
||||||
@@ -500,7 +517,7 @@ def main():
|
|||||||
decon.result['changed'] = False
|
decon.result['changed'] = False
|
||||||
decon.result['msg'] = ("Invalid target state '{}' requested for non-existent "
|
decon.result['msg'] = ("Invalid target state '{}' requested for non-existent "
|
||||||
"Disk name '{}'").format(amodule.params['state'],
|
"Disk name '{}'").format(amodule.params['state'],
|
||||||
amodule.params['disk_name'])
|
amodule.params['name'])
|
||||||
|
|
||||||
#
|
#
|
||||||
# conditional switch end - complete module run
|
# conditional switch end - complete module run
|
||||||
|
|||||||
@@ -105,6 +105,11 @@ options:
|
|||||||
it accordingly. Note that resize operation on a running VM may generate errors as not all OS images support
|
it accordingly. Note that resize operation on a running VM may generate errors as not all OS images support
|
||||||
hot resize feature.'
|
hot resize feature.'
|
||||||
required: no
|
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:
|
id:
|
||||||
description:
|
description:
|
||||||
- ID of the KVM VM to manage.
|
- ID of the KVM VM to manage.
|
||||||
@@ -542,7 +547,7 @@ class decort_kvmvm(DecortController):
|
|||||||
|
|
||||||
# if we get through here, all parameters required to create new Compute instance should be at hand
|
# if we get through here, all parameters required to create new Compute instance should be at hand
|
||||||
|
|
||||||
self.comp_id = self.compute_provision(rg_id=self.rg_id,
|
self.comp_id = self.kvmvm_provision(rg_id=self.rg_id,
|
||||||
comp_name=self.amodule.params['name'], arch=self.amodule.params['arch'],
|
comp_name=self.amodule.params['name'], arch=self.amodule.params['arch'],
|
||||||
cpu=self.amodule.params['cpu'], ram=self.amodule.params['ram'],
|
cpu=self.amodule.params['cpu'], ram=self.amodule.params['ram'],
|
||||||
boot_disk=validated_bdisk_size,
|
boot_disk=validated_bdisk_size,
|
||||||
|
|||||||
@@ -763,14 +763,16 @@ class DecortController(object):
|
|||||||
|
|
||||||
api_params = dict(rgId=rg_id,
|
api_params = dict(rgId=rg_id,
|
||||||
name=comp_name,
|
name=comp_name,
|
||||||
description=annotation,
|
cpu=cpu, ram=ram,
|
||||||
vcpus=cpu, memory=ram,
|
|
||||||
imageId=image_id,
|
imageId=image_id,
|
||||||
disksize=boot_disk,
|
bootDisk=boot_disk,
|
||||||
start_machine=start_on_create) # start_machine parameter requires DECORT API ver 3.3.1 or higher
|
start=start_on_create) # start_machine parameter requires DECORT API ver 3.3.1 or higher
|
||||||
if userdata:
|
if userdata:
|
||||||
api_params['userdata'] = json.dumps(userdata) # we need to pass a string object as "userdata"
|
api_params['userdata'] = json.dumps(userdata) # we need to pass a string object as "userdata"
|
||||||
|
|
||||||
|
if annotation:
|
||||||
|
api_params['decs'] = annotation
|
||||||
|
|
||||||
api_resp = self.decort_api_call(requests.post, api_url, api_params)
|
api_resp = self.decort_api_call(requests.post, api_url, 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.
|
||||||
self.result['failed'] = False
|
self.result['failed'] = False
|
||||||
@@ -2212,17 +2214,10 @@ class DecortController(object):
|
|||||||
return 0, None
|
return 0, None
|
||||||
elif disk_name != "":
|
elif disk_name != "":
|
||||||
if account_id > 0:
|
if account_id > 0:
|
||||||
# TODO: in the absense of disks/list or disks/search API call it is not possible to
|
|
||||||
# fully implement this method
|
|
||||||
#
|
|
||||||
self.result['failed'] = True
|
|
||||||
self.result['msg'] = "disk_find(): looking up disk by name and account ID not implemented."
|
|
||||||
self.amodule.fail_json(**self.result)
|
|
||||||
#
|
|
||||||
api_params = dict(accountId=account_id,
|
api_params = dict(accountId=account_id,
|
||||||
name=disk_name,
|
name=disk_name,
|
||||||
showAll=False) # we do not want to see disks in DESTROYED, PURGED or invalid states
|
showAll=False) # we do not want to see disks in DESTROYED, PURGED or invalid states
|
||||||
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/disks/search", api_params)
|
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/disks/list", api_params)
|
||||||
# the above call may return more than one matching disk
|
# the above call may return more than one matching disk
|
||||||
disks_list = json.loads(api_resp.content.decode('utf8'))
|
disks_list = json.loads(api_resp.content.decode('utf8'))
|
||||||
for runner in disks_list:
|
for runner in disks_list:
|
||||||
@@ -2287,6 +2282,9 @@ class DecortController(object):
|
|||||||
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'))
|
||||||
|
|
||||||
|
self.result['failed'] = False
|
||||||
|
self.result['changed'] = True
|
||||||
|
|
||||||
return ret_disk_id
|
return ret_disk_id
|
||||||
|
|
||||||
def disk_resize(self, disk_facts, new_size):
|
def disk_resize(self, disk_facts, new_size):
|
||||||
|
|||||||
Reference in New Issue
Block a user