Browse Source

Merge "objects: Add MigrationTypeField"

changes/83/738583/1
Zuul 1 week ago
committed by Gerrit Code Review
parent
commit
d4c857dfcb
14 changed files with 81 additions and 49 deletions
  1. +4
    -1
      nova/api/openstack/compute/migrations.py
  2. +1
    -1
      nova/api/openstack/compute/server_migrations.py
  3. +4
    -6
      nova/compute/api.py
  4. +4
    -3
      nova/compute/claims.py
  5. +5
    -4
      nova/compute/manager.py
  6. +13
    -10
      nova/compute/resource_tracker.py
  7. +1
    -1
      nova/conductor/manager.py
  8. +0
    -1
      nova/network/constants.py
  9. +4
    -4
      nova/network/neutron.py
  10. +14
    -0
      nova/objects/fields.py
  11. +9
    -3
      nova/objects/migration.py
  12. +16
    -12
      nova/tests/unit/network/test_neutron.py
  13. +1
    -1
      nova/tests/unit/objects/test_objects.py
  14. +5
    -2
      nova/tests/unit/policies/test_server_migrations.py

+ 4
- 1
nova/api/openstack/compute/migrations.py View File

@@ -23,6 +23,7 @@ from nova.compute import api as compute
from nova import exception
from nova.i18n import _
from nova.objects import base as obj_base
from nova.objects import fields
from nova.policies import migrations as migrations_policies


