4341b79b3a
This patch introduces an insecure flag for the Keystone internal and admin endpoints: * keystone_service_adminuri_insecure * keystone_service_internaluri_insecure Both values default to false. If you have setup SSL endpoints for Keystone using an untrusted certificate then you should set the appropriate flag to true in your user_variables. This patch is used to enable testing and development with Keystone SSL endpoints without having to make use of SSL certificates signed by a trusted, public CA. The patch introduces a new optional argument (insecure) to the keystone, glance and neutron Ansible libraries. This is a boolean value which, when true, enables these libraries to access Keystone endpoints 'insecurely'. When these libraries are used in plays, the appropriate value is set automatically as per the above conditions. Implements: blueprint keystone-federation Change-Id: Ia07e7e201f901042dd06a86efe5c6f6725e9ce13
234 lines
7.3 KiB
Python
234 lines
7.3 KiB
Python
#!/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)
|
|
- false (private)
|
|
api_version:
|
|
description:
|
|
- which version of the glance api to use
|
|
choices:
|
|
- 1
|
|
- 2
|
|
default: 1
|
|
insecure:
|
|
description:
|
|
- Explicitly allow client to perform "insecure" TLS
|
|
choices:
|
|
- false
|
|
- true
|
|
default: false
|
|
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://example-domain.com/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 glanceclient.client as glclient
|
|
import keystoneclient.v2_0.client as ksclient
|
|
|
|
|
|
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 (?P<key>OS_\w*)=(?P<value>[^\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()
|
|
insecure = self.module.params['insecure']
|
|
self.keystone = ksclient.Client(insecure=insecure,
|
|
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()
|
|
p = self.module.params
|
|
v = p['api_version']
|
|
ep = self.keystone.service_catalog.url_for(
|
|
service_type='image',
|
|
endpoint_type=openrc['OS_ENDPOINT_TYPE']
|
|
)
|
|
|
|
self.glance = glclient.Client(
|
|
endpoint='%s/v%s' % (ep, v),
|
|
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."""
|
|
p = self.module.params
|
|
v = p['api_version']
|
|
if v == '1':
|
|
return dict(
|
|
(i.name, i.to_dict()) for i in self.glance.images.list()
|
|
)
|
|
elif v == '2':
|
|
return dict(
|
|
(i.name, i) for i in self.glance.images.list()
|
|
)
|
|
|
|
def list_images(self):
|
|
"""Get information about available glance images.
|
|
|
|
Returns as a fact dictionary glance_images
|
|
"""
|
|
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
|
|
v = p['api_version']
|
|
image_name = p['image_name']
|
|
image_opts = dict(
|
|
name=image_name,
|
|
disk_format=p['image_disk_format'],
|
|
container_format=p['image_container_format'],
|
|
copy_from=p['image_url']
|
|
)
|
|
if v == '1':
|
|
image_opts['is_public'] = p['image_is_public']
|
|
elif v == '2':
|
|
if p['image_is_public']:
|
|
vis = 'public'
|
|
else:
|
|
vis = 'private'
|
|
image_opts['visibility'] = vis
|
|
|
|
images = {i.name for i in self.glance.images.list()}
|
|
if image_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(**image_opts)
|
|
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),
|
|
api_version=dict(default='1', required=False, choices=['1', '2']),
|
|
insecure=dict(default=False, required=False,
|
|
choices=BOOLEANS + ['True', 'False'])
|
|
),
|
|
supports_check_mode=False
|
|
)
|
|
mg = ManageGlance(module)
|
|
mg.route()
|
|
|
|
from ansible.module_utils.basic import *
|
|
if __name__ == '__main__':
|
|
main()
|