Refactor server_volume to be compatible with openstacksdk>=0.99.0

Change-Id: Id636bc5de1acb59ad8587cd6c7181e022097cfe7
This commit is contained in:
Rafael Castillo 2022-09-21 16:11:02 -07:00
parent 41299b9666
commit ed36d82a0c
5 changed files with 262 additions and 57 deletions

View File

@ -103,6 +103,7 @@
security_group security_group
security_group_rule security_group_rule
server server
server_volume
stack stack
subnet subnet
subnet_pool subnet_pool

View File

@ -0,0 +1,32 @@
expected_fields:
- attachments
- availability_zone
- consistency_group_id
- created_at
- description
- extended_replication_status
- group_id
- host
- id
- image_id
- is_bootable
- is_encrypted
- metadata
- migration_id
- migration_status
- name
- project_id
- replication_driver_data
- replication_status
- scheduler_hints
- size
- snapshot_id
- source_volume_id
- status
- updated_at
- user_id
- volume_image_metadata
- volume_type
flavor: m1.tiny
server_name: ansible_server
server_network: private

View File

@ -0,0 +1,90 @@
- name: Create server
openstack.cloud.server:
cloud: "{{ cloud }}"
state: present
name: "{{ server_name }}"
image: "cirros-0.5.2-x86_64-disk"
flavor: "{{ flavor }}"
network: "{{ server_network }}"
auto_ip: false
wait: true
register: server
- name: Create volume
openstack.cloud.volume:
cloud: "{{ cloud }}"
state: present
size: 1
name: ansible_volume
wait: true
register: volume
- name: Attach volume to server
openstack.cloud.server_volume:
cloud: "{{ cloud }}"
server: "{{ server.server.id }}"
volume: "{{ volume.volume.id }}"
wait: true
register: server_volume
- name: Assert changed
assert:
that: server_volume is changed
- name: Assert return values of server_volume module
assert:
that:
# allow new fields to be introduced but prevent fields from being removed
- expected_fields|difference(server_volume.volume.keys())|length == 0
- name: Attach volume to server again
openstack.cloud.server_volume:
cloud: "{{ cloud }}"
server: "{{ server.server.id }}"
volume: "{{ volume.volume.id }}"
wait: true
register: server_volume
- name: Assert not changed
assert:
that: server_volume is not changed
- name: Detach volume to server
openstack.cloud.server_volume:
cloud: "{{ cloud }}"
state: absent
server: "{{ server.server.id }}"
volume: "{{ volume.volume.id }}"
wait: true
register: server_volume
- name: Assert changed
assert:
that: server_volume is changed
- name: Detach volume to server again
openstack.cloud.server_volume:
cloud: "{{ cloud }}"
state: absent
server: "{{ server.server.id }}"
volume: "{{ volume.volume.id }}"
wait: true
register: server_volume
- name: Assert not changed
assert:
that: server_volume is not changed
- name: Delete volume
openstack.cloud.volume:
cloud: "{{ cloud }}"
state: absent
name: ansible_volume
wait: true
- name: Delete server
openstack.cloud.server:
cloud: "{{ cloud }}"
state: absent
name: "{{ server_name }}"
wait: true

View File

@ -58,6 +58,7 @@
- { role: security_group, tags: security_group } - { role: security_group, tags: security_group }
- { role: security_group_rule, tags: security_group_rule } - { role: security_group_rule, tags: security_group_rule }
- { role: server, tags: server } - { role: server, tags: server }
- { role: server_volume, tags: server_volume }
- { role: stack, tags: stack } - { role: stack, tags: stack }
- { role: subnet, tags: subnet } - { role: subnet, tags: subnet }
- { role: subnet_pool, tags: subnet_pool } - { role: subnet_pool, tags: subnet_pool }

View File

