Get device profile by name

Nowadays showing device_profile is supported only by uuid,
this patch supports to getting device profile by name.

Implements: blueprint show-device-profile-with-name
Change-Id: Ib9aff3312676923fc7478f2bcef79333e10496bf
This commit is contained in:
ericxiett 2021-11-11 00:54:33 +00:00
parent 2490e5b78f
commit cde7b78e22
9 changed files with 276 additions and 177 deletions

View File

@ -49,9 +49,9 @@ Response
Get One Device Profile
----------------------
.. rest_method:: GET /v2/device_profiles/{device_profile_uuid}
.. rest_method:: GET /v2/device_profiles/{device_profile_name_or_uuid}
Gets the UUID, name, groups for one device_profile with the specified UUID.
Gets the UUID, name, groups for one device_profile with the specified name or UUID.
Normal response codes: 200
@ -61,7 +61,8 @@ Request
=======
.. rest_parameters:: parameters.yaml
- device_profile_uuid: device_profile_uuid
- device_profile_uuid: device_profile_uuid_v_21
- device_profile_name_or_uuid: device_profile_name_or_uuid
Response
========
@ -76,9 +77,9 @@ Response
- updated_at: updated
- links: links
**Example response: get details of a specific device profile**
**Example response: get details of a specific device profile(v2.2)**
.. literalinclude:: ../../doc/api_samples/device_profiles/device_profiles-getone-resp.json
.. literalinclude:: ../../doc/api_samples/device_profiles/v22/device_profiles-getone-resp.json
:language: javascript
Create Device Profile

View File

@ -12,13 +12,28 @@ deployable_uuid:
in: path
required: true
type: string
device_profile_uuid:
device_profile_name_or_uuid:
description: |
The UUID of the device_profile for your accelerator request.
This must be a valid UUID otherwise API will return 400.
The name or uuid of the device_profile for your accelerator request.
in: path
required: true
type: string
min_version: 2.2
device_profile_uuid:
description: |
The uuid of the device_profile for your accelerator request.
This must be a valid uuid otherwise api will return 400.
in: path
required: true
type: string
device_profile_uuid_v_21:
description: |
The uuid of the device_profile for your accelerator request.
This must be a valid uuid otherwise api will return 400.
in: path
required: true
type: string
max_version: 2.1
device_uuid:
description: |
The UUID of the device.

View File

