Merge "Pass target host to RequestGroup.in_tree"
This commit is contained in:
commit
11de108daa
|
@ -133,7 +133,8 @@ class SchedulerManager(manager.Manager):
|
|||
except exception.RequestFilterFailed as e:
|
||||
raise exception.NoValidHost(reason=e.message)
|
||||
|
||||
resources = utils.resources_from_request_spec(spec_obj)
|
||||
resources = utils.resources_from_request_spec(
|
||||
ctxt, spec_obj, self.driver.host_manager)
|
||||
res = self.placement_client.get_allocation_candidates(ctxt,
|
||||
resources)
|
||||
if res is None:
|
||||
|
|
|
@ -412,9 +412,16 @@ def resources_from_flavor(instance, flavor):
|
|||
return resources
|
||||
|
||||
|
||||
def resources_from_request_spec(spec_obj):
|
||||
def resources_from_request_spec(ctxt, spec_obj, host_manager):
|
||||
"""Given a RequestSpec object, returns a ResourceRequest of the resources,
|
||||
traits, and aggregates it represents.
|
||||
|
||||
:param context: The request context.
|
||||
:param spec_obj: A RequestSpec object.
|
||||
:param host_manager: A HostManager object.
|
||||
|
||||
:return: A ResourceRequest object.
|
||||
:raises NoValidHost: If the specified host/node is not found in the DB.
|
||||
"""
|
||||
spec_resources = {
|
||||
orc.VCPU: spec_obj.vcpus,
|
||||
|
@ -478,18 +485,54 @@ def resources_from_request_spec(spec_obj):
|
|||
for group in requested_resources:
|
||||
res_req.add_request_group(group)
|
||||
|
||||
# values to get the destination target compute uuid
|
||||
target_host = None
|
||||
target_node = None
|
||||
target_cell = None
|
||||
|
||||
if 'requested_destination' in spec_obj:
|
||||
destination = spec_obj.requested_destination
|
||||
if destination and destination.aggregates:
|
||||
grp = res_req.get_request_group(None)
|
||||
grp.aggregates = [ored.split(',')
|
||||
for ored in destination.aggregates]
|
||||
if destination:
|
||||
if 'host' in destination:
|
||||
target_host = destination.host
|
||||
if 'node' in destination:
|
||||
target_node = destination.node
|
||||
if 'cell' in destination:
|
||||
target_cell = destination.cell
|
||||
if destination.aggregates:
|
||||
grp = res_req.get_request_group(None)
|
||||
grp.aggregates = [ored.split(',')
|
||||
for ored in destination.aggregates]
|
||||
|
||||
# Don't limit allocation candidates when using force_hosts or force_nodes.
|
||||
if 'force_hosts' in spec_obj and spec_obj.force_hosts:
|
||||
res_req._limit = None
|
||||
# Prioritize the value from requested_destination just in case
|
||||
# so that we don't inadvertently overwrite it to the old value
|
||||
# of force_hosts persisted in the DB
|
||||
target_host = target_host or spec_obj.force_hosts[0]
|
||||
|
||||
if 'force_nodes' in spec_obj and spec_obj.force_nodes:
|
||||
res_req._limit = None
|
||||
# Prioritize the value from requested_destination just in case
|
||||
# so that we don't inadvertently overwrite it to the old value
|
||||
# of force_nodes persisted in the DB
|
||||
target_node = target_node or spec_obj.force_nodes[0]
|
||||
|
||||
if target_host or target_node:
|
||||
nodes = host_manager.get_compute_nodes_by_host_or_node(
|
||||
ctxt, target_host, target_node, cell=target_cell)
|
||||
if not nodes:
|
||||
reason = (_('No such host - host: %(host)s node: %(node)s ') %
|
||||
{'host': target_host, 'node': target_node})
|
||||
raise exception.NoValidHost(reason=reason)
|
||||
if len(nodes) == 1:
|
||||
grp = res_req.get_request_group(None)
|
||||
grp.in_tree = nodes[0].uuid
|
||||
else:
|
||||
# Multiple nodes are found when a target host is specified
|
||||
# without a specific node. Since placement doesn't support
|
||||
# multiple uuids in the `in_tree` queryparam, what we can do here
|
||||
# is to remove the limit from the `GET /a_c` query to prevent
|
||||
# the found nodes from being filtered out in placement.
|
||||
res_req._limit = None
|
||||
|
||||
return res_req
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ class TestUtils(test.NoDBTestCase):
|
|||
def setUp(self):
|
||||
super(TestUtils, self).setUp()
|
||||
self.context = nova_context.get_admin_context()
|
||||
self.mock_host_manager = mock.Mock()
|
||||
|
||||
def assertResourceRequestsEqual(self, expected, observed):
|
||||
self.assertEqual(expected._limit, observed._limit)
|
||||
|
@ -54,7 +55,8 @@ class TestUtils(test.NoDBTestCase):
|
|||
def _test_resources_from_request_spec(self, expected, flavor,
|
||||
image=objects.ImageMeta()):
|
||||
fake_spec = objects.RequestSpec(flavor=flavor, image=image)
|
||||
resources = utils.resources_from_request_spec(fake_spec)
|
||||
resources = utils.resources_from_request_spec(
|
||||
self.context, fake_spec, self.mock_host_manager)
|
||||
self.assertResourceRequestsEqual(expected, resources)
|
||||
return resources
|
||||
|
||||
|
@ -232,7 +234,8 @@ class TestUtils(test.NoDBTestCase):
|
|||
"resources:DOESNT_EXIST": 0})
|
||||
fake_spec = objects.RequestSpec(flavor=flavor)
|
||||
with mock.patch("nova.scheduler.utils.LOG.warning") as mock_log:
|
||||
utils.resources_from_request_spec(fake_spec)
|
||||
utils.resources_from_request_spec(
|
||||
self.context, fake_spec, self.mock_host_manager)
|
||||
mock_log.assert_called_once()
|
||||
args = mock_log.call_args[0]
|
||||
self.assertEqual(args[0], "Received an invalid ResourceClass "
|
||||
|
@ -321,12 +324,14 @@ class TestUtils(test.NoDBTestCase):
|
|||
requested_destination=destination)
|
||||
|
||||
destination.require_aggregates(['foo', 'bar'])
|
||||
req = utils.resources_from_request_spec(reqspec)
|
||||
req = utils.resources_from_request_spec(
|
||||
self.context, reqspec, self.mock_host_manager)
|
||||
self.assertEqual([['foo', 'bar']],
|
||||
req.get_request_group(None).aggregates)
|
||||
|
||||
destination.require_aggregates(['baz'])
|
||||
req = utils.resources_from_request_spec(reqspec)
|
||||
req = utils.resources_from_request_spec(
|
||||
self.context, reqspec, self.mock_host_manager)
|
||||
self.assertEqual([['foo', 'bar'], ['baz']],
|
||||
req.get_request_group(None).aggregates)
|
||||
|
||||
|
@ -336,19 +341,23 @@ class TestUtils(test.NoDBTestCase):
|
|||
swap=0)
|
||||
reqspec = objects.RequestSpec(flavor=flavor)
|
||||
|
||||
req = utils.resources_from_request_spec(reqspec)
|
||||
req = utils.resources_from_request_spec(
|
||||
self.context, reqspec, self.mock_host_manager)
|
||||
self.assertEqual([], req.get_request_group(None).aggregates)
|
||||
|
||||
reqspec.requested_destination = None
|
||||
req = utils.resources_from_request_spec(reqspec)
|
||||
req = utils.resources_from_request_spec(
|
||||
self.context, reqspec, self.mock_host_manager)
|
||||
self.assertEqual([], req.get_request_group(None).aggregates)
|
||||
|
||||
reqspec.requested_destination = objects.Destination()
|
||||
req = utils.resources_from_request_spec(reqspec)
|
||||
req = utils.resources_from_request_spec(
|
||||
self.context, reqspec, self.mock_host_manager)
|
||||
self.assertEqual([], req.get_request_group(None).aggregates)
|
||||
|
||||
reqspec.requested_destination.aggregates = None
|
||||
req = utils.resources_from_request_spec(reqspec)
|
||||
req = utils.resources_from_request_spec(
|
||||
self.context, reqspec, self.mock_host_manager)
|
||||
self.assertEqual([], req.get_request_group(None).aggregates)
|
||||
|
||||
@mock.patch("nova.scheduler.utils.ResourceRequest.from_extra_specs")
|
||||
|
@ -360,7 +369,8 @@ class TestUtils(test.NoDBTestCase):
|
|||
swap=0,
|
||||
extra_specs={"resources:CUSTOM_TEST_CLASS": 1})
|
||||
fake_spec = objects.RequestSpec(flavor=flavor)
|
||||
utils.resources_from_request_spec(fake_spec)
|
||||
utils.resources_from_request_spec(
|
||||
self.context, fake_spec, self.mock_host_manager)
|
||||
mock_proc.assert_called_once()
|
||||
|
||||
@mock.patch("nova.scheduler.utils.ResourceRequest.from_extra_specs")
|
||||
|
@ -371,7 +381,8 @@ class TestUtils(test.NoDBTestCase):
|
|||
ephemeral_gb=5,
|
||||
swap=0)
|
||||
fake_spec = objects.RequestSpec(flavor=flavor)
|
||||
utils.resources_from_request_spec(fake_spec)
|
||||
utils.resources_from_request_spec(
|
||||
self.context, fake_spec, self.mock_host_manager)
|
||||
mock_proc.assert_not_called()
|
||||
|
||||
def test_process_missing_extra_specs_value(self):
|
||||
|
@ -383,7 +394,8 @@ class TestUtils(test.NoDBTestCase):
|
|||
swap=0,
|
||||
extra_specs={"resources:CUSTOM_TEST_CLASS": ""})
|
||||
fake_spec = objects.RequestSpec(flavor=flavor)
|
||||
utils.resources_from_request_spec(fake_spec)
|
||||
utils.resources_from_request_spec(
|
||||
self.context, fake_spec, self.mock_host_manager)
|
||||
|
||||
def test_process_no_force_hosts_or_force_nodes(self):
|
||||
flavor = objects.Flavor(vcpus=1,
|
||||
|
@ -408,6 +420,11 @@ class TestUtils(test.NoDBTestCase):
|
|||
self.assertEqual(expected_querystring, rr.to_querystring())
|
||||
|
||||
def test_process_use_force_nodes(self):
|
||||
fake_nodes = objects.ComputeNodeList(objects=[
|
||||
objects.ComputeNode(host='fake-host',
|
||||
uuid='12345678-1234-1234-1234-123456789012')])
|
||||
self.mock_host_manager.get_compute_nodes_by_host_or_node.\
|
||||
return_value = fake_nodes
|
||||
flavor = objects.Flavor(vcpus=1,
|
||||
memory_mb=1024,
|
||||
root_gb=15,
|
||||
|
@ -422,16 +439,58 @@ class TestUtils(test.NoDBTestCase):
|
|||
'MEMORY_MB': 1024,
|
||||
'DISK_GB': 15,
|
||||
},
|
||||
in_tree='12345678-1234-1234-1234-123456789012',
|
||||
)
|
||||
expected._limit = None
|
||||
resources = utils.resources_from_request_spec(fake_spec)
|
||||
resources = utils.resources_from_request_spec(
|
||||
self.context, fake_spec, self.mock_host_manager)
|
||||
self.assertResourceRequestsEqual(expected, resources)
|
||||
expected_querystring = (
|
||||
'resources=DISK_GB%3A15%2CMEMORY_MB%3A1024%2CVCPU%3A1'
|
||||
)
|
||||
'limit=1000&resources=DISK_GB%3A15%2CMEMORY_MB%3A1024%2CVCPU%3A1')
|
||||
self.assertEqual(expected_querystring, resources.to_querystring())
|
||||
self.mock_host_manager.get_compute_nodes_by_host_or_node.\
|
||||
assert_called_once_with(self.context, None, 'test', cell=None)
|
||||
|
||||
def test_process_use_force_hosts(self):
|
||||
fake_nodes = objects.ComputeNodeList(objects=[
|
||||
objects.ComputeNode(host='fake-host',
|
||||
uuid='12345678-1234-1234-1234-123456789012')
|
||||
])
|
||||
self.mock_host_manager.get_compute_nodes_by_host_or_node.\
|
||||
return_value = fake_nodes
|
||||
flavor = objects.Flavor(vcpus=1,
|
||||
memory_mb=1024,
|
||||
root_gb=15,
|
||||
ephemeral_gb=0,
|
||||
swap=0)
|
||||
fake_spec = objects.RequestSpec(flavor=flavor, force_hosts=['test'])
|
||||
expected = utils.ResourceRequest()
|
||||
expected._rg_by_id[None] = objects.RequestGroup(
|
||||
use_same_provider=False,
|
||||
resources={
|
||||
'VCPU': 1,
|
||||
'MEMORY_MB': 1024,
|
||||
'DISK_GB': 15,
|
||||
},
|
||||
in_tree='12345678-1234-1234-1234-123456789012',
|
||||
)
|
||||
resources = utils.resources_from_request_spec(
|
||||
self.context, fake_spec, self.mock_host_manager)
|
||||
self.assertResourceRequestsEqual(expected, resources)
|
||||
expected_querystring = (
|
||||
'limit=1000&resources=DISK_GB%3A15%2CMEMORY_MB%3A1024%2CVCPU%3A1')
|
||||
self.assertEqual(expected_querystring, resources.to_querystring())
|
||||
self.mock_host_manager.get_compute_nodes_by_host_or_node.\
|
||||
assert_called_once_with(self.context, 'test', None, cell=None)
|
||||
|
||||
def test_process_use_force_hosts_multinodes_found(self):
|
||||
fake_nodes = objects.ComputeNodeList(objects=[
|
||||
objects.ComputeNode(host='fake-host',
|
||||
uuid='12345678-1234-1234-1234-123456789012'),
|
||||
objects.ComputeNode(host='fake-host',
|
||||
uuid='87654321-4321-4321-4321-210987654321'),
|
||||
])
|
||||
self.mock_host_manager.get_compute_nodes_by_host_or_node.\
|
||||
return_value = fake_nodes
|
||||
flavor = objects.Flavor(vcpus=1,
|
||||
memory_mb=1024,
|
||||
root_gb=15,
|
||||
|
@ -447,13 +506,55 @@ class TestUtils(test.NoDBTestCase):
|
|||
'DISK_GB': 15,
|
||||
},
|
||||
)
|
||||
# Validate that the limit is unset
|
||||
expected._limit = None
|
||||
resources = utils.resources_from_request_spec(fake_spec)
|
||||
|
||||
resources = utils.resources_from_request_spec(
|
||||
self.context, fake_spec, self.mock_host_manager)
|
||||
self.assertResourceRequestsEqual(expected, resources)
|
||||
# Validate that the limit is unset
|
||||
expected_querystring = (
|
||||
'resources=DISK_GB%3A15%2CMEMORY_MB%3A1024%2CVCPU%3A1')
|
||||
self.assertEqual(expected_querystring, resources.to_querystring())
|
||||
self.mock_host_manager.get_compute_nodes_by_host_or_node.\
|
||||
assert_called_once_with(self.context, 'test', None, cell=None)
|
||||
|
||||
def test_process_use_requested_destination(self):
|
||||
fake_cell = objects.CellMapping(uuid=uuids.cell1, name='foo')
|
||||
destination = objects.Destination(
|
||||
host='fake-host', node='fake-node', cell=fake_cell)
|
||||
fake_nodes = objects.ComputeNodeList(objects=[
|
||||
objects.ComputeNode(host='fake-host',
|
||||
uuid='12345678-1234-1234-1234-123456789012')
|
||||
])
|
||||
self.mock_host_manager.get_compute_nodes_by_host_or_node.\
|
||||
return_value = fake_nodes
|
||||
flavor = objects.Flavor(vcpus=1,
|
||||
memory_mb=1024,
|
||||
root_gb=15,
|
||||
ephemeral_gb=0,
|
||||
swap=0)
|
||||
fake_spec = objects.RequestSpec(
|
||||
flavor=flavor, requested_destination=destination)
|
||||
expected = utils.ResourceRequest()
|
||||
expected._rg_by_id[None] = objects.RequestGroup(
|
||||
use_same_provider=False,
|
||||
resources={
|
||||
'VCPU': 1,
|
||||
'MEMORY_MB': 1024,
|
||||
'DISK_GB': 15,
|
||||
},
|
||||
in_tree='12345678-1234-1234-1234-123456789012',
|
||||
)
|
||||
resources = utils.resources_from_request_spec(
|
||||
self.context, fake_spec, self.mock_host_manager)
|
||||
self.assertResourceRequestsEqual(expected, resources)
|
||||
expected_querystring = (
|
||||
'resources=DISK_GB%3A15%2CMEMORY_MB%3A1024%2CVCPU%3A1'
|
||||
)
|
||||
'limit=1000&resources=DISK_GB%3A15%2CMEMORY_MB%3A1024%2CVCPU%3A1')
|
||||
self.assertEqual(expected_querystring, resources.to_querystring())
|
||||
self.mock_host_manager.get_compute_nodes_by_host_or_node.\
|
||||
assert_called_once_with(
|
||||
self.context, 'fake-host', 'fake-node', cell=fake_cell)
|
||||
|
||||
def test_resources_from_request_spec_having_requested_resources(self):
|
||||
flavor = objects.Flavor(
|
||||
|
@ -466,7 +567,8 @@ class TestUtils(test.NoDBTestCase):
|
|||
rg2 = objects.RequestGroup()
|
||||
reqspec = objects.RequestSpec(flavor=flavor,
|
||||
requested_resources=[rg1, rg2])
|
||||
req = utils.resources_from_request_spec(reqspec)
|
||||
req = utils.resources_from_request_spec(
|
||||
self.context, reqspec, self.mock_host_manager)
|
||||
self.assertEqual({'MEMORY_MB': 1024, 'DISK_GB': 15, 'VCPU': 1},
|
||||
req.get_request_group(None).resources)
|
||||
self.assertIs(rg1, req.get_request_group(1))
|
||||
|
@ -480,13 +582,15 @@ class TestUtils(test.NoDBTestCase):
|
|||
ephemeral_gb=5,
|
||||
swap=0)
|
||||
reqspec = objects.RequestSpec(flavor=flavor)
|
||||
req = utils.resources_from_request_spec(reqspec)
|
||||
req = utils.resources_from_request_spec(
|
||||
self.context, reqspec, self.mock_host_manager)
|
||||
self.assertEqual({'MEMORY_MB': 1024, 'DISK_GB': 15, 'VCPU': 1},
|
||||
req.get_request_group(None).resources)
|
||||
self.assertEqual(1, len(list(req.resource_groups())))
|
||||
|
||||
reqspec = objects.RequestSpec(flavor=flavor, requested_resources=[])
|
||||
req = utils.resources_from_request_spec(reqspec)
|
||||
req = utils.resources_from_request_spec(
|
||||
self.context, reqspec, self.mock_host_manager)
|
||||
self.assertEqual({'MEMORY_MB': 1024, 'DISK_GB': 15, 'VCPU': 1},
|
||||
req.get_request_group(None).resources)
|
||||
self.assertEqual(1, len(list(req.resource_groups())))
|
||||
|
|
Loading…
Reference in New Issue