#!/usr/bin/env python # Copyright 2014, Rackspace US, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. DOCUMENTATION=''' --- module: glance short_description: - Basic module for interacting with openstack glance description: - Basic module for interacting with openstack glance options: command: description: - Operation for the module to perform. Currently available choices: - image-list - image-create openrc_path: decription: - Path to openrc file from which credentials and keystoneclient - endpoint will be extracted image_name: description: - Name of the image to create image_url: description: - URL from which to download the image data image_container_format: description: - container format that the image uses (bare) image_disk_format: description: - disk format that the image uses image_is_public: description: - Should the image be visible to all tenants? choices: - true (public) - flase (private) author: Hugh Saunders ''' EXAMPLES = ''' # Create an image - name: Ensure cirros image glance: command: 'image-create' openrc_path: /root/openrc image_name: cirros image_url: 'https://launchpad.net/cirros/trunk/0.3.2/+download/cirros-0.3.2-source.tar.gz' image_container_format: bare image_disk_format: qcow2 image_is_public: True # Get facts about existing images - name: Get image facts glance: command: 'image-list' openrc_path: /root/openrc ''' import re import keystoneclient.v2_0.client as ksclient import glanceclient.v1.client as glclient COMMAND_MAP = {'image-list': 'list_images', 'image-create': 'create_image'} class ManageGlance(object): def __init__(self, module): self.state_change = False self.glance = None self.keystone = None self.module = module try: self._keystone_authenticate() self._init_glance() except Exception as e: self.module.fail_json( err="Initialisation Error: %s" % e, rc=2, msg=str(e)) def _parse_openrc(self): """ Get credentials from an openrc file """ openrc_path = self.module.params['openrc_path'] line_re = re.compile('^export (?POS_\w*)=(?P[^\n]*)') with open(openrc_path) as openrc: matches = [line_re.match(l) for l in openrc] return dict( (g.groupdict()['key'], g.groupdict()['value']) for g in matches if g) def _keystone_authenticate(self): """ Authenticate with Keystone """ openrc = self._parse_openrc() self.keystone = ksclient.Client(username=openrc['OS_USERNAME'], password=openrc['OS_PASSWORD'], tenant_name=openrc['OS_TENANT_NAME'], auth_url=openrc['OS_AUTH_URL']) def _init_glance(self): """ Create glance client object using token and url from keystone """ openrc = self._parse_openrc() self.glance = glclient.Client( version='1', endpoint=self.keystone.service_catalog.url_for( service_type='image', endpoint_type=openrc['OS_ENDPOINT_TYPE']), token=self.keystone.get_token(self.keystone.session)) def route(self): """ Run the command specified by the command parameter """ getattr(self, COMMAND_MAP[self.module.params['command']])() def _get_image_facts(self): """ Helper function to format image list as a dictionary """ return dict((i.name, i.to_dict()) for i in self.glance.images.list()) def list_images(self): """ Get information about available glance images and return as a fact dictionary glance_iamges """ self.module.exit_json( changed=self.state_change, ansible_facts=dict(glance_images=self._get_image_facts())) def create_image(self): """ Create a glance image that references a remote url """ p = self.module.params name = p['image_name'] images = {i.name for i in self.glance.images.list()} if name in images: self.module.exit_json(changed=self.state_change, ansible_facts=dict(glance_images=self._get_image_facts())) else: self.glance.images.create(name=name, is_public=p['image_is_public'], disk_format=p['image_disk_format'], container_format=p['image_container_format'], copy_from=p['image_url']) self.state_change = True self.module.exit_json( changed=self.state_change, ansible_facts=dict(glance_images=self._get_image_facts())) def main(): module = AnsibleModule( argument_spec=dict( command=dict(required=True, choices=COMMAND_MAP.keys()), openrc_path=dict(required=True), image_name=dict(required=False), image_url=dict(required=False), image_container_format=dict(required=False), image_disk_format=dict(required=False), image_is_public=dict(required=False, choices=BOOLEANS) ), supports_check_mode=False ) mg = ManageGlance(module) mg.route() from ansible.module_utils.basic import * if __name__ == '__main__': main()