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.
17 from cinderclient.client import Client
18 from cinderclient.exceptions import NotFound
20 from snaps.domain.volume import QoSSpec, VolumeType, VolumeTypeEncryption
21 from snaps.openstack.utils import keystone_utils
23 __author__ = 'spisarski'
25 logger = logging.getLogger('cinder_utils')
31 Utilities for basic neutron API calls
35 def cinder_client(os_creds):
37 Creates and returns a cinder client object
38 :return: the cinder client
40 return Client(version=os_creds.volume_api_version,
41 session=keystone_utils.keystone_session(os_creds),
42 region_name=os_creds.region_name)
45 def get_volume_type(cinder, volume_type_name=None, volume_type_settings=None):
47 Returns an OpenStack volume type object for a given name
48 :param cinder: the Cinder client
49 :param volume_type_name: the volume type name to lookup
50 :param volume_type_settings: the volume type settings used for lookups
51 :return: the volume type object or None
53 if not volume_type_name and not volume_type_settings:
56 if volume_type_settings:
57 volume_type_name = volume_type_settings.name
59 volume_types = cinder.volume_types.list()
60 for vol_type in volume_types:
61 if vol_type.name == volume_type_name:
62 encryption = get_volume_encryption_by_type(cinder, vol_type)
63 return VolumeType(vol_type.name, vol_type.id, vol_type.is_public,
67 def __get_os_volume_type_by_id(cinder, volume_type_id):
69 Returns an OpenStack volume type object for a given name
70 :param cinder: the Cinder client
71 :param volume_type_id: the volume_type ID to lookup
72 :return: the SNAPS-OO Domain Volume object or None
75 return cinder.volume_types.get(volume_type_id)
77 logger.info('Volume with ID [%s] does not exist',
81 def get_volume_type_by_id(cinder, volume_type_id):
83 Returns an OpenStack volume type object for a given name
84 :param cinder: the Cinder client
85 :param volume_type_id: the volume_type ID to lookup
86 :return: the SNAPS-OO Domain Volume object or None
88 os_vol_type = __get_os_volume_type_by_id(cinder, volume_type_id)
90 temp_vol_type = VolumeType(os_vol_type.name, os_vol_type.id,
91 os_vol_type.is_public, None, None)
92 encryption = get_volume_encryption_by_type(cinder, temp_vol_type)
95 if os_vol_type.qos_specs_id:
96 qos_spec = get_qos_by_id(cinder, os_vol_type.qos_specs_id)
98 return VolumeType(os_vol_type.name, os_vol_type.id,
99 os_vol_type.is_public, encryption, qos_spec)
102 def create_volume_type(cinder, type_settings):
104 Creates and returns OpenStack volume type object with an external URL
105 :param cinder: the cinder client
106 :param type_settings: the volume type settings object
107 :return: the volume type domain object
108 :raise Exception if using a file and it cannot be found
110 vol_type = cinder.volume_types.create(
111 type_settings.name, type_settings.description,
112 type_settings.public)
114 vol_encryption = None
115 if type_settings.encryption:
117 vol_encryption = create_volume_encryption(
118 cinder, vol_type, type_settings.encryption)
119 except Exception as e:
120 logger.warn('Error creating volume encryption - %s', e)
123 if type_settings.qos_spec_name:
125 qos_spec = get_qos(cinder, qos_name=type_settings.qos_spec_name)
126 cinder.qos_specs.associate(qos_spec, vol_type.id)
127 except NotFound as e:
128 logger.warn('Unable to locate qos_spec named %s - %s',
129 type_settings.qos_spec_name, e)
131 return VolumeType(vol_type.name, vol_type.id, vol_type.is_public,
132 vol_encryption, qos_spec)
135 def delete_volume_type(cinder, vol_type):
137 Deletes an volume from OpenStack
138 :param cinder: the cinder client
139 :param vol_type: the VolumeType domain object
141 logger.info('Deleting volume named - %s', vol_type.name)
142 cinder.volume_types.delete(vol_type.id)
145 def get_volume_encryption_by_type(cinder, volume_type):
147 Returns an OpenStack volume type object for a given name
148 :param cinder: the Cinder client
149 :param volume_type: the VolumeType domain object
150 :return: the VolumeEncryption domain object or None
152 os_vol_type = __get_os_volume_type_by_id(cinder, volume_type.id)
153 encryption = cinder.volume_encryption_types.get(os_vol_type)
154 if hasattr(encryption, 'encryption_id'):
156 if hasattr(encryption, 'cipher'):
157 cipher = encryption.cipher
159 if hasattr(encryption, 'key_size'):
160 key_size = encryption.key_size
161 return VolumeTypeEncryption(
162 encryption.encryption_id, encryption.volume_type_id,
163 encryption.control_location, encryption.provider, cipher, key_size)
166 def create_volume_encryption(cinder, volume_type, encryption_settings):
168 Creates and returns OpenStack volume type object with an external URL
169 :param cinder: the cinder client
170 :param volume_type: the VolumeType object to associate the encryption
171 :param encryption_settings: the volume type encryption settings object
172 :return: the VolumeTypeEncryption domain object
174 specs = {'name': encryption_settings.name,
175 'provider': encryption_settings.provider_class}
176 if encryption_settings.key_size:
177 specs['key_size'] = encryption_settings.key_size
178 if encryption_settings.provider_class:
179 specs['provider_class'] = encryption_settings.provider_class
180 if encryption_settings.control_location:
181 specs['control_location'] = encryption_settings.control_location.value
182 if encryption_settings.cipher:
183 specs['cipher'] = encryption_settings.cipher
185 encryption = cinder.volume_encryption_types.create(volume_type.id, specs)
188 if hasattr(encryption, 'cipher'):
189 cipher = encryption.cipher
191 if hasattr(encryption, 'key_size'):
192 key_size = encryption.key_size
193 return VolumeTypeEncryption(
194 encryption.encryption_id, encryption.volume_type_id,
195 encryption.control_location, encryption.provider, cipher, key_size)
198 def delete_volume_type_encryption(cinder, vol_type):
200 Deletes an volume from OpenStack
201 :param cinder: the cinder client
202 :param vol_type: the associated VolumeType domain object
204 logger.info('Deleting volume encryption for volume type - %s',
206 os_vol_type = __get_os_volume_type_by_id(cinder, vol_type.id)
207 cinder.volume_encryption_types.delete(os_vol_type)
210 def __get_os_qos(cinder, qos_name=None, qos_settings=None):
212 Returns an OpenStack QoS object for a given name
213 :param cinder: the Cinder client
214 :param qos_name: the qos name to lookup
215 :param qos_settings: the qos settings used for lookups
216 :return: the qos object or None
218 if not qos_name and not qos_settings:
222 qos_name = qos_settings.name
224 qoss = cinder.qos_specs.list()
226 if qos.name == qos_name:
230 def get_qos(cinder, qos_name=None, qos_settings=None):
232 Returns an OpenStack QoS object for a given name
233 :param cinder: the Cinder client
234 :param qos_name: the qos name to lookup
235 :param qos_settings: the qos settings used for lookups
236 :return: the qos object or None
238 os_qos = __get_os_qos(cinder, qos_name, qos_settings)
240 return QoSSpec(name=os_qos.name, spec_id=os_qos.id,
241 consumer=os_qos.consumer)
244 def get_qos_by_id(cinder, qos_id):
246 Returns an OpenStack qos object for a given name
247 :param cinder: the Cinder client
248 :param qos_id: the qos ID to lookup
249 :return: the SNAPS-OO Domain Volume object or None
251 qos = cinder.qos_specs.get(qos_id)
252 return QoSSpec(name=qos.name, spec_id=qos.id, consumer=qos.consumer)
255 def create_qos(cinder, qos_settings):
257 Creates and returns OpenStack qos object with an external URL
258 :param cinder: the cinder client
259 :param qos_settings: the qos settings object
260 :return: the qos domain object
261 :raise Exception if using a file and it cannot be found
263 specs = qos_settings.specs
264 specs['consumer'] = qos_settings.consumer.value
265 qos = cinder.qos_specs.create(qos_settings.name, qos_settings.specs)
266 return QoSSpec(name=qos.name, spec_id=qos.id, consumer=qos.consumer)
269 def delete_qos(cinder, qos):
271 Deletes an QoS from OpenStack
272 :param cinder: the cinder client
273 :param qos: the qos domain object to delete
275 logger.info('Deleting QoS named - %s', qos.name)
276 cinder.qos_specs.delete(qos.id)