Skip to content

Commit d3968f1

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Reproduce bug 1907522 in functional test" into stable/victoria
2 parents f3ee20f + 7366e3c commit d3968f1

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

nova/compute/api.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3879,6 +3879,8 @@ def _allow_cross_cell_resize(context, instance):
38793879
:param instance: Instance object being resized
38803880
:returns: True if cross-cell resize is allowed, False otherwise
38813881
"""
3882+
# TODO(gibi): do not allow cross cell migration if the instance has
3883+
# neutron ports with resource request. See bug 1907522.
38823884
# First check to see if the requesting project/user is allowed by
38833885
# policy to perform cross-cell resize.
38843886
allowed = context.can(

nova/tests/functional/test_servers.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
from nova.network import neutron as neutronapi
4141
from nova import objects
4242
from nova.objects import block_device as block_device_obj
43+
from nova.policies import base as base_policies
44+
from nova.policies import servers as servers_policies
4345
from nova.scheduler import utils
4446
from nova import test
4547
from nova.tests import fixtures as nova_fixtures
@@ -8256,3 +8258,110 @@ def test_rebuild_old_compute(self, old_compute_version):
82568258
'OS-DCF:diskConfig': 'AUTO'}})
82578259
self.assertEqual(403, ex.response.status_code)
82588260
self._check_allocations_usage(self.server)
8261+
8262+
8263+
class CrossCellResizeWithQoSPort(PortResourceRequestBasedSchedulingTestBase):
8264+
NUMBER_OF_CELLS = 2
8265+
8266+
def setUp(self):
8267+
# Use our custom weigher defined above to make sure that we have
8268+
# a predictable host order in the alternate list returned by the
8269+
# scheduler for migration.
8270+
self.useFixture(nova_fixtures.HostNameWeigherFixture())
8271+
super(CrossCellResizeWithQoSPort, self).setUp()
8272+
# start compute2 in cell2, compute1 is started in cell1 by default
8273+
self.compute2 = self._start_compute('host2', cell_name='cell2')
8274+
self.compute2_rp_uuid = self._get_provider_uuid_by_host('host2')
8275+
self._create_networking_rp_tree('host2', self.compute2_rp_uuid)
8276+
self.compute2_service_id = self.admin_api.get_services(
8277+
host='host2', binary='nova-compute')[0]['id']
8278+
8279+
# Enable cross-cell resize policy since it defaults to not allow
8280+
# anyone to perform that type of operation. For these tests we'll
8281+
# just allow admins to perform cross-cell resize.
8282+
self.policy.set_rules({
8283+
servers_policies.CROSS_CELL_RESIZE:
8284+
base_policies.RULE_ADMIN_API},
8285+
overwrite=False)
8286+
8287+
def test_cross_cell_migrate_server_with_qos_ports(self):
8288+
"""Test that cross cell migration is not supported with qos ports and
8289+
nova therefore falls back to do a same cell migration instead.
8290+
To test this properly we first make sure that there is no valid host
8291+
in the same cell but there is valid host in another cell and observe
8292+
that the migration fails with NoValidHost. Then we start a new compute
8293+
in the same cell the instance is in and retry the migration that is now
8294+
expected to pass.
8295+
"""
8296+
8297+
non_qos_normal_port = self.neutron.port_1
8298+
qos_normal_port = self.neutron.port_with_resource_request
8299+
qos_sriov_port = self.neutron.port_with_sriov_resource_request
8300+
8301+
server = self._create_server_with_ports_and_check_allocation(
8302+
non_qos_normal_port, qos_normal_port, qos_sriov_port)
8303+
8304+
orig_create_binding = neutronapi.API._create_port_binding
8305+
8306+
hosts = {
8307+
'host1': self.compute1_rp_uuid, 'host2': self.compute2_rp_uuid}
8308+
8309+
# Add an extra check to our neutron fixture. This check makes sure that
8310+
# the RP sent in the binding corresponds to host of the binding. In a
8311+
# real deployment this is checked by the Neutron server. As bug
8312+
# 1907522 showed we fail this check for cross cell migration with qos
8313+
# ports in a real deployment. So to reproduce that bug we need to have
8314+
# the same check in our test env too.
8315+
def spy_on_create_binding(context, client, port_id, data):
8316+
host_rp_uuid = hosts[data['binding']['host']]
8317+
device_rp_uuid = data['binding']['profile'].get('allocation')
8318+
if port_id == qos_normal_port['id']:
8319+
if device_rp_uuid != self.ovs_bridge_rp_per_host[host_rp_uuid]:
8320+
raise exception.PortBindingFailed(port_id=port_id)
8321+
elif port_id == qos_sriov_port['id']:
8322+
if (device_rp_uuid not in
8323+
self.sriov_dev_rp_per_host[host_rp_uuid].values()):
8324+
raise exception.PortBindingFailed(port_id=port_id)
8325+
8326+
return orig_create_binding(context, client, port_id, data)
8327+
8328+
with mock.patch(
8329+
'nova.network.neutron.API._create_port_binding',
8330+
side_effect=spy_on_create_binding, autospec=True
8331+
):
8332+
# We expect the migration to fail as the only available target
8333+
# host is in a different cell and while cross cell migration is
8334+
# enabled it is not supported for neutron ports with resource
8335+
# request.
8336+
# FIXME(gibi): We expect this to fail with NoValidHost.
8337+
# Unfortunately it fails by not finding the target compute service
8338+
# in the same cell the source service. This is bug 1907511. If
8339+
# there would be a standalone fix for 1907511 then the next failure
8340+
# would be 1907522. Our coming fix will fix both bug with a same
8341+
# fix.
8342+
self.api.post_server_action(server['id'], {'migrate': None})
8343+
self._wait_for_migration_status(server, ['error'])
8344+
self._wait_for_action_fail_completion(
8345+
server, 'migrate', 'conductor_migrate_server')
8346+
# This is the root case
8347+
self.assertIn(
8348+
"AttributeError: 'NoneType' object has no attribute 'version'",
8349+
self.stdlog.logger.output)
8350+
8351+
# Now start a new compute in the same cell as the instance and retry
8352+
# the migration.
8353+
#
8354+
# This should work after the fallback to same cell resize is
8355+
# implemented
8356+
#
8357+
# self._start_compute('host3', cell_name='cell1')
8358+
#
8359+
# with mock.patch(
8360+
# 'nova.network.neutron.API._create_port_binding',
8361+
# side_effect=spy_on_create_binding, autospec=True
8362+
# ):
8363+
# server = self._migrate_server(server)
8364+
# self.assertEqual('host3', server['OS-EXT-SRV-ATTR:host'])
8365+
8366+
self._delete_server_and_check_allocations(
8367+
server, qos_normal_port, qos_sriov_port)

0 commit comments

Comments
 (0)