@@ -72,7 +73,9 @@ class MigrationsController(wsgi.Controller):
# NOTE(Shaohe Feng) above version 2.23, add migration_type for all
# kinds of migration, but we only add links just for in-progress
# live-migration.
if add_link and obj['migration_type'] == "live-migration" and (
if (add_link and
obj['migration_type'] ==
fields.MigrationType.LIVE_MIGRATION and
obj["status"] in live_migration_in_progress):
obj["links"] = self._view_builder._get_links(
req, obj["id"],


+ 1
- 1
nova/api/openstack/compute/server_migrations.py View File

@@ -132,7 +132,7 @@ class ServerMigrationsController(wsgi.Controller):
" server %(uuid)s.") % {"id": id, "uuid": server_id}
raise exc.HTTPNotFound(explanation=msg)

if migration.get("migration_type") != "live-migration":
if not migration.is_live_migration:
msg = _("Migration %(id)s for server %(uuid)s is not"
" live-migration.") % {"id": id, "uuid": server_id}
raise exc.HTTPNotFound(explanation=msg)


+ 4
- 6
nova/compute/api.py View File

@@ -5033,12 +5033,10 @@ class API(base.Base):

# NOTE(danms): Create this as a tombstone for the source compute
# to find and cleanup. No need to pass it anywhere else.
migration = objects.Migration(context,
source_compute=instance.host,
source_node=instance.node,
instance_uuid=instance.uuid,
status='accepted',
migration_type='evacuation')
migration = objects.Migration(
context, source_compute=instance.host, source_node=instance.node,
instance_uuid=instance.uuid, status='accepted',
migration_type=fields_obj.MigrationType.EVACUATION)
if host:
migration.dest_compute = host
migration.create()


+ 4
- 3
nova/compute/claims.py View File

@@ -194,9 +194,10 @@ class MoveClaim(Claim):
migration, all types of PCI requests are supported, so we just call up
to normal Claim's _test_pci().
"""
if self.migration.migration_type != 'live-migration':
if not self.migration.is_live_migration:
return super(MoveClaim, self)._test_pci()
elif self._pci_requests.requests:

if self._pci_requests.requests:
for pci_request in self._pci_requests.requests:
if (pci_request.source !=
objects.InstancePCIRequest.NEUTRON_PORT):
@@ -225,7 +226,7 @@ class MoveClaim(Claim):
something we want to support, so fail the claim if the page sizes are
different.
"""
if (self.migration.migration_type == 'live-migration' and
if (self.migration.is_live_migration and
self.instance.numa_topology and
# NOTE(artom) We only support a single page size across all
# cells, checking cell 0 is sufficient.


+ 5
- 4
nova/compute/manager.py View File

@@ -685,7 +685,7 @@ class ComputeManager(manager.Manager):
# the user can rebuild the instance (in ERROR state) on the source
# host.
'status': ['accepted', 'pre-migrating', 'done'],
'migration_type': 'evacuation',
'migration_type': fields.MigrationType.EVACUATION,
}
with utils.temporary_mutation(context, read_deleted='yes'):
evacuations = objects.MigrationList.get_by_filters(context,
@@ -8475,9 +8475,10 @@ class ComputeManager(manager.Manager):
# NOTE(mriedem): This is a no-op for neutron.
self.network_api.setup_networks_on_host(context, instance,
self.host)
migration = objects.Migration(source_compute=instance.host,
dest_compute=self.host,
migration_type='live-migration')
migration = objects.Migration(
source_compute=instance.host,
dest_compute=self.host,
migration_type=fields.MigrationType.LIVE_MIGRATION)
self.network_api.migrate_instance_finish(
context, instance, migration, provider_mappings=None)



+ 13
- 10
nova/compute/resource_tracker.py View File

@@ -39,6 +39,7 @@ from nova import exception
from nova.i18n import _
from nova import objects
from nova.objects import base as obj_base
from nova.objects import fields
from nova.objects import migration as migration_obj
from nova.pci import manager as pci_manager
from nova.pci import request as pci_request
@@ -191,9 +192,10 @@ class ResourceTracker(object):
limits=None, image_meta=None, migration=None):
"""Create a claim for a rebuild operation."""
instance_type = instance.flavor
return self._move_claim(context, instance, instance_type, nodename,
migration, allocations, move_type='evacuation',
limits=limits, image_meta=image_meta)
return self._move_claim(
context, instance, instance_type, nodename, migration, allocations,
move_type=fields.MigrationType.EVACUATION,
image_meta=image_meta, limits=limits)

@utils.synchronized(COMPUTE_RESOURCE_SEMAPHORE, fair=True)
def resize_claim(self, context, instance, instance_type, nodename,
@@ -225,9 +227,11 @@ class ResourceTracker(object):
# Flavor and image cannot change during a live migration.
instance_type = instance.flavor
image_meta = instance.image_meta
return self._move_claim(context, instance, instance_type, nodename,
migration, allocs, move_type='live-migration',
image_meta=image_meta, limits=limits)
return self._move_claim(
context, instance, instance_type, nodename, migration, allocs,
move_type=fields.MigrationType.LIVE_MIGRATION,
image_meta=image_meta, limits=limits,
)

def _move_claim(self, context, instance, new_instance_type, nodename,
migration, allocations, move_type=None,
@@ -293,7 +297,7 @@ class ResourceTracker(object):
# migration to avoid stepping on that code's toes. Ideally,
# MoveClaim/this method would be used for all live migration resource
# claims.
if self.pci_tracker and migration.migration_type != 'live-migration':
if self.pci_tracker and not migration.is_live_migration:
# NOTE(jaypipes): ComputeNode.pci_device_pools is set below
# in _update_usage_from_instance().
claimed_pci_devices_objs = self.pci_tracker.claim_instance(
@@ -369,7 +373,7 @@ class ResourceTracker(object):
# NOTE(artom) Migration objects for live migrations are created with
# status 'accepted' by the conductor in live_migrate_instance() and do
# not have a 'pre-migrating' status.
if migration.migration_type != 'live-migration':
if not migration.is_live_migration:
migration.status = 'pre-migrating'
migration.save()

@@ -1637,8 +1641,7 @@ class ResourceTracker(object):

def _get_instance_type(self, instance, prefix, migration):
"""Get the instance type from instance."""
stashed_flavors = migration.migration_type in ('resize',)
if stashed_flavors:
if migration.is_resize:
return getattr(instance, '%sflavor' % prefix)
else:
# NOTE(ndipanov): Certain migration types (all but resize)


+ 1
- 1
nova/conductor/manager.py View File

@@ -456,7 +456,7 @@ class ComputeTaskManager(base.Base):
migration.status = 'accepted'
migration.instance_uuid = instance.uuid
migration.source_compute = instance.host
migration.migration_type = 'live-migration'
migration.migration_type = fields.MigrationType.LIVE_MIGRATION
if instance.obj_attr_is_set('flavor'):
migration.old_instance_type_id = instance.flavor.id
migration.new_instance_type_id = instance.flavor.id


+ 0
- 1
nova/network/constants.py View File

@@ -21,7 +21,6 @@ MULTI_NET_EXT = 'Multi Provider Network'
FIP_PORT_DETAILS = 'Floating IP Port Details Extension'
SUBSTR_PORT_FILTERING = 'IP address substring filtering'
PORT_BINDING_EXTENDED = 'Port Bindings Extended'
LIVE_MIGRATION = 'live-migration'
DEFAULT_SECGROUP = 'default'
BINDING_PROFILE = 'binding:profile'
BINDING_HOST_ID = 'binding:host_id'


+ 4
- 4
nova/network/neutron.py View File

@@ -3413,7 +3413,7 @@ class API(base.Base):
vnic_type = p.get('binding:vnic_type')
if (vnic_type in network_model.VNIC_TYPES_SRIOV and
migration is not None and
migration['migration_type'] != constants.LIVE_MIGRATION):
not migration.is_live_migration):
# Note(adrianc): for live migration binding profile was already
# updated in conductor when calling bind_ports_to_host()
if not pci_mapping:
@@ -3435,9 +3435,9 @@ class API(base.Base):
# allocation key in the port binding. However during resize, cold
# migrate, evacuate and unshelve we have to set the binding here.
# Also note that during unshelve no migration object is created.
if (p.get('resource_request') and
(migration is None or
migration['migration_type'] != constants.LIVE_MIGRATION)):
if p.get('resource_request') and (
migration is None or not migration.is_live_migration
):
if not provider_mappings:
# TODO(gibi): Remove this check when compute RPC API is
# bumped to 6.0


+ 14
- 0
nova/objects/fields.py View File

@@ -464,6 +464,16 @@ class ImageSignatureKeyType(BaseNovaEnum):
)


class MigrationType(BaseNovaEnum):

MIGRATION = 'migration' # cold migration
RESIZE = 'resize'
LIVE_MIGRATION = 'live-migration'
EVACUATION = 'evacuation'

ALL = (MIGRATION, RESIZE, LIVE_MIGRATION, EVACUATION)


class OSType(BaseNovaEnum):

LINUX = "linux"
@@ -1207,6 +1217,10 @@ class ImageSignatureKeyTypeField(BaseEnumField):
AUTO_TYPE = ImageSignatureKeyType()


class MigrationTypeField(BaseEnumField):
AUTO_TYPE = MigrationType()


class OSTypeField(BaseEnumField):
AUTO_TYPE = OSType()



+ 9
- 3
nova/objects/migration.py View File

@@ -57,9 +57,7 @@ class Migration(base.NovaPersistentObject, base.NovaObject,
'new_instance_type_id': fields.IntegerField(nullable=True),
'instance_uuid': fields.StringField(nullable=True),
'status': fields.StringField(nullable=True),
'migration_type': fields.EnumField(['migration', 'resize',
'live-migration', 'evacuation'],
nullable=False),
'migration_type': fields.MigrationTypeField(nullable=False),
'hidden': fields.BooleanField(nullable=False, default=False),
'memory_total': fields.IntegerField(nullable=True),
'memory_processed': fields.IntegerField(nullable=True),
@@ -205,6 +203,14 @@ class Migration(base.NovaPersistentObject, base.NovaObject,
def is_same_host(self):
return self.source_compute == self.dest_compute

@property
def is_live_migration(self):
return self.migration_type == fields.MigrationType.LIVE_MIGRATION

@property
def is_resize(self):
return self.migration_type == fields.MigrationType.RESIZE


@base.NovaObjectRegistry.register
class MigrationList(base.ObjectListBase, base.NovaObject):


+ 16
- 12
nova/tests/unit/network/test_neutron.py View File

@@ -4382,8 +4382,8 @@ class TestAPI(TestAPIBase):
'pci_vendor_info': 'old_pci_vendor_info'}},
{'id': 'fake-port-2',
constants.BINDING_HOST_ID: instance.host}]}
migration = {'status': 'confirmed',
'migration_type': "migration"}
migration = objects.Migration(
status='confirmed', migration_type='migration')
list_ports_mock = mock.Mock(return_value=fake_ports)
get_client_mock.return_value.list_ports = list_ports_mock

@@ -4439,8 +4439,8 @@ class TestAPI(TestAPIBase):
{'pci_slot': '0000:0a:00.1',
'physical_network': 'old_phys_net',
'pci_vendor_info': 'old_pci_vendor_info'}}]}
migration = {'status': 'confirmed',
'migration_type': "migration"}
migration = objects.Migration(
status='confirmed', migration_type='migration')
list_ports_mock = mock.Mock(return_value=fake_ports)
get_client_mock.return_value.list_ports = list_ports_mock

