mypy: backup
Change-Id: I8ee0e214eb1c1fe5a26304055737dd36cefec6ec
This commit is contained in:
parent
cf7c2fcc75
commit
ce34288e47
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import random
|
import random
|
||||||
|
from typing import List, Optional # noqa: H301
|
||||||
|
|
||||||
from eventlet import greenthread
|
from eventlet import greenthread
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
@ -65,17 +66,24 @@ class API(base.Base):
|
|||||||
self.volume_api = cinder.volume.API()
|
self.volume_api = cinder.volume.API()
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
def get(self, context, backup_id):
|
def get(self,
|
||||||
|
context: context.RequestContext,
|
||||||
|
backup_id: str) -> 'objects.Backup':
|
||||||
backup = objects.Backup.get_by_id(context, backup_id)
|
backup = objects.Backup.get_by_id(context, backup_id)
|
||||||
context.authorize(policy.GET_POLICY, target_obj=backup)
|
context.authorize(policy.GET_POLICY, target_obj=backup)
|
||||||
return backup
|
return backup
|
||||||
|
|
||||||
def _check_support_to_force_delete(self, context, backup_host):
|
def _check_support_to_force_delete(self,
|
||||||
|
context: context.RequestContext,
|
||||||
|
backup_host: str) -> bool:
|
||||||
result = self.backup_rpcapi.check_support_to_force_delete(context,
|
result = self.backup_rpcapi.check_support_to_force_delete(context,
|
||||||
backup_host)
|
backup_host)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def delete(self, context, backup, force=False):
|
def delete(self,
|
||||||
|
context: context.RequestContext,
|
||||||
|
backup: 'objects.Backup',
|
||||||
|
force: bool = False) -> None:
|
||||||
"""Make the RPC call to delete a volume backup.
|
"""Make the RPC call to delete a volume backup.
|
||||||
|
|
||||||
Call backup manager to execute backup delete or force delete operation.
|
Call backup manager to execute backup delete or force delete operation.
|
||||||
@ -109,8 +117,14 @@ class API(base.Base):
|
|||||||
backup.save()
|
backup.save()
|
||||||
self.backup_rpcapi.delete_backup(context, backup)
|
self.backup_rpcapi.delete_backup(context, backup)
|
||||||
|
|
||||||
def get_all(self, context, search_opts=None, marker=None, limit=None,
|
def get_all(self,
|
||||||
offset=None, sort_keys=None, sort_dirs=None):
|
context: context.RequestContext,
|
||||||
|
search_opts: dict = None,
|
||||||
|
marker: str = None,
|
||||||
|
limit: int = None,
|
||||||
|
offset: int = None,
|
||||||
|
sort_keys: List[str] = None,
|
||||||
|
sort_dirs: List[str] = None) -> 'objects.BackupList':
|
||||||
context.authorize(policy.GET_ALL_POLICY)
|
context.authorize(policy.GET_ALL_POLICY)
|
||||||
|
|
||||||
search_opts = search_opts or {}
|
search_opts = search_opts or {}
|
||||||
@ -132,11 +146,15 @@ class API(base.Base):
|
|||||||
|
|
||||||
return backups
|
return backups
|
||||||
|
|
||||||
def _az_matched(self, service, availability_zone):
|
def _az_matched(self,
|
||||||
|
service: 'objects.Service',
|
||||||
|
availability_zone: str) -> bool:
|
||||||
return ((not availability_zone) or
|
return ((not availability_zone) or
|
||||||
service.availability_zone == availability_zone)
|
service.availability_zone == availability_zone)
|
||||||
|
|
||||||
def _is_backup_service_enabled(self, availability_zone, host):
|
def _is_backup_service_enabled(self,
|
||||||
|
availability_zone: str,
|
||||||
|
host: str) -> bool:
|
||||||
"""Check if there is a backup service available."""
|
"""Check if there is a backup service available."""
|
||||||
topic = constants.BACKUP_TOPIC
|
topic = constants.BACKUP_TOPIC
|
||||||
ctxt = context.get_admin_context()
|
ctxt = context.get_admin_context()
|
||||||
@ -148,7 +166,9 @@ class API(base.Base):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _get_any_available_backup_service(self, availability_zone):
|
def _get_any_available_backup_service(
|
||||||
|
self,
|
||||||
|
availability_zone: str) -> Optional[str]:
|
||||||
"""Get an available backup service host.
|
"""Get an available backup service host.
|
||||||
|
|
||||||
Get an available backup service host in the specified
|
Get an available backup service host in the specified
|
||||||
@ -166,10 +186,10 @@ class API(base.Base):
|
|||||||
idx = idx + 1
|
idx = idx + 1
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_available_backup_service_host(self, host, az):
|
def get_available_backup_service_host(self, host: str, az: str) -> str:
|
||||||
return self._get_available_backup_service_host(host, az)
|
return self._get_available_backup_service_host(host, az)
|
||||||
|
|
||||||
def _get_available_backup_service_host(self, host, az):
|
def _get_available_backup_service_host(self, host: str, az: str) -> str:
|
||||||
"""Return an appropriate backup service host."""
|
"""Return an appropriate backup service host."""
|
||||||
backup_host = None
|
backup_host = None
|
||||||
if not host or not CONF.backup_use_same_host:
|
if not host or not CONF.backup_use_same_host:
|
||||||
@ -180,7 +200,7 @@ class API(base.Base):
|
|||||||
raise exception.ServiceNotFound(service_id='cinder-backup')
|
raise exception.ServiceNotFound(service_id='cinder-backup')
|
||||||
return backup_host
|
return backup_host
|
||||||
|
|
||||||
def _list_backup_services(self):
|
def _list_backup_services(self) -> List['objects.Service']:
|
||||||
"""List all enabled backup services.
|
"""List all enabled backup services.
|
||||||
|
|
||||||
:returns: list -- hosts for services that are enabled for backup.
|
:returns: list -- hosts for services that are enabled for backup.
|
||||||
@ -191,14 +211,22 @@ class API(base.Base):
|
|||||||
ctxt, topic, disabled=False)
|
ctxt, topic, disabled=False)
|
||||||
return services
|
return services
|
||||||
|
|
||||||
def _list_backup_hosts(self):
|
def _list_backup_hosts(self) -> list:
|
||||||
services = self._list_backup_services()
|
services = self._list_backup_services()
|
||||||
return [srv.host for srv in services
|
return [srv.host for srv in services
|
||||||
if not srv.disabled and srv.is_up]
|
if not srv.disabled and srv.is_up]
|
||||||
|
|
||||||
def create(self, context, name, description, volume_id,
|
def create(self,
|
||||||
container, incremental=False, availability_zone=None,
|
context: context.RequestContext,
|
||||||
force=False, snapshot_id=None, metadata=None):
|
name: Optional[str],
|
||||||
|
description: Optional[str],
|
||||||
|
volume_id: str,
|
||||||
|
container: str,
|
||||||
|
incremental: bool = False,
|
||||||
|
availability_zone: str = None,
|
||||||
|
force: bool = False,
|
||||||
|
snapshot_id: Optional[str] = None,
|
||||||
|
metadata: dict = None) -> 'objects.Backup':
|
||||||
"""Make the RPC call to create a volume backup."""
|
"""Make the RPC call to create a volume backup."""
|
||||||
volume = self.volume_api.get(context, volume_id)
|
volume = self.volume_api.get(context, volume_id)
|
||||||
context.authorize(policy.CREATE_POLICY, target_obj=volume)
|
context.authorize(policy.CREATE_POLICY, target_obj=volume)
|
||||||
@ -334,7 +362,11 @@ class API(base.Base):
|
|||||||
|
|
||||||
return backup
|
return backup
|
||||||
|
|
||||||
def restore(self, context, backup_id, volume_id=None, name=None):
|
def restore(self,
|
||||||
|
context: context.RequestContext,
|
||||||
|
backup_id: str,
|
||||||
|
volume_id: str = None,
|
||||||
|
name: str = None) -> dict:
|
||||||
"""Make the RPC call to restore a volume backup."""
|
"""Make the RPC call to restore a volume backup."""
|
||||||
backup = self.get(context, backup_id)
|
backup = self.get(context, backup_id)
|
||||||
context.authorize(policy.RESTORE_POLICY, target_obj=backup)
|
context.authorize(policy.RESTORE_POLICY, target_obj=backup)
|
||||||
@ -410,7 +442,10 @@ class API(base.Base):
|
|||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def reset_status(self, context, backup_id, status):
|
def reset_status(self,
|
||||||
|
context: context.RequestContext,
|
||||||
|
backup_id: str,
|
||||||
|
status: str) -> None:
|
||||||
"""Make the RPC call to reset a volume backup's status.
|
"""Make the RPC call to reset a volume backup's status.
|
||||||
|
|
||||||
Call backup manager to execute backup status reset operation.
|
Call backup manager to execute backup status reset operation.
|
||||||
@ -431,7 +466,9 @@ class API(base.Base):
|
|||||||
self.backup_rpcapi.reset_status(ctxt=context, backup=backup,
|
self.backup_rpcapi.reset_status(ctxt=context, backup=backup,
|
||||||
status=status)
|
status=status)
|
||||||
|
|
||||||
def export_record(self, context, backup_id):
|
def export_record(self,
|
||||||
|
context: context.RequestContext,
|
||||||
|
backup_id: str) -> dict:
|
||||||
"""Make the RPC call to export a volume backup.
|
"""Make the RPC call to export a volume backup.
|
||||||
|
|
||||||
Call backup manager to execute backup export.
|
Call backup manager to execute backup export.
|
||||||
@ -462,7 +499,9 @@ class API(base.Base):
|
|||||||
|
|
||||||
return export_data
|
return export_data
|
||||||
|
|
||||||
def _get_import_backup(self, context, backup_url):
|
def _get_import_backup(self,
|
||||||
|
context: context.RequestContext,
|
||||||
|
backup_url: str) -> 'objects.Backup':
|
||||||
"""Prepare database backup record for import.
|
"""Prepare database backup record for import.
|
||||||
|
|
||||||
This method decodes provided backup_url and expects to find the id of
|
This method decodes provided backup_url and expects to find the id of
|
||||||
@ -553,7 +592,10 @@ class API(base.Base):
|
|||||||
QUOTAS.rollback(context, reservations)
|
QUOTAS.rollback(context, reservations)
|
||||||
return backup
|
return backup
|
||||||
|
|
||||||
def import_record(self, context, backup_service, backup_url):
|
def import_record(self,
|
||||||
|
context: context.RequestContext,
|
||||||
|
backup_service: str,
|
||||||
|
backup_url: str) -> 'objects.Backup':
|
||||||
"""Make the RPC call to import a volume backup.
|
"""Make the RPC call to import a volume backup.
|
||||||
|
|
||||||
:param context: running context
|
:param context: running context
|
||||||
@ -588,7 +630,10 @@ class API(base.Base):
|
|||||||
|
|
||||||
return backup
|
return backup
|
||||||
|
|
||||||
def update(self, context, backup_id, fields):
|
def update(self,
|
||||||
|
context: context.RequestContext,
|
||||||
|
backup_id: str,
|
||||||
|
fields: list) -> 'objects.Service':
|
||||||
backup = self.get(context, backup_id)
|
backup = self.get(context, backup_id)
|
||||||
context.authorize(policy.UPDATE_POLICY, target_obj=backup)
|
context.authorize(policy.UPDATE_POLICY, target_obj=backup)
|
||||||
backup.update(fields)
|
backup.update(fields)
|
||||||
|
@ -70,7 +70,7 @@ class BackupAPI(rpc.RPCAPI):
|
|||||||
cctxt = self._get_cctxt(server=backup.host)
|
cctxt = self._get_cctxt(server=backup.host)
|
||||||
cctxt.cast(ctxt, 'delete_backup', backup=backup)
|
cctxt.cast(ctxt, 'delete_backup', backup=backup)
|
||||||
|
|
||||||
def export_record(self, ctxt, backup):
|
def export_record(self, ctxt, backup) -> dict:
|
||||||
LOG.debug("export_record in rpcapi backup_id %(id)s "
|
LOG.debug("export_record in rpcapi backup_id %(id)s "
|
||||||
"on host %(host)s.",
|
"on host %(host)s.",
|
||||||
{'id': backup.id,
|
{'id': backup.id,
|
||||||
@ -79,7 +79,7 @@ class BackupAPI(rpc.RPCAPI):
|
|||||||
return cctxt.call(ctxt, 'export_record', backup=backup)
|
return cctxt.call(ctxt, 'export_record', backup=backup)
|
||||||
|
|
||||||
def import_record(self, ctxt, host, backup, backup_service, backup_url,
|
def import_record(self, ctxt, host, backup, backup_service, backup_url,
|
||||||
backup_hosts):
|
backup_hosts) -> None:
|
||||||
LOG.debug("import_record rpcapi backup id %(id)s "
|
LOG.debug("import_record rpcapi backup id %(id)s "
|
||||||
"on host %(host)s for backup_url %(url)s.",
|
"on host %(host)s for backup_url %(url)s.",
|
||||||
{'id': backup.id, 'host': host, 'url': backup_url})
|
{'id': backup.id, 'host': host, 'url': backup_url})
|
||||||
@ -97,7 +97,7 @@ class BackupAPI(rpc.RPCAPI):
|
|||||||
cctxt = self._get_cctxt(server=backup.host)
|
cctxt = self._get_cctxt(server=backup.host)
|
||||||
return cctxt.cast(ctxt, 'reset_status', backup=backup, status=status)
|
return cctxt.cast(ctxt, 'reset_status', backup=backup, status=status)
|
||||||
|
|
||||||
def check_support_to_force_delete(self, ctxt, host):
|
def check_support_to_force_delete(self, ctxt, host) -> bool:
|
||||||
LOG.debug("Check if backup driver supports force delete "
|
LOG.debug("Check if backup driver supports force delete "
|
||||||
"on host %(host)s.", {'host': host})
|
"on host %(host)s.", {'host': host})
|
||||||
cctxt = self._get_cctxt(server=host)
|
cctxt = self._get_cctxt(server=host)
|
||||||
|
@ -17,6 +17,7 @@ from oslo_serialization import base64
|
|||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
from oslo_versionedobjects import fields
|
from oslo_versionedobjects import fields
|
||||||
|
|
||||||
|
from cinder import context
|
||||||
from cinder import db
|
from cinder import db
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
@ -103,15 +104,17 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
|
|||||||
return CONF.backup_name_template % self.id
|
return CONF.backup_name_template % self.id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_incremental(self):
|
def is_incremental(self) -> bool:
|
||||||
return bool(self.parent_id)
|
return bool(self.parent_id)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def has_dependent_backups(self):
|
def has_dependent_backups(self) -> bool:
|
||||||
return bool(self.num_dependent_backups)
|
return bool(self.num_dependent_backups)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _from_db_object(cls, context, backup, db_backup, expected_attrs=None):
|
def _from_db_object(cls,
|
||||||
|
context: context.RequestContext,
|
||||||
|
backup, db_backup, expected_attrs=None) -> 'Backup':
|
||||||
if expected_attrs is None:
|
if expected_attrs is None:
|
||||||
expected_attrs = []
|
expected_attrs = []
|
||||||
for name, field in backup.fields.items():
|
for name, field in backup.fields.items():
|
||||||
@ -159,7 +162,7 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
|
|||||||
|
|
||||||
return changes
|
return changes
|
||||||
|
|
||||||
def create(self):
|
def create(self) -> None:
|
||||||
if self.obj_attr_is_set('id'):
|
if self.obj_attr_is_set('id'):
|
||||||
raise exception.ObjectActionError(action='create',
|
raise exception.ObjectActionError(action='create',
|
||||||
reason='already created')
|
reason='already created')
|
||||||
@ -168,7 +171,7 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
|
|||||||
db_backup = db.backup_create(self._context, updates)
|
db_backup = db.backup_create(self._context, updates)
|
||||||
self._from_db_object(self._context, self, db_backup)
|
self._from_db_object(self._context, self, db_backup)
|
||||||
|
|
||||||
def save(self):
|
def save(self) -> None:
|
||||||
updates = self.cinder_obj_get_changes()
|
updates = self.cinder_obj_get_changes()
|
||||||
if updates:
|
if updates:
|
||||||
if 'metadata' in updates:
|
if 'metadata' in updates:
|
||||||
@ -181,14 +184,14 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
|
|||||||
|
|
||||||
self.obj_reset_changes()
|
self.obj_reset_changes()
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self) -> None:
|
||||||
with self.obj_as_admin():
|
with self.obj_as_admin():
|
||||||
updated_values = db.backup_destroy(self._context, self.id)
|
updated_values = db.backup_destroy(self._context, self.id)
|
||||||
self.update(updated_values)
|
self.update(updated_values)
|
||||||
self.obj_reset_changes(updated_values.keys())
|
self.obj_reset_changes(updated_values.keys())
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def decode_record(backup_url):
|
def decode_record(backup_url) -> dict:
|
||||||
"""Deserialize backup metadata from string into a dictionary.
|
"""Deserialize backup metadata from string into a dictionary.
|
||||||
|
|
||||||
:raises InvalidInput:
|
:raises InvalidInput:
|
||||||
@ -201,7 +204,7 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
|
|||||||
msg = _("Can't parse backup record.")
|
msg = _("Can't parse backup record.")
|
||||||
raise exception.InvalidInput(reason=msg)
|
raise exception.InvalidInput(reason=msg)
|
||||||
|
|
||||||
def encode_record(self, **kwargs):
|
def encode_record(self, **kwargs) -> str:
|
||||||
"""Serialize backup object, with optional extra info, into a string."""
|
"""Serialize backup object, with optional extra info, into a string."""
|
||||||
# We don't want to export extra fields and we want to force lazy
|
# We don't want to export extra fields and we want to force lazy
|
||||||
# loading, so we can't use dict(self) or self.obj_to_primitive
|
# loading, so we can't use dict(self) or self.obj_to_primitive
|
||||||
@ -223,8 +226,10 @@ class BackupList(base.ObjectListBase, base.CinderObject):
|
|||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_all(cls, context, filters=None, marker=None, limit=None,
|
def get_all(cls,
|
||||||
offset=None, sort_keys=None, sort_dirs=None):
|
context: context.RequestContext,
|
||||||
|
filters=None, marker=None, limit=None,
|
||||||
|
offset=None, sort_keys=None, sort_dirs=None) -> 'BackupList':
|
||||||
backups = db.backup_get_all(context, filters, marker, limit, offset,
|
backups = db.backup_get_all(context, filters, marker, limit, offset,
|
||||||
sort_keys, sort_dirs)
|
sort_keys, sort_dirs)
|
||||||
expected_attrs = Backup._get_expected_attrs(context)
|
expected_attrs = Backup._get_expected_attrs(context)
|
||||||
@ -232,7 +237,9 @@ class BackupList(base.ObjectListBase, base.CinderObject):
|
|||||||
backups, expected_attrs=expected_attrs)
|
backups, expected_attrs=expected_attrs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_all_by_host(cls, context, host):
|
def get_all_by_host(cls,
|
||||||
|
context: context.RequestContext,
|
||||||
|
host: str) -> 'BackupList':
|
||||||
backups = db.backup_get_all_by_host(context, host)
|
backups = db.backup_get_all_by_host(context, host)
|
||||||
expected_attrs = Backup._get_expected_attrs(context)
|
expected_attrs = Backup._get_expected_attrs(context)
|
||||||
return base.obj_make_list(context, cls(context), objects.Backup,
|
return base.obj_make_list(context, cls(context), objects.Backup,
|
||||||
@ -251,7 +258,11 @@ class BackupList(base.ObjectListBase, base.CinderObject):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_all_by_volume(
|
def get_all_by_volume(
|
||||||
cls, context, volume_id, vol_project_id, filters=None):
|
cls,
|
||||||
|
context: context.RequestContext,
|
||||||
|
volume_id: str,
|
||||||
|
vol_project_id: str,
|
||||||
|
filters=None) -> 'BackupList':
|
||||||
backups = db.backup_get_all_by_volume(
|
backups = db.backup_get_all_by_volume(
|
||||||
context, volume_id, vol_project_id, filters)
|
context, volume_id, vol_project_id, filters)
|
||||||
expected_attrs = Backup._get_expected_attrs(context)
|
expected_attrs = Backup._get_expected_attrs(context)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
cinder/backup/api.py
|
||||||
cinder/backup/manager.py
|
cinder/backup/manager.py
|
||||||
cinder/common/constants.py
|
cinder/common/constants.py
|
||||||
cinder/context.py
|
cinder/context.py
|
||||||
@ -8,6 +9,7 @@ cinder/image/glance.py
|
|||||||
cinder/image/image_utils.py
|
cinder/image/image_utils.py
|
||||||
cinder/exception.py
|
cinder/exception.py
|
||||||
cinder/manager.py
|
cinder/manager.py
|
||||||
|
cinder/objects/backup.py
|
||||||
cinder/scheduler/base_handler.py
|
cinder/scheduler/base_handler.py
|
||||||
cinder/scheduler/base_weight.py
|
cinder/scheduler/base_weight.py
|
||||||
cinder/scheduler/evaluator/evaluator.py
|
cinder/scheduler/evaluator/evaluator.py
|
||||||
|
Loading…
Reference in New Issue
Block a user