Merge "Add rc check for POST Device Profile"

This commit is contained in:
Zuul 2020-09-27 09:59:00 +00:00 committed by Gerrit Code Review
commit 665abe1f00
5 changed files with 76 additions and 17 deletions

View File

@ -28,6 +28,7 @@ from cyborg.api.controllers import link
from cyborg.api.controllers import types
from cyborg.api import expose
from cyborg.common import authorize_wsgi
from cyborg.common import constants
from cyborg.common import exception
from cyborg import objects
LOG = log.getLogger(__name__)
@ -186,6 +187,24 @@ class DeviceProfilesController(base.CyborgController,
del group[key]
standard_key = "trait:" + inner_trait
group[standard_key] = value
# check rc name and it's value
if key.startswith("resources:"):
inner_origin_rc = ":".join(key.split(":")[1:])
inner_rc = inner_origin_rc.strip(" ")
if inner_rc not in constants.SUPPORT_RESOURCES and \
not inner_rc.startswith('CUSTOM_'):
raise exception.InvalidParameterValue(
err="Unsupported resource class %s" % inner_rc)
try:
int(value)
except ValueError:
raise exception.InvalidParameterValue(
err="Resources nummber %s is invalid" % value)
# strip " " and update old group key.
if inner_origin_rc != inner_rc:
del group[key]
standard_key = "resources:" + inner_rc
group[standard_key] = value
def _get_device_profile_list(self, names=None, uuid=None):
"""Get a list of API objects representing device profiles."""

View File

@ -49,7 +49,7 @@ class ExtARQJobMixin(object):
def get_suitable_ext_arq(cls, context, uuid):
"""From the inherit subclass find the suitable ExtARQ."""
extarq = cls.get(context, uuid)
typ, _ = extarq.get_resources_from_device_profile_group()
typ = extarq.get_resources_from_device_profile_group()
factory = cls.factory(typ)
if factory != cls:
return factory.get(context, uuid)
@ -222,19 +222,8 @@ class ExtARQJobMixin(object):
if not resources:
raise exception.InvalidParameterValue(
'No resources in device_profile_group: %s' % group)
res_type, res_num = resources[0]
# TODO(Sundar): this should be caught in ARQ create, not bind.
if res_type not in constants.SUPPORT_RESOURCES:
raise exception.InvalidParameterValue(
'Unsupport resources %s from device_profile_group: %s' %
(res_type, group))
try:
res_num = int(res_num)
except ValueError:
raise exception.InvalidParameterValue(
'Resources nummber is a invalid in'
' device_profile_group: %s' % group)
return res_type, res_num
res_type = resources[0][0]
return res_type
@classmethod
def apply_patch(cls, context, patch_list, valid_fields):

View File

@ -123,6 +123,57 @@ class TestDeviceProfileController(v2_test.APITestV2):
# {'trait:CUSTOM_FPGA_INTEL_PAC_ARRIA10': 'required}
self.assertTrue(out_dp['groups'] == self.fake_dp_objs[0]['groups'])
@mock.patch('cyborg.conductor.rpcapi.ConductorAPI.device_profile_create')
def test_create_with_extra_space_in_rc(self, mock_cond_dp):
test_unsupport_dp = self.fake_dps[0]
# generate a requested dp which has extra space in rc
del test_unsupport_dp['groups'][0]['resources:FPGA']
test_unsupport_dp['groups'][0]['resources: FPGA '] = '1'
dp = [test_unsupport_dp]
mock_cond_dp.return_value = self.fake_dp_objs[0]
dp[0]['created_at'] = str(dp[0]['created_at'])
response = self.post_json(self.DP_URL, dp, headers=self.headers)
out_dp = jsonutils.loads(response.controller_output)
# check that the extra space in rc:{'resources: FPGA ': '1'} is
# successful stripped by the _validate_post_request function, and
# the created device_profile has no extra space in
# rc:{'resources:FPGA': '1'}
self.assertTrue(out_dp['groups'] == self.fake_dp_objs[0]['groups'])
def test_create_with_unsupported_rc(self):
test_unsupport_dp = self.fake_dps[0]
# generate a special rc for test
del test_unsupport_dp['groups'][0]['resources:FPGA']
test_unsupport_dp['groups'][0]["resources:FAKE_RC"] = '1'
dp = [test_unsupport_dp]
dp[0]['created_at'] = str(dp[0]['created_at'])
self.assertRaisesRegex(
webtest.app.AppError,
".*Unsupported resource class FAKE_RC.*",
self.post_json,
self.DP_URL,
dp,
headers=self.headers)
def test_create_with_invalid_resource_value(self):
test_unsupport_dp = self.fake_dps[0]
del test_unsupport_dp['groups'][0]['resources:FPGA']
test_unsupport_dp['groups'][0]["resources:CUSTOM_FAKE_RC"] = 'fake'
dp = [test_unsupport_dp]
dp[0]['created_at'] = str(dp[0]['created_at'])
self.assertRaisesRegex(
webtest.app.AppError,
".*Resources nummber fake is invalid.*",
self.post_json,
self.DP_URL,
dp,
headers=self.headers)
@mock.patch('cyborg.conductor.rpcapi.ConductorAPI.device_profile_delete')
@mock.patch('cyborg.objects.DeviceProfile.get_by_name')
@mock.patch('cyborg.objects.DeviceProfile.get_by_uuid')

View File

@ -41,7 +41,7 @@ def _get_device_profiles_as_dict():
"created_at": date1,
"updated_at": None,
"groups": [
{"resources:ACCELERATOR_FPGA": "1",
{"resources:FPGA": "1",
"trait:CUSTOM_FPGA_INTEL_PAC_ARRIA10": "required",
"trait:CUSTOM_FUNCTION_ID_3AFB": "required",
},
@ -58,7 +58,7 @@ def _get_device_profiles_as_dict():
"updated_at": None,
"description": "fake-daas_example_2-desc",
"groups": [
{"resources:ACCELERATOR_FPGA": "1",
{"resources:FPGA": "1",
"trait:CUSTOM_REGION_ID_3ACD": "required",
"accel:bitstream_id": "ea0d149c-8555-495b-bc79-608d7bab1260"
}

View File

@ -53,7 +53,7 @@ class TestExtARQJobMixin(base.DbTestCase):
"device_profile_group"][constants.ACCEL_FUNCTION_ID]
def test_get_resources_from_device_profile_group(self):
expect = [("GPU", 1)] + [("FPGA", 1)] * 4
expect = [("GPU")] + [("FPGA")] * 4
actual = [v.get_resources_from_device_profile_group()
for v in self.class_objects.values()]
self.assertEqual(expect, actual)