@ -23,13 +23,16 @@ from wsme import types as wtypes
from oslo_log import log
from oslo_utils import uuidutils
from cyborg import api
from cyborg.api.controllers import base
from cyborg.api.controllers import link
from cyborg.api.controllers import types
from cyborg.api.controllers.v2 import versions
from cyborg.api import expose
from cyborg.common import authorize_wsgi
from cyborg.common import constants
from cyborg.common import exception
from cyborg.common.i18n import _
from cyborg import objects
LOG = log.getLogger(__name__)
@ -257,21 +260,33 @@ class DeviceProfilesController(base.CyborgController,
@authorize_wsgi.authorize_wsgi("cyborg:device_profile", "get_one")
@expose.expose('json', wtypes.text)
def get_one(self, uuid):
"""Retrieve a single device profile by uuid."""
LOG.info('[device_profiles] get_one. uuid=%s', uuid)
obj_devprofs = self._get_device_profile_list(uuid=uuid)
api_obj_devprofs = self.get_device_profiles(obj_devprofs)
if len(api_obj_devprofs) == 0:
def get_one(self, dp_uuid_or_name):
"""Retrieve a single device profile by uuid or name."""
context = pecan.request.context
if uuidutils.is_uuid_like(dp_uuid_or_name):
LOG.info('[device_profiles] get_one. uuid=%s', dp_uuid_or_name)
obj_devprof = objects.DeviceProfile.get_by_uuid(context,
dp_uuid_or_name)
else:
if api.request.version.minor >= versions.MINOR_2_DP_BY_NAME:
LOG.info('[device_profiles] get_one. name=%s', dp_uuid_or_name)
obj_devprof = \
objects.DeviceProfile.get_by_name(context,
dp_uuid_or_name)
else:
raise exception.NotAcceptable(_(
"Request not acceptable. The minimal required API "
"version should be %(base)s.%(opr)s") %
{'base': versions.BASE_VERSION,
'opr': versions.MINOR_2_DP_BY_NAME})
if not obj_devprof:
LOG.warning("Device profile with %s not found!", dp_uuid_or_name)
raise exception.ResourceNotFound(
resource='Device profile',
msg='with uuid %s' % uuid)
msg='with %s' % dp_uuid_or_name)
api_obj_devprof = self.get_device_profile(obj_devprof)
count = len(api_obj_devprofs)
if count != 1: # Should never happen because names are unique
raise exception.ExpectedOneObject(obj='device profile',
count=count)
ret = {"device_profile": api_obj_devprofs[0]}
ret = {"device_profile": api_obj_devprof}
LOG.info('[device_profiles] get_one returned: %s', ret)
# TODO(Sundar) Replace this with convert_with_links()
return wsme.api.Response(ret, status_code=HTTPStatus.OK,

View File

@ -24,8 +24,10 @@ BASE_VERSION = 2
#
# v2.0: Initial minor version.
# v2.1: Add project_id for arq patch
# v2.2: Support getting device profile by name (newly introduced) and uuid.
MINOR_0_INITIAL_VERSION = 0
MINOR_1_PROJECT_ID = 1
MINOR_2_DP_BY_NAME = 2
# When adding another version, update:
@ -34,7 +36,7 @@ MINOR_1_PROJECT_ID = 1
# explanation of what changed in the new version
MINOR_MAX_VERSION = MINOR_1_PROJECT_ID
MINOR_MAX_VERSION = MINOR_2_DP_BY_NAME
# String representations of the minor and maximum versions
_MIN_VERSION_STRING = '{}.{}'.format(BASE_VERSION, MINOR_0_INITIAL_VERSION)

View File

@ -27,3 +27,11 @@ microversions.
Add ``project_id`` for Accelerator Requests PATCH API. ``project_id`` is
used to control the operation of arq with different roles.
2.2
---
Changed ``device_profile_uuid`` to ``device_profile_name_or_uuid`` in
`Get One Device Profile` API path, so support getting device profile by
name (newly introduced) and uuid.
- GET /v2/device_profiles/{device_profile_name_or_uuid}

View File

@ -19,6 +19,7 @@ import webtest
from oslo_serialization import jsonutils
from cyborg.api.controllers import base
from cyborg.tests.unit.api.controllers.v2 import base as v2_test
from cyborg.tests.unit import fake_device_profile
@ -51,13 +52,40 @@ class TestDeviceProfileController(v2_test.APITestV2):
# Check that the link is properly set up
self._validate_links(out_dp['links'], in_dp['uuid'])
@mock.patch('cyborg.objects.DeviceProfile.list')
def test_get_one_by_uuid(self, mock_dp):
@mock.patch('cyborg.objects.DeviceProfile.get_by_uuid')
def test_get_one_by_uuid(self, mock_dp_uuid):
dp = self.fake_dp_objs[0]
mock_dp.return_value = [dp]
mock_dp_uuid.return_value = dp
url = self.DP_URL + '/%s'
data = self.get_json(url % dp['uuid'], headers=self.headers)
mock_dp.assert_called_once()
mock_dp_uuid.assert_called_once()
out_dp = data['device_profile']
self._validate_dp(dp, out_dp)
@mock.patch('cyborg.objects.DeviceProfile.get_by_name')
def test_get_one_by_name_before_v22(self, mock_dp_name):
dp = self.fake_dp_objs[0]
mock_dp_name.return_value = dp
url = self.DP_URL + '/%s'
headers = self.headers
headers[base.Version.current_api_version] = 'accelerator 2.1'
self.assertRaisesRegex(
webtest.app.AppError,
"Request not acceptable.*",
self.get_json,
url % dp['name'],
headers=headers)
@mock.patch('cyborg.objects.DeviceProfile.get_by_name')
def test_get_one_by_name(self, mock_dp_name):
dp = self.fake_dp_objs[0]
mock_dp_name.return_value = dp
url = self.DP_URL + '/%s'
headers = self.headers
headers[base.Version.current_api_version] = 'accelerator 2.2'
data = self.get_json(url % dp['name'],
headers=headers)
mock_dp_name.assert_called_once()
out_dp = data['device_profile']
self._validate_dp(dp, out_dp)

View File

@ -5,7 +5,7 @@
"description": "",
"groups":[
{
"trait:CUSTOM_CHENKE_TRAITS":"required",
"trait:CUSTOM_FPGA_INSPUR":"required",
"resources:FPGA":"1",
"accel:bitstream_id":"d5ca2f11-3108-4426-a11c-a959987565df"
}

View File

@ -0,0 +1,22 @@
{
"device_profile":{
"name":"fpga-dp1",
"uuid":"5518a925-1c2c-49a2-a8bf-0927d9456f3e",
"description": "",
"groups":[
{
"trait:CUSTOM_FPGA_INSPUR":"required",
"resources:FPGA":"1",
"accel:bitstream_id":"d5ca2f11-3108-4426-a11c-a959987565df"
}
],
"created_at": "2020-03-09 11:26:05+00:00",
"updated_at": null,
"links":[
{
"href":"http://192.168.32.217/accelerator/v2/device_profiles/5518a925-1c2c-49a2-a8bf-0927d9456f3e",
"rel":"self"
}
]
}
}

View File

@ -0,0 +1,8 @@
---
features:
- |
Changed ``device_profile_uuid`` to ``device_profile_name_or_uuid`` in
`Get One Device Profile` API path, so it can support getting one device
profile by its `name` since microversion 2.2, not just uuid.
- GET /v2/device_profiles/{device_profile_name_or_uuid}