@@ -4595,8 +4595,8 @@ class TestAPI(TestAPIBase):
{'pci_slot': '0000:0a:00.1',
'physical_network': 'phys_net',
'pci_vendor_info': 'vendor_info'}}]}
migration = {'status': 'confirmed',
'migration_type': "live-migration"}
migration = objects.Migration(
status='confirmed', migration_type='live-migration')
list_ports_mock = mock.Mock(return_value=fake_ports)
get_client_mock.return_value.list_ports = list_ports_mock
update_port_mock = mock.Mock()
@@ -4727,7 +4727,7 @@ class TestAPI(TestAPIBase):
def test_get_pci_mapping_for_migration(self):
instance = fake_instance.fake_instance_obj(self.context)
instance.migration_context = objects.MigrationContext()
migration = {'status': 'confirmed'}
migration = objects.Migration(status='confirmed')

with mock.patch.object(instance.migration_context,
'get_pci_mapping_for_migration') as map_func:
@@ -4737,7 +4737,7 @@ class TestAPI(TestAPIBase):
def test_get_pci_mapping_for_migration_reverted(self):
instance = fake_instance.fake_instance_obj(self.context)
instance.migration_context = objects.MigrationContext()
migration = {'status': 'reverted'}
migration = objects.Migration(status='reverted')

