Просмотр исходного кода

Define storage mapping utility method for providers.

Nashwan Azhari 7 лет назад
Родитель
Сommit
bc1f718952
2 измененных файлов с 118 добавлено и 0 удалено
  1. 9 0
      coriolis/exception.py
  2. 109 0
      coriolis/providers/provider_utils.py

+ 9 - 0
coriolis/exception.py

@@ -236,6 +236,15 @@ class NetworkNotFound(NotFound):
     message = _("Network \"%(network_name)s\" could not be found.")
 
 
+class DiskStorageMappingNotFound(NotFound):
+    message = _('No storage mapping for disk with ID "%(id)s" could be found.')
+
+
+class StorageBackendNotFound(NotFound):
+    message = _(
+        'Storage backend with name "%(storage_name)s" could not be found.')
+
+
 class ImageNotFound(NotFound):
     message = _("Image \"%(image_name)s\" could not be found.")
 

+ 109 - 0
coriolis/providers/provider_utils.py

@@ -0,0 +1,109 @@
+# Copyright 2018 Cloudbase Solutions Srl
+# All Rights Reserved.
+
+from oslo_log import log as logging
+
+from coriolis import exception
+
+
+LOG = logging.getLogger(__name__)
+
+
+def get_storage_mapping_for_disk(
+        storage_mappings, disk_info, storage_backends,
+        config_default=None, error_on_missing_mapping=True,
+        error_on_backend_not_found=True):
+    """ Returns the storage backend identifier from the given list of
+    `storage_backends` to map for the disk given by its `disk_info`.
+
+    Order of mapping resolution is:
+        - per-disk-ID mappings from storage_mappings['disk_mappings']
+        - per-storage-bakend mappings for storage_mappings['backend_mappings']
+        - storage_mappings['default']
+        - the supplies `config_default` parameter
+
+    param storage_mappings: dict(): storage mappings dict compliant with the
+    `coriolis.schemas.CORIOLIS_STORAGE_MAPPINGS_SCHEMA`
+    param disk_info: dict(): dict with the disk info compliant with the
+    structure of the `devices['disks']` fields in the
+    `coriolis.schemas.CORIOLIS_VM_EXPORT_INFO_SCHEMA`
+    param storage_backends: list(dict()): list of dicts corresponding to the
+    available storage backends as specified in the
+    `coriolis.schemas.CORIOLIS_STORAGE_SCHEMA`
+    param config_default: str: optional default value from the configuration
+    file to fall back to.
+    param error_on_missing_mapping: bool(): whether or not to raise an
+    exception if there is no mapping found for the disk and no
+    storage_mappings['default'] or `config_default` is provided.
+    param error_on_backend_not_found: bool(): whether or not ro raise an
+    exception if a storage backend scpecified in the mapping is not found.
+    """
+    disk_mappings = {
+        mapping['disk_id']: mapping['destination']
+        for mapping in storage_mappings.get("disk_mappings", [])}
+    backend_mappings = {
+        mapping['source']: mapping['destination']
+        for mapping in storage_mappings.get('backend_mappings', [])}
+
+    LOG.debug(
+        "Resolving disk storage backend mapping for disk '%s' from available "
+        "backends: %s (disk_mappings=%s, backend_mappings=%s, default=%s, "
+        "config_default=%s)", disk_info, storage_backends, disk_mappings,
+        backend_mappings, storage_mappings.get('default'), config_default)
+
+    mapped_backend = None
+
+    # 1) check for explicit disk mapping:
+    # NOTE: the core VM export info schema allows for the disk IDs to be ints
+    # as well, so we need to convert to a string (the JSON structure of the
+    # 'storage_mappings' API field guarantees the disk ID keys will be strings)
+    disk_id = str(disk_info['id'])
+    if disk_id in disk_mappings:
+        mapped_backend = disk_mappings[disk_id]
+        LOG.debug(
+            "Found mapping for disk ID '%s' in the 'disk_mappings': %s",
+            disk_id, mapped_backend)
+
+    # 2) check for backend mapping if available:
+    if not mapped_backend:
+        if 'storage_backend_identifier' in disk_info:
+            if disk_info['storage_backend_identifier'] in backend_mappings:
+                mapped_backend = backend_mappings[
+                    disk_info['storage_backend_identifier']]
+                LOG.debug(
+                    "Found mapping for disk ID '%s' in the "
+                    "'backend_mappings': %s", disk_id, mapped_backend)
+            else:
+                LOG.debug(
+                    "'storage_backend_identifier' for disk '%s' is not mapped "
+                    "in the 'backend_mappings' from the 'storage_mappings'.",
+                    disk_info)
+        else:
+            LOG.debug(
+                "No 'storage_backend_identifier' set for disk '%s'", disk_info)
+
+    # 3) use provided default:
+    if not mapped_backend:
+        mapped_backend = storage_mappings.get('default', config_default)
+
+    if mapped_backend is None:
+        LOG.warn(
+            "Could not find mapped storage backend for disk '%s'", disk_info)
+        if error_on_missing_mapping:
+            raise exception.DiskStorageMappingNotFound(id=disk_id)
+
+    if mapped_backend:
+        if mapped_backend not in [
+                backend['name'] for backend in storage_backends]:
+            LOG.warn(
+                "Mapped storage backend for disk '%s' ('%s') does not exist!",
+                disk_info, mapped_backend)
+            if error_on_backend_not_found:
+                raise exception.StorageBackendNotFound(
+                    storage_name=mapped_backend)
+
+    LOG.info(
+        "Mapped storage backend for disk '%s' is: %s",
+        disk_info, mapped_backend)
+
+    return mapped_backend