Ejemplo n.º 1
0
    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']
        }
Ejemplo n.º 2
0
    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']}
Ejemplo n.º 3
0
    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']}
Ejemplo n.º 4
0
    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']
        }