Skip to content

Commit 751c7b0

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Test multi create with vGPUs"
2 parents 22757f4 + 32bbbd6 commit 751c7b0

File tree

1 file changed

+68
-4
lines changed

1 file changed

+68
-4
lines changed

nova/tests/functional/libvirt/test_vgpu.py

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,19 @@
1414
import fixtures
1515
import re
1616

17+
import collections
1718
import mock
1819
import os_resource_classes as orc
1920
from oslo_config import cfg
2021
from oslo_log import log as logging
2122
from oslo_utils import uuidutils
2223

24+
from nova.compute import instance_actions
2325
import nova.conf
2426
from nova import context
2527
from nova import objects
2628
from nova.tests.functional.libvirt import base
29+
from nova.tests.unit import policy_fixture
2730
from nova.tests.unit.virt.libvirt import fakelibvirt
2831
from nova.virt.libvirt import driver as libvirt_driver
2932
from nova.virt.libvirt import utils as libvirt_utils
@@ -149,10 +152,16 @@ def setUp(self):
149152
return_value=[]))
150153
self.useFixture(fixtures.MockPatch('os.rename'))
151154

155+
policy = self.useFixture(policy_fixture.RealPolicyFixture())
156+
# Allow non-admins to see instance action events.
157+
policy.set_rules({
158+
'os_compute_api:os-instance-actions:events': 'rule:admin_or_owner'
159+
}, overwrite=False)
160+
152161
self.compute1 = self._start_compute_service(_DEFAULT_HOST)
153162

154163
def assert_vgpu_usage_for_compute(self, compute, expected):
155-
total_usage = 0
164+
total_usages = collections.defaultdict(int)
156165
# We only want to get mdevs that are assigned to instances
157166
mdevs = compute.driver._get_all_assigned_mediated_devices()
158167
for mdev in mdevs:
@@ -163,10 +172,11 @@ def assert_vgpu_usage_for_compute(self, compute, expected):
163172
parent_rp_name = compute.host + '_' + parent_name
164173
parent_rp_uuid = self._get_provider_uuid_by_name(parent_rp_name)
165174
parent_usage = self._get_provider_usages(parent_rp_uuid)
166-
if orc.VGPU in parent_usage:
167-
total_usage += parent_usage[orc.VGPU]
175+
if orc.VGPU in parent_usage and parent_rp_name not in total_usages:
176+
# We only set the total amount if we didn't had it already
177+
total_usages[parent_rp_name] = parent_usage[orc.VGPU]
168178
self.assertEqual(expected, len(mdevs))
169-
self.assertEqual(expected, total_usage)
179+
self.assertEqual(expected, sum(total_usages[k] for k in total_usages))
170180

171181
def test_create_servers_with_vgpu(self):
172182
self._create_server(
@@ -223,6 +233,60 @@ def test_resize_servers_with_vgpu(self):
223233
self.assert_vgpu_usage_for_compute(self.compute1, expected=0)
224234
self.assert_vgpu_usage_for_compute(self.compute2, expected=1)
225235

236+
def test_multiple_instance_create(self):
237+
body = self._build_server(
238+
name=None, image_uuid='155d900f-4e14-4e4c-a73d-069cbf4541e6',
239+
flavor_id=self.flavor, networks='auto', az=None,
240+
host=self.compute1.host)
241+
# Asking to multicreate two instances, each of them asking for 1 vGPU
242+
body['min_count'] = 2
243+
server = self.api.post_server({'server': body})
244+
self._wait_for_state_change(server, 'ACTIVE')
245+
246+
# Let's verify we created two mediated devices and we have a total of
247+
# 2 vGPUs
248+
self.assert_vgpu_usage_for_compute(self.compute1, expected=2)
249+
250+
def test_multiple_instance_create_filling_up_capacity(self):
251+
# Each pGPU created by fakelibvirt defaults to a capacity of 16 vGPUs.
252+
# By default, we created a compute service with 2 pGPUs before, so we
253+
# have a total capacity of 32. In theory, we should be able to find
254+
# space for two instances asking for 16 vGPUs each.
255+
extra_spec = {"resources:VGPU": "16"}
256+
flavor = self._create_flavor(extra_spec=extra_spec)
257+
body = self._build_server(
258+
name=None, image_uuid='155d900f-4e14-4e4c-a73d-069cbf4541e6',
259+
flavor_id=flavor, networks='auto', az=None,
260+
host=self.compute1.host)
261+
# Asking to multicreate two instances, each of them asking for 8 vGPU
262+
body['min_count'] = 2
263+
server = self.api.post_server({'server': body})
264+
# But... we fail miserably because of bug #1874664
265+
# FIXME(sbauza): Change this once we fix the above bug
266+
server = self._wait_for_state_change(server, 'ERROR')
267+
self.assertIn('fault', server)
268+
self.assertIn('No valid host', server['fault']['message'])
269+
self.assertEqual('', server['hostId'])
270+
# Assert the "create" instance action exists and is failed.
271+
actions = self.api.get_instance_actions(server['id'])
272+
self.assertEqual(1, len(actions), actions)
273+
action = actions[0]
274+
self.assertEqual(instance_actions.CREATE, action['action'])
275+
self.assertEqual('Error', action['message'])
276+
# Get the events. There should be one with an Error result.
277+
action = self.api.api_get(
278+
'/servers/%s/os-instance-actions/%s' %
279+
(server['id'], action['request_id'])).body['instanceAction']
280+
events = action['events']
281+
self.assertEqual(1, len(events), events)
282+
event = events[0]
283+
self.assertEqual('conductor_schedule_and_build_instances',
284+
event['event'])
285+
self.assertEqual('Error', event['result'])
286+
# Normally non-admins cannot see the event traceback but we enabled
287+
# that via policy in setUp so assert something was recorded.
288+
self.assertIn('select_destinations', event['traceback'])
289+
226290

227291
class VGPUMultipleTypesTests(VGPUTestBase):
228292

0 commit comments

Comments
 (0)