Exemple #1
0
    def _handle_bootable_volume_glance_meta(self, context, volume_id,
                                            **kwargs):
        """Enable bootable flag and properly handle glance metadata.

        Caller should provide one and only one of snapshot_id,source_volid
        and image_id. If an image_id specified, a image_meta should also be
        provided, otherwise will be treated as an empty dictionary.
        """

        log_template = _("Copying metadata from %(src_type)s %(src_id)s to "
                         "%(vol_id)s.")
        exception_template = _("Failed updating volume %(vol_id)s metadata"
                               " using the provided %(src_type)s"
                               " %(src_id)s metadata")
        src_type = None
        src_id = None
        self._enable_bootable_flag(context, volume_id)
        try:
            if kwargs.get('snapshot_id'):
                src_type = 'snapshot'
                src_id = kwargs['snapshot_id']
                snapshot_id = src_id
                LOG.debug(log_template % {
                    'src_type': src_type,
                    'src_id': src_id,
                    'vol_id': volume_id
                })
                self.db.volume_glance_metadata_copy_to_volume(
                    context, volume_id, snapshot_id)
            elif kwargs.get('source_volid'):
                src_type = 'source volume'
                src_id = kwargs['source_volid']
                source_volid = src_id
                LOG.debug(log_template % {
                    'src_type': src_type,
                    'src_id': src_id,
                    'vol_id': volume_id
                })
                self.db.volume_glance_metadata_copy_from_volume_to_volume(
                    context, source_volid, volume_id)
            elif kwargs.get('image_id'):
                src_type = 'image'
                src_id = kwargs['image_id']
                image_id = src_id
                image_meta = kwargs.get('image_meta', {})
                LOG.debug(log_template % {
                    'src_type': src_type,
                    'src_id': src_id,
                    'vol_id': volume_id
                })
                self._capture_volume_image_metadata(context, volume_id,
                                                    image_id, image_meta)
        except exception.CinderException as ex:
            LOG.exception(exception_template % {
                'src_type': src_type,
                'src_id': src_id,
                'vol_id': volume_id
            })
            raise exception.MetadataCopyFailure(reason=ex)
Exemple #2
0
    def create_snapshot(self, context, volume_id, snapshot_id):
        """Creates and exports the snapshot."""
        caller_context = context
        context = context.elevated()
        snapshot_ref = self.db.snapshot_get(context, snapshot_id)
        LOG.info(_("snapshot %s: creating"), snapshot_ref['id'])

        self._notify_about_snapshot_usage(context, snapshot_ref,
                                          "create.start")

        try:
            LOG.debug(_("snapshot %(snap_id)s: creating"),
                      {'snap_id': snapshot_ref['id']})

            # Pass context so that drivers that want to use it, can,
            # but it is not a requirement for all drivers.
            snapshot_ref['context'] = caller_context

            model_update = self.driver.create_snapshot(snapshot_ref)
            if model_update:
                self.db.snapshot_update(context, snapshot_ref['id'],
                                        model_update)

        except Exception:
            with excutils.save_and_reraise_exception():
                self.db.snapshot_update(context, snapshot_ref['id'],
                                        {'status': 'error'})

        self.db.snapshot_update(context, snapshot_ref['id'], {
            'status': 'available',
            'progress': '100%'
        })

        vol_ref = self.db.volume_get(context, volume_id)
        if vol_ref.bootable:
            try:
                self.db.volume_glance_metadata_copy_to_snapshot(
                    context, snapshot_ref['id'], volume_id)
            except exception.CinderException as ex:
                LOG.exception(
                    _("Failed updating %(snapshot_id)s"
                      " metadata using the provided volumes"
                      " %(volume_id)s metadata") % {
                          'volume_id': volume_id,
                          'snapshot_id': snapshot_id
                      })
                raise exception.MetadataCopyFailure(reason=ex)
        LOG.info(_("snapshot %s: created successfully"), snapshot_ref['id'])
        self._notify_about_snapshot_usage(context, snapshot_ref, "create.end")
        return snapshot_id
Exemple #3
0
    def test_create_snapshot_from_bootable_volume_fail(self, mock_qemu_info):
        """Test create snapshot from bootable volume.

        But it fails to volume_glance_metadata_copy_to_snapshot.
        As a result, status of snapshot is changed to ERROR.
        """
        # create bootable volume from image
        volume = self._create_volume_from_image()
        volume_id = volume['id']
        self.assertEqual('available', volume['status'])
        self.assertTrue(volume['bootable'])

        image_info = imageutils.QemuImgInfo()
        image_info.virtual_size = '1073741824'
        mock_qemu_info.return_value = image_info

        # get volume's volume_glance_metadata
        ctxt = context.get_admin_context()
        vol_glance_meta = db.volume_glance_metadata_get(ctxt, volume_id)
        self.assertTrue(vol_glance_meta)
        snap = create_snapshot(volume_id)
        snap_stat = snap.status
        self.assertTrue(snap.id)
        self.assertTrue(snap_stat)

        # set to return DB exception
        with mock.patch.object(db, 'volume_glance_metadata_copy_to_snapshot')\
                as mock_db:
            mock_db.side_effect = exception.MetadataCopyFailure(
                reason="Because of DB service down.")
            # create snapshot from bootable volume
            self.assertRaises(exception.MetadataCopyFailure,
                              self.volume.create_snapshot,
                              ctxt,
                              snap)

        # get snapshot's volume_glance_metadata
        self.assertRaises(exception.GlanceMetadataNotFound,
                          db.volume_snapshot_glance_metadata_get,
                          ctxt, snap.id)

        # ensure that status of snapshot is 'error'
        self.assertEqual(fields.SnapshotStatus.ERROR, snap.status)

        # cleanup resource
        snap.destroy()
        db.volume_destroy(ctxt, volume_id)
Exemple #4
0
    def create_volume(self, volume):
        '''
        Create volume
        '''
        LOG.info(_('create_volume,Enter method'))
        element_path = None
        metadata = None
        v_metadata = None
        d_metadata = {}
        data = None

        v_metadata = volume.get('volume_metadata')
        for data in v_metadata:
            d_metadata[data['key']] = data['value']

        if FJ_SRC_VOL_ID not in d_metadata:
            # create volume
            (element_path, metadata) = self.common.create_volume(volume)
        else:
            # create cloned volume for backup solution
            # get source & target volume information
            ctxt = context.get_admin_context()
            volume_id = volume['id']
            volume_size = volume['size']
            src_volid = d_metadata[FJ_SRC_VOL_ID]
            if src_volid is None:
                msg = (_('create_volume,Source volume id is None'))
                LOG.error(msg)
                raise exception.VolumeBackendAPIException(data=msg)
            # end of if

            src_vref = self.db.volume_get(ctxt, src_volid)

            # check target volume information with reference to  source volume
            src_vref_size = src_vref['size']
            src_vref_status = src_vref['status']
            if ('error' in src_vref_status) or ('deleting' in src_vref_status):
                msg = (_('Invalid volume status : %(status)s') % {
                    'status': src_vref_status
                })
                LOG.error(msg)
                raise exception.VolumeBackendAPIException(data=msg)
            elif volume_size < src_vref_size:
                msg = (_(
                    'Volume size %(volume_size)sGB cannot be smaller than original volume size %(src_vref_size)sGB. They must be >= original volume size.'
                ) % {
                    'volume_size': volume_size,
                    'src_vref_size': src_vref_size
                })
                LOG.error(msg)
                raise exception.VolumeBackendAPIException(data=msg)
            # end of if

            # main processing
            LOG.info(_('create_volume,Call create cloned volume'))
            (element_path, metadata) = self.common.create_cloned_volume(
                volume, src_vref, use_service_name=True)
            LOG.info(_('create_volume,Return create cloned volume'))

            # post processing
            try:
                if src_vref.bootable:
                    self.db.volume_update(ctxt, volume['id'],
                                          {'bootable': True})
                    self.db.volume_glance_metadata_copy_from_volume_to_volume(
                        ctxt, src_volid, volume['id'])
                # end of if

                self.db.volume_update(ctxt, volume['id'],
                                      {'source_volid': src_volid})
            except Exception as ex:
                msg = (_('create volume, Failed updating volume metadata,'
                         'reason: %(reason)s,'
                         'volume_id: %(volume_id)s,'
                         'src_volid: %(src_volid)s,') % {
                             'reason': ex,
                             'volume_id': volume['id'],
                             'src_volid': src_volid
                         })
                raise exception.MetadataCopyFailure(reason=msg)
        # end of if

        d_metadata.update(metadata)

        LOG.info(_('create_volume,Exit method'))
        return {
            'provider_location': six.text_type(element_path),
            'metadata': d_metadata
        }
    def create_snapshot(self, context, volume_id, snapshot_id):
        """Creates and exports the snapshot."""
        caller_context = context
        context = context.elevated()
        snapshot_ref = self.db.snapshot_get(context, snapshot_id)
        LOG.info(_("snapshot %s: creating"), snapshot_ref['id'])

        vol_ref = self.db.volume_get(context, volume_id)
        volume_type_id = vol_ref.get('volume_type_id', None)
        if self._is_share_volume(volume_type_id):
            msg = _("Volume is share volume")
            self.db.snapshot_update(context,
                                    snapshot_ref['id'],
                                    {'status': 'error'})
            raise exception.InvalidVolume(reason=msg)

        self._notify_about_snapshot_usage(
            context, snapshot_ref, "create.start")

        try:
            # NOTE(flaper87): Verify the driver is enabled
            # before going forward. The exception will be caught
            # and the snapshot status updated.
            utils.require_driver_initialized(self.driver)

            LOG.debug(_("snapshot %(snap_id)s: creating"),
                      {'snap_id': snapshot_ref['id']})

            # Pass context so that drivers that want to use it, can,
            # but it is not a requirement for all drivers.
            snapshot_ref['context'] = caller_context

            model_update = self.driver.create_snapshot(snapshot_ref)
            if model_update:
                self.db.snapshot_update(context, snapshot_ref['id'],
                                        model_update)

        except Exception:
            with excutils.save_and_reraise_exception():
                self.db.snapshot_update(context,
                                        snapshot_ref['id'],
                                        {'status': 'error'})

        self.db.snapshot_update(context,
                                snapshot_ref['id'], {'status': 'available',
                                                     'progress': '100%'})

        if vol_ref.bootable:
            try:
                self.db.volume_glance_metadata_copy_to_snapshot(
                    context, snapshot_ref['id'], volume_id)
            except exception.CinderException as ex:
                LOG.exception(_("Failed updating %(snapshot_id)s"
                                " metadata using the provided volumes"
                                " %(volume_id)s metadata") %
                              {'volume_id': volume_id,
                               'snapshot_id': snapshot_id})
                raise exception.MetadataCopyFailure(reason=ex)
        LOG.info(_("snapshot %s: created successfully"), snapshot_ref['id'])
        self._notify_about_snapshot_usage(context, snapshot_ref, "create.end")
        return snapshot_id