Merge "accelerator: Add device status field and enable/disable support"

This commit is contained in:
Zuul authored and Gerrit Code Review committed 2026-09-24 12:38:25 +00:00
commit 533fb5eb4b
5 files changed
+109 -1

No files matched your search

+20
View File
@@ -141,6 +141,26 @@ class Proxy(proxy.Proxy):
return self._get(_device.Device, device)
def enable_device(self, device: str | _device.Device) -> _device.Device:
"""Enable a device.
:param device: The value can be the ID of a device or a
:class:`~openstack.accelerator.v2.device.Device` instance.
:returns: The updated device.
"""
res = self._get_resource(_device.Device, device)
return res.enable(self)
def disable_device(self, device: str | _device.Device) -> _device.Device:
"""Disable a device.
:param device: The value can be the ID of a device or a
:class:`~openstack.accelerator.v2.device.Device` instance.
:returns: The updated device.
"""
res = self._get_resource(_device.Device, device)
return res.disable(self)
# ====== Device Profiles ======
def device_profiles(
+19
View File
@@ -9,7 +9,12 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from typing import Self
from keystoneauth1 import adapter
from openstack import resource
from openstack import utils
class Device(resource.Resource):
@@ -30,6 +35,8 @@ class Device(resource.Resource):
id = resource.Body('id')
#: The model of the device.
model = resource.Body('model')
#: The status of the device.
status = resource.Body('status')
#: The std board information of the device.
std_board_info = resource.Body('std_board_info')
#: The type of the device.
@@ -42,3 +49,15 @@ class Device(resource.Resource):
vendor = resource.Body('vendor')
#: The vendor board information of the device.
vendor_board_info = resource.Body('vendor_board_info')
def enable(self, session: adapter.Adapter) -> Self:
"""Enable the device."""
url = utils.urljoin(Device.base_path, self.id, 'enable')
session.post(url)
return self
def disable(self, session: adapter.Adapter) -> Self:
"""Disable the device."""
url = utils.urljoin(Device.base_path, self.id, 'disable')
session.post(url)
return self
@@ -12,6 +12,7 @@
from openstack.accelerator.v2 import device as _device
from openstack.tests.functional import base
from openstack import utils
class TestDevice(base.BaseFunctionalTest):
@@ -24,7 +25,20 @@ class TestDevice(base.BaseFunctionalTest):
def setUp(self):
super().setUp()
self.require_service('accelerator')
self.require_service('accelerator', min_microversion='2.3')
self._set_operator_cloud(accelerator_default_microversion='2.3')
def _wait_for_device_status(self, device_id, expected_status):
for _ in utils.iterate_timeout(
30,
(
f'Timeout waiting for device {device_id} '
f'to become {expected_status}'
),
):
device = self.operator_cloud.accelerator.get_device(device_id)
if device.status == expected_status:
return device
def test_device(self):
# List
@@ -40,3 +54,18 @@ class TestDevice(base.BaseFunctionalTest):
device = self.operator_cloud.accelerator.get_device(devices[0].uuid)
self.assertIsInstance(device, _device.Device)
self.assertEqual(devices[0].uuid, device.uuid)
self.assertIsNotNone(device.status)
# Disable
self.addCleanup(
self.operator_cloud.accelerator.enable_device,
device.id,
)
self.operator_cloud.accelerator.disable_device(device.id)
disabled = self._wait_for_device_status(device.id, 'maintaining')
self.assertEqual('maintaining', disabled.status)
# Enable
self.operator_cloud.accelerator.enable_device(device.id)
enabled = self._wait_for_device_status(device.id, 'enabled')
self.assertEqual('enabled', enabled.status)
@@ -11,6 +11,7 @@
# under the License.
from typing import Any
from unittest import mock
import uuid
from openstack.accelerator.v2 import device
@@ -25,6 +26,7 @@ EXAMPLE: dict[str, Any] = {
'type': 'test_type',
'vendor': '0x8086',
'model': 'test_model',
'status': 'enabled',
'std_board_info': '{"product_id": "0x09c4"}',
'vendor_board_info': 'test_vb_info',
}
@@ -49,7 +51,22 @@ class TestDevice(base.TestCase):
self.assertEqual(EXAMPLE['type'], sot.type)
self.assertEqual(EXAMPLE['vendor'], sot.vendor)
self.assertEqual(EXAMPLE['model'], sot.model)
self.assertEqual(EXAMPLE['status'], sot.status)
self.assertEqual(EXAMPLE['std_board_info'], sot.std_board_info)
self.assertEqual(EXAMPLE['vendor_board_info'], sot.vendor_board_info)
self.assertEqual(EXAMPLE['created_at'], sot.created_at)
self.assertEqual(EXAMPLE['updated_at'], sot.updated_at)
def test_enable(self):
sess = mock.Mock()
sot = device.Device(uuid='device-uuid')
self.assertIs(sot, sot.enable(sess))
sess.post.assert_called_once_with('devices/device-uuid/enable')
def test_disable(self):
sess = mock.Mock()
sot = device.Device(uuid='device-uuid')
self.assertIs(sot, sot.disable(sess))
sess.post.assert_called_once_with('devices/device-uuid/disable')
@@ -14,6 +14,7 @@ from openstack.accelerator.v2 import _proxy
from openstack.accelerator.v2 import accelerator_request
from openstack.accelerator.v2 import attribute
from openstack.accelerator.v2 import deployable
from openstack.accelerator.v2 import device
from openstack.accelerator.v2 import device_profile
from openstack.tests.unit import test_proxy_base as test_proxy_base
@@ -30,6 +31,28 @@ class TestAcceleratorDeployable(TestAcceleratorProxy):
class TestAcceleratorDevice(TestAcceleratorProxy):
def test_list_device(self):
self.verify_list(self.proxy.devices, device.Device)
def test_get_device(self):
self.verify_get(self.proxy.get_device, device.Device)
def test_enable_device(self):
self._verify(
'openstack.accelerator.v2.device.Device.enable',
self.proxy.enable_device,
method_args=['value'],
expected_args=[self.proxy],
)
def test_disable_device(self):
self._verify(
'openstack.accelerator.v2.device.Device.disable',
self.proxy.disable_device,
method_args=['value'],
expected_args=[self.proxy],
)
def test_list_device_profile(self):
self.verify_list(
self.proxy.device_profiles, device_profile.DeviceProfile