Package yakumo :: Package cinder :: Package v2 :: Module volume
[hide private]
[frames] | no frames]

Source Code for Module yakumo.cinder.v2.volume

  1  # Copyright 2014-2017 by Akira Yoshiyama <akirayoshiyama@gmail.com>. 
  2  # All Rights Reserved. 
  3  # 
  4  #    Licensed under the Apache License, Version 2.0 (the "License"); you may 
  5  #    not use this file except in compliance with the License. You may obtain 
  6  #    a copy of the License at 
  7  # 
  8  #         http://www.apache.org/licenses/LICENSE-2.0 
  9  # 
 10  #    Unless required by applicable law or agreed to in writing, software 
 11  #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
 12  #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
 13  #    License for the specific language governing permissions and limitations 
 14  #    under the License. 
 15   
 16  """ 
 17  Resource class and its manager for volumes on Block Storage V2 API 
 18  """ 
 19   
 20  from yakumo import base 
 21  from yakumo.constant import UNDEF 
 22  from yakumo import mapper 
 23  from yakumo import utils 
 24   
 25  from yakumo.cinder.v2.snapshot import Resource as Snapshot 
 26  from yakumo.cinder.v2.volume_type import Resource as VolumeType 
 27  from yakumo.nova.v2.image import Resource as NovaV2Image 
 28  from yakumo.glance.v1.image import Resource as GlanceV1Image 
 29  from yakumo.glance.v2.image import Resource as GlanceV2Image 
 30   
 31   
 32  ATTRIBUTE_MAPPING = [ 
 33      ('name', 'name', mapper.Noop), 
 34      ('description', 'description', mapper.Noop), 
 35      ('volume_type', 'volume_type', mapper.Noop), 
 36      ('size', 'size', mapper.Noop), 
 37      ('availability_zone', 'availability_zone', 
 38       mapper.Resource('availability_zone')), 
 39      ('source_image', 'imageRef', mapper.Resource('image')), 
 40      ('source_volume', 'source_volid', mapper.Resource('cinder.volume')), 
 41      ('source_snapshot', 'snapshot_id', 
 42       mapper.Resource('cinder.volume_snapshot')), 
 43      ('source_replica', 'source_replica', mapper.Noop), 
 44      ('consistencygroup', 'consistencygroup_id', 
 45       mapper.Resource('cinder.consistency_group')), 
 46      ('scheduler_hints', 'scheduler_hints', mapper.Noop), 
 47      ('metadata', 'metadata', mapper.Noop), 
 48      ('project', 'tenant_id', mapper.Resource('project')), 
 49      ('project', 'os-vol-tenant-attr:tenant_id', mapper.Resource('project')), 
 50      ('is_multiattach', 'multiattach', mapper.Noop), 
 51      ('id', 'id', mapper.Noop), 
 52      ('attachments', 'attachments', mapper.Noop), 
 53      ('attachment', 'attachment', mapper.Resource('volume_attachment')), 
 54      ('host', 'host', mapper.Noop), 
 55      ('host', 'os-vol-host-attr:host', mapper.Noop), 
 56      ('volume_replication_driver', 'os-volume-replication:driver_data', 
 57       mapper.DateTime), 
 58      ('replication_status', 'replication_status', mapper.Noop), 
 59      ('extended_replication_status', 'os-volume-replication:extended_status', 
 60       mapper.Noop), 
 61      ('migration_status', 'migration_status', mapper.Noop), 
 62      ('backend_volume_id', 'os-vol-mig-status-attr:name_id', mapper.Noop), 
 63      ('user', 'user_id', mapper.Resource('user')), 
 64      ('status', 'status', mapper.Noop), 
 65      ('is_bootable', 'bootable', mapper.BoolStr), 
 66      ('is_encrypted', 'encrypted', mapper.Noop), 
 67      ('created_at', 'created_at', mapper.DateTime), 
 68      ('updated_at', 'updated_at', mapper.DateTime), 
 69  ] 
 70   
 71   
