From 0bdf9f4d27262711430dc9ed0858636def034768 Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Tue, 31 Mar 2015 16:37:07 -0400 Subject: [PATCH 1/4] Add OpenStack Image module Also deprecate old glance_image module --- .../{glance_image.py => _glance_image.py} | 1 + cloud/openstack/os_image.py | 193 ++++++++++++++++++ 2 files changed, 194 insertions(+) rename cloud/openstack/{glance_image.py => _glance_image.py} (99%) create mode 100644 cloud/openstack/os_image.py diff --git a/cloud/openstack/glance_image.py b/cloud/openstack/_glance_image.py similarity index 99% rename from cloud/openstack/glance_image.py rename to cloud/openstack/_glance_image.py index 97b89f03484..0f2de791b38 100644 --- a/cloud/openstack/glance_image.py +++ b/cloud/openstack/_glance_image.py @@ -20,6 +20,7 @@ DOCUMENTATION = ''' --- module: glance_image version_added: "1.2" +deprecated: Deprecated in 1.10. Use os_image instead short_description: Add/Delete images from glance description: - Add or Remove images from the glance repository. diff --git a/cloud/openstack/os_image.py b/cloud/openstack/os_image.py new file mode 100644 index 00000000000..bdb8755e84c --- /dev/null +++ b/cloud/openstack/os_image.py @@ -0,0 +1,193 @@ +#!/usr/bin/python + +# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# Copyright (c) 2013, Benno Joy +# +# This module is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software. If not, see . + +#TODO(mordred): we need to support "location"(v1) and "locations"(v2) +try: + import shade + HAS_SHADE = True +except ImportError: + HAS_SHADE = False + + +DOCUMENTATION = ''' +--- +module: os_image +short_description: Add/Delete images from OpenStack Cloud +extends_documentation_fragment: openstack +version_added: "1.10" +description: + - Add or Remove images from the OpenStack Image Repository +options: + name: + description: + - Name that has to be given to the image + required: true + default: None + disk_format: + description: + - The format of the disk that is getting uploaded + required: false + default: qcow2 + container_format: + description: + - The format of the container + required: false + default: bare + owner: + description: + - The owner of the image + required: false + default: None + min_disk: + description: + - The minimum disk space required to deploy this image + required: false + default: None + min_ram: + description: + - The minimum ram required to deploy this image + required: false + default: None + is_public: + description: + - Whether the image can be accessed publicly. Note that publicizing an image requires admin role by default. + required: false + default: 'yes' + filename: + description: + - The path to the file which has to be uploaded + required: false + default: None + ramdisk: + descrption: + - The name of an existing ramdisk image that will be associated with this image + required: false + default: None + kernel: + descrption: + - The name of an existing kernel image that will be associated with this image + required: false + default: None + properties: + description: + - Additional properties to be associated with this image +requirements: ["shade"] + state: + description: + - Should the resource be present or absent. + choices: [present, absent] + default: present +''' + +EXAMPLES = ''' +# Upload an image from a local file named cirros-0.3.0-x86_64-disk.img +- os_image: + auth: + username: admin + password: passme + project_name: admin + name: cirros + container_format: bare + disk_format: qcow2 + state: present + filename: cirros-0.3.0-x86_64-disk.img + kernel: cirros-vmlinuz + ramdisk: cirros-initrd + properties: + cpu_arch: x86_64 + distro: ubuntu +''' + +import time + + +def _glance_delete_image(module, params, client): + try: + for image in client.images.list(): + if image.name == params['name']: + client.images.delete(image) + except Exception, e: + module.fail_json(msg="Error in deleting image: %s" % e.message) + module.exit_json(changed=True, result="Deleted") + + +def main(): + + argument_spec = openstack_full_argument_spec( + name = dict(required=True), + disk_format = dict(default='qcow2', choices=['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso']), + container_format = dict(default='bare', choices=['ami', 'aki', 'ari', 'bare', 'ovf', 'ova']), + owner = dict(default=None), + min_disk = dict(default=None), + min_ram = dict(default=None), + is_public = dict(default=False), + filename = dict(default=None), + ramdisk = dict(default=None), + kernel = dict(default=None), + properties = dict(default={}), + state = dict(default='present', choices=['absent', 'present']), + ) + module_kwargs = openstack_module_kwargs() + module = AnsibleModule(argument_spec, **module_kwargs) + + if not HAS_SHADE: + module.fail_json(msg='shade is required for this module') + + try: + cloud = shade.openstack_cloud(**module.params) + + changed = False + image = cloud.get_image(name_or_id=module.params['name']) + + if module.params['state'] == 'present': + if not image: + result = cloud.create_image( + name=module.params['name'], + filename=module.params['filename'], + disk_format=module.params['disk_format'], + container_format=module.params['container_format'], + wait=module.params['wait'], + timeout=module.params['timeout'] + ) + changed = True + if not module.params['wait']: + module.exit_json(changed=changed, result=result) + image = cloud.get_image(name_or_id=result['id']) + + cloud.update_image_properties( + image=image, + kernel=module.params['kernel'], + ramdisk=module.params['ramdisk'], + **module.params['properties']) + + if module.params['state'] == 'absent': + if not image: + module.exit_json(changed=False, result="success") + else: + _glance_delete_image(module, module.params, cloud.glance_client) + changed = True + + module.exit_json(changed=changed, id=image.id, result="success") + + except shade.OpenStackCloudException as e: + module.fail_json(msg=e.message, extra_data=e.extra_data) + +# this is magic, see lib/ansible/module_common.py +from ansible.module_utils.basic import * +from ansible.module_utils.openstack import * +main() From bd26df1c578b0c703daa52ea8c3c8a693320594f Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Wed, 1 Apr 2015 10:09:09 -0400 Subject: [PATCH 2/4] Don't update image properties if we're deleting --- cloud/openstack/os_image.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cloud/openstack/os_image.py b/cloud/openstack/os_image.py index bdb8755e84c..7842137f7d9 100644 --- a/cloud/openstack/os_image.py +++ b/cloud/openstack/os_image.py @@ -169,13 +169,13 @@ def main(): module.exit_json(changed=changed, result=result) image = cloud.get_image(name_or_id=result['id']) - cloud.update_image_properties( - image=image, - kernel=module.params['kernel'], - ramdisk=module.params['ramdisk'], - **module.params['properties']) + cloud.update_image_properties( + image=image, + kernel=module.params['kernel'], + ramdisk=module.params['ramdisk'], + **module.params['properties']) - if module.params['state'] == 'absent': + elif module.params['state'] == 'absent': if not image: module.exit_json(changed=False, result="success") else: From 3ffebeac5b575721660783fb15ece6713aad44a2 Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Wed, 1 Apr 2015 10:43:29 -0400 Subject: [PATCH 3/4] Use the delete method from shade Sigh. Turns out glance v1 and glance v2 delete images differently too. --- cloud/openstack/os_image.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/cloud/openstack/os_image.py b/cloud/openstack/os_image.py index 7842137f7d9..7e97b3800a9 100644 --- a/cloud/openstack/os_image.py +++ b/cloud/openstack/os_image.py @@ -116,16 +116,6 @@ EXAMPLES = ''' import time -def _glance_delete_image(module, params, client): - try: - for image in client.images.list(): - if image.name == params['name']: - client.images.delete(image) - except Exception, e: - module.fail_json(msg="Error in deleting image: %s" % e.message) - module.exit_json(changed=True, result="Deleted") - - def main(): argument_spec = openstack_full_argument_spec( @@ -179,7 +169,10 @@ def main(): if not image: module.exit_json(changed=False, result="success") else: - _glance_delete_image(module, module.params, cloud.glance_client) + cloud.delete_image( + name_or_id=module.params['name'], + wait=module.params['wait'], + timeout=module.params['timeout']) changed = True module.exit_json(changed=changed, id=image.id, result="success") From 86fc12e27900ff0f5d5a5842fa663d69058c3a65 Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Fri, 5 Jun 2015 16:01:15 -0400 Subject: [PATCH 4/4] Update doc params and version_added --- cloud/openstack/os_image.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cloud/openstack/os_image.py b/cloud/openstack/os_image.py index 7e97b3800a9..ffc99064ad2 100644 --- a/cloud/openstack/os_image.py +++ b/cloud/openstack/os_image.py @@ -1,6 +1,6 @@ #!/usr/bin/python -# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# Copyright (c) 2015 Hewlett-Packard Development Company, L.P. # Copyright (c) 2013, Benno Joy # # This module is free software: you can redistribute it and/or modify @@ -29,7 +29,7 @@ DOCUMENTATION = ''' module: os_image short_description: Add/Delete images from OpenStack Cloud extends_documentation_fragment: openstack -version_added: "1.10" +version_added: "2.0" description: - Add or Remove images from the OpenStack Image Repository options: @@ -86,18 +86,21 @@ options: properties: description: - Additional properties to be associated with this image -requirements: ["shade"] + required: false + default: {} state: description: - Should the resource be present or absent. choices: [present, absent] default: present +requirements: ["shade"] ''' EXAMPLES = ''' # Upload an image from a local file named cirros-0.3.0-x86_64-disk.img - os_image: auth: + auth_url: http://localhost/auth/v2.0 username: admin password: passme project_name: admin @@ -113,8 +116,6 @@ EXAMPLES = ''' distro: ubuntu ''' -import time - def main():