implementation of bp disable-enable-device

add disable and enable device api

Change-Id: I3d2f7ac3b8de29bc0c3125b7340d9a90cffa7127
This commit is contained in:
anguoming 2023-08-15 18:56:36 +08:00
parent 4d329240f9
commit 018f772c32
7 changed files with 93 additions and 2 deletions

View File

@ -16,6 +16,7 @@
import pecan
import wsme
from wsme import types as wtypes
from http import HTTPStatus
from oslo_log import log
@ -25,6 +26,8 @@ from cyborg.api.controllers import types
from cyborg.api import expose
from cyborg.common import authorize_wsgi
from cyborg import objects
from cyborg.common import placement_client
from cyborg.common import exception
LOG = log.getLogger(__name__)
@ -56,6 +59,9 @@ class Device(base.APIBase):
hostname = wtypes.text
"""The hostname of the device"""
status = wtypes.text
"""The status of the device"""
links = wsme.wsattr([link.Link], readonly=True)
"""A list containing a self link"""
@ -92,6 +98,11 @@ class DeviceCollection(base.APIBase):
class DevicesController(base.CyborgController):
"""REST controller for Devices."""
def __init__(self):
super(DevicesController, self).__init__()
self.placement_client = placement_client.PlacementClient()
_custom_actions = {'disable': ['POST'], 'enable': ['POST']}
@authorize_wsgi.authorize_wsgi("cyborg:device", "get_one")
@expose.expose(Device, wtypes.text)
@ -128,3 +139,47 @@ class DevicesController(base.CyborgController):
obj_devices = objects.Device.list(context, filters=filters_dict)
LOG.info('[devices:get_all] Returned: %s', obj_devices)
return DeviceCollection.convert_with_links(obj_devices)
@authorize_wsgi.authorize_wsgi("cyborg:device", "disable")
@expose.expose(None, wtypes.text, types.uuid,
status_code=HTTPStatus.OK)
def disable(self, uuid):
context = pecan.request.context
device = objects.Device.get(context, uuid)
device.status = 'maintaining'
device.save(context)
# update resource provider inventories
deployable = objects.Deployable.get_by_id(context, device.id)
filters = {'deployable_id': deployable.id, 'key': 'rc'}
attributes = objects.Attribute.get_by_filter(context, filters)
if attributes:
att_type = attributes[0].value
else:
raise exception.ResourceNotFound(
resource='Attribute',
msg='with deployable_id=%s,key=%s' % (deployable.id, 'rc'))
total = deployable.num_accelerators
update_inventories = {att_type: {"total": total, "reserved": total}}
self.placement_client.update_inventory(deployable.rp_uuid, update_inventories)
@authorize_wsgi.authorize_wsgi("cyborg:device", "enable")
@expose.expose(None, wtypes.text, types.uuid,
status_code=HTTPStatus.OK)
def enable(self, uuid):
context = pecan.request.context
device = objects.Device.get(context, uuid)
device.status = 'enabled'
device.save(context)
# update resource provider inventories
deployable = objects.Deployable.get_by_id(context, device.id)
filters = {'deployable_id': deployable.id, 'key': 'rc'}
attributes = objects.Attribute.get_by_filter(context, filters)
if attributes:
att_type = attributes[0].value
else:
raise exception.ResourceNotFound(
resource='Attribute',
msg='with deployable_id=%s,key=%s' % (deployable.id, 'rc'))
total = deployable.num_accelerators
update_inventories = {att_type: {"total": total, "reserved": 0}}
self.placement_client.update_inventory(deployable.rp_uuid, update_inventories)

View File

@ -66,6 +66,10 @@ DEVICE_TYPE = (DEVICE_GPU, DEVICE_FPGA, DEVICE_AICHIP, DEVICE_QAT, DEVICE_NIC,
DEVICE_SSD)
# Device type
DEVICE_STATUS = ("enabled", "maintaining")
# Attach handle type
# 'TEST_PCI': used by fake driver, ignored by Nova virt driver.
ATTACH_HANDLE_TYPES = (AH_TYPE_PCI, AH_TYPE_MDEV, AH_TYPE_TEST_PCI) = (

View File

@ -155,7 +155,7 @@ class PlacementClient(object):
'inventories': inventories
}
try:
return self.put(url, body).json()
return self.put(url, body, version='1.26').json()
except ks_exc.NotFound:
raise exception.PlacementResourceProviderNotFound(
resource_provider=resource_provider_uuid)

View File

@ -48,6 +48,12 @@ device_policies = [
policy.RuleDefault('cyborg:device:get_all',
'rule:allow',
description='Retrieve all device records'),
policy.RuleDefault('cyborg:device:disable',
'rule:admin_api',
description='Disable a device'),
policy.RuleDefault('cyborg:device:enable',
'rule:admin_api',
description='Enable a device'),
]
deployable_policies = [

View File

@ -0,0 +1,21 @@
"""add-device-status
Revision ID: 6c77bd6afea5
Revises: 4cc1d79978fc
Create Date: 2023-08-15 23:05:31.918963
"""
# revision identifiers, used by Alembic.
revision = '6c77bd6afea5'
down_revision = '4cc1d79978fc'
from alembic import op
import sqlalchemy as sa
def upgrade():
new_column = sa.Column('status', sa.Enum('enabled', 'maintaining'),
nullable=False, default='enabled')
op.add_column('devices', new_column)

View File

@ -88,6 +88,8 @@ class Device(Base):
std_board_info = Column(Text, nullable=True)
vendor_board_info = Column(Text, nullable=True)
hostname = Column(String(255), nullable=False)
status = Column(Enum("enabled", "maintaining", name='device_status'),
default='enabled', nullable=False)
class Deployable(Base):

View File

@ -29,7 +29,8 @@ LOG = logging.getLogger(__name__)
class Device(base.CyborgObject, object_base.VersionedObjectDictCompat):
# Version 1.0: Initial version
# Version 1.1: Add AICHIP, GENERIC type
VERSION = '1.1'
# Version 1.2: Add status field
VERSION = '1.2'
dbapi = dbapi.get_instance()
@ -43,6 +44,8 @@ class Device(base.CyborgObject, object_base.VersionedObjectDictCompat):
'std_board_info': object_fields.StringField(nullable=True),
'vendor_board_info': object_fields.StringField(nullable=True),
'hostname': object_fields.StringField(nullable=False),
'status': object_fields.EnumField(valid_values=constants.DEVICE_STATUS,
nullable=False, default="enabled"),
}
def create(self, context):