72 -class Resource(base.Resource):
73 """resource class for volumes on Block Storage V2 API""" 74 75 _stable_state = ['available', 'in-use', 'error', 'error_deleting'] 76
77 - def update(self, name=UNDEF, description=UNDEF, metadata=UNDEF):
78 """ 79 Update properties of a volume 80 81 @keyword name: Volume name 82 @type name: str 83 @keyword description: Description 84 @type description: str 85 @keyword metadata: Metadata (key=value) 86 @type metadata: dict 87 @rtype: None 88 """ 89 super(Resource, self).update( 90 name=name, 91 description=description, 92 metadata=metadata)
93
94 - def get_metadata(self):
95 """ 96 Get metadata of a volume 97 98 @return: Metadata 99 @rtype: dict 100 """ 101 ret = self._http.get(self._url_resource_path, self._id, 'metadata') 102 return ret.get('metadata')
103
104 - def set_metadata(self, **metadata):
105 """ 106 Update metadata of a volume 107 108 @keyword metadata: key=value style. 109 @type metadata: dict 110 @rtype: None 111 """ 112 self._http.post(self._url_resource_path, self._id, 'metadata', 113 data={'metadata': metadata}) 114 self.reload()
115
116 - def unset_metadata(self, *keys):
117 """ 118 Delete metadata of a volume 119 120 @param key: key of the metadata 121 @type keys: [str] 122 @rtype: None 123 """ 124 for key in keys: 125 self._http.delete(self._url_resource_path, self._id, 126 'metadata', key) 127 self.reload()
128
129 - def extend(self, size=None):
130 """ 131 Extend a volume 132 133 @keyword size: new size; should be larger than the current size 134 @type size: int 135 @rtype: None 136 """ 137 self._http.post(self._url_resource_path, self._id, 'action', 138 data=utils.get_json_body("os-extend", new_size=size))
139
140 - def reset_status(self, status=None, attach_status=None, 141 migration_status=None):
142 """ 143 Reset status of a volume 144 145 @keyword status: new status 146 @type status: str 147 @keyword attach_status: new attach status 148 @type status: str 149 @keyword migration_status: new migration status 150 @type migration_status: str 151 @rtype: None 152 """ 153 self._http.post(self._url_resource_path, self._id, 'action', 154 data=utils.get_json_body( 155 "os-reset_status", 156 status=status, 157 attach_status=attach_status, 158 migration_status=migration_status))
159
160 - def set_image_metadata(self, metadata=None):
161 """ 162 Set image metadata 163 164 @keyword metadata: new metadata 165 @type metadata: dict 166 @rtype: None 167 """ 168 self._http.post(self._url_resource_path, self._id, 'action', 169 data=utils.get_json_body("os-set_image_metadata", 170 metadata=metadata))
171
172 - def delete_image_metadata(self, key=None):
173 """ 174 Set image metadata 175 176 @keyword key: key to delete 177 @type key: str 178 @rtype: None 179 """ 180 self._http.post(self._url_resource_path, self._id, 'action', 181 data=utils.get_json_body("os-unset_image_metadata", 182 key=key))
183
184 - def unmanage(self):
185 """ 186 Unmanage a volume 187 188 @rtype: None 189 """ 190 self._http.post(self._url_resource_path, self._id, 'action', 191 data=utils.get_json_body("os-unmanage"))
192
193 - def force_detach(self, attachment=None, connector=None):
194 """ 195 Force detach a volume 196 197 @keyword attachment: Volume attachment 198 @type attachment: yakumo.server.volume_attachment.Resource 199 @keyword connector: Connector information 200 @type connector: dict 201 @rtype: None 202 """ 203 self._http.post(self._url_resource_path, self._id, 'action', 204 data=utils.get_json_body( 205 "os-force_detach", 206 attachment=attachment, 207 connector=connector))
208
209 - def upload(self, name=None, disk_format='raw', force=False):
210 """ 211 Upload volume image to Glance 212 213 @keyword name: Image name 214 @type name: str 215 @keyword disk_format: Disk format (default: 'raw') 216 @type disk_format: str 217 @keyword force: Force creation 218 @type force: bool 219 """ 220 ret = self._http.post(self._url_resource_path, self._id, 'action', 221 data=utils.get_json_body( 222 "os-volume_upload_image", 223 image_name=name, 224 disk_format=disk_format, 225 force=force)) 226 image_id = ret.get('os-volume_upload_image', {}).get('image_id') 227 return self._client.image.get_empty(image_id)
228 229
230 -class Manager(base.Manager):
231 """manager class for volumes on Block Storage V2 API""" 232 233 resource_class = Resource 234 service_type = 'volume' 235 _attr_mapping = ATTRIBUTE_MAPPING 236 _json_resource_key = 'volume' 237 _json_resources_key = 'volumes' 238 _url_resource_list_path = '/volumes/detail' 239 _url_resource_path = '/volumes' 240
241 - def _attr2json(self, attrs):
242 volume_type = attrs.get('volume_type') 243 if isinstance(volume_type, VolumeType): 244 attrs['volume_type'] = volume_type.name 245 return super(Manager, self)._attr2json(attrs)
246
247 - def _json2attr(self, json_params):
248 ret = super(Manager, self)._json2attr(json_params) 249 image = json_params.get('volume_image_metadata', {}).get('image_id') 250 if image: 251 ret['source_image'] = self._client.image.get_empty(image) 252 volume_type = json_params.get('volume_type') 253 if volume_type: 254 ret['volume_type'] = self._client.volume_type.find_one( 255 name=volume_type) 256 return ret
257
258 - def create(self, name=UNDEF, description=UNDEF, volume_type=UNDEF, 259 size=UNDEF, availability_zone=UNDEF, source=UNDEF, 260 is_replication=UNDEF, consistency_group=UNDEF, 261 scheduler_hints=UNDEF, metadata=UNDEF, 262 project=UNDEF, is_multiattach=UNDEF):
263 """ 264 Create a volume 265 266 @keyword name: Volume name 267 @type name: str 268 @keyword description: Description 269 @type description: str 270 @keyword volume_type: Volume type 271 @type volume_type: yakumo.cinder.v2.volume_type.Resource 272 @keyword size: Size in GB 273 @type size: int 274 @keyword availability_zone: Availability zone 275 @type availability_zone: yakumo.availability_zone.Resource 276 @keyword source: Source image/snapshot/volume (optional) 277 @type source: one of yakumo.image.Resource, 278 yakumo.volume_snapshot.Resource and yakumo.volume.Resource 279 @keyword is_replication: Whether the volume is a replica of another 280 volume 281 @type source: bool 282 @keyword consistency_group: Consistency group (optional) 283 @type consistency_group: yakumo.cinder.v2.consistency_group.Resource 284 @keyword scheduler_hints: Scheduler hints (optional) 285 @type scheduler_hints: dict 286 @keyword metadata: Metadata (key=value) 287 @type metadata: dict 288 @keyword is_multiattach: Whether multiattach is allowed 289 @type is_multiattach: bool 290 @return: Created volume 291 @rtype: yakumo.cinder.v2.volume.Resource 292 """ 293 source_image = UNDEF 294 source_volume = UNDEF 295 source_snapshot = UNDEF 296 source_replica = UNDEF 297 if isinstance(source, Resource): 298 if is_replication is not UNDEF: 299 source_replica = source 300 else: 301 source_volume = source 302 elif isinstance(source, Snapshot): 303 source_snapshot = source 304 elif isinstance(source, (GlanceV1Image, GlanceV2Image, NovaV2Image)): 305 source_image = source 306 return super(Manager, self).create( 307 name=name, 308 description=description, 309 volume_type=volume_type, 310 size=size, 311 availability_zone=availability_zone, 312 source_image=source_image, 313 source_volume=source_volume, 314 source_snapshot=source_snapshot, 315 source_replica=source_replica, 316 consistency_group=consistency_group, 317 scheduler_hints=scheduler_hints, 318 metadata=metadata, 319 is_multiattach=is_multiattach)
320
321 - def manage(self, name=UNDEF, description=UNDEF, volume_type=UNDEF, 322 size=UNDEF, availability_zone=UNDEF, metadata=UNDEF, 323 ref=UNDEF, project=UNDEF, is_bootable=UNDEF):
324 """ 325 Manage a volume 326 327 @keyword name: Volume name 328 @type name: str 329 @keyword description: Description 330 @type description: str 331 @keyword volume_type: Volume type 332 @type volume_type: yakumo.cinder.v2.volume_type.Resource 333 @keyword size: Size in GB 334 @type size: int 335 @keyword availability_zone: Availability zone 336 @type availability_zone: yakumo.availability_zone.Resource 337 @keyword metadata: Metadata (key=value) 338 @type metadata: dict 339 @keyword host: Reference for volume host 340 @type host: str 341 @keyword ref: Reference for existing volume (key=value) 342 @type ref: dict 343 @keyword is_bootable: Whether volume is bootable 344 @type is_bootable: bool 345 @return: Created volume 346 @rtype: yakumo.cinder.v2.volume.Resource 347 """ 348 json_attr = self._attr2json(dict( 349 name=name, 350 description=description, 351 volume_type=volume_type, 352 size=size, 353 availability_zone=availability_zone, 354 metadata=metadata, 355 host=host, 356 ref=ref, 357 is_bootable=is_bootable)) 358 ret = self._http.post(self._url_resource_path, 'os-volume-manage', 359 data=utils.get_json_body("volume", **json_attr)) 360 attrs = self._json2attr(ret) 361 return self.get_empty(attrs[self._id_attr])
362