예제 #1
0
 def _find_ovs_model_disk_by_location(self, location, hostname, retry=3,
                                      timeout=3):
     """Find OVS disk object based on location and hostname
     :return VDisk: OVS DAL model object
     """
     hostname = self._get_real_hostname(hostname)
     LOG.debug('[_FIND OVS DISK] Location %s, hostname %s',
               location, hostname)
     attempt = 0
     while attempt <= retry:
         for vd in vdisklist.VDiskList.get_vdisks():
             if vd.vpool:
                 for vsr in vd.vpool.storagedrivers:
                     if vsr.storagerouter.name == hostname:
                         _location = "{0}/{1}".format(vsr.mountpoint,
                                                      vd.devicename)
                         if _location == location:
                             LOG.debug('Location %s Disk found %s',
                                       (location, vd.guid))
                             disk = vdiskhybrid.VDisk(vd.guid)
                             return disk
         msg = 'NO RESULT Attempt %s timeout %s max attempts %s'
         LOG.debug(msg, attempt, timeout, retry)
         if timeout:
             time.sleep(timeout)
         attempt += 1
     msg = (_('No disk found for location %s') % location)
     LOG.exception(msg)
     raise exception.VolumeBackendAPIException(data=msg)
예제 #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 = vdisklib.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 = vdiskhybrid.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']
        }
예제 #3
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
        """

        mountpoint = self._get_hostname_mountpoint(str(volume.host))
        ovs_snap_disk = self._find_ovs_model_disk_by_snapshot_id(snapshot.id)
        devicename = volume.display_name
        if not devicename:
            devicename = volume.name
        pmachineguid = self._find_ovs_model_pmachine_guid_by_hostname(
            six.text_type(volume.host))

        LOG.debug(
            '[CLONE FROM SNAP] %(disk)s %(snapshot)s %(device)s '
            '%(machine)s', {
                'disk': ovs_snap_disk.guid,
                'snapshot': snapshot.id,
                'device': devicename,
                'machine': pmachineguid
            })
        disk_meta = vdisklib.VDiskController.clone(diskguid=ovs_snap_disk.guid,
                                                   snapshotid=snapshot.id,
                                                   devicename=devicename,
                                                   pmachineguid=pmachineguid,
                                                   machinename="",
                                                   machineguid=None)
        volume['provider_location'] = '{}{}'.format(mountpoint,
                                                    disk_meta['backingdevice'])

        LOG.debug('[CLONE FROM SNAP] Meta: %s', six.text_type(disk_meta))
        LOG.debug('[CLONE FROM SNAP] New volume %s',
                  volume['provider_location'])
        vdisk = vdiskhybrid.VDisk(disk_meta['diskguid'])
        vdisk.cinder_id = volume.id
        vdisk.name = devicename
        vdisk.save()

        return {
            'provider_location': volume['provider_location'],
            'display_name': volume['display_name']
        }
예제 #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
        """

        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(
            six.text_type(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.debug('[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 = vdisklib.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 = vdiskhybrid.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.debug('[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
            if not len(source_ovs_disk.snapshots):
                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 = vdisklib.VDiskController.create_snapshot(
                    diskguid = source_ovs_disk.guid,
                    metadata = metadata,
                    snapshotid = None)
                LOG.debug('CREATE_SNAP OK')

            else:
                snapshotid = source_ovs_disk.snapshots[-1]['guid']
            LOG.debug('[CREATE CLONE FROM SNAP] %s ', snapshotid)

            disk_meta = vdisklib.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 = vdiskhybrid.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']}