def _cache_vol_2_2(self, context, vol, image_meta, image_service): image_id = image_meta['id'] # Pull down image and determine if valid with image_utils.TemporaryImages.fetch(image_service, context, image_id) as tmp_image: data = image_utils.qemu_img_info(tmp_image) fmt = data.file_format if fmt is None: raise exception.ImageUnacceptable( reason=_("'qemu-img info' parsing failed."), image_id=image_id) backing_file = data.backing_file if backing_file is not None: raise exception.ImageUnacceptable( image_id=image_id, reason=_("fmt=%(fmt)s backed by:%(backing_file)s") % {'fmt': fmt, 'backing_file': backing_file, }) vsize = int( math.ceil(float(data.virtual_size) / units.Gi)) vol['size'] = vsize vtype = vol['volume_type_id'] LOG.info("Creating cached image with volume type: %(vtype)s and " "size %(size)s", {'vtype': vtype, 'size': vsize}) self._create_volume_2_2(vol) with self._connect_vol(context, vol) as device: LOG.debug("Moving image %s to volume %s", image_meta['id'], datc.get_name(vol)) image_utils.convert_image(tmp_image, device, 'raw', run_as_root=True) LOG.debug("Finished moving image %s to volume %s", image_meta['id'], datc.get_name(vol)) data = image_utils.qemu_img_info(device, run_as_root=True) if data.file_format != 'raw': raise exception.ImageUnacceptable( image_id=image_id, reason=_( "Converted to %(vol_format)s, but format is " "now %(file_format)s") % { 'vol_format': 'raw', 'file_format': data.file_format}) # TODO(_alastor_): Remove this snapshot creation when we fix # "created_at" attribute in the frontend # We don't actually care about the snapshot uuid, we just want # a single snapshot snapshot = {'id': str(uuid.uuid4()), 'volume_id': vol['id'], 'project_id': vol['project_id']} self._create_snapshot_2_2(snapshot) metadata = {'type': 'cached_image'} tenant = self.get_tenant(vol['project_id']) ai = self.cvol_to_ai(vol, tenant=tenant) ai.metadata.set(tenant=tenant, **metadata) # Cloning offline AI is ~4 seconds faster than cloning online AI self._detach_volume_2_2(None, vol)
def _manage_existing_2_2(self, volume, existing_ref): # Only volumes created under the requesting tenant can be managed in # the v2.1+ API. Eg. If tenant A is the tenant for the volume to be # managed, it must also be tenant A that makes this request. # This will be fixed in a later API update existing_ref = existing_ref['source-name'] app_inst_name, __, __, __ = datc._parse_vol_ref(existing_ref) LOG.debug("Managing existing Datera volume %s " "Changing name to %s", datc.get_name(volume), existing_ref) # Rename AppInstance dummy_vol = {'id': app_inst_name, 'project_id': volume['project_id']} tenant = self.get_tenant(volume['project_id']) ai = self.cvol_to_ai(dummy_vol, tenant=tenant) data = {'name': datc.get_name(volume)} ai.set(tenant=tenant, **data) self._add_vol_meta_2_2(volume)
def _create_volume_from_snapshot_2_2(self, volume, snapshot): # Handle case where snapshot is "managed" dummy_vol = {'id': snapshot['volume_id'], 'project_id': snapshot['project_id']} tenant = self.get_tenant(dummy_vol['project_id']) dvol = self.cvol_to_dvol(dummy_vol, tenant=tenant) found_snap = None provider_location = snapshot.get('provider_location') if provider_location: found_snap = dvol.snapshots.get(provider_location, tenant=tenant) else: snapshots = dvol.snapshots.list(tenant=tenant) for snap in snapshots: if snap.uuid == snapshot['id']: found_snap = snap break else: raise exception.SnapshotNotFound(snapshot_id=snapshot['id']) self._snap_poll_2_2(found_snap, tenant) src = found_snap.path app_params = ( { 'create_mode': 'openstack', 'uuid': str(volume['id']), 'name': datc.get_name(volume), 'clone_snapshot_src': {'path': src}, }) self.api.app_instances.create(tenant=tenant, **app_params) if (volume['size'] > snapshot['volume_size']): self._extend_volume_2_2(volume, volume['size']) self._add_vol_meta_2_2(volume)
def _update_migrated_volume_2_2(self, context, volume, new_volume, volume_status): """Rename the newly created volume to the original volume. So we can find it correctly. """ tenant = self.get_tenant(new_volume['project_id']) ai = self.cvol_to_ai(new_volume, tenant=tenant) data = {'name': datc.get_name(volume)} ai.set(tenant=tenant, **data) return {'_name_id': None}
def _create_volume_2_1(self, volume): policies = self._get_policies_for_resource(volume) num_replicas = int(policies['replica_count']) storage_name = 'storage-1' volume_name = 'volume-1' template = policies['template'] placement = policies['placement_mode'] ip_pool = policies['ip_pool'] name = datc.get_name(volume) if template: app_params = ({ 'create_mode': 'openstack', # 'uuid': str(volume['id']), 'name': name, 'app_template': { 'path': '/app_templates/{}'.format(template) } }) else: app_params = ({ 'create_mode': 'openstack', 'uuid': str(volume['id']), 'name': name, 'access_control_mode': 'deny_all', 'storage_instances': [{ 'name': storage_name, 'ip_pool': { 'path': ('/access_network_ip_pools/' '{}'.format(ip_pool)) }, 'volumes': [{ 'name': volume_name, 'size': volume['size'], 'placement_mode': placement, 'replica_count': num_replicas, 'snapshot_policies': [] }] }] }) tenant = self.create_tenant(volume['project_id']) self.api.app_instances.create(tenant=tenant, **app_params) self._update_qos_2_1(volume, policies) self._add_vol_meta_2_1(volume)
def _delete_snapshot_2_2(self, snapshot): # Handle case where snapshot is "managed" dummy_vol = { 'id': snapshot['volume_id'], 'project_id': snapshot['project_id'] } tenant = self.get_tenant(dummy_vol['project_id']) dvol = self.cvol_to_dvol(dummy_vol, tenant=tenant) snapshots = None # Shortcut if this is a managed snapshot provider_location = snapshot.get('provider_location') if provider_location: snap = dvol.snapshots.get(provider_location, tenant=tenant) snap.delete(tenant=tenant) return # Long-way. UUID identification try: snapshots = dvol.snapshots.list(tenant=tenant) except exception.NotFound: msg = ("Tried to delete snapshot %s, but parent volume %s was " "not found in Datera cluster. Continuing with delete.") LOG.info(msg, datc.get_name(snapshot), datc.get_name({'id': snapshot['volume_id']})) return try: for snap in snapshots: if snap.uuid == snapshot['id']: snap.delete(tenant=tenant) break else: raise exception.NotFound except exception.NotFound: msg = ("Tried to delete snapshot %s, but was not found in " "Datera cluster. Continuing with delete.") LOG.info(msg, datc.get_name(snapshot))
def _create_cloned_volume_2_2(self, volume, src_vref): tenant = self.get_tenant(volume['project_id']) sdvol = self.cvol_to_dvol(src_vref, tenant=tenant) src = sdvol.path data = { 'create_mode': 'openstack', 'name': datc.get_name(volume), 'uuid': str(volume['id']), 'clone_volume_src': {'path': src}, } tenant = self.get_tenant(volume['project_id']) self.api.app_instances.create(tenant=tenant, **data) if volume['size'] > src_vref['size']: self._extend_volume_2_2(volume, volume['size']) self._add_vol_meta_2_2(volume)
def _delete_volume_2_2(self, volume): try: tenant = self.get_tenant(volume['project_id']) ai = self.cvol_to_ai(volume, tenant=tenant) si = ai.storage_instances.list(tenant=tenant)[0] # Clear out ACL acl = si.acl_policy.get(tenant=tenant) acl.set(tenant=tenant, initiators=[]) # Bring volume offline data = {'admin_state': 'offline', 'force': True} ai.set(tenant=tenant, **data) ai.delete(tenant=tenant, force=True) except exception.NotFound: msg = ("Tried to delete volume %s, but it was not found in the " "Datera cluster. Continuing with delete.") LOG.info(msg, datc.get_name(volume))
def _manage_existing_snapshot_2_2(self, snapshot, existing_ref): existing_ref = existing_ref['source-name'] datc._check_snap_ref(existing_ref) LOG.debug("Managing existing Datera volume snapshot %s for volume %s", existing_ref, datc.get_name({'id': snapshot['volume_id']})) return {'provider_location': existing_ref}
def _create_volume_2_2(self, volume): policies = self._get_policies_for_resource(volume) num_replicas = int(policies['replica_count']) storage_name = 'storage-1' volume_name = 'volume-1' template = policies['template'] placement = policies['placement_mode'] ppolicy = policies['placement_policy'] ip_pool = datc.get_ip_pool(policies) name = datc.get_name(volume) if template: app_params = ({ 'create_mode': 'openstack', # 'uuid': str(volume['id']), 'name': name, 'app_template': { 'path': '/app_templates/{}'.format(template) } }) if self._support_template_override_2_2(): app_params['template_override'] = { 'storage_instances': { storage_name: { 'volumes': { volume_name: { 'size': str(volume['size']) } } } } } else: app_params = ({ 'create_mode': 'openstack', 'uuid': str(volume['id']), 'name': name, 'access_control_mode': 'deny_all', 'storage_instances': [{ 'name': storage_name, 'ip_pool': { 'path': ('/access_network_ip_pools/' '{}'.format(ip_pool)) }, 'volumes': [{ 'name': volume_name, 'size': volume['size'], 'replica_count': num_replicas, 'snapshot_policies': [] }] }] }) create_vol = app_params['storage_instances'][0]['volumes'][0] if datc.dat_version_gte(self.datera_version, '3.3.0.0'): create_vol['placement_policy'] = { 'path': '/placement_policies/{}'.format(ppolicy) } else: create_vol['placement_mode'] = placement tenant = self.create_tenant(volume['project_id']) self.api.app_instances.create(tenant=tenant, **app_params) self._update_qos_2_2(volume, policies) self._add_vol_meta_2_2(volume)