diff --git a/lib/ansible/modules/cloud/openstack/glance_image.py b/lib/ansible/modules/cloud/openstack/_glance_image.py similarity index 99% rename from lib/ansible/modules/cloud/openstack/glance_image.py rename to lib/ansible/modules/cloud/openstack/_glance_image.py index 6425fa2ca5d..4d779f2c227 100644 --- a/lib/ansible/modules/cloud/openstack/glance_image.py +++ b/lib/ansible/modules/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/lib/ansible/modules/cloud/openstack/os_image.py b/lib/ansible/modules/cloud/openstack/os_image.py new file mode 100644 index 00000000000..bdb8755e84c --- /dev/null +++ b/lib/ansible/modules/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()