mypy: backup

Change-Id: I8ee0e214eb1c1fe5a26304055737dd36cefec6ec
This commit is contained in:
Eric Harney 2021-04-19 15:40:32 -04:00
parent cf7c2fcc75
commit ce34288e47
4 changed files with 94 additions and 36 deletions

View File

@ -19,6 +19,7 @@
from datetime import datetime
import random
from typing import List, Optional # noqa: H301
from eventlet import greenthread
from oslo_config import cfg
@ -65,17 +66,24 @@ class API(base.Base):
self.volume_api = cinder.volume.API()
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)
context.authorize(policy.GET_POLICY, target_obj=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,
backup_host)
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.
Call backup manager to execute backup delete or force delete operation.
@ -109,8 +117,14 @@ class API(base.Base):
backup.save()
self.backup_rpcapi.delete_backup(context, backup)
def get_all(self, context, search_opts=None, marker=None, limit=None,
offset=None, sort_keys=None, sort_dirs=None):
def get_all(self,
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)
search_opts = search_opts or {}
@ -132,11 +146,15 @@ class API(base.Base):
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
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."""
topic = constants.BACKUP_TOPIC
ctxt = context.get_admin_context()
@ -148,7 +166,9 @@ class API(base.Base):
return True
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 in the specified
@ -166,10 +186,10 @@ class API(base.Base):
idx = idx + 1
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)
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."""
backup_host = None
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')
return backup_host
def _list_backup_services(self):
def _list_backup_services(self) -> List['objects.Service']:
"""List all enabled backup services.
:returns: list -- hosts for services that are enabled for backup.
@ -191,14 +211,22 @@ class API(base.Base):
ctxt, topic, disabled=False)
return services
def _list_backup_hosts(self):
def _list_backup_hosts(self) -> list:
services = self._list_backup_services()
return [srv.host for srv in services
if not srv.disabled and srv.is_up]
def create(self, context, name, description, volume_id,
container, incremental=False, availability_zone=None,
force=False, snapshot_id=None, metadata=None):
def create(self,
context: context.RequestContext,
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."""
volume = self.volume_api.get(context, volume_id)
context.authorize(policy.CREATE_POLICY, target_obj=volume)
@ -334,7 +362,11 @@ class API(base.Base):
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."""
backup = self.get(context, backup_id)
context.authorize(policy.RESTORE_POLICY, target_obj=backup)
@ -410,7 +442,10 @@ class API(base.Base):
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.
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,
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.
Call backup manager to execute backup export.
@ -462,7 +499,9 @@ class API(base.Base):
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.
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)
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.
:param context: running context
@ -588,7 +630,10 @@ class API(base.Base):
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)
context.authorize(policy.UPDATE_POLICY, target_obj=backup)
backup.update(fields)

View File

@ -70,7 +70,7 @@ class BackupAPI(rpc.RPCAPI):
cctxt = self._get_cctxt(server=backup.host)
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 "
"on host %(host)s.",
{'id': backup.id,
@ -79,7 +79,7 @@ class BackupAPI(rpc.RPCAPI):
return cctxt.call(ctxt, 'export_record', backup=backup)
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 "
"on host %(host)s for backup_url %(url)s.",
{'id': backup.id, 'host': host, 'url': backup_url})
@ -97,7 +97,7 @@ class BackupAPI(rpc.RPCAPI):
cctxt = self._get_cctxt(server=backup.host)
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 "
"on host %(host)s.", {'host': host})
cctxt = self._get_cctxt(server=host)

View File

@ -17,6 +17,7 @@ from oslo_serialization import base64
from oslo_serialization import jsonutils
from oslo_versionedobjects import fields
from cinder import context
from cinder import db
from cinder import exception
from cinder.i18n import _
@ -103,15 +104,17 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
return CONF.backup_name_template % self.id
@property
def is_incremental(self):
def is_incremental(self) -> bool:
return bool(self.parent_id)
@property
def has_dependent_backups(self):
def has_dependent_backups(self) -> bool:
return bool(self.num_dependent_backups)
@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:
expected_attrs = []
for name, field in backup.fields.items():
@ -159,7 +162,7 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
return changes
def create(self):
def create(self) -> None:
if self.obj_attr_is_set('id'):
raise exception.ObjectActionError(action='create',
reason='already created')
@ -168,7 +171,7 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
db_backup = db.backup_create(self._context, updates)
self._from_db_object(self._context, self, db_backup)
def save(self):
def save(self) -> None:
updates = self.cinder_obj_get_changes()
if updates:
if 'metadata' in updates:
@ -181,14 +184,14 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
self.obj_reset_changes()
def destroy(self):
def destroy(self) -> None:
with self.obj_as_admin():
updated_values = db.backup_destroy(self._context, self.id)
self.update(updated_values)
self.obj_reset_changes(updated_values.keys())
@staticmethod
def decode_record(backup_url):
def decode_record(backup_url) -> dict:
"""Deserialize backup metadata from string into a dictionary.
:raises InvalidInput:
@ -201,7 +204,7 @@ class Backup(base.CinderPersistentObject, base.CinderObject,
msg = _("Can't parse backup record.")
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."""
# 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
@ -223,8 +226,10 @@ class BackupList(base.ObjectListBase, base.CinderObject):
}
@classmethod
def get_all(cls, context, filters=None, marker=None, limit=None,
offset=None, sort_keys=None, sort_dirs=None):
def get_all(cls,
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,
sort_keys, sort_dirs)
expected_attrs = Backup._get_expected_attrs(context)
@ -232,7 +237,9 @@ class BackupList(base.ObjectListBase, base.CinderObject):
backups, expected_attrs=expected_attrs)
@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)
expected_attrs = Backup._get_expected_attrs(context)
return base.obj_make_list(context, cls(context), objects.Backup,
@ -251,7 +258,11 @@ class BackupList(base.ObjectListBase, base.CinderObject):
@classmethod
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(
context, volume_id, vol_project_id, filters)
expected_attrs = Backup._get_expected_attrs(context)

View File

@ -1,3 +1,4 @@
cinder/backup/api.py
cinder/backup/manager.py
cinder/common/constants.py
cinder/context.py
@ -8,6 +9,7 @@ cinder/image/glance.py
cinder/image/image_utils.py
cinder/exception.py
cinder/manager.py
cinder/objects/backup.py
cinder/scheduler/base_handler.py
cinder/scheduler/base_weight.py
cinder/scheduler/evaluator/evaluator.py