1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 # and others. All rights reserved.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
19 from snaps import file_utils
20 from glanceclient.client import Client
22 from snaps.domain.image import Image
23 from snaps.openstack.utils import keystone_utils
25 __author__ = 'spisarski'
27 logger = logging.getLogger('glance_utils')
33 Utilities for basic neutron API calls
37 def glance_client(os_creds):
39 Creates and returns a glance client object
40 :return: the glance client
42 return Client(version=os_creds.image_api_version, session=keystone_utils.keystone_session(os_creds))
45 def get_image(glance, image_name=None):
47 Returns an OpenStack image object for a given name
48 :param glance: the Glance client
49 :param image_name: the image name to lookup
50 :return: the image object or None
52 images = glance.images.list()
54 if glance.version == VERSION_1:
55 if image.name == image_name:
56 image = glance.images.get(image.id)
57 return Image(name=image.name, image_id=image.id, size=image.size, properties=image.properties)
58 elif glance.version == VERSION_2:
59 if image['name'] == image_name:
60 return Image(name=image['name'], image_id=image['id'], size=image['size'],
61 properties=image.get('properties'))
65 def get_image_status(glance, image):
67 Returns a new OpenStack Image object for a given OpenStack image object
68 :param glance: the Glance client
69 :param image: the domain Image object
70 :return: the OpenStack Image object
72 if glance.version == VERSION_1:
73 os_image = glance.images.get(image.id)
74 return os_image.status
75 elif glance.version == VERSION_2:
76 os_image = glance.images.get(image.id)
77 return os_image['status']
79 raise Exception('Unsupported glance client version')
82 def create_image(glance, image_settings):
84 Creates and returns OpenStack image object with an external URL
85 :param glance: the glance client
86 :param image_settings: the image settings object
87 :return: the OpenStack image object
88 :raise Exception if using a file and it cannot be found
90 if glance.version == VERSION_1:
91 return __create_image_v1(glance, image_settings)
92 elif glance.version == VERSION_2:
93 return __create_image_v2(glance, image_settings)
95 raise Exception('Unsupported glance client version')
98 def __create_image_v1(glance, image_settings):
100 Creates and returns OpenStack image object with an external URL
101 :param glance: the glance client
102 :param image_settings: the image settings object
103 :return: the OpenStack image object
104 :raise Exception if using a file and it cannot be found
108 if image_settings.url:
109 if image_settings.extra_properties:
110 created_image = glance.images.create(
111 name=image_settings.name, disk_format=image_settings.format, container_format="bare",
112 location=image_settings.url, properties=image_settings.extra_properties)
114 created_image = glance.images.create(name=image_settings.name, disk_format=image_settings.format,
115 container_format="bare", location=image_settings.url)
116 elif image_settings.image_file:
117 image_file = file_utils.get_file(image_settings.image_file)
118 if image_settings.extra_properties:
119 created_image = glance.images.create(
120 name=image_settings.name, disk_format=image_settings.format, container_format="bare", data=image_file,
121 properties=image_settings.extra_properties)
123 created_image = glance.images.create(
124 name=image_settings.name, disk_format=image_settings.format, container_format="bare", data=image_file)
126 return Image(name=image_settings.name, image_id=created_image.id, size=created_image.size,
127 properties=created_image.properties)
130 def __create_image_v2(glance, image_settings):
132 Creates and returns OpenStack image object with an external URL
133 :param glance: the glance client v2
134 :param image_settings: the image settings object
135 :return: the OpenStack image object
136 :raise Exception if using a file and it cannot be found
139 if image_settings.image_file:
140 image_filename = image_settings.image_file
141 elif image_settings.url:
142 image_file = file_utils.download(image_settings.url, '/tmp', str(uuid.uuid4()))
143 image_filename = image_file.name
146 raise Exception('Filename or URL of image not configured')
151 kwargs['name'] = image_settings.name
152 kwargs['disk_format'] = image_settings.format
153 kwargs['container_format'] = 'bare'
155 if image_settings.extra_properties:
156 for key, value in image_settings.extra_properties.iteritems():
159 created_image = glance.images.create(**kwargs)
160 image_file = file_utils.get_file(image_filename)
161 glance.images.upload(created_image['id'], image_file)
162 except Exception as e:
163 logger.error('Unexpected exception creating image. Rolling back')
165 delete_image(glance, created_image)
169 os.remove(image_filename)
171 updated_image = glance.images.get(created_image['id'])
172 return Image(name=updated_image['name'], image_id=updated_image['id'], size=updated_image['size'],
173 properties=updated_image.get('properties'))
176 def delete_image(glance, image):
178 Deletes an image from OpenStack
179 :param glance: the glance client
180 :param image: the image to delete
182 if glance.version == VERSION_1:
183 glance.images.delete(image)
184 elif glance.version == VERSION_2:
185 glance.images.delete(image.id)
187 raise Exception('Unsupported glance client version')