From cc9ca5a34b42457e07c6b6c3ab0b921c61fa9b50 Mon Sep 17 00:00:00 2001 From: Jakob Meng Date: Fri, 13 Jan 2023 14:29:17 +0100 Subject: [PATCH] Refactored image{,_info} modules Code of the image module has been refactored partially only. It will have to be completed in a follow up patch. Change-Id: Id2360163117db9639a0af502ab44e02cae5cebaa --- ci/roles/image/tasks/main.yml | 556 +++++++++++------------ ci/roles/image_info/defaults/main.yml | 65 --- ci/roles/image_info/tasks/main.yml | 11 - ci/run-collection.yml | 1 - plugins/modules/image.py | 468 ++++++++------------ plugins/modules/image_info.py | 614 +++++++++++--------------- 6 files changed, 737 insertions(+), 978 deletions(-) delete mode 100644 ci/roles/image_info/defaults/main.yml delete mode 100644 ci/roles/image_info/tasks/main.yml diff --git a/ci/roles/image/tasks/main.yml b/ci/roles/image/tasks/main.yml index baed225d..419bab9c 100644 --- a/ci/roles/image/tasks/main.yml +++ b/ci/roles/image/tasks/main.yml @@ -1,317 +1,331 @@ --- -- name: Ensure image does not exist before tests - openstack.cloud.image: - cloud: "{{ cloud }}" - state: absent - name: ansible_image +- name: Test images + block: + - name: List all images + openstack.cloud.image_info: + cloud: "{{ cloud }}" + register: images -- name: Create a test image file - shell: mktemp - register: tmp_file + - name: Assert existence of CirrOS image + assert: + that: + - images.images | length > 0 -- name: Fill test image file to 1MB - shell: truncate -s 1048576 {{ tmp_file.stdout }} + - name: Ensure clean environment + ansible.builtin.set_fact: + tmp_file: !!null -- name: ensure mock kernel and ramdisk images (defaults) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - name: "{{ item }}" - filename: "{{ tmp_file.stdout }}" - disk_format: raw - loop: - - cirros-vmlinuz - - cirros-initrd + - name: Create a test image file + ansible.builtin.tempfile: + register: tmp_file -- name: Create raw image (defaults) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - name: ansible_image - filename: "{{ tmp_file.stdout }}" - is_protected: true - disk_format: raw - tags: - - test - - ansible - register: returned_image + - name: Fill test image file to 1MB + community.general.filesize: + path: '{{ tmp_file.path }}' + size: 1M -- debug: - var: returned_image + - name: Ensure mock kernel and ramdisk images (defaults) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + name: "{{ item }}" + filename: "{{ tmp_file.path }}" + disk_format: raw + loop: + - cirros-vmlinuz + - cirros-initrd -- name: Assert changed - assert: - that: returned_image is changed + - name: Create raw image (defaults) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + name: ansible_image + filename: "{{ tmp_file.path }}" + is_protected: true + disk_format: raw + tags: + - test + - ansible + register: image -- name: Assert fields - assert: - that: - - item in returned_image.image - loop: "{{ expected_fields }}" + - name: Assert changed + assert: + that: + - image is changed -- name: Get details of created image - openstack.cloud.image_info: - cloud: "{{ cloud }}" - image: ansible_image - register: image_info_result + - name: Assert return values of image module + assert: + that: + - image is changed + - image.image.name == 'ansible_image' + # allow new fields to be introduced but prevent fields from being removed + - expected_fields|difference(image.image.keys())|length == 0 -- name: Verify image info - assert: - that: - - image_info_result.images[0].name == "ansible_image" - - image_info_result.images[0].tags | sort == ['test', 'ansible'] | sort + - name: Get details of created image + openstack.cloud.image_info: + cloud: "{{ cloud }}" + image: ansible_image + register: images -- name: Create raw image again (defaults) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - name: ansible_image - filename: "{{ tmp_file.stdout }}" - is_protected: true - disk_format: raw - tags: - - test - - ansible - register: returned_image + - name: Assert return values of image_info module + assert: + that: + - images.images | length > 0 + - images.images.0.name == "ansible_image" + - images.images.0.tags | sort == ['test', 'ansible'] | sort + # allow new fields to be introduced but prevent fields from being removed + - expected_fields|difference(images.images.0.keys())|length == 0 -- name: Assert not changed - assert: - that: returned_image is not changed + - name: Create raw image again (defaults) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + name: ansible_image + filename: "{{ tmp_file.path }}" + is_protected: true + disk_format: raw + tags: + - test + - ansible + register: image -- name: Assert fields - assert: - that: - - item in returned_image.image - loop: "{{ expected_fields }}" + - name: Assert not changed + assert: + that: + - image is not changed -- name: Update is_protected on raw image (defaults) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - name: ansible_image - is_protected: false - register: returned_image + - name: Update is_protected on raw image (defaults) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + name: ansible_image + is_protected: false + register: image -- name: Assert changed - assert: - that: - - returned_image is changed - - returned_image.image.is_protected == false + - name: Assert changed + assert: + that: + - image is changed + - image.image.is_protected == false -- name: Assert changed - assert: - that: - - returned_image is changed + - name: Assert changed + assert: + that: + - image is changed -- name: Update visibility on raw image (defaults) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - name: ansible_image - is_public: false - register: returned_image + - name: Update visibility on raw image (defaults) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + name: ansible_image + is_public: false + register: image -- name: Assert changed - assert: - that: - - returned_image.image.visibility == 'private' + - name: Assert changed + assert: + that: + - image.image.visibility == 'private' -- name: Update again visibility on raw image (defaults) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - name: ansible_image - is_public: true - register: returned_image + - name: Update again visibility on raw image (defaults) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + name: ansible_image + is_public: true + register: image -- name: Assert changed - assert: - that: - - returned_image is changed - - returned_image.image.visibility == 'public' + - name: Assert changed + assert: + that: + - image is changed + - image.image.visibility == 'public' -- name: Define visibility on raw image (defaults) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - name: ansible_image - visibility: shared - register: returned_image + - name: Define visibility on raw image (defaults) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + name: ansible_image + visibility: shared + register: image -- name: Assert changed - assert: - that: - - returned_image is changed - - returned_image.image.visibility == 'shared' + - name: Assert changed + assert: + that: + - image is changed + - image.image.visibility == 'shared' -- name: Rename raw image (defaults) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - id: "{{ returned_image.id }}" - name: 'ansible_image-changed' - register: returned_image + - name: Rename raw image (defaults) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + id: "{{ image.image.id }}" + name: 'ansible_image-changed' + register: image -- name: Assert changed - assert: - that: - - returned_image is changed - - returned_image.image.name == 'ansible_image-changed' + - name: Assert changed + assert: + that: + - image is changed + - image.image.name == 'ansible_image-changed' -- name: Rename back raw image (defaults) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - id: "{{ returned_image.id }}" - name: ansible_image - register: returned_image + - name: Rename back raw image (defaults) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + id: "{{ image.image.id }}" + name: ansible_image + register: image -- name: Delete raw image (defaults) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: absent - name: ansible_image - register: returned_image + - name: Delete raw image (defaults) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: absent + name: ansible_image + register: image -- name: assert image changed - assert: - that: returned_image is changed + - name: assert image changed + assert: + that: + - image is changed -- name: Delete raw image again (defaults) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: absent - name: ansible_image - register: returned_image + - name: Delete raw image again (defaults) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: absent + name: ansible_image + register: image -- name: assert image not changed - assert: - that: returned_image is not changed + - name: assert image not changed + assert: + that: + - image is not changed -- name: Create raw image (complex) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - name: ansible_image - filename: "{{ tmp_file.stdout }}" - disk_format: raw - is_public: True - min_disk: 10 - min_ram: 1024 - # TODO(rcastillo): upload cirros-vmlinuz, cirros-initrd in test setup - kernel: cirros-vmlinuz - ramdisk: cirros-initrd - properties: - cpu_arch: x86_64 - distro: ubuntu - register: returned_image + - name: Create raw image (complex) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + name: ansible_image + filename: "{{ tmp_file.path }}" + disk_format: raw + is_public: True + min_disk: 10 + min_ram: 1024 + # TODO(rcastillo): upload cirros-vmlinuz, cirros-initrd in test setup + kernel: cirros-vmlinuz + ramdisk: cirros-initrd + properties: + cpu_arch: x86_64 + distro: ubuntu + register: image -- name: Assert visibility - assert: - that: returned_image.image.visibility == 'public' + - name: Assert visibility + assert: + that: + - image.image.visibility == 'public' -- name: Assert fields - assert: - that: - - item in returned_image.image - loop: "{{ expected_fields }}" + - name: Delete raw image (complex) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: absent + name: ansible_image -- name: Delete raw image (complex) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: absent - name: ansible_image + - name: Try to get details of deleted image + openstack.cloud.image_info: + cloud: "{{ cloud }}" + image: ansible_image + register: images -- name: Try to get details of deleted image - openstack.cloud.image_info: - cloud: "{{ cloud }}" - image: ansible_image - register: deleted_image_info_result + - name: Verify image is deleted + assert: + that: + - images.images | length == 0 -- name: Verify image is deleted - assert: - that: - - not deleted_image_info_result.images + - name: Create owner project + openstack.cloud.project: + cloud: "{{ cloud }}" + state: present + name: ansible_project + description: Project owning test image + domain: default + is_enabled: True + register: project -- name: Create owner project - openstack.cloud.project: - cloud: "{{ cloud }}" - state: present - name: image_owner_project - description: Project owning test image - domain: default - is_enabled: True - register: owner_project + - name: Create raw image (owner by project name) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + name: ansible_image + filename: "{{ tmp_file.path }}" + disk_format: raw + tags: + - test + - ansible + project: ansible_project + register: image -- name: Create raw image (owner by project name) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - name: ansible_image - filename: "{{ tmp_file.stdout }}" - disk_format: raw - tags: - - test - - ansible - project: image_owner_project - register: returned_image + - name: Get details of created image (owner by project name) + openstack.cloud.image_info: + cloud: "{{ cloud }}" + image: ansible_image + register: images -- name: Get details of created image (owner by project name) - openstack.cloud.image_info: - cloud: "{{ cloud }}" - image: ansible_image - register: image_info_result + - name: Verify image owner (owner by project name) + assert: + that: + - images.images.0.owner == project.project.id -- name: Verify image owner (owner by project name) - assert: - that: - - image_info_result.images[0].owner == owner_project.project.id + - name: Delete raw image (owner by project name) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: absent + name: ansible_image -- name: Delete raw image (owner by project name) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: absent - name: ansible_image + - name: Create raw image (owner by project name and domain name) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: present + name: ansible_image + filename: "{{ tmp_file.path }}" + disk_format: raw + tags: + - test + - ansible + project: ansible_project + project_domain: default + register: image -- name: Create raw image (owner by project name and domain name) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: present - name: ansible_image - filename: "{{ tmp_file.stdout }}" - disk_format: raw - tags: - - test - - ansible - project: image_owner_project - project_domain: default - register: returned_image + - name: Get details of created image (owner by project name and domain name) + openstack.cloud.image_info: + cloud: "{{ cloud }}" + image: ansible_image + register: images -- name: Get details of created image (owner by project name and domain name) - openstack.cloud.image_info: - cloud: "{{ cloud }}" - image: ansible_image - register: image_info_result + - name: Verify image owner (owner by project name and domain name) + assert: + that: + - images.images.0.owner == project.project.id -- name: Verify image owner (owner by project name and domain name) - assert: - that: - - image_info_result.images[0].owner == owner_project.project.id + - name: Delete raw image (owner by project name and domain name) + openstack.cloud.image: + cloud: "{{ cloud }}" + state: absent + name: ansible_image -- name: Delete raw image (owner by project name and domain name) - openstack.cloud.image: - cloud: "{{ cloud }}" - state: absent - name: ansible_image + - name: Delete owner project + openstack.cloud.project: + cloud: "{{ cloud }}" + state: absent + name: ansible_project + domain: default -- name: Delete owner project - openstack.cloud.project: - cloud: "{{ cloud }}" - state: absent - name: image_owner_project - domain: default + - name: Delete test image file + file: + name: "{{ tmp_file.path }}" + state: absent -- name: Delete test image file - file: - name: "{{ tmp_file.stdout }}" - state: absent + always: + - name: Remove temporary image file + ansible.builtin.file: + path: "{{ tmp_file.path }}" + state: absent + when: tmp_file is defined and 'path' in tmp_file diff --git a/ci/roles/image_info/defaults/main.yml b/ci/roles/image_info/defaults/main.yml deleted file mode 100644 index e7985898..00000000 --- a/ci/roles/image_info/defaults/main.yml +++ /dev/null @@ -1,65 +0,0 @@ -expected_fields: - - architecture - - checksum - - container_format - - created_at - - direct_url - - disk_format - - file - - has_auto_disk_config - - hash_algo - - hash_value - - hw_cpu_cores - - hw_cpu_policy - - hw_cpu_sockets - - hw_cpu_thread_policy - - hw_cpu_threads - - hw_disk_bus - - hw_machine_type - - hw_qemu_guest_agent - - hw_rng_model - - hw_scsi_model - - hw_serial_port_count - - hw_video_model - - hw_video_ram - - hw_vif_model - - hw_watchdog_action - - hypervisor_type - - id - - instance_type_rxtx_factor - - instance_uuid - - is_hidden - - is_hw_boot_menu_enabled - - is_hw_vif_multiqueue_enabled - - is_protected - - kernel_id - - locations - - metadata - - min_disk - - min_ram - - name - - needs_config_drive - - needs_secure_boot - - os_admin_user - - os_command_line - - os_distro - - os_require_quiesce - - os_shutdown_timeout - - os_type - - os_version - - owner - - owner_id - - properties - - ramdisk_id - - schema - - size - - status - - store - - tags - - updated_at - - url - - virtual_size - - visibility - - vm_mode - - vmware_adaptertype - - vmware_ostype diff --git a/ci/roles/image_info/tasks/main.yml b/ci/roles/image_info/tasks/main.yml deleted file mode 100644 index 5622ea02..00000000 --- a/ci/roles/image_info/tasks/main.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -- name: List all images # This will list at least the default cirros image of devstack - openstack.cloud.image_info: - cloud: "{{ cloud }}" - register: image_list_result - -- name: Assert fields - assert: - that: - - item in image_list_result.images.0.keys() - loop: "{{ expected_fields }}" diff --git a/ci/run-collection.yml b/ci/run-collection.yml index 6798aa62..a5d71c15 100644 --- a/ci/run-collection.yml +++ b/ci/run-collection.yml @@ -26,7 +26,6 @@ - { role: identity_role, tags: identity_role } - { role: identity_role_info, tags: identity_role_info } - { role: image, tags: image } - - { role: image_info, tags: image_info } - { role: keypair, tags: keypair } - { role: keystone_domain, tags: keystone_domain } - role: keystone_idp diff --git a/plugins/modules/image.py b/plugins/modules/image.py index 8530b88d..4c8f1dca 100644 --- a/plugins/modules/image.py +++ b/plugins/modules/image.py @@ -5,135 +5,134 @@ # Copyright (c) 2013, Benno Joy # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -DOCUMENTATION = ''' ---- +DOCUMENTATION = r''' module: image -short_description: Add/Delete images from OpenStack Cloud +short_description: Manage images of OpenStack image (Glance) service. author: OpenStack Ansible SIG description: - - Add or Remove images from the OpenStack Image Repository + - Create or delete images in OpenStack image (Glance) service. options: - name: - description: - - The name of the image when uploading - or the name/ID of the image if deleting - - If provided with the id, it can be used to change the name of existing image - required: true - type: str - id: - description: - - The ID of the image when uploading an image - - This image attribute cannot be changed. - type: str - checksum: - description: - - The checksum of the image - type: str - disk_format: - description: - - The format of the disk that is getting uploaded - - This image attribute cannot be changed. - default: qcow2 - choices: ['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso', 'vhdx', 'ploop'] - type: str - container_format: - description: - - The format of the container - - This image attribute cannot be changed. - default: bare - choices: ['ami', 'aki', 'ari', 'bare', 'ovf', 'ova', 'docker'] - type: str - owner: - description: - - The name or ID of the project owning the image - type: str - aliases: ['project'] - owner_domain: - description: - - The name or id of the domain the project owning the image belongs to - - May be used to identify a unique project when providing a name to the project argument and multiple projects with such name exist - type: str - aliases: ['project_domain'] - min_disk: - description: - - The minimum disk space (in GB) required to boot this image - type: int - min_ram: - description: - - The minimum ram (in MB) required to boot this image - type: int - is_public: - description: - - Whether the image can be accessed publicly. - Note that publicizing an image requires admin role by default. - - Use I(visibility) instead of I(is_public), - the latter has been deprecated. - type: bool - default: false - is_protected: - description: - - Prevent image from being deleted - aliases: ['protected'] - type: bool - filename: - description: - - The path to the file which has to be uploaded - - This image attribute cannot be changed. - type: str - ramdisk: - description: - - The name of an existing ramdisk image that will be associated with this image - type: str - kernel: - description: - - The name of an existing kernel image that will be associated with this image - type: str - properties: - description: - - Additional properties to be associated with this image - default: {} - type: dict - state: - description: - - Should the resource be present or absent. - choices: [present, absent] - default: present - type: str - tags: - description: - - List of tags to be applied to the image - default: [] - type: list - elements: str - visibility: - description: - - The image visibility - type: str - choices: [public, private, shared, community] - volume: - description: - - ID of a volume to create an image from. - - The volume must be in AVAILABLE state. - - Switch to module M(openstack.cloud.volume) instead of using I(volume), - the latter has been deprecated. - type: str + checksum: + description: + - The checksum of the image. + type: str + container_format: + description: + - The format of the container. + - This image attribute cannot be changed. + - Examples are C(ami), C(aki), C(ari), C(bare), C(ovf), C(ova) or + C(docker). + default: bare + type: str + disk_format: + description: + - The format of the disk that is getting uploaded. + - This image attribute cannot be changed. + - Examples are C(ami), C(ari), C(aki), C(vhd), C(vmdk), C(raw), + C(qcow2), C(vdi), c(iso), C(vhdx) or C(ploop). + default: qcow2 + type: str + filename: + description: + - The path to the file which has to be uploaded. + - This image attribute cannot be changed. + type: str + id: + description: + - The ID of the image when uploading an image. + - This image attribute cannot be changed. + type: str + is_protected: + description: + - Prevent image from being deleted. + aliases: ['protected'] + type: bool + is_public: + description: + - Whether the image can be accessed publicly. + - Setting I(is_public) to C(true) requires admin role by default. + - I(is_public) has been deprecated. Use I(visibility) instead of + I(is_public). + type: bool + default: false + kernel: + description: + - The name of an existing kernel image that will be associated with this + image. + type: str + min_disk: + description: + - The minimum disk space (in GB) required to boot this image. + type: int + min_ram: + description: + - The minimum ram (in MB) required to boot this image. + type: int + name: + description: + - The name of the image when uploading - or the name/ID of the image if + deleting. + - If provided with the id, it can be used to change the name of existing + image. + required: true + type: str + owner: + description: + - The name or ID of the project owning the image. + type: str + aliases: ['project'] + owner_domain: + description: + - The name or id of the domain the project owning the image belongs to. + - May be used to identify a unique project when providing a name to the + project argument and multiple projects with such name exist. + type: str + aliases: ['project_domain'] + properties: + description: + - Additional properties to be associated with this image. + default: {} + type: dict + ramdisk: + description: + - The name of an existing ramdisk image that will be associated with this + image. + type: str + state: + description: + - Should the resource be present or absent. + choices: [present, absent] + default: present + type: str + tags: + description: + - List of tags to be applied to the image. + default: [] + type: list + elements: str + visibility: + description: + - The image visibility. + type: str + choices: [public, private, shared, community] + volume: + description: + - ID of a volume to create an image from. + - The volume must be in AVAILABLE state. + - I(volume) has been deprecated. Use module M(openstack.cloud.volume) + instead. + type: str requirements: - - "python >= 3.6" - - "openstacksdk" - + - "python >= 3.6" + - "openstacksdk" extends_documentation_fragment: -- openstack.cloud.openstack + - openstack.cloud.openstack ''' -EXAMPLES = ''' -# Upload an image from a local file named cirros-0.3.0-x86_64-disk.img -- openstack.cloud.image: - auth: - auth_url: https://identity.example.com - username: admin - password: passme - project_name: admin - openstack.cloud.identity_user_domain_name: Default - openstack.cloud.project_domain_name: Default +EXAMPLES = r''' +- name: Upload an image from a local file named cirros-0.3.0-x86_64-disk.img + openstack.cloud.image: + cloud: devstack-admin name: cirros container_format: bare disk_format: qcow2 @@ -148,303 +147,226 @@ EXAMPLES = ''' distro: ubuntu ''' -RETURN = ''' -id: - description: ID of the image. - returned: On success when I(state) is 'present'. - type: str +RETURN = r''' image: - description: Dictionary describing the image. + description: Dictionary describing the Glance image. + returned: On success when I(state) is C(present). type: dict - returned: On success when I(state) is 'present'. contains: id: description: Unique UUID. - returned: success type: str name: description: Name given to the image. - returned: success type: str status: description: Image status. - returned: success type: str architecture: - description: | - The CPU architecture that must be supported by the hypervisor. - returned: success + description: The CPU architecture that must be supported by + the hypervisor. type: str created_at: description: Image created at timestamp. - returned: success type: str container_format: description: Container format of the image. - returned: success type: str direct_url: description: URL to access the image file kept in external store. - returned: success type: str min_ram: description: Min amount of RAM required for this image. - returned: success type: int disk_format: description: Disk format of the image. - returned: success type: str file: description: The URL for the virtual machine image file. - returned: success type: str has_auto_disk_config: - description: > - If root partition on disk is automatically resized before the instance - boots. - returned: success + description: If root partition on disk is automatically resized + before the instance boots. type: bool hash_algo: - description: | - The algorithm used to compute a secure hash of the image data. - returned: success + description: The algorithm used to compute a secure hash of the + image data. type: str hash_value: - description: > - The hexdigest of the secure hash of the image data computed using the - algorithm whose name is the value of the os_hash_algo property. - returned: success + description: The hexdigest of the secure hash of the image data + computed using the algorithm whose name is the value of the + os_hash_algo property. type: str hw_cpu_cores: - description: > - Used to pin the virtual CPUs (vCPUs) of instances to the host's physical - CPU cores (pCPUs). - returned: success + description: Used to pin the virtual CPUs (vCPUs) of instances to + the host's physical CPU cores (pCPUs). type: str hw_cpu_policy: description: The hexdigest of the secure hash of the image data. - returned: success type: str hw_cpu_sockets: description: Preferred number of sockets to expose to the guest. - returned: success type: str hw_cpu_thread_policy: - description: > - Defines how hardware CPU threads in a simultaneous multithreading-based - (SMT) architecture be used. - returned: success + description: Defines how hardware CPU threads in a simultaneous + multithreading-based (SMT) architecture be used. type: str hw_cpu_threads: - description: | - The preferred number of threads to expose to the guest. - returned: success + description: The preferred number of threads to expose to the guest. type: str hw_disk_bus: - description: | - Specifies the type of disk controller to attach disk devices to. - returned: success + description: Specifies the type of disk controller to attach disk + devices to. type: str hw_machine_type: - description: | - Enables booting an ARM system using the specified machine type. - returned: success + description: Enables booting an ARM system using the + specified machine type. type: str hw_qemu_guest_agent: - description: > - A string boolean, which if "true", QEMU guest agent will be exposed to - the instance. - returned: success + description: "A string boolean, which if 'true', QEMU guest agent + will be exposed to the instance." type: str hw_rng_model: - description: Adds a random-number generator device to the image's instances. - returned: success + description: "Adds a random-number generator device to the image's + instances." type: str hw_scsi_model: - description: > - Enables the use of VirtIO SCSI (virtio-scsi) to provide block device - access for compute instances. - returned: success + description: Enables the use of VirtIO SCSI (virtio-scsi) to + provide block device access for compute instances. type: str hw_video_model: description: The video image driver used. - returned: success type: str hw_video_ram: description: Maximum RAM for the video image. - returned: success type: str hw_vif_model: - description: Specifies the model of virtual network interface device to use. - returned: success + description: Specifies the model of virtual network interface device to + use. type: str hw_watchdog_action: - description: > - Enables a virtual hardware watchdog device that carries out the - specified action if the server hangs. - returned: success + description: Enables a virtual hardware watchdog device that + carries out the specified action if the server hangs. type: str hypervisor_type: description: The hypervisor type. - returned: success type: str instance_type_rxtx_factor: - description: > - Optional property allows created servers to have a different bandwidth - cap than that defined in the network they are attached to. - returned: success + description: Optional property allows created servers to have a + different bandwidth cap than that defined in the network + they are attached to. type: str instance_uuid: - description: > - For snapshot images, this is the UUID of the server used to create this - image. - returned: success + description: For snapshot images, this is the UUID of the server + used to create this image. type: str is_hidden: - description: >- - Controls whether an image is displayed in the default image-list - response - returned: success + description: Controls whether an image is displayed in the default + image-list response type: bool is_hw_boot_menu_enabled: description: Enables the BIOS bootmenu. - returned: success type: bool is_hw_vif_multiqueue_enabled: - description: | - Enables the virtio-net multiqueue feature. - returned: success + description: Enables the virtio-net multiqueue feature. type: bool kernel_id: - description: > - The ID of an image stored in the Image service that should be used as - the kernel when booting an AMI-style image. - returned: success + description: The ID of an image stored in the Image service that + should be used as the kernel when booting an AMI-style + image. type: str locations: description: A list of URLs to access the image file in external store. - returned: success type: str metadata: description: The location metadata. - returned: success type: str needs_config_drive: description: Specifies whether the image needs a config drive. - returned: success type: bool needs_secure_boot: description: Whether Secure Boot is needed. - returned: success type: bool os_admin_user: description: The operating system admin username. - returned: success type: str os_command_line: description: The kernel command line to be used by libvirt driver. - returned: success type: str os_distro: - description: | - The common name of the operating system distribution in lowercase. - returned: success + description: The common name of the operating system distribution + in lowercase. type: str os_require_quiesce: - description: | - If true, require quiesce on snapshot via QEMU guest agent. - returned: success + description: If true, require quiesce on snapshot via + QEMU guest agent. type: str os_shutdown_timeout: description: Time for graceful shutdown. - returned: success type: str os_type: description: The operating system installed on the image. - returned: success type: str os_version: - description: | - The operating system version as specified by the distributor. - returned: success + description: The operating system version as specified by + the distributor. type: str owner_id: - description: 'The ID of the owner, or project, of the image.' - returned: success + description: The ID of the owner, or project, of the image. type: str ramdisk_id: - description: > - The ID of image stored in the Image service that should be used as the - ramdisk when booting an AMI-style image. - returned: success + description: The ID of image stored in the Image service that should + be used as the ramdisk when booting an AMI-style image. type: str schema: description: URL for the schema describing a virtual machine image. - returned: success type: str store: - description: > - Glance will attempt to store the disk image data in the backing store - indicated by the value of the header. - returned: success + description: Glance will attempt to store the disk image data in the + backing store indicated by the value of the header. type: str updated_at: description: Image updated at timestamp. - returned: success type: str url: description: URL to access the image file kept in external store. - returned: success type: str virtual_size: description: The virtual size of the image. - returned: success type: str vm_mode: description: The virtual machine mode. - returned: success type: str vmware_adaptertype: - description: | - The virtual SCSI or IDE controller used by the hypervisor. - returned: success + description: The virtual SCSI or IDE controller used by the + hypervisor. type: str vmware_ostype: description: Operating system installed in the image. - returned: success type: str filters: description: Additional properties associated with the image. - returned: success type: dict min_disk: description: Min amount of disk space required for this image. - returned: success type: int is_protected: description: Image protected flag. - returned: success type: bool checksum: description: Checksum for the image. - returned: success type: str owner: description: Owner for the image. - returned: success type: str visibility: description: Indicates who has access to the image. - returned: success type: str size: description: Size of the image. - returned: success type: int tags: description: List of tags assigned to the image - returned: success type: list ''' @@ -454,26 +376,25 @@ from ansible_collections.openstack.cloud.plugins.module_utils.openstack import O class ImageModule(OpenStackModule): argument_spec = dict( - name=dict(required=True), - id=dict(), checksum=dict(), - disk_format=dict(default='qcow2', - choices=['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso', 'vhdx', 'ploop']), - container_format=dict(default='bare', choices=['ami', 'aki', 'ari', 'bare', 'ovf', 'ova', 'docker']), - owner=dict(aliases=['project']), - owner_domain=dict(aliases=['project_domain']), + container_format=dict(default='bare'), + disk_format=dict(default='qcow2'), + filename=dict(), + id=dict(), + is_protected=dict(type='bool', aliases=['protected']), + is_public=dict(type='bool', default=False), + kernel=dict(), min_disk=dict(type='int'), min_ram=dict(type='int'), - is_public=dict(type='bool', default=False), - is_protected=dict(type='bool', aliases=['protected']), - filename=dict(), - ramdisk=dict(), - kernel=dict(), + name=dict(required=True), + owner=dict(aliases=['project']), + owner_domain=dict(aliases=['project_domain']), properties=dict(type='dict', default={}), - volume=dict(), - tags=dict(type='list', default=[], elements='str'), + ramdisk=dict(), state=dict(default='present', choices=['absent', 'present']), + tags=dict(type='list', default=[], elements='str'), visibility=dict(choices=['public', 'private', 'shared', 'community']), + volume=dict(), ) module_kwargs = dict( @@ -574,15 +495,15 @@ class ImageModule(OpenStackModule): if self.params['state'] == 'present': attrs = self._build_params(owner) if not image: - # self.conn.image.create_image cannot be used because - # self.conn.create_image provides a volume parameter - # Ref.: https://opendev.org/openstack/openstacksdk/src/commit/a41d04ea197439c2f134ce3554995693933a46ac/openstack/cloud/_image.py#L306 + # self.conn.image.create_image() cannot be used because it does + # not provide self.conn.create_image()'s volume parameter [0]. + # [0] https://opendev.org/openstack/openstacksdk/src/commit/ + # a41d04ea197439c2f134ce3554995693933a46ac/openstack/cloud/_image.py#L306 image = self.conn.create_image(**attrs) changed = True if not self.params['wait']: self.exit_json(changed=changed, - image=self._return_value(image.id), - id=image.id) + image=self._return_value(image.id)) update_payload = self._build_update(image) @@ -590,8 +511,7 @@ class ImageModule(OpenStackModule): self.conn.image.update_image(image.id, **update_payload) changed = True - self.exit_json(changed=changed, image=self._return_value(image.id), - id=image.id) + self.exit_json(changed=changed, image=self._return_value(image.id)) elif self.params['state'] == 'absent' and image is not None: # self.conn.image.delete_image() does not offer a wait parameter diff --git a/plugins/modules/image_info.py b/plugins/modules/image_info.py index 85713dbc..9ef10caf 100644 --- a/plugins/modules/image_info.py +++ b/plugins/modules/image_info.py @@ -4,394 +4,296 @@ # Copyright (c) 2015 Hewlett-Packard Development Company, L.P. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -DOCUMENTATION = ''' +DOCUMENTATION = r''' --- module: image_info -short_description: Retrieve information about an image within OpenStack. +short_description: Fetch images from OpenStack image (Glance) service. author: OpenStack Ansible SIG description: - - Retrieve information about a image image from OpenStack. + - Fetch images from OpenStack image (Glance) service. options: - image: - description: - - Name or ID of the image - required: false - type: str - filters: - description: - - Dict of properties of the images used for query - type: dict - required: false - aliases: ['properties'] + name: + description: + - Name or ID of the image + type: str + aliases: ['image'] + filters: + description: + - Dict of properties of the images used for query + type: dict + aliases: ['properties'] requirements: - - "python >= 3.6" - - "openstacksdk" - + - "python >= 3.6" + - "openstacksdk" extends_documentation_fragment: -- openstack.cloud.openstack + - openstack.cloud.openstack ''' -EXAMPLES = ''' -- name: Gather information about a previously created image named image1 +EXAMPLES = r''' +- name: Gather previously created image named image1 openstack.cloud.image_info: - auth: - auth_url: https://identity.example.com - username: user - password: password - project_name: someproject + cloud: devstack-admin image: image1 - register: result -- name: Show openstack information - debug: - msg: "{{ result.image }}" - -# Show all available Openstack images -- name: Retrieve all available Openstack images +- name: List all images openstack.cloud.image_info: - register: result -- name: Show images - debug: - msg: "{{ result.image }}" - -# Show images matching requested properties -- name: Retrieve images having properties with desired values - openstack.cloud.image_facts: +- name: Retrieve and filter images + openstack.cloud.image_info: filters: - some_property: some_value - OtherProp: OtherVal - -- name: Show images - debug: - msg: "{{ result.image }}" + is_protected: False ''' -RETURN = ''' +RETURN = r''' images: - description: has all the openstack information about the image - returned: always, but can be null - type: complex - contains: - id: - description: Unique UUID. - returned: success - type: str - name: - description: Name given to the image. - returned: success - type: str - status: - description: Image status. - returned: success - type: str - architecture: - description: > - The CPU architecture that must be supported by - the hypervisor. - returned: success - type: str - created_at: - description: Image created at timestamp. - returned: success - type: str - container_format: - description: Container format of the image. - returned: success - type: str - direct_url: - description: URL to access the image file kept in external store. - returned: success - type: str - min_ram: - description: Min amount of RAM required for this image. - returned: success - type: int - disk_format: - description: Disk format of the image. - returned: success - type: str - file: - description: The URL for the virtual machine image file. - returned: success - type: str - has_auto_disk_config: - description: > - If root partition on disk is automatically resized - before the instance boots. - returned: success - type: bool - hash_algo: - description: > - The algorithm used to compute a secure hash of the - image data. - returned: success - type: str - hash_value: - description: > - The hexdigest of the secure hash of the image data - computed using the algorithm whose name is the value of the os_hash_algo property. - returned: success - type: str - hw_cpu_cores: - description: > - Used to pin the virtual CPUs (vCPUs) of instances to - the host's physical CPU cores (pCPUs). - returned: success - type: str - hw_cpu_policy: - description: The hexdigest of the secure hash of the image data. - returned: success - type: str - hw_cpu_sockets: - description: Preferred number of sockets to expose to the guest. - returned: success - type: str - hw_cpu_thread_policy: - description: > - Defines how hardware CPU threads in a simultaneous - multithreading-based (SMT) architecture be used. - returned: success - type: str - hw_cpu_threads: - description: > - The preferred number of threads to expose to the guest. - returned: success - type: str - hw_disk_bus: - description: > - Specifies the type of disk controller to attach disk - devices to. - returned: success - type: str - hw_machine_type: - description: > - Enables booting an ARM system using the - specified machine type. - returned: success - type: str - hw_qemu_guest_agent: - description: > - A string boolean, which if "true", QEMU guest agent - will be exposed to the instance. - returned: success - type: str - hw_rng_model: - description: Adds a random-number generator device to the image's instances. - returned: success - type: str - hw_scsi_model: - description: > - Enables the use of VirtIO SCSI (virtio-scsi) to - provide block device access for compute instances. - returned: success - type: str - hw_video_model: - description: The video image driver used. - returned: success - type: str - hw_video_ram: - description: Maximum RAM for the video image. - returned: success - type: str - hw_vif_model: - description: Specifies the model of virtual network interface device to use. - returned: success - type: str - hw_watchdog_action: - description: > - Enables a virtual hardware watchdog device that - carries out the specified action if the server hangs. - returned: success - type: str - hypervisor_type: - description: The hypervisor type. - returned: success - type: str - instance_type_rxtx_factor: - description: > - Optional property allows created servers to have a - different bandwidth cap than that defined in the network they are attached to. - returned: success - type: str - instance_uuid: - description: > - For snapshot images, this is the UUID of the server - used to create this image. - returned: success - type: str - is_hidden: - description: Controls whether an image is displayed in the default image-list response - returned: success - type: bool - is_hw_boot_menu_enabled: - description: Enables the BIOS bootmenu. - returned: success - type: bool - is_hw_vif_multiqueue_enabled: - description: > - Enables the virtio-net multiqueue - feature. - returned: success - type: bool - kernel_id: - description: > - The ID of an image stored in the Image service that - should be used as the kernel when booting an AMI-style image. - returned: success - type: str - locations: - description: A list of URLs to access the image file in external store. - returned: success - type: str - metadata: - description: The location metadata. - returned: success - type: str - needs_config_drive: - description: Specifies whether the image needs a config drive. - returned: success - type: bool - needs_secure_boot: - description: Whether Secure Boot is needed. - returned: success - type: bool - os_admin_user: - description: The operating system admin username. - returned: success - type: str - os_command_line: - description: The kernel command line to be used by libvirt driver. - returned: success - type: str - os_distro: - description: > - The common name of the operating system distribution - in lowercase. - returned: success - type: str - os_require_quiesce: - description: > - If true, require quiesce on snapshot via - QEMU guest agent. - returned: success - type: str - os_shutdown_timeout: - description: Time for graceful shutdown. - returned: success - type: str - os_type: - description: The operating system installed on the image. - returned: success - type: str - os_version: - description: > - The operating system version as specified by - the distributor. - returned: success - type: str - owner_id: - description: The ID of the owner, or project, of the image. - returned: success - type: str - ramdisk_id: - description: > - The ID of image stored in the Image service that - should be used as the ramdisk when booting an AMI-style image. - returned: success - type: str - schema: - description: URL for the schema describing a virtual machine image. - returned: success - type: str - store: - description: > - Glance will attempt to store the disk - image data in the backing store indicated by the value of the - header. - returned: success - type: str - updated_at: - description: Image updated at timestamp. - returned: success - type: str - url: - description: URL to access the image file kept in external store. - returned: success - type: str - virtual_size: - description: The virtual size of the image. - returned: success - type: str - vm_mode: - description: The virtual machine mode. - returned: success - type: str - vmware_adaptertype: - description: > - The virtual SCSI or IDE controller used by the - hypervisor. - returned: success - type: str - vmware_ostype: - description: Operating system installed in the image. - returned: success - type: str - filters: - description: Additional properties associated with the image. - returned: success - type: dict - min_disk: - description: Min amount of disk space required for this image. - returned: success - type: int - is_protected: - description: Image protected flag. - returned: success - type: bool - checksum: - description: Checksum for the image. - returned: success - type: str - owner: - description: Owner for the image. - returned: success - type: str - visibility: - description: Indicates who has access to the image. - returned: success - type: str - size: - description: Size of the image. - returned: success - type: int - tags: - description: List of tags assigned to the image - returned: success - type: list + description: List of dictionaries describing matching images. + returned: always + type: list + elements: dict + contains: + id: + description: Unique UUID. + type: str + name: + description: Name given to the image. + type: str + status: + description: Image status. + type: str + architecture: + description: The CPU architecture that must be supported by + the hypervisor. + type: str + created_at: + description: Image created at timestamp. + type: str + container_format: + description: Container format of the image. + type: str + direct_url: + description: URL to access the image file kept in external store. + type: str + min_ram: + description: Min amount of RAM required for this image. + type: int + disk_format: + description: Disk format of the image. + type: str + file: + description: The URL for the virtual machine image file. + type: str + has_auto_disk_config: + description: If root partition on disk is automatically resized + before the instance boots. + type: bool + hash_algo: + description: The algorithm used to compute a secure hash of the + image data. + type: str + hash_value: + description: The hexdigest of the secure hash of the image data + computed using the algorithm whose name is the value of the + os_hash_algo property. + type: str + hw_cpu_cores: + description: Used to pin the virtual CPUs (vCPUs) of instances to + the host's physical CPU cores (pCPUs). + type: str + hw_cpu_policy: + description: The hexdigest of the secure hash of the image data. + type: str + hw_cpu_sockets: + description: Preferred number of sockets to expose to the guest. + type: str + hw_cpu_thread_policy: + description: Defines how hardware CPU threads in a simultaneous + multithreading-based (SMT) architecture be used. + type: str + hw_cpu_threads: + description: The preferred number of threads to expose to the guest. + type: str + hw_disk_bus: + description: Specifies the type of disk controller to attach disk + devices to. + type: str + hw_machine_type: + description: Enables booting an ARM system using the + specified machine type. + type: str + hw_qemu_guest_agent: + description: "A string boolean, which if 'true', QEMU guest agent + will be exposed to the instance." + type: str + hw_rng_model: + description: "Adds a random-number generator device to the image's + instances." + type: str + hw_scsi_model: + description: Enables the use of VirtIO SCSI (virtio-scsi) to + provide block device access for compute instances. + type: str + hw_video_model: + description: The video image driver used. + type: str + hw_video_ram: + description: Maximum RAM for the video image. + type: str + hw_vif_model: + description: Specifies the model of virtual network interface device to + use. + type: str + hw_watchdog_action: + description: Enables a virtual hardware watchdog device that + carries out the specified action if the server hangs. + type: str + hypervisor_type: + description: The hypervisor type. + type: str + instance_type_rxtx_factor: + description: Optional property allows created servers to have a + different bandwidth cap than that defined in the network + they are attached to. + type: str + instance_uuid: + description: For snapshot images, this is the UUID of the server + used to create this image. + type: str + is_hidden: + description: Controls whether an image is displayed in the default + image-list response + type: bool + is_hw_boot_menu_enabled: + description: Enables the BIOS bootmenu. + type: bool + is_hw_vif_multiqueue_enabled: + description: Enables the virtio-net multiqueue feature. + type: bool + kernel_id: + description: The ID of an image stored in the Image service that + should be used as the kernel when booting an AMI-style + image. + type: str + locations: + description: A list of URLs to access the image file in external store. + type: str + metadata: + description: The location metadata. + type: str + needs_config_drive: + description: Specifies whether the image needs a config drive. + type: bool + needs_secure_boot: + description: Whether Secure Boot is needed. + type: bool + os_admin_user: + description: The operating system admin username. + type: str + os_command_line: + description: The kernel command line to be used by libvirt driver. + type: str + os_distro: + description: The common name of the operating system distribution + in lowercase. + type: str + os_require_quiesce: + description: If true, require quiesce on snapshot via + QEMU guest agent. + type: str + os_shutdown_timeout: + description: Time for graceful shutdown. + type: str + os_type: + description: The operating system installed on the image. + type: str + os_version: + description: The operating system version as specified by + the distributor. + type: str + owner_id: + description: The ID of the owner, or project, of the image. + type: str + ramdisk_id: + description: The ID of image stored in the Image service that should + be used as the ramdisk when booting an AMI-style image. + type: str + schema: + description: URL for the schema describing a virtual machine image. + type: str + store: + description: Glance will attempt to store the disk image data in the + backing store indicated by the value of the header. + type: str + updated_at: + description: Image updated at timestamp. + type: str + url: + description: URL to access the image file kept in external store. + type: str + virtual_size: + description: The virtual size of the image. + type: str + vm_mode: + description: The virtual machine mode. + type: str + vmware_adaptertype: + description: The virtual SCSI or IDE controller used by the + hypervisor. + type: str + vmware_ostype: + description: Operating system installed in the image. + type: str + filters: + description: Additional properties associated with the image. + type: dict + min_disk: + description: Min amount of disk space required for this image. + type: int + is_protected: + description: Image protected flag. + type: bool + checksum: + description: Checksum for the image. + type: str + owner: + description: Owner for the image. + type: str + visibility: + description: Indicates who has access to the image. + type: str + size: + description: Size of the image. + type: int + tags: + description: List of tags assigned to the image + type: list ''' + from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule class ImageInfoModule(OpenStackModule): argument_spec = dict( - image=dict(), filters=dict(type='dict', aliases=['properties']), + name=dict(aliases=['image']), ) + module_kwargs = dict( supports_check_mode=True ) def run(self): - args = { - 'name_or_id': self.params['image'], - 'filters': self.params['filters'], - } - args = {k: v for k, v in args.items() if v is not None} - images = [image.to_dict(computed=False) for image in - self.conn.search_images(**args)] - self.exit(changed=False, images=images) + kwargs = dict((k, self.params[k]) + for k in ['filters'] + if self.params[k] is not None) + + name_or_id = self.params['name'] + if name_or_id is not None: + kwargs['name_or_id'] = name_or_id + + self.exit(changed=False, + images=[i.to_dict(computed=False) + for i in self.conn.search_images(**kwargs)]) def main():