@ -4,7 +4,7 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. # Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
DOCUMENTATION = ''' DOCUMENTATION = r'''
--- ---
module: server_volume module: server_volume
short_description: Attach/Detach Volumes from OpenStack VM's short_description: Attach/Detach Volumes from OpenStack VM's
@ -12,27 +12,26 @@ author: OpenStack Ansible SIG
description: description:
- Attach or Detach volumes from OpenStack VM's - Attach or Detach volumes from OpenStack VM's
options: options:
state: device:
description: description:
- Should the resource be present or absent. - Device you want to attach. Defaults to auto finding a device name.
choices: [present, absent]
default: present
required: false
type: str type: str
server: server:
description: description:
- Name or ID of server you want to attach a volume to - Name or ID of server you want to attach a volume to
required: true required: true
type: str type: str
state:
description:
- Should the resource be present or absent.
choices: [present, absent]
default: present
type: str
volume: volume:
description: description:
- Name or id of volume you want to attach to a server - Name or id of volume you want to attach to a server
required: true required: true
type: str type: str
device:
description:
- Device you want to attach. Defaults to auto finding a device name.
type: str
requirements: requirements:
- "python >= 3.6" - "python >= 3.6"
- "openstacksdk" - "openstacksdk"
@ -41,18 +40,120 @@ extends_documentation_fragment:
- openstack.cloud.openstack - openstack.cloud.openstack
''' '''
EXAMPLES = ''' RETURN = r'''
# Attaches a volume to a compute host volume:
- name: attach a volume type: dict
hosts: localhost description: Volume that was just attached
tasks: returned: On success when I(state) is present
- name: attach volume to host contains:
openstack.cloud.server_volume: attachments:
state: present description: Instance attachment information. If this volume is attached
cloud: mordred to a server instance, the attachments list includes the UUID
server: Mysql-server of the attached server, an attachment UUID, the name of the
volume: mysql-data attached host, if any, the volume UUID, the device, and the
device: /dev/vdb device UUID. Otherwise, this list is empty.
type: list
availability_zone:
description: The name of the availability zone.
type: str
consistency_group_id:
description: The UUID of the consistency group.
type: str
created_at:
description: The date and time when the resource was created.
type: str
description:
description: The volume description.
type: str
extended_replication_status:
description: Extended replication status on this volume.
type: str
group_id:
description: The ID of the group.
type: str
host:
description: The volume's current back-end.
type: str
id:
description: The UUID of the volume.
type: str
image_id:
description: Image on which the volume was based
type: str
is_bootable:
description: Enables or disables the bootable attribute. You can boot an
instance from a bootable volume.
type: str
is_encrypted:
description: If true, this volume is encrypted.
type: bool
metadata:
description: A metadata object. Contains one or more metadata key and
value pairs that are associated with the volume.
type: dict
migration_id:
description: The volume ID that this volume name on the backend is
based on.
type: str
migration_status:
description: The status of this volume migration (None means that a
migration is not currently in progress).
type: str
name:
description: The volume name.
type: str
project_id:
description: The project ID which the volume belongs to.
type: str
replication_driver_data:
description: Data set by the replication driver
type: str
replication_status:
description: The volume replication status.
type: str
scheduler_hints:
description: Scheduler hints for the volume
type: dict
size:
description: The size of the volume, in gibibytes (GiB).
type: int
snapshot_id:
description: To create a volume from an existing snapshot, specify the
UUID of the volume snapshot. The volume is created in same
availability zone and with same size as the snapshot.
type: str
source_volume_id:
description: The UUID of the source volume. The API creates a new volume
with the same size as the source volume unless a larger size
is requested.
type: str
status:
description: The volume status.
type: str
updated_at:
description: The date and time when the resource was updated.
type: str
user_id:
description: The UUID of the user.
type: str
volume_image_metadata:
description: List of image metadata entries. Only included for volumes
that were created from an image, or from a snapshot of a
volume originally created from an image.
type: dict
volume_type:
description: The associated volume type name for the volume.
type: str
'''
EXAMPLES = r'''
- name: Attaches a volume to a compute host
openstack.cloud.server_volume:
state: present
cloud: mordred
server: Mysql-server
volume: mysql-data
device: /dev/vdb
''' '''
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
@ -60,15 +161,8 @@ from ansible_collections.openstack.cloud.plugins.module_utils.openstack import O
def _system_state_change(state, device): def _system_state_change(state, device):
"""Check if system state would change.""" """Check if system state would change."""
if state == 'present': return (state == 'present' and not device) \
if device: or (state == 'absent' and device)
return False
return True
if state == 'absent':
if device:
return True
return False
return False
class ServerVolumeModule(OpenStackModule): class ServerVolumeModule(OpenStackModule):
@ -81,53 +175,40 @@ class ServerVolumeModule(OpenStackModule):
) )
def run(self): def run(self):
state = self.params['state'] state = self.params['state']
wait = self.params['wait'] wait = self.params['wait']
timeout = self.params['timeout'] timeout = self.params['timeout']
server = self.conn.get_server(self.params['server']) server = self.conn.compute.find_server(self.params['server'],
volume = self.conn.get_volume(self.params['volume']) ignore_missing=False)
volume = self.conn.block_storage.find_volume(self.params['volume'],
if not server: ignore_missing=False)
self.fail(msg='server %s is not found' % self.params['server'])
if not volume:
self.fail(msg='volume %s is not found' % self.params['volume'])
dev = self.conn.get_volume_attach_device(volume, server.id) dev = self.conn.get_volume_attach_device(volume, server.id)
if self.ansible.check_mode: if self.ansible.check_mode:
self.exit(changed=_system_state_change(state, dev)) self.exit_json(changed=_system_state_change(state, dev))
if state == 'present': if state == 'present':
changed = False changed = False
if not dev: if not dev:
changed = True changed = True
self.conn.attach_volume(server, volume, self.params['device'], self.conn.attach_volume(server, volume,
device=self.params['device'],
wait=wait, timeout=timeout) wait=wait, timeout=timeout)
# refresh volume object
volume = self.conn.block_storage.get_volume(volume.id)
server = self.conn.get_server(self.params['server']) # refresh self.exit_json(changed=changed,
volume = self.conn.get_volume(self.params['volume']) # refresh volume=volume.to_dict(computed=False))
hostvars = self.conn.get_openstack_vars(server)
self.exit(
changed=changed,
id=volume['id'],
attachments=volume['attachments'],
openstack=hostvars
)
elif state == 'absent': elif state == 'absent':
if not dev: if not dev:
# Volume is not attached to this server # Volume is not attached to this server
self.exit(changed=False) self.exit_json(changed=False)
self.conn.detach_volume(server, volume, wait=wait, timeout=timeout) self.conn.detach_volume(server, volume, wait=wait, timeout=timeout)
self.exit( self.exit_json(changed=True)
changed=True,
result='Detached volume from server'
)
def main(): def main():