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:
parent
2490e5b78f
commit
cde7b78e22
|
@ -1,156 +1,157 @@
|
||||||
.. -*- rst -*-
|
.. -*- rst -*-
|
||||||
.. needs:body_verification
|
.. needs:body_verification
|
||||||
|
|
||||||
Device Profiles
|
Device Profiles
|
||||||
+++++++++++++++
|
+++++++++++++++
|
||||||
|
|
||||||
Lists, creates, shows details for, updates and deletes device profiles.
|
Lists, creates, shows details for, updates and deletes device profiles.
|
||||||
|
|
||||||
A `device_profile
|
A `device_profile
|
||||||
<http://specs.openstack.org/openstack/cyborg-specs/specs/train/implemented/device-profiles.html>`_
|
<http://specs.openstack.org/openstack/cyborg-specs/specs/train/implemented/device-profiles.html>`_
|
||||||
is a named set of the user requirements for one or more
|
is a named set of the user requirements for one or more
|
||||||
accelerators. It can be viewed as a flavor for devices. Broadly it includes
|
accelerators. It can be viewed as a flavor for devices. Broadly it includes
|
||||||
two things: the desired amounts of specific resource classes and the
|
two things: the desired amounts of specific resource classes and the
|
||||||
requirements that the resource provider(s) must satisfy. While the resource
|
requirements that the resource provider(s) must satisfy. While the resource
|
||||||
classes are the same as those known to Placement, some requirements would
|
classes are the same as those known to Placement, some requirements would
|
||||||
correspond to Placement traits and others to properties that Cyborg alone
|
correspond to Placement traits and others to properties that Cyborg alone
|
||||||
knows about.
|
knows about.
|
||||||
|
|
||||||
|
|
||||||
List Device Profiles
|
List Device Profiles
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
.. rest_method:: GET /v2/device_profiles
|
.. rest_method:: GET /v2/device_profiles
|
||||||
|
|
||||||
Lists UUIDs, names, groups for all device profiles.
|
Lists UUIDs, names, groups for all device profiles.
|
||||||
|
|
||||||
Normal response codes: 200
|
Normal response codes: 200
|
||||||
|
|
||||||
Error response codes: unauthorized(401), forbidden(403)
|
Error response codes: unauthorized(401), forbidden(403)
|
||||||
|
|
||||||
Response
|
Response
|
||||||
========
|
========
|
||||||
.. rest_parameters:: parameters.yaml
|
.. rest_parameters:: parameters.yaml
|
||||||
|
|
||||||
- device_profiles: device_profiles
|
- device_profiles: device_profiles
|
||||||
- name: device_prof_name_resp
|
- name: device_prof_name_resp
|
||||||
- uuid: device_profile_uuid
|
- uuid: device_profile_uuid
|
||||||
- description: device_profile_description
|
- description: device_profile_description
|
||||||
- groups: device_prof_groups_resp
|
- groups: device_prof_groups_resp
|
||||||
- created_at: created
|
- created_at: created
|
||||||
- updated_at: updated
|
- updated_at: updated
|
||||||
- links: links
|
- links: links
|
||||||
|
|
||||||
**Example response: list all device profiles**
|
**Example response: list all device profiles**
|
||||||
|
|
||||||
.. literalinclude:: ../../doc/api_samples/device_profiles/device_profiles-list-resp.json
|
.. literalinclude:: ../../doc/api_samples/device_profiles/device_profiles-list-resp.json
|
||||||
:language: javascript
|
:language: javascript
|
||||||
|
|
||||||
Get One Device Profile
|
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
|
Normal response codes: 200
|
||||||
|
|
||||||
Error response codes: badRequest(400), unauthorized(401), forbidden(403)
|
Error response codes: badRequest(400), unauthorized(401), forbidden(403)
|
||||||
|
|
||||||
Request
|
Request
|
||||||
=======
|
=======
|
||||||
.. rest_parameters:: parameters.yaml
|
.. 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
|
|
||||||
========
|
Response
|
||||||
.. rest_parameters:: parameters.yaml
|
========
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
- device_profile: device_profile
|
|
||||||
- name: device_prof_name_resp
|
- device_profile: device_profile
|
||||||
- uuid: device_profile_uuid
|
- name: device_prof_name_resp
|
||||||
- description: device_profile_description
|
- uuid: device_profile_uuid
|
||||||
- groups: device_prof_groups_resp
|
- description: device_profile_description
|
||||||
- created_at: created
|
- groups: device_prof_groups_resp
|
||||||
- updated_at: updated
|
- created_at: created
|
||||||
- links: links
|
- 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
|
|
||||||
:language: javascript
|
.. literalinclude:: ../../doc/api_samples/device_profiles/v22/device_profiles-getone-resp.json
|
||||||
|
:language: javascript
|
||||||
Create Device Profile
|
|
||||||
---------------------
|
Create Device Profile
|
||||||
|
---------------------
|
||||||
.. rest_method:: POST /v2/device_profiles
|
|
||||||
|
.. rest_method:: POST /v2/device_profiles
|
||||||
Creates a device profile. The payload should have these fields:
|
|
||||||
|
Creates a device profile. The payload should have these fields:
|
||||||
Normal response codes: 201
|
|
||||||
|
Normal response codes: 201
|
||||||
Error response codes: badRequest(400), unauthorized(401), forbidden(403),
|
|
||||||
conflict(409)
|
Error response codes: badRequest(400), unauthorized(401), forbidden(403),
|
||||||
|
conflict(409)
|
||||||
Request
|
|
||||||
=======
|
Request
|
||||||
.. rest_parameters:: parameters.yaml
|
=======
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
- name: device_prof_name_req
|
|
||||||
- groups: device_prof_groups_req
|
- name: device_prof_name_req
|
||||||
|
- groups: device_prof_groups_req
|
||||||
Response
|
|
||||||
========
|
Response
|
||||||
.. rest_parameters:: parameters.yaml
|
========
|
||||||
|
.. rest_parameters:: parameters.yaml
|
||||||
- name: device_prof_name_resp
|
|
||||||
- uuid: device_profile_uuid
|
- name: device_prof_name_resp
|
||||||
- description: device_profile_description
|
- uuid: device_profile_uuid
|
||||||
- groups: device_prof_groups_resp
|
- description: device_profile_description
|
||||||
- created_at: created
|
- groups: device_prof_groups_resp
|
||||||
- updated_at: updated
|
- created_at: created
|
||||||
- links: links
|
- updated_at: updated
|
||||||
|
- links: links
|
||||||
**Example post curl with resource/trait**
|
|
||||||
|
**Example post curl with resource/trait**
|
||||||
.. literalinclude:: ../../doc/api_samples/device_profiles/device_profiles-post-curl.json
|
|
||||||
:language: javascript
|
.. literalinclude:: ../../doc/api_samples/device_profiles/device_profiles-post-curl.json
|
||||||
|
:language: javascript
|
||||||
**Example post curl with a cyborg property when bitstream is required**
|
|
||||||
|
**Example post curl with a cyborg property when bitstream is required**
|
||||||
.. literalinclude:: ../../doc/api_samples/device_profiles/device_profiles-post-curl-with-bitstream.json
|
|
||||||
:language: javascript
|
.. literalinclude:: ../../doc/api_samples/device_profiles/device_profiles-post-curl-with-bitstream.json
|
||||||
|
:language: javascript
|
||||||
**Example response: create a device profile**
|
|
||||||
|
**Example response: create a device profile**
|
||||||
.. literalinclude:: ../../doc/api_samples/device_profiles/device_profiles-create-resp.json
|
|
||||||
:language: javascript
|
.. literalinclude:: ../../doc/api_samples/device_profiles/device_profiles-create-resp.json
|
||||||
|
:language: javascript
|
||||||
Delete One Device Profile by uuid
|
|
||||||
---------------------------------
|
Delete One Device Profile by uuid
|
||||||
|
---------------------------------
|
||||||
.. rest_method:: DELETE /v2/device_profiles/{device_profile_uuid}
|
|
||||||
|
.. rest_method:: DELETE /v2/device_profiles/{device_profile_uuid}
|
||||||
Delete a device profile. No query parameters required.
|
|
||||||
|
Delete a device profile. No query parameters required.
|
||||||
Delete Multiple Device Profiles by names
|
|
||||||
----------------------------------------
|
Delete Multiple Device Profiles by names
|
||||||
|
----------------------------------------
|
||||||
.. rest_method:: DELETE /v2/device_profiles?value={device_profile_name1},{device_profile_name2}
|
|
||||||
|
.. rest_method:: DELETE /v2/device_profiles?value={device_profile_name1},{device_profile_name2}
|
||||||
In the URL, Device profiles to be deleted should be in comma-delimited list of
|
|
||||||
device profile names.
|
In the URL, Device profiles to be deleted should be in comma-delimited list of
|
||||||
|
device profile names.
|
||||||
.. note::
|
|
||||||
Today we do not allow deletion of a device profile when it is in use by
|
.. note::
|
||||||
VMs, because ARQs have a foreign key on device profile table. But we copy
|
Today we do not allow deletion of a device profile when it is in use by
|
||||||
the device profile groups into the ARQ, so this foreign key is not needed.
|
VMs, because ARQs have a foreign key on device profile table. But we copy
|
||||||
So we can improve in Ussuri.
|
the device profile groups into the ARQ, so this foreign key is not needed.
|
||||||
|
So we can improve in Ussuri.
|
||||||
Response
|
|
||||||
========
|
Response
|
||||||
|
========
|
||||||
Normal response codes: 204
|
|
||||||
|
Normal response codes: 204
|
||||||
There is no body content for the response of a successful DELETE query
|
|
||||||
|
There is no body content for the response of a successful DELETE query
|
||||||
|
|
|
@ -12,13 +12,28 @@ deployable_uuid:
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
device_profile_uuid:
|
device_profile_name_or_uuid:
|
||||||
description: |
|
description: |
|
||||||
The UUID of the device_profile for your accelerator request.
|
The name or uuid of the device_profile for your accelerator request.
|
||||||
This must be a valid UUID otherwise API will return 400.
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
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:
|
device_uuid:
|
||||||
description: |
|
description: |
|
||||||
The UUID of the device.
|
The UUID of the device.
|
||||||
|
|
|
@ -23,13 +23,16 @@ from wsme import types as wtypes
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
from cyborg import api
|
||||||
from cyborg.api.controllers import base
|
from cyborg.api.controllers import base
|
||||||
from cyborg.api.controllers import link
|
from cyborg.api.controllers import link
|
||||||
from cyborg.api.controllers import types
|
from cyborg.api.controllers import types
|
||||||
|
from cyborg.api.controllers.v2 import versions
|
||||||
from cyborg.api import expose
|
from cyborg.api import expose
|
||||||
from cyborg.common import authorize_wsgi
|
from cyborg.common import authorize_wsgi
|
||||||
from cyborg.common import constants
|
from cyborg.common import constants
|
||||||
from cyborg.common import exception
|
from cyborg.common import exception
|
||||||
|
from cyborg.common.i18n import _
|
||||||
from cyborg import objects
|
from cyborg import objects
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -257,21 +260,33 @@ class DeviceProfilesController(base.CyborgController,
|
||||||
|
|
||||||
@authorize_wsgi.authorize_wsgi("cyborg:device_profile", "get_one")
|
@authorize_wsgi.authorize_wsgi("cyborg:device_profile", "get_one")
|
||||||
@expose.expose('json', wtypes.text)
|
@expose.expose('json', wtypes.text)
|
||||||
def get_one(self, uuid):
|
def get_one(self, dp_uuid_or_name):
|
||||||
"""Retrieve a single device profile by uuid."""
|
"""Retrieve a single device profile by uuid or name."""
|
||||||
LOG.info('[device_profiles] get_one. uuid=%s', uuid)
|
context = pecan.request.context
|
||||||
obj_devprofs = self._get_device_profile_list(uuid=uuid)
|
if uuidutils.is_uuid_like(dp_uuid_or_name):
|
||||||
api_obj_devprofs = self.get_device_profiles(obj_devprofs)
|
LOG.info('[device_profiles] get_one. uuid=%s', dp_uuid_or_name)
|
||||||
if len(api_obj_devprofs) == 0:
|
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(
|
raise exception.ResourceNotFound(
|
||||||
resource='Device profile',
|
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)
|
ret = {"device_profile": api_obj_devprof}
|
||||||
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]}
|
|
||||||
LOG.info('[device_profiles] get_one returned: %s', ret)
|
LOG.info('[device_profiles] get_one returned: %s', ret)
|
||||||
# TODO(Sundar) Replace this with convert_with_links()
|
# TODO(Sundar) Replace this with convert_with_links()
|
||||||
return wsme.api.Response(ret, status_code=HTTPStatus.OK,
|
return wsme.api.Response(ret, status_code=HTTPStatus.OK,
|
||||||
|
|
|
@ -24,8 +24,10 @@ BASE_VERSION = 2
|
||||||
#
|
#
|
||||||
# v2.0: Initial minor version.
|
# v2.0: Initial minor version.
|
||||||
# v2.1: Add project_id for arq patch
|
# 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_0_INITIAL_VERSION = 0
|
||||||
MINOR_1_PROJECT_ID = 1
|
MINOR_1_PROJECT_ID = 1
|
||||||
|
MINOR_2_DP_BY_NAME = 2
|
||||||
|
|
||||||
|
|
||||||
# When adding another version, update:
|
# When adding another version, update:
|
||||||
|
@ -34,7 +36,7 @@ MINOR_1_PROJECT_ID = 1
|
||||||
# explanation of what changed in the new version
|
# 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
|
# String representations of the minor and maximum versions
|
||||||
_MIN_VERSION_STRING = '{}.{}'.format(BASE_VERSION, MINOR_0_INITIAL_VERSION)
|
_MIN_VERSION_STRING = '{}.{}'.format(BASE_VERSION, MINOR_0_INITIAL_VERSION)
|
||||||
|
|
|
@ -27,3 +27,11 @@ microversions.
|
||||||
Add ``project_id`` for Accelerator Requests PATCH API. ``project_id`` is
|
Add ``project_id`` for Accelerator Requests PATCH API. ``project_id`` is
|
||||||
used to control the operation of arq with different roles.
|
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}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import webtest
|
||||||
|
|
||||||
from oslo_serialization import jsonutils
|
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.api.controllers.v2 import base as v2_test
|
||||||
from cyborg.tests.unit import fake_device_profile
|
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
|
# Check that the link is properly set up
|
||||||
self._validate_links(out_dp['links'], in_dp['uuid'])
|
self._validate_links(out_dp['links'], in_dp['uuid'])
|
||||||
|
|
||||||
@mock.patch('cyborg.objects.DeviceProfile.list')
|
@mock.patch('cyborg.objects.DeviceProfile.get_by_uuid')
|
||||||
def test_get_one_by_uuid(self, mock_dp):
|
def test_get_one_by_uuid(self, mock_dp_uuid):
|
||||||
dp = self.fake_dp_objs[0]
|
dp = self.fake_dp_objs[0]
|
||||||
mock_dp.return_value = [dp]
|
mock_dp_uuid.return_value = dp
|
||||||
url = self.DP_URL + '/%s'
|
url = self.DP_URL + '/%s'
|
||||||
data = self.get_json(url % dp['uuid'], headers=self.headers)
|
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']
|
out_dp = data['device_profile']
|
||||||
self._validate_dp(dp, out_dp)
|
self._validate_dp(dp, out_dp)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"description": "",
|
"description": "",
|
||||||
"groups":[
|
"groups":[
|
||||||
{
|
{
|
||||||
"trait:CUSTOM_CHENKE_TRAITS":"required",
|
"trait:CUSTOM_FPGA_INSPUR":"required",
|
||||||
"resources:FPGA":"1",
|
"resources:FPGA":"1",
|
||||||
"accel:bitstream_id":"d5ca2f11-3108-4426-a11c-a959987565df"
|
"accel:bitstream_id":"d5ca2f11-3108-4426-a11c-a959987565df"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -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}
|
Loading…
Reference in New Issue