Refactored volume_snapshot{,_info} modules

Change-Id: I70fc744f786a9de654592c97188af48ddbe8751d
This commit is contained in:
Jakob Meng
2022-11-03 11:29:01 +01:00
parent 8c889f8eb3
commit b3c2e8f1ce
7 changed files with 327 additions and 197 deletions

View File

@@ -4,7 +4,7 @@
# Copyright (c) 2016, Mario Santos <mario.rf.santos@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
DOCUMENTATION = '''
DOCUMENTATION = r'''
---
module: volume_snapshot
short_description: Create/Delete Cinder Volume Snapshots
@@ -12,75 +12,109 @@ author: OpenStack Ansible SIG
description:
- Create or Delete cinder block storage volume snapshots
options:
display_name:
description:
- Name of the snapshot
required: true
aliases: ['name']
type: str
display_description:
description:
- String describing the snapshot
aliases: ['description']
type: str
volume:
description:
- The volume name or id to create/delete the snapshot
required: True
type: str
force:
description:
- Allows or disallows snapshot of a volume to be created when the volume
is attached to an instance.
type: bool
default: 'no'
state:
description:
- Should the resource be present or absent.
choices: [present, absent]
default: present
type: str
description:
description:
- String describing the snapshot
aliases: ['display_description']
type: str
force:
description:
- Allows or disallows snapshot of a volume to be created,
when the volume is attached to an instance.
type: bool
default: 'no'
name:
description:
- Name of the snapshot
required: true
aliases: ['display_name']
type: str
state:
description:
- Should the snapshot be C(present) or C(absent).
choices: [present, absent]
default: present
type: str
volume:
description:
- Volume name or ID to create the snapshot from.
- Required when I(state) is C(present).
type: str
requirements:
- "python >= 3.6"
- "openstacksdk"
notes:
- Updating existing volume snapshots has not been implemented yet.
extends_documentation_fragment:
- openstack.cloud.openstack
'''
EXAMPLES = '''
# Creates a snapshot on volume 'test_volume'
- name: create and delete snapshot
hosts: localhost
tasks:
- name: create snapshot
openstack.cloud.volume_snapshot:
state: present
cloud: mordred
availability_zone: az2
display_name: test_snapshot
volume: test_volume
- name: delete snapshot
openstack.cloud.volume_snapshot:
state: absent
cloud: mordred
availability_zone: az2
display_name: test_snapshot
volume: test_volume
EXAMPLES = r'''
- name: create snapshot
openstack.cloud.volume_snapshot:
state: present
cloud: mordred
name: test_snapshot
volume: test_volume
- name: delete snapshot
openstack.cloud.volume_snapshot:
state: absent
cloud: mordred
name: test_snapshot
volume: test_volume
'''
RETURN = '''
RETURN = r'''
snapshot:
description: The snapshot instance after the change
description: Same as C(volume_snapshot), kept for backward compatibility.
returned: On success when C(state=present)
type: dict
volume_snapshot:
description: The snapshot instance
returned: success
type: dict
sample:
id: 837aca54-c0ee-47a2-bf9a-35e1b4fdac0c
name: test_snapshot
volume_id: ec646a7c-6a35-4857-b38b-808105a24be6
size: 2
status: available
display_name: test_snapshot
contains:
created_at:
description: Snapshot creation time.
type: str
description:
description: Snapshot desciption.
type: str
id:
description: Unique UUID.
type: str
sample: "39007a7e-ee4f-4d13-8283-b4da2e037c69"
is_forced:
description: Indicate whether to create snapshot,
even if the volume is attached.
type: bool
metadata:
description: Snapshot metadata.
type: dict
name:
description: Snapshot Name.
type: str
progress:
description: The percentage of completeness the snapshot is
currently at.
type: str
project_id:
description: The project ID this snapshot is associated with.
type: str
size:
description: The size of the volume, in GBs.
type: int
status:
description: Snapshot status.
type: str
updated_at:
description: Snapshot update time.
type: str
volume_id:
description: Volume ID.
type: str
'''
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
@@ -88,74 +122,86 @@ from ansible_collections.openstack.cloud.plugins.module_utils.openstack import O
class VolumeSnapshotModule(OpenStackModule):
argument_spec = dict(
display_name=dict(required=True, aliases=['name']),
display_description=dict(aliases=['description']),
volume=dict(required=True),
description=dict(aliases=['display_description']),
name=dict(required=True, aliases=['display_name']),
force=dict(default=False, type='bool'),
state=dict(default='present', choices=['absent', 'present']),
volume=dict(),
)
module_kwargs = dict(
required_if=[
('state', 'present', ['volume'])
],
supports_check_mode=True
)
def _present_volume_snapshot(self):
volume = self.conn.get_volume(self.params['volume'])
snapshot = self.conn.get_volume_snapshot(
self.params['display_name'], filters={'volume_id': volume.id})
if not snapshot:
snapshot = self.conn.create_volume_snapshot(
volume.id,
force=self.params['force'],
wait=self.params['wait'],
timeout=self.params['timeout'],
name=self.params['display_name'],
description=self.params.get('display_description')
)
self.exit_json(changed=True, snapshot=snapshot)
else:
self.exit_json(changed=False, snapshot=snapshot)
def _absent_volume_snapshot(self):
volume = self.conn.get_volume(self.params['volume'])
snapshot = self.conn.get_volume_snapshot(
self.params['display_name'], filters={'volume_id': volume.id})
if not snapshot:
self.exit_json(changed=False)
else:
self.conn.delete_volume_snapshot(
name_or_id=snapshot.id,
wait=self.params['wait'],
timeout=self.params['timeout'],
)
self.exit_json(changed=True, snapshot_id=snapshot.id)
def _system_state_change(self):
volume = self.conn.get_volume(self.params['volume'])
snapshot = self.conn.get_volume_snapshot(
self.params['display_name'],
filters={'volume_id': volume.id})
state = self.params['state']
if state == 'present':
return snapshot is None
if state == 'absent':
return snapshot is not None
def run(self):
name = self.params['name']
state = self.params['state']
if self.conn.volume_exists(self.params['volume']):
if self.ansible.check_mode:
self.exit_json(changed=self._system_state_change())
if state == 'present':
self._present_volume_snapshot()
if state == 'absent':
self._absent_volume_snapshot()
snapshot = self.conn.block_storage.find_snapshot(name)
if self.ansible.check_mode:
self.exit_json(changed=self._will_change(state, snapshot))
if state == 'present' and not snapshot:
snapshot = self._create()
self.exit_json(changed=True,
snapshot=snapshot.to_dict(computed=False),
volume_snapshot=snapshot.to_dict(computed=False))
elif state == 'present' and snapshot:
# We do not support snapshot updates yet
# TODO: Implement module updates
self.exit_json(changed=False,
snapshot=snapshot.to_dict(computed=False),
volume_snapshot=snapshot.to_dict(computed=False))
elif state == 'absent' and snapshot:
self._delete(snapshot)
self.exit_json(changed=True)
else: # state == 'absent' and not snapshot
self.exit_json(changed=False)
def _create(self):
args = dict()
for k in ['description', 'force', 'name']:
if self.params[k] is not None:
args[k] = self.params[k]
volume_name_or_id = self.params['volume']
volume = self.conn.block_storage.find_volume(volume_name_or_id,
ignore_missing=False)
args['volume_id'] = volume.id
snapshot = self.conn.block_storage.create_snapshot(**args)
if self.params['wait']:
snapshot = self.conn.block_storage.wait_for_status(
snapshot, wait=self.params['timeout'])
return snapshot
def _delete(self, snapshot):
self.conn.block_storage.delete_snapshot(snapshot)
if self.params['wait']:
self.conn.block_storage.wait_for_delete(
snapshot, wait=self.params['timeout'])
def _will_change(self, state, snapshot):
if state == 'present' and not snapshot:
return True
elif state == 'present' and snapshot:
# We do not support snapshot updates yet
# TODO: Implement module updates
return False
elif state == 'absent' and snapshot:
return True
else:
self.fail_json(
msg="No volume with name or id '{0}' was found.".format(
self.params['volume']))
# state == 'absent' and not snapshot:
return False
def main():