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

Merged in aznashwan/coriolis/volumetype-support (pull request #31)

Volumetype support
Nashwan Azhari 9 лет назад
Родитель
Сommit
de324fec21

+ 3 - 1
coriolis/providers/openstack/common.py

@@ -154,7 +154,8 @@ def get_volume_from_snapshot(cinder, snapshot_id):
 
 
 @utils.retry_on_error()
-def create_volume(cinder, size, name, image_ref=None, snapshot_id=None):
+def create_volume(cinder, size, name, image_ref=None,
+                  snapshot_id=None, volume_type=None):
     if snapshot_id:
         volume_size_gb = None
     else:
@@ -162,6 +163,7 @@ def create_volume(cinder, size, name, image_ref=None, snapshot_id=None):
     return cinder.volumes.create(
         size=volume_size_gb,
         name=name,
+        volume_type=volume_type,
         imageRef=image_ref,
         snapshot_id=snapshot_id)
 

+ 1 - 0
coriolis/providers/openstack/exp.py

@@ -179,6 +179,7 @@ class ExportProvider(base.BaseExportProvider, base.BaseReplicaExportProvider):
                 'format': constants.DISK_FORMAT_RAW,
                 'guest_device': vol_attachment.device,
                 'size_bytes': volume.size * units.Gi,
+                'storage_backend_identifier': volume.volume_type,
                 'path': '',
                 'id': volume.id
             })

+ 62 - 5
coriolis/providers/openstack/imp.py