with mock.patch.object(instance.migration_context,
'get_pci_mapping_for_migration') as map_func:
@@ -6132,7 +6132,8 @@ class TestAPI(TestAPIBase):
# Just create a simple instance with a single port.
instance = objects.Instance(info_cache=objects.InstanceInfoCache(
network_info=model.NetworkInfo([model.VIF(uuids.port_id)])))
migration = {'source_compute': 'source', 'dest_compute': 'dest'}
migration = objects.Migration(
source_compute='source', dest_compute='dest')
with mock.patch.object(self.api, 'activate_port_binding') as activate:
with mock.patch.object(self.api, 'supports_port_binding_extension',
return_value=True):
@@ -6155,7 +6156,8 @@ class TestAPI(TestAPIBase):
# Just create a simple instance with a single port.
instance = objects.Instance(info_cache=objects.InstanceInfoCache(
network_info=model.NetworkInfo([model.VIF(uuids.port_id)])))
migration = {'source_compute': 'source', 'dest_compute': 'dest'}
migration = objects.Migration(
source_compute='source', dest_compute='dest')
with mock.patch.object(self.api, 'activate_port_binding',
new_callable=mock.NonCallableMock):
with mock.patch.object(self.api, 'supports_port_binding_extension',
@@ -6180,7 +6182,8 @@ class TestAPI(TestAPIBase):
instance = objects.Instance(info_cache=objects.InstanceInfoCache(
network_info=model.NetworkInfo([
model.VIF(uuids.port1), model.VIF(uuids.port2)])))
migration = {'source_compute': 'source', 'dest_compute': 'dest'}
migration = objects.Migration(
source_compute='source', dest_compute='dest')
with mock.patch.object(self.api, 'activate_port_binding',
new_callable=mock.NonCallableMock):
with mock.patch.object(self.api, 'supports_port_binding_extension',
@@ -6202,7 +6205,8 @@ class TestAPI(TestAPIBase):
instance = objects.Instance(info_cache=objects.InstanceInfoCache(
network_info=model.NetworkInfo([
model.VIF(uuids.port1), model.VIF(uuids.port2)])))
migration = {'source_compute': 'source', 'dest_compute': 'dest'}
migration = objects.Migration(
source_compute='source', dest_compute='dest')
with mock.patch.object(self.api, 'activate_port_binding',
new_callable=mock.NonCallableMock):
with mock.patch.object(self.api, 'supports_port_binding_extension',


+ 1
- 1
nova/tests/unit/objects/test_objects.py View File

@@ -1103,7 +1103,7 @@ object_data = {
'LibvirtLiveMigrateData': '1.10-348cf70ea44d3b985f45f64725d6f6a7',
'LibvirtLiveMigrateNUMAInfo': '1.0-0e777677f3459d0ed1634eabbdb6c22f',
'MemoryDiagnostics': '1.0-2c995ae0f2223bb0f8e523c5cc0b83da',
'Migration': '1.7-b77066a88d08bdb0b05d7bc18780c55a',
'Migration': '1.7-bd45b232fd7c95cd79ae9187e10ef582',
'MigrationContext': '1.2-89f10a83999f852a489962ae37d8a026',
'MigrationList': '1.4-983a9c29d4f1e747ce719dc9063b729b',
'MonitorMetric': '1.1-53b1db7c4ae2c531db79761e7acc52ba',


+ 5
- 2
nova/tests/unit/policies/test_server_migrations.py View File

@@ -17,6 +17,7 @@ from oslo_utils.fixture import uuidsentinel as uuids

from nova.api.openstack.compute import server_migrations
from nova.compute import vm_states
from nova import objects
from nova.policies import base as base_policy
from nova.policies import servers_migrations as policies
from nova.tests.unit.api.openstack import fakes
@@ -82,8 +83,10 @@ class ServerMigrationsPolicyTest(base.BasePolicyTest):
@mock.patch('nova.compute.api.API.get_migration_by_id_and_instance')
def test_show_server_migrations_policy(self, mock_show, mock_output):
rule_name = policies.POLICY_ROOT % 'show'
mock_show.return_value = {"migration_type": "live-migration",
"status": "running"}
mock_show.return_value = objects.Migration(
migration_type='live-migration',
status='running',
)
self.common_policy_check(self.reader_authorized_contexts,
self.reader_unauthorized_contexts,
rule_name, self.controller.show,


Loading…
Cancel
Save