def create_volume_from_snapshot(self, volume, snapshot): """Creates a volume from a snapshot. Called on "cinder create --snapshot-id ..." :param snapshot: snapshot reference (sqlalchemy Model) :param volume: volume reference (sqlalchemy Model) Volume here is just a ModelObject, it doesn't exist physically, it will be created by OVS. Diskguid to be passed to the clone method is the ovs diskguid of the parent of the snapshot with snapshot.id OVS: Clone from arbitrary volume, requires volumedriver 3.6 release > 15.08.2014 """ _debug_vol_info('CLONE_VOL', volume) _debug_vol_info('CLONE_SNAP', snapshot) mountpoint = self._get_hostname_mountpoint(str(volume.host)) ovs_snap_disk = self._find_ovs_model_disk_by_snapshot_id(snapshot.id) OVSVolumeDriver._wait_for_snapshot(ovs_snap_disk, snapshot.id) devicename = volume.display_name if not devicename: devicename = volume.name pmachineguid = self._find_ovs_model_pmachine_guid_by_hostname( str(volume.host)) LOG.info('[CLONE FROM SNAP] %s %s %s %s' % (ovs_snap_disk.guid, snapshot.id, devicename, pmachineguid)) try: kwargs = dict(diskguid=ovs_snap_disk.guid, snapshotid=snapshot.id, devicename=devicename, pmachineguid=pmachineguid, machinename="", machineguid=None) LOG.debug('[CLONE FROM SNAP] Executing clone - async') # Execute "clone" task async, using celery workers # wait for the result for 30 minutes then raise TimeoutError disk_meta = VDiskController.clone.apply_async(kwargs = kwargs)\ .get(timeout = 1800) LOG.debug('[CLONE FROM SNAP] Executing clone - async - DONE') volume['provider_location'] = '{}{}'.format( mountpoint, disk_meta['backingdevice']) LOG.debug('[CLONE FROM SNAP] Meta: %s' % str(disk_meta)) LOG.debug('[CLONE FROM SNAP] New volume %s' % volume['provider_location']) vdisk = VDisk(disk_meta['diskguid']) vdisk.cinder_id = volume.id vdisk.name = devicename vdisk.save() except Exception as ex: LOG.error('CLONE FROM SNAP: Internal error %s ' % str(ex)) self.delete_volume(volume) raise return { 'provider_location': volume['provider_location'], 'display_name': volume['display_name'] }
def create_volume_from_snapshot(self, volume, snapshot): """Creates a volume from a snapshot. Called on "cinder create --snapshot-id ..." :param snapshot: snapshot reference (sqlalchemy Model) :param volume: volume reference (sqlalchemy Model) Volume here is just a ModelObject, it doesn't exist physically, it will be created by OVS. Diskguid to be passed to the clone method is the ovs diskguid of the parent of the snapshot with snapshot.id OVS: Clone from arbitrary volume, requires volumedriver 3.6 release > 15.08.2014 """ _debug_vol_info('CLONE_VOL', volume) _debug_vol_info('CLONE_SNAP', snapshot) mountpoint = self._get_hostname_mountpoint(str(volume.host)) ovs_snap_disk = self._find_ovs_model_disk_by_snapshot_id(snapshot.id) OVSVolumeDriver._wait_for_snapshot(ovs_snap_disk, snapshot.id) devicename = volume.display_name if not devicename: devicename = volume.name pmachineguid = self._find_ovs_model_pmachine_guid_by_hostname( str(volume.host)) LOG.info('[CLONE FROM SNAP] %s %s %s %s' % (ovs_snap_disk.guid, snapshot.id, devicename, pmachineguid)) try: kwargs = dict(diskguid = ovs_snap_disk.guid, snapshotid = snapshot.id, devicename = devicename, pmachineguid = pmachineguid, machinename = "", machineguid=None) LOG.debug('[CLONE FROM SNAP] Executing clone - async') # Execute "clone" task async, using celery workers # wait for the result for 30 minutes then raise TimeoutError disk_meta = VDiskController.clone.apply_async(kwargs = kwargs)\ .get(timeout = 1800) LOG.debug('[CLONE FROM SNAP] Executing clone - async - DONE') volume['provider_location'] = '{}{}'.format( mountpoint, disk_meta['backingdevice']) LOG.debug('[CLONE FROM SNAP] Meta: %s' % str(disk_meta)) LOG.debug('[CLONE FROM SNAP] New volume %s' % volume['provider_location']) vdisk = VDisk(disk_meta['diskguid']) vdisk.cinder_id = volume.id vdisk.name = devicename vdisk.save() except Exception as ex: LOG.error('CLONE FROM SNAP: Internal error %s ' % str(ex)) self.delete_volume(volume) raise return {'provider_location': volume['provider_location'], 'display_name': volume['display_name']}
def create_cloned_volume(self, volume, src_vref): """Create a cloned volume from another volume. Called on "cinder create --source-volid ... " :param volume: volume reference - target volume (sqlalchemy Model) :param src_vref: volume reference - source volume (sqlalchemy Model) OVS: Create clone from template if the source is a template Create volume from snapshot if the source is a volume - create snapshot of source volume if it doesn't have snapshots """ _debug_vol_info('CREATE_CLONED_VOL', volume) _debug_vol_info('CREATE_CLONED_VOL Source', src_vref) mountpoint = self._get_hostname_mountpoint(str(volume.host)) name = volume.display_name if not name: name = volume.name volume.display_name = volume.name pmachineguid = self._find_ovs_model_pmachine_guid_by_hostname( str(volume.host)) #source source_ovs_disk = self._find_ovs_model_disk_by_location( str(src_vref.provider_location), src_vref.host) if source_ovs_disk.info['object_type'] == 'TEMPLATE': LOG.info('[CREATE_FROM_TEMPLATE] VDisk %s is a template' % source_ovs_disk.devicename) # cloning from a template LOG.debug('[CREATE FROM TEMPLATE] ovs_disk %s ' % (source_ovs_disk.devicename)) disk_meta = VDiskController.create_from_template( diskguid = source_ovs_disk.guid, machinename = "", devicename = str(name), pmachineguid = pmachineguid, machineguid = None, storagedriver_guid = None) volume['provider_location'] = '{}{}'.format( mountpoint, disk_meta['backingdevice']) LOG.debug('[CREATE FROM TEMPLATE] New volume %s' % volume['provider_location']) vdisk = VDisk(disk_meta['diskguid']) vdisk.cinder_id = volume.id vdisk.name = name LOG.debug('[CREATE FROM TEMPLATE] Updating meta %s %s' % (volume.id, name)) vdisk.save() else: LOG.info('[THIN CLONE] VDisk %s is not a template' % source_ovs_disk.devicename) # We do not support yet full volume clone # - requires "emancipate" functionality # So for now we'll take a snapshot # (or the latest snapshot existing) and clone from that snapshot available_snapshots = [snapshot for snapshot in source_ovs_disk.snapshots if 'in_backend' not in snapshot or snapshot['in_backend'] is True] if len(available_snapshots) == 0: metadata = {'label': "Cinder clone snapshot {0}".format(name), 'is_consistent': False, 'timestamp': time.time(), 'machineguid': source_ovs_disk.vmachine_guid, 'is_automatic': False} LOG.debug('CREATE_SNAP %s %s' % (name, str(metadata))) snapshotid = VDiskController.create_snapshot( diskguid = source_ovs_disk.guid, metadata = metadata, snapshotid = None) LOG.debug('CREATE_SNAP OK') OVSVolumeDriver._wait_for_snapshot(source_ovs_disk, snapshotid) else: snapshotid = available_snapshots[-1]['guid'] LOG.debug('[CREATE CLONE FROM SNAP] %s ' % snapshotid) disk_meta = VDiskController.clone(diskguid = source_ovs_disk.guid, snapshotid = snapshotid, devicename = str(name), pmachineguid = pmachineguid, machinename = "", machineguid=None) volume['provider_location'] = '{}{}'.format( mountpoint, disk_meta['backingdevice']) LOG.debug('[CLONE FROM SNAP] Meta: %s' % str(disk_meta)) LOG.debug('[CLONE FROM SNAP] New volume %s' % volume['provider_location']) vdisk = VDisk(disk_meta['diskguid']) vdisk.cinder_id = volume.id vdisk.name = name vdisk.save() return {'provider_location': volume['provider_location'], 'display_name': volume['display_name']}
def create_cloned_volume(self, volume, src_vref): """Create a cloned volume from another volume. Called on "cinder create --source-volid ... " :param volume: volume reference - target volume (sqlalchemy Model) :param src_vref: volume reference - source volume (sqlalchemy Model) OVS: Create clone from template if the source is a template Create volume from snapshot if the source is a volume - create snapshot of source volume if it doesn't have snapshots """ _debug_vol_info('CREATE_CLONED_VOL', volume) _debug_vol_info('CREATE_CLONED_VOL Source', src_vref) mountpoint = self._get_hostname_mountpoint(str(volume.host)) name = volume.display_name if not name: name = volume.name volume.display_name = volume.name pmachineguid = self._find_ovs_model_pmachine_guid_by_hostname( str(volume.host)) #source source_ovs_disk = self._find_ovs_model_disk_by_location( str(src_vref.provider_location), src_vref.host) if source_ovs_disk.info['object_type'] == 'TEMPLATE': LOG.info('[CREATE_FROM_TEMPLATE] VDisk %s is a template' % source_ovs_disk.devicename) # cloning from a template LOG.debug('[CREATE FROM TEMPLATE] ovs_disk %s ' % (source_ovs_disk.devicename)) disk_meta = VDiskController.create_from_template( diskguid=source_ovs_disk.guid, machinename="", devicename=str(name), pmachineguid=pmachineguid, machineguid=None, storagedriver_guid=None) volume['provider_location'] = '{}{}'.format( mountpoint, disk_meta['backingdevice']) LOG.debug('[CREATE FROM TEMPLATE] New volume %s' % volume['provider_location']) vdisk = VDisk(disk_meta['diskguid']) vdisk.cinder_id = volume.id vdisk.name = name LOG.debug('[CREATE FROM TEMPLATE] Updating meta %s %s' % (volume.id, name)) vdisk.save() else: LOG.info('[THIN CLONE] VDisk %s is not a template' % source_ovs_disk.devicename) # We do not support yet full volume clone # - requires "emancipate" functionality # So for now we'll take a snapshot # (or the latest snapshot existing) and clone from that snapshot available_snapshots = [ snapshot for snapshot in source_ovs_disk.snapshots if 'in_backend' not in snapshot or snapshot['in_backend'] is True ] if len(available_snapshots) == 0: metadata = { 'label': "Cinder clone snapshot {0}".format(name), 'is_consistent': False, 'timestamp': time.time(), 'machineguid': source_ovs_disk.vmachine_guid, 'is_automatic': False } LOG.debug('CREATE_SNAP %s %s' % (name, str(metadata))) snapshotid = VDiskController.create_snapshot( diskguid=source_ovs_disk.guid, metadata=metadata, snapshotid=None) LOG.debug('CREATE_SNAP OK') OVSVolumeDriver._wait_for_snapshot(source_ovs_disk, snapshotid) else: snapshotid = available_snapshots[-1]['guid'] LOG.debug('[CREATE CLONE FROM SNAP] %s ' % snapshotid) disk_meta = VDiskController.clone(diskguid=source_ovs_disk.guid, snapshotid=snapshotid, devicename=str(name), pmachineguid=pmachineguid, machinename="", machineguid=None) volume['provider_location'] = '{}{}'.format( mountpoint, disk_meta['backingdevice']) LOG.debug('[CLONE FROM SNAP] Meta: %s' % str(disk_meta)) LOG.debug('[CLONE FROM SNAP] New volume %s' % volume['provider_location']) vdisk = VDisk(disk_meta['diskguid']) vdisk.cinder_id = volume.id vdisk.name = name vdisk.save() return { 'provider_location': volume['provider_location'], 'display_name': volume['display_name'] }