@@ -46,6 +46,10 @@ opts = [
     cfg.StrOpt('glance_upload',
                default=True,
                help='Set to "True" to use Glance to upload images.'),
+    cfg.StrOpt('default_cinder_volume_type',
+               default='',
+               help='Name of the Cinder volume type to be used for '
+                    'volumes with unspecified storage backing options.'),
     cfg.DictOpt('migr_image_name_map',
                 default={},
                 help='Default image names used for worker instances during '
@@ -364,6 +368,7 @@ class ImportProvider(base.BaseImportProvider, base.BaseReplicaImportProvider):
              "delete_disks_on_vm_termination",
              "fip_pool_name",
              "network_map",
+             "storage_map",
              "keypair_name",
              "migr_image_name",
              "migr_flavor_name",
@@ -387,6 +392,7 @@ class ImportProvider(base.BaseImportProvider, base.BaseReplicaImportProvider):
             "delete_disks_on_vm_termination",
             CONF.openstack_migration_provider.delete_disks_on_vm_termination)
         config.network_map = target_environment.get("network_map", {})
+        config.storage_map = target_environment.get("storage_map", {})
         config.keypair_name = target_environment.get("keypair_name")
 
         config.migr_image_name = target_environment.get(
@@ -491,12 +497,55 @@ class ImportProvider(base.BaseImportProvider, base.BaseReplicaImportProvider):
             self._event_manager.progress_update(
                 "Creating Cinder volume")
 
+            volume_type = self._get_volume_type_for_disk(
+                cinder, disk_info, config.storage_map)
+
             volume = common.create_volume(
-                cinder, virtual_disk_size, common.get_unique_name(), image.id)
+                cinder, virtual_disk_size, common.get_unique_name(),
+                image.id, volume_type=volume_type)
             volumes.append(volume)
 
         return images, volumes
 
+    def _get_volume_type_for_disk(self, cinder, disk_info, storage_map):
+        default = CONF.openstack_migration_provider.default_cinder_volume_type
+        if not default:
+            # NOTE: needed so as to explicitly use None instead of an
+            # empty string in case a default is not configured.
+            default = None
+
+        dest_stor = None
+        source_stor = None
+        if 'storage_backend_identifier' in disk_info:
+            # if 'storage_backend_identifier' was provided, fetch its
+            # correspondent from the 'storage_map' or use the default.
+            source_stor = disk_info['storage_backend_identifier']
+            dest_stor = storage_map.get(source_stor, None)
+            if not dest_stor:
+                LOG.debug(
+                    'Unable to find mapping for storage system "%s" in the '
+                    'storage_map for volume "%s". Setting volume type to the '
+                    'configured default of \"%s\"',
+                    source_stor, disk_info['path'], default)
+                dest_stor = default
+        else:
+            # else if unspecified, just use the default volume type:
+            LOG.debug("No 'storage_backend_identifier' provided for disk %s. "
+                     "Trying to use default volume type of '%s'", default)
+            dest_stor = default
+
+        # ensure the volume type exists:
+        if dest_stor and not utils.retry_on_error()(
+                cinder.volume_types.findall)(name=dest_stor):
+            raise exception.CoriolisException(
+                'Unable to find volume type "%s" (mapped from "%s" on the '
+                'source). Please ensure the storage_map is correct' % (
+                    dest_stor, source_stor))
+
+        LOG.info("Chosen volume_type for disk '%s' is '%s'",
+                 disk_info['path'], dest_stor)
+        return dest_stor
+
     def _create_neutron_ports(self, neutron, config, nics_info):
         ports = []
 
@@ -776,8 +825,9 @@ class ImportProvider(base.BaseImportProvider, base.BaseReplicaImportProvider):
                 volumes_info.remove(volume_info)
         return volumes_info
 
-    def _create_new_disk_volumes(self, cinder, disks_info, volumes_info,
-                                 instance_name):
+    def _create_new_disk_volumes(
+            self, cinder, target_environment, disks_info,
+            volumes_info, instance_name):
         try:
             new_volumes = []
             for i, disk_info in enumerate(disks_info):
@@ -790,8 +840,14 @@ class ImportProvider(base.BaseImportProvider, base.BaseReplicaImportProvider):
 
                     volume_name = REPLICA_VOLUME_NAME_FORMAT % {
                         "instance_name": instance_name, "num": i + 1}
+
+                    storage_map = target_environment.get(
+                        'storage_map', {})
+                    volume_type = self._get_volume_type_for_disk(
+                        cinder, disk_info, storage_map)
                     volume = common.create_volume(
-                        cinder, virtual_disk_size, volume_name)
+                        cinder, virtual_disk_size, volume_name,
+                        volume_type=volume_type)
 
                     new_volumes.append(volume)
                     volumes_info.append({
@@ -826,7 +882,8 @@ class ImportProvider(base.BaseImportProvider, base.BaseReplicaImportProvider):
             cinder, disks_info, volumes_info)
 
         volumes_info = self._create_new_disk_volumes(
-            cinder, disks_info, volumes_info, instance_name)
+            cinder, target_environment, disks_info,
+            volumes_info, instance_name)
 
         return volumes_info
 

+ 3 - 0
coriolis/providers/openstack/schemas/target_environment_schema.json

@@ -7,6 +7,9 @@
         "network_map": {
           "type": "object"
         },
+        "storage_map": {
+          "type": "object"
+        },
         "glance_upload": {
           "type": "boolean"
         },

+ 2 - 0
coriolis/providers/vmware_vsphere/__init__.py

@@ -243,6 +243,8 @@ class ExportProvider(base.BaseExportProvider, base.BaseReplicaExportProvider):
                           'unit_number': device.unitNumber,
                           'id': device.key,
                           'controller_id': device.controllerKey,
+                          'storage_backend_identifier':
+                              device.backing.datastore.name,
                           'path': device.backing.fileName,
                           'format': constants.DISK_FORMAT_VMDK})
 

+ 4 - 0
coriolis/schemas/vm_export_info_schema.json

@@ -76,6 +76,10 @@
               },
               "controller_id": {
                 "$ref": "#/definitions/numberOrString"
+              },
+              "storage_backend_identifier": {
+                  "type": "string",
+                  "help": "A string identifier for the storage system the disk is hosted on."
               }
             },
             "required": [