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,
43 session=keystone_utils.keystone_session(os_creds),
44 region_name=os_creds.region_name)
47 def get_image(glance, image_name=None):
49 Returns an OpenStack image object for a given name
50 :param glance: the Glance client
51 :param image_name: the image name to lookup
52 :return: the image object or None
54 images = glance.images.list()
56 if glance.version == VERSION_1:
57 if image.name == image_name:
58 image = glance.images.get(image.id)
59 return Image(name=image.name, image_id=image.id,
60 size=image.size, properties=image.properties)
61 elif glance.version == VERSION_2:
62 if image['name'] == image_name:
64 name=image['name'], image_id=image['id'],
65 size=image['size'], properties=image.get('properties'))
69 def get_image_by_id(glance, image_id):
71 Returns an OpenStack image object for a given name
72 :param glance: the Glance client
73 :param image_id: the image ID to lookup
74 :return: the SNAPS-OO Domain Image object or None
76 image = glance.images.get(image_id)
78 name=image['name'], image_id=image['id'],
79 size=image['size'], properties=image.get('properties'))
82 def get_image_status(glance, image):
84 Returns a new OpenStack Image object for a given OpenStack image object
85 :param glance: the Glance client
86 :param image: the domain Image object
87 :return: the OpenStack Image object
89 if glance.version == VERSION_1:
90 os_image = glance.images.get(image.id)
91 return os_image.status
92 elif glance.version == VERSION_2:
93 os_image = glance.images.get(image.id)
94 return os_image['status']
96 raise GlanceException('Unsupported glance client version')
99 def create_image(glance, image_settings):
101 Creates and returns OpenStack image object with an external URL
102 :param glance: the glance client
103 :param image_settings: the image settings object
104 :return: the OpenStack image object
105 :raise Exception if using a file and it cannot be found
107 if glance.version == VERSION_1:
108 return __create_image_v1(glance, image_settings)
109 elif glance.version == VERSION_2:
110 return __create_image_v2(glance, image_settings)
112 raise GlanceException('Unsupported glance client version')
115 def __create_image_v1(glance, image_settings):
117 Creates and returns OpenStack image object with an external URL
118 :param glance: the glance client
119 :param image_settings: the image settings object
120 :return: the OpenStack image object
121 :raise exceptions from the Glance client or IOError when opening a file
124 'name': image_settings.name, 'disk_format': image_settings.format,
125 'container_format': 'bare', 'is_public': image_settings.public}
130 if image_settings.extra_properties:
131 kwargs['properties'] = image_settings.extra_properties
133 if image_settings.url:
134 kwargs['location'] = image_settings.url
135 elif image_settings.image_file:
136 image_file = open(image_settings.image_file, 'rb')
137 kwargs['data'] = image_file
140 'Unable to create image with name - %s. No file or URL',
144 created_image = glance.images.create(**kwargs)
145 return Image(name=image_settings.name, image_id=created_image.id,
146 size=created_image.size,
147 properties=created_image.properties)
153 def __create_image_v2(glance, image_settings):
155 Creates and returns OpenStack image object with an external URL
156 :param glance: the glance client v2
157 :param image_settings: the image settings object
158 :return: the OpenStack image object
159 :raise GlanceException or IOException or URLError
161 cleanup_temp_file = False
163 if image_settings.image_file:
164 image_filename = image_settings.image_file
165 elif image_settings.url:
166 file_name = str(uuid.uuid4())
168 image_file = file_utils.download(
169 image_settings.url, './tmp', file_name)
170 image_filename = image_file.name
173 os.remove(image_file.name)
176 cleanup_temp_file = True
178 raise GlanceException('Filename or URL of image not configured')
183 kwargs['name'] = image_settings.name
184 kwargs['disk_format'] = image_settings.format
185 kwargs['container_format'] = 'bare'
187 if image_settings.public:
188 kwargs['visibility'] = 'public'
190 if image_settings.extra_properties:
191 kwargs.update(image_settings.extra_properties)
193 os_image = glance.images.create(**kwargs)
194 image_file = open(image_filename, 'rb')
195 glance.images.upload(os_image['id'], image_file)
197 logger.error('Unexpected exception creating image. Rolling back')
199 delete_image(glance, Image(
200 name=os_image['name'], image_id=os_image['id'],
201 size=os_image['size'], properties=os_image.get('properties')))
205 logger.debug('Closing file %s', image_file.name)
207 if cleanup_temp_file:
208 logger.info('Removing file %s', image_file.name)
209 os.remove(image_filename)
211 return get_image_by_id(glance, os_image['id'])
214 def delete_image(glance, image):
216 Deletes an image from OpenStack
217 :param glance: the glance client
218 :param image: the image to delete
220 logger.info('Deleting image named - %s', image.name)
221 glance.images.delete(image.id)
224 class GlanceException(Exception):
226 Exception when calls to the Glance client cannot be served properly