one_image: Add image creation and timeout (#9075)
* Add creation one_image * Add CHANGELOG * PR fix docs * Add doc line for createpull/9098/head
parent
2429e228a4
commit
cecaa1840d
|
@ -0,0 +1,3 @@
|
||||||
|
minor_changes:
|
||||||
|
- one_image - add ``create``, ``template`` and ``datastore_id`` arguments for image creation (https://github.com/ansible-collections/community.general/pull/9075).
|
||||||
|
- one_image - add ``wait_timeout`` argument for adjustable timeouts (https://github.com/ansible-collections/community.general/pull/9075).
|
|
@ -20,42 +20,65 @@ extends_documentation_fragment:
|
||||||
- community.general.opennebula
|
- community.general.opennebula
|
||||||
- community.general.attributes
|
- community.general.attributes
|
||||||
attributes:
|
attributes:
|
||||||
check_mode:
|
check_mode:
|
||||||
support: full
|
support: full
|
||||||
diff_mode:
|
diff_mode:
|
||||||
support: none
|
support: none
|
||||||
options:
|
options:
|
||||||
id:
|
id:
|
||||||
description:
|
description:
|
||||||
- A O(id) of the image you would like to manage.
|
- A O(id) of the image you would like to manage.
|
||||||
type: int
|
type: int
|
||||||
name:
|
name:
|
||||||
description:
|
description:
|
||||||
- A O(name) of the image you would like to manage.
|
- A O(name) of the image you would like to manage.
|
||||||
type: str
|
- Required if O(create=true).
|
||||||
state:
|
type: str
|
||||||
description:
|
state:
|
||||||
- V(present) - state that is used to manage the image
|
description:
|
||||||
- V(absent) - delete the image
|
- V(present) - state that is used to manage the image.
|
||||||
- V(cloned) - clone the image
|
- V(absent) - delete the image.
|
||||||
- V(renamed) - rename the image to the O(new_name)
|
- V(cloned) - clone the image.
|
||||||
choices: ["present", "absent", "cloned", "renamed"]
|
- V(renamed) - rename the image to the O(new_name).
|
||||||
default: present
|
choices: ["present", "absent", "cloned", "renamed"]
|
||||||
type: str
|
default: present
|
||||||
enabled:
|
type: str
|
||||||
description:
|
enabled:
|
||||||
- Whether the image should be enabled or disabled.
|
description:
|
||||||
type: bool
|
- Whether the image should be enabled or disabled.
|
||||||
new_name:
|
type: bool
|
||||||
description:
|
new_name:
|
||||||
- A name that will be assigned to the existing or new image.
|
description:
|
||||||
- In the case of cloning, by default O(new_name) will take the name of the origin image with the prefix 'Copy of'.
|
- A name that will be assigned to the existing or new image.
|
||||||
type: str
|
- In the case of cloning, by default O(new_name) will take the name of the origin image with the prefix 'Copy of'.
|
||||||
persistent:
|
type: str
|
||||||
description:
|
persistent:
|
||||||
- Whether the image should be persistent or non-persistent.
|
description:
|
||||||
type: bool
|
- Whether the image should be persistent or non-persistent.
|
||||||
version_added: 9.5.0
|
type: bool
|
||||||
|
version_added: 9.5.0
|
||||||
|
create:
|
||||||
|
description:
|
||||||
|
- Whether the image should be created if not present.
|
||||||
|
- This is ignored if O(state=absent).
|
||||||
|
type: bool
|
||||||
|
version_added: 10.0.0
|
||||||
|
template:
|
||||||
|
description:
|
||||||
|
- Use with O(create=true) to specify image template.
|
||||||
|
type: str
|
||||||
|
version_added: 10.0.0
|
||||||
|
datastore_id:
|
||||||
|
description:
|
||||||
|
- Use with O(create=true) to specify datastore for image.
|
||||||
|
type: int
|
||||||
|
version_added: 10.0.0
|
||||||
|
wait_timeout:
|
||||||
|
description:
|
||||||
|
- Seconds to wait until image is ready, deleted or cloned.
|
||||||
|
type: int
|
||||||
|
default: 60
|
||||||
|
version_added: 10.0.0
|
||||||
author:
|
author:
|
||||||
- "Milan Ilic (@ilicmilan)"
|
- "Milan Ilic (@ilicmilan)"
|
||||||
'''
|
'''
|
||||||
|
@ -102,6 +125,35 @@ EXAMPLES = '''
|
||||||
community.general.one_image:
|
community.general.one_image:
|
||||||
id: '{{ result.id }}'
|
id: '{{ result.id }}'
|
||||||
state: absent
|
state: absent
|
||||||
|
|
||||||
|
- name: Make sure IMAGE is present
|
||||||
|
community.general.one_image:
|
||||||
|
name: myyy-image
|
||||||
|
state: present
|
||||||
|
create: true
|
||||||
|
datastore_id: 100
|
||||||
|
template: |
|
||||||
|
PATH = "/var/tmp/image"
|
||||||
|
TYPE = "OS"
|
||||||
|
SIZE = 20512
|
||||||
|
FORMAT = "qcow2"
|
||||||
|
PERSISTENT = "Yes"
|
||||||
|
DEV_PREFIX = "vd"
|
||||||
|
|
||||||
|
- name: Make sure IMAGE is present with a longer timeout
|
||||||
|
community.general.one_image:
|
||||||
|
name: big-image
|
||||||
|
state: present
|
||||||
|
create: true
|
||||||
|
datastore_id: 100
|
||||||
|
wait_timeout: 900
|
||||||
|
template: |
|
||||||
|
PATH = "https://192.0.2.200/repo/tipa_image.raw"
|
||||||
|
TYPE = "OS"
|
||||||
|
SIZE = 82048
|
||||||
|
FORMAT = "raw"
|
||||||
|
PERSISTENT = "Yes"
|
||||||
|
DEV_PREFIX = "vd"
|
||||||
'''
|
'''
|
||||||
|
|
||||||
RETURN = '''
|
RETURN = '''
|
||||||
|
@ -328,15 +380,20 @@ IMAGE_STATES = ['INIT', 'READY', 'USED', 'DISABLED', 'LOCKED', 'ERROR', 'CLONE',
|
||||||
class ImageModule(OpenNebulaModule):
|
class ImageModule(OpenNebulaModule):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
argument_spec = dict(
|
argument_spec = dict(
|
||||||
id=dict(type='int', required=False),
|
id=dict(type='int'),
|
||||||
name=dict(type='str', required=False),
|
name=dict(type='str'),
|
||||||
state=dict(type='str', choices=['present', 'absent', 'cloned', 'renamed'], default='present'),
|
state=dict(type='str', choices=['present', 'absent', 'cloned', 'renamed'], default='present'),
|
||||||
enabled=dict(type='bool', required=False),
|
enabled=dict(type='bool'),
|
||||||
new_name=dict(type='str', required=False),
|
new_name=dict(type='str'),
|
||||||
persistent=dict(type='bool', required=False),
|
persistent=dict(type='bool'),
|
||||||
|
create=dict(type='bool'),
|
||||||
|
template=dict(type='str'),
|
||||||
|
datastore_id=dict(type='int'),
|
||||||
|
wait_timeout=dict(type='int', default=60),
|
||||||
)
|
)
|
||||||
required_if = [
|
required_if = [
|
||||||
['state', 'renamed', ['id']]
|
['state', 'renamed', ['id']],
|
||||||
|
['create', True, ['template', 'datastore_id', 'name']],
|
||||||
]
|
]
|
||||||
mutually_exclusive = [
|
mutually_exclusive = [
|
||||||
['id', 'name'],
|
['id', 'name'],
|
||||||
|
@ -356,26 +413,32 @@ class ImageModule(OpenNebulaModule):
|
||||||
enabled = params.get('enabled')
|
enabled = params.get('enabled')
|
||||||
new_name = params.get('new_name')
|
new_name = params.get('new_name')
|
||||||
persistent = params.get('persistent')
|
persistent = params.get('persistent')
|
||||||
|
create = params.get('create')
|
||||||
|
template = params.get('template')
|
||||||
|
datastore_id = params.get('datastore_id')
|
||||||
|
wait_timeout = params.get('wait_timeout')
|
||||||
|
|
||||||
self.result = {}
|
self.result = {}
|
||||||
|
|
||||||
image = self.get_image_instance(id, name)
|
image = self.get_image_instance(id, name)
|
||||||
if not image and desired_state != 'absent':
|
if not image and desired_state != 'absent':
|
||||||
|
if create:
|
||||||
|
self.result = self.create_image(name, template, datastore_id, wait_timeout)
|
||||||
# Using 'if id:' doesn't work properly when id=0
|
# Using 'if id:' doesn't work properly when id=0
|
||||||
if id is not None:
|
elif id is not None:
|
||||||
module.fail_json(msg="There is no image with id=" + str(id))
|
module.fail_json(msg="There is no image with id=" + str(id))
|
||||||
elif name is not None:
|
elif name is not None:
|
||||||
module.fail_json(msg="There is no image with name=" + name)
|
module.fail_json(msg="There is no image with name=" + name)
|
||||||
|
|
||||||
if desired_state == 'absent':
|
if desired_state == 'absent':
|
||||||
self.result = self.delete_image(image)
|
self.result = self.delete_image(image, wait_timeout)
|
||||||
else:
|
else:
|
||||||
if persistent is not None:
|
if persistent is not None:
|
||||||
self.result = self.change_persistence(image, persistent)
|
self.result = self.change_persistence(image, persistent)
|
||||||
if enabled is not None:
|
if enabled is not None:
|
||||||
self.result = self.enable_image(image, enabled)
|
self.result = self.enable_image(image, enabled)
|
||||||
if desired_state == "cloned":
|
if desired_state == "cloned":
|
||||||
self.result = self.clone_image(image, new_name)
|
self.result = self.clone_image(image, new_name, wait_timeout)
|
||||||
elif desired_state == "renamed":
|
elif desired_state == "renamed":
|
||||||
self.result = self.rename_image(image, new_name)
|
self.result = self.rename_image(image, new_name)
|
||||||
|
|
||||||
|
@ -404,6 +467,16 @@ class ImageModule(OpenNebulaModule):
|
||||||
else:
|
else:
|
||||||
return self.get_image_by_name(requested_name)
|
return self.get_image_by_name(requested_name)
|
||||||
|
|
||||||
|
def create_image(self, image_name, template, datastore_id, wait_timeout):
|
||||||
|
if not self.module.check_mode:
|
||||||
|
image_id = self.one.image.allocate("NAME = \"" + image_name + "\"\n" + template, datastore_id)
|
||||||
|
self.wait_for_ready(image_id, wait_timeout)
|
||||||
|
image = self.get_image_by_id(image_id)
|
||||||
|
result = self.get_image_info(image)
|
||||||
|
|
||||||
|
result['changed'] = True
|
||||||
|
return result
|
||||||
|
|
||||||
def wait_for_ready(self, image_id, wait_timeout=60):
|
def wait_for_ready(self, image_id, wait_timeout=60):
|
||||||
import time
|
import time
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
@ -491,7 +564,7 @@ class ImageModule(OpenNebulaModule):
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def clone_image(self, image, new_name):
|
def clone_image(self, image, new_name, wait_timeout):
|
||||||
if new_name is None:
|
if new_name is None:
|
||||||
new_name = "Copy of " + image.NAME
|
new_name = "Copy of " + image.NAME
|
||||||
|
|
||||||
|
@ -506,7 +579,7 @@ class ImageModule(OpenNebulaModule):
|
||||||
|
|
||||||
if not self.module.check_mode:
|
if not self.module.check_mode:
|
||||||
new_id = self.one.image.clone(image.ID, new_name)
|
new_id = self.one.image.clone(image.ID, new_name)
|
||||||
self.wait_for_ready(new_id)
|
self.wait_for_ready(new_id, wait_timeout)
|
||||||
image = self.one.image.info(new_id)
|
image = self.one.image.info(new_id)
|
||||||
|
|
||||||
result = self.get_image_info(image)
|
result = self.get_image_info(image)
|
||||||
|
@ -534,7 +607,7 @@ class ImageModule(OpenNebulaModule):
|
||||||
result['changed'] = True
|
result['changed'] = True
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def delete_image(self, image):
|
def delete_image(self, image, wait_timeout):
|
||||||
if not image:
|
if not image:
|
||||||
return {'changed': False}
|
return {'changed': False}
|
||||||
|
|
||||||
|
@ -543,7 +616,7 @@ class ImageModule(OpenNebulaModule):
|
||||||
|
|
||||||
if not self.module.check_mode:
|
if not self.module.check_mode:
|
||||||
self.one.image.delete(image.ID)
|
self.one.image.delete(image.ID)
|
||||||
self.wait_for_delete(image.ID)
|
self.wait_for_delete(image.ID, wait_timeout)
|
||||||
|
|
||||||
return {'changed': True}
|
return {'changed': True}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue