def delete(self, context, backup, force=False): """Make the RPC call to delete a volume backup. Call backup manager to execute backup delete or force delete operation. :param context: running context :param backup: the dict of backup that is got from DB. :param force: indicate force delete or not :raises InvalidBackup: :raises BackupDriverException: :raises ServiceNotFound: """ context.authorize(policy.DELETE_POLICY, target_obj=backup) if not force and backup.status not in [ fields.BackupStatus.AVAILABLE, fields.BackupStatus.ERROR ]: msg = _('Backup status must be available or error') raise exception.InvalidBackup(reason=msg) if force and not self._check_support_to_force_delete( context, backup.host): msg = _('force delete') raise exception.NotSupportedOperation(operation=msg) # Don't allow backup to be deleted if there are incremental # backups dependent on it. deltas = self.get_all(context, search_opts={'parent_id': backup.id}) if deltas and len(deltas): msg = _('Incremental backups exist for this backup.') raise exception.InvalidBackup(reason=msg) backup.status = fields.BackupStatus.DELETING backup.host = self._get_available_backup_service_host( backup.host, backup.availability_zone) backup.save() self.backup_rpcapi.delete_backup(context, backup)
def delete(self, context, backup, force=False): """Make the RPC call to delete a volume backup. Call backup manager to execute backup delete or force delete operation. :param context: running context :param backup: the dict of backup that is got from DB. :param force: indicate force delete or not :raises: InvalidBackup :raises: BackupDriverException """ check_policy(context, 'delete') if not force and backup.status not in ['available', 'error']: msg = _('Backup status must be available or error') raise exception.InvalidBackup(reason=msg) if force and not self._check_support_to_force_delete(context, backup.host): msg = _('force delete') raise exception.NotSupportedOperation(operation=msg) # Don't allow backup to be deleted if there are incremental # backups dependent on it. deltas = self.get_all(context, {'parent_id': backup.id}) if deltas and len(deltas): msg = _('Incremental backups exist for this backup.') raise exception.InvalidBackup(reason=msg) backup.status = 'deleting' backup.save() self.backup_rpcapi.delete_backup(context, backup)
def _copy_volume_from_snapshot(self, snapshot, volume, volume_size, src_encryption_key_id=None, new_encryption_key_id=None): """Copy data from snapshot to destination volume.""" if new_encryption_key_id: msg = _("Encryption key %s was requested. Volume " "encryption is not currently supported.") raise exception.NotSupportedOperation( message=msg % new_encryption_key_id) LOG.debug("snapshot: %(snap)s, volume: %(vol)s, " "volume_size: %(size)s", {'snap': snapshot.id, 'vol': volume.id, 'size': snapshot.volume_size}) vol_dir = self._local_volume_dir(snapshot.volume) # Find the file which backs this file, which represents the point # when this snapshot was created. backing_file = self._get_snapshot_backing_file(snapshot) snapshot_path = os.path.join(vol_dir, backing_file) volume_path = self.local_path(volume) vhd_type = self._get_vhd_type() self._delete(volume_path) self._vhdutils.convert_vhd(snapshot_path, volume_path, vhd_type=vhd_type) self._vhdutils.set_vhd_guid(volume_path, volume.id) self._vhdutils.resize_vhd(volume_path, volume_size * units.Gi, is_file_max_size=False)
def _get_qemu_convert_cmd(src, dest, out_format, src_format=None, out_subformat=None, cache_mode=None, prefix=None, cipher_spec=None, passphrase_file=None, compress=False, src_passphrase_file=None): if src_passphrase_file is not None: if passphrase_file is None: message = _("Can't create unencrypted volume %(format)s " "from an encrypted source volume.") % { 'format': out_format } LOG.error(message) # TODO(enriquetaso): handle encrypted->unencrypted raise exception.NotSupportedOperation(operation=message) return _get_qemu_convert_luks_cmd( src, dest, out_format, src_format=src_format, out_subformat=out_subformat, cache_mode=cache_mode, prefix=None, cipher_spec=cipher_spec, passphrase_file=passphrase_file, src_passphrase_file=src_passphrase_file) if out_format == 'vhd': # qemu-img still uses the legacy vpc name out_format = 'vpc' cmd = ['qemu-img', 'convert', '-O', out_format] if prefix: cmd = list(prefix) + cmd if cache_mode: cmd += ('-t', cache_mode) if CONF.image_compress_on_upload and compress: if out_format in COMPRESSIBLE_IMAGE_FORMATS: cmd += ('-c', ) if out_subformat: cmd += ('-o', 'subformat=%s' % out_subformat) # AMI images can be raw or qcow2 but qemu-img doesn't accept "ami" as # an image format, so we use automatic detection. # TODO(geguileo): This fixes unencrypted AMI image case, but we need to # fix the encrypted case. if (src_format or '').lower() not in ('', 'ami'): cmd += ('-f', src_format) # prevent detection of format # NOTE(lyarwood): When converting to LUKS add the cipher spec if present # and create a secret for the passphrase, written to a temp file if out_format == 'luks': check_qemu_img_version(QEMU_IMG_MIN_CONVERT_LUKS_VERSION) if cipher_spec: cmd += ('-o', 'cipher-alg=%s,cipher-mode=%s,ivgen-alg=%s' % (cipher_spec['cipher_alg'], cipher_spec['cipher_mode'], cipher_spec['ivgen_alg'])) cmd += ('--object', 'secret,id=luks_sec,format=raw,file=%s' % passphrase_file, '-o', 'key-secret=luks_sec') cmd += [src, dest] return cmd