cloud: create_server: fix scheduler_hints/group

Change I1a6ba311ddedc1b8910051257299d3acd367df46 stopped sending
server_json data and instead called self.compute.create_server(**kwargs).

Before this change the code would pop() scheduler_hints from kwargs, so
it was not present when creating the server. Additionally the "group"
code would also only operate on the no longer used server_json.

Remove server_json and override/set the scheduler_hints group key
directly in kwargs if "group" is supplied.

Also add tests for this functionality.

Co-Authored-by: stephenfin <stephenfin@redhat.com>
Change-Id: I7ac2fd85970bf4c6c6e73af8aad11348a290a90a
This commit is contained in:
Patrik Lundin 2022-11-25 10:32:16 +01:00
parent 2baee35a5b
commit 4ad5c174c8
No known key found for this signature in database
GPG Key ID: A0A812BA2249F294
2 changed files with 176 additions and 6 deletions
openstack

@ -779,8 +779,6 @@ class ComputeCloudMixin:
raise TypeError(
"create_server() requires either 'image' or 'boot_volume'")
server_json = {'server': kwargs}
# TODO(mordred) Add support for description starting in 2.19
security_groups = kwargs.get('security_groups', [])
if security_groups and not isinstance(kwargs['security_groups'], list):
@ -803,16 +801,16 @@ class ComputeCloudMixin:
if value:
kwargs[desired] = value
hints = kwargs.pop('scheduler_hints', {})
if group:
group_obj = self.get_server_group(group)
if not group_obj:
raise exc.OpenStackCloudException(
"Server Group {group} was requested but was not found"
" on the cloud".format(group=group))
hints['group'] = group_obj['id']
if hints:
server_json['os:scheduler_hints'] = hints
if 'scheduler_hints' not in kwargs:
kwargs['scheduler_hints'] = {}
kwargs['scheduler_hints']['group'] = group_obj['id']
kwargs.setdefault('max_count', kwargs.get('max_count', 1))
kwargs.setdefault('min_count', kwargs.get('min_count', 1))

@ -1012,3 +1012,175 @@ class TestCreateServer(base.TestCase):
wait=False)
self.assert_calls()
def test_create_server_scheduler_hints(self):
"""
Test that setting scheduler_hints will include them in POST request
"""
scheduler_hints = {
'group': self.getUniqueString('group'),
}
fake_server = fakes.make_fake_server('1234', '', 'BUILD')
fake_server['scheduler_hints'] = scheduler_hints
self.register_uris([
dict(method='GET',
uri=self.get_mock_url(
'network', 'public', append=['v2.0', 'networks']),
json={'networks': []}),
self.get_nova_discovery_mock_dict(),
dict(method='POST',
uri=self.get_mock_url(
'compute', 'public', append=['servers']),
json={'server': fake_server},
validate=dict(
json={
'server': {
u'flavorRef': u'flavor-id',
u'imageRef': u'image-id',
u'max_count': 1,
u'min_count': 1,
u'name': u'server-name',
'networks': 'auto'},
u'OS-SCH-HNT:scheduler_hints': scheduler_hints, })),
dict(method='GET',
uri=self.get_mock_url(
'compute', 'public', append=['servers', '1234']),
json={'server': fake_server}),
])
self.cloud.create_server(
name='server-name', image=dict(id='image-id'),
flavor=dict(id='flavor-id'),
scheduler_hints=scheduler_hints, wait=False)
self.assert_calls()
def test_create_server_scheduler_hints_group_merge(self):
"""
Test that setting both scheduler_hints and group results in merged
hints in POST request
"""
group_id = uuid.uuid4().hex
group_name = self.getUniqueString('server-group')
policies = ['affinity']
fake_group = fakes.make_fake_server_group(
group_id, group_name, policies)
# The scheduler hints we pass in
scheduler_hints = {
'different_host': [],
}
# The scheduler hints we expect to be in POST request
scheduler_hints_merged = {
'different_host': [],
'group': group_id,
}
fake_server = fakes.make_fake_server('1234', '', 'BUILD')
fake_server['scheduler_hints'] = scheduler_hints_merged
self.register_uris([
self.get_nova_discovery_mock_dict(),
dict(method='GET',
uri=self.get_mock_url(
'compute', 'public', append=['os-server-groups']),
json={'server_groups': [fake_group]}),
dict(method='GET',
uri=self.get_mock_url(
'network', 'public', append=['v2.0', 'networks']),
json={'networks': []}),
dict(method='POST',
uri=self.get_mock_url(
'compute', 'public', append=['servers']),
json={'server': fake_server},
validate=dict(
json={
'server': {
u'flavorRef': u'flavor-id',
u'imageRef': u'image-id',
u'max_count': 1,
u'min_count': 1,
u'name': u'server-name',
'networks': 'auto'},
u'OS-SCH-HNT:scheduler_hints': scheduler_hints_merged,
})),
dict(method='GET',
uri=self.get_mock_url(
'compute', 'public', append=['servers', '1234']),
json={'server': fake_server}),
])
self.cloud.create_server(
name='server-name', image=dict(id='image-id'),
flavor=dict(id='flavor-id'),
scheduler_hints=dict(scheduler_hints), group=group_name,
wait=False)
self.assert_calls()
def test_create_server_scheduler_hints_group_override(self):
"""
Test that setting group in both scheduler_hints and group param prefers
param
"""
group_id_scheduler_hints = uuid.uuid4().hex
group_id_param = uuid.uuid4().hex
group_name = self.getUniqueString('server-group')
policies = ['affinity']
fake_group = fakes.make_fake_server_group(
group_id_param, group_name, policies)
# The scheduler hints we pass in that are expected to be ignored in
# POST call
scheduler_hints = {
'group': group_id_scheduler_hints,
}
# The scheduler hints we expect to be in POST request
group_scheduler_hints = {
'group': group_id_param,
}
fake_server = fakes.make_fake_server('1234', '', 'BUILD')
fake_server['scheduler_hints'] = group_scheduler_hints
self.register_uris([
self.get_nova_discovery_mock_dict(),
dict(method='GET',
uri=self.get_mock_url(
'compute', 'public', append=['os-server-groups']),
json={'server_groups': [fake_group]}),
dict(method='GET',
uri=self.get_mock_url(
'network', 'public', append=['v2.0', 'networks']),
json={'networks': []}),
dict(method='POST',
uri=self.get_mock_url(
'compute', 'public', append=['servers']),
json={'server': fake_server},
validate=dict(
json={
'server': {
u'flavorRef': u'flavor-id',
u'imageRef': u'image-id',
u'max_count': 1,
u'min_count': 1,
u'name': u'server-name',
'networks': 'auto'},
u'OS-SCH-HNT:scheduler_hints': group_scheduler_hints,
})),
dict(method='GET',
uri=self.get_mock_url(
'compute', 'public', append=['servers', '1234']),
json={'server': fake_server}),
])
self.cloud.create_server(
name='server-name', image=dict(id='image-id'),
flavor=dict(id='flavor-id'),
scheduler_hints=dict(scheduler_hints), group=group_name,
wait=False)
self.assert_calls()