Add ARQ_UNBIND_FAILED status for ARQ
When we unbind ARQ faild, we should set ARQ status to ARQ_UNBIND_FAILED. Add try except for unbind ARQ operation. Depends-On: https://review.opendev.org/c/openstack/cyborg/+/833529 Change-Id: I9a04b63a8ac7f20a0265f604eabc4107a40010b2
This commit is contained in:
parent
82d1ed968b
commit
82255a0e09
|
@ -24,13 +24,15 @@ DEVICE_NIC = 'NIC'
|
||||||
|
|
||||||
|
|
||||||
ARQ_STATES = (ARQ_INITIAL, ARQ_BIND_STARTED, ARQ_BOUND, ARQ_UNBOUND,
|
ARQ_STATES = (ARQ_INITIAL, ARQ_BIND_STARTED, ARQ_BOUND, ARQ_UNBOUND,
|
||||||
ARQ_BIND_FAILED, ARQ_DELETING) = (
|
ARQ_BIND_FAILED, ARQ_UNBIND_FAILED, ARQ_DELETING) = (
|
||||||
'Initial', 'BindStarted', 'Bound', 'Unbound', 'BindFailed', 'Deleting')
|
'Initial', 'BindStarted', 'Bound', 'Unbound', 'BindFailed', 'UnbindFailed',
|
||||||
|
'Deleting')
|
||||||
|
|
||||||
|
|
||||||
ARQ_BIND_STAGE = (ARQ_PRE_BIND, ARQ_FINISH_BIND,
|
ARQ_BIND_STAGE = (ARQ_PRE_BIND, ARQ_FINISH_BIND,
|
||||||
ARQ_OUFOF_BIND_FLOW) = (
|
ARQ_OUFOF_BIND_FLOW) = (
|
||||||
[ARQ_INITIAL, ARQ_BIND_STARTED], [ARQ_BOUND, ARQ_BIND_FAILED],
|
[ARQ_INITIAL, ARQ_BIND_STARTED],
|
||||||
|
[ARQ_BOUND, ARQ_BIND_FAILED],
|
||||||
[ARQ_UNBOUND, ARQ_DELETING])
|
[ARQ_UNBOUND, ARQ_DELETING])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -198,7 +198,7 @@ class ExtARQ(base.CyborgObject, object_base.VersionedObjectDictCompat,
|
||||||
self.update_check_state(
|
self.update_check_state(
|
||||||
context, constants.ARQ_BIND_FAILED)
|
context, constants.ARQ_BIND_FAILED)
|
||||||
raise
|
raise
|
||||||
LOG.info('Attach handle(%s) for ARQ(%s) successfully.',
|
LOG.info('Attach handle(%s) allocate for ARQ(%s) successfully.',
|
||||||
ah.uuid, self.arq.uuid)
|
ah.uuid, self.arq.uuid)
|
||||||
|
|
||||||
def bind(self, context, deployable):
|
def bind(self, context, deployable):
|
||||||
|
@ -211,6 +211,19 @@ class ExtARQ(base.CyborgObject, object_base.VersionedObjectDictCompat,
|
||||||
# if (self.arq.state == constants.ARQ_DELETING
|
# if (self.arq.state == constants.ARQ_DELETING
|
||||||
# or self.arq.state == ARQ_UNBOUND):
|
# or self.arq.state == ARQ_UNBOUND):
|
||||||
|
|
||||||
|
def _deallocate_attach_handle(self, context, ah_id):
|
||||||
|
try:
|
||||||
|
attach_handle = AttachHandle.get_by_id(context, ah_id)
|
||||||
|
attach_handle.deallocate(context)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.error("Failed to deallocate attach handle %s for ARQ %s."
|
||||||
|
"Reason: %s", ah_id, self.arq.uuid, str(e))
|
||||||
|
self.update_check_state(
|
||||||
|
context, constants.ARQ_UNBIND_FAILED)
|
||||||
|
raise
|
||||||
|
LOG.info('Attach handle(%s) deallocate for ARQ(%s) successfully.',
|
||||||
|
ah_id, self.arq.uuid)
|
||||||
|
|
||||||
def unbind(self, context):
|
def unbind(self, context):
|
||||||
arq = self.arq
|
arq = self.arq
|
||||||
arq.hostname = None
|
arq.hostname = None
|
||||||
|
@ -221,8 +234,7 @@ class ExtARQ(base.CyborgObject, object_base.VersionedObjectDictCompat,
|
||||||
# Unbind: mark attach handles as freed
|
# Unbind: mark attach handles as freed
|
||||||
ah_id = self.attach_handle_id
|
ah_id = self.attach_handle_id
|
||||||
if ah_id:
|
if ah_id:
|
||||||
attach_handle = AttachHandle.get_by_id(context, ah_id)
|
self._deallocate_attach_handle(context, ah_id)
|
||||||
attach_handle.deallocate(context)
|
|
||||||
self.attach_handle_id = None
|
self.attach_handle_id = None
|
||||||
self.save(context)
|
self.save(context)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
# Copyright 2021 Inspur.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# 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 oslo_utils import uuidutils
|
||||||
|
|
||||||
|
from cyborg import objects
|
||||||
|
from cyborg.objects import attach_handle
|
||||||
|
from cyborg.objects import fields
|
||||||
|
|
||||||
|
|
||||||
|
def get_fake_attach_handle_as_dict():
|
||||||
|
attach_handle1 = {
|
||||||
|
'id': 1,
|
||||||
|
'uuid': uuidutils.generate_uuid(),
|
||||||
|
'in_use': 0,
|
||||||
|
'cp_id': 1,
|
||||||
|
'deployable_id': 1,
|
||||||
|
'attach_type': "PCI",
|
||||||
|
'attach_info': '{"domain": "0000", "bus": "0c",'
|
||||||
|
'"device": "0", "function": "1"}',
|
||||||
|
}
|
||||||
|
|
||||||
|
attach_handle2 = {
|
||||||
|
'id': 2,
|
||||||
|
'uuid': uuidutils.generate_uuid(),
|
||||||
|
'in_use': 1,
|
||||||
|
'cp_id': 2,
|
||||||
|
'deployable_id': 2,
|
||||||
|
'attach_type': "PCI",
|
||||||
|
'attach_info': '{"domain": "0000", "bus": "0c",'
|
||||||
|
'"device": "0", "function": "1"}',
|
||||||
|
}
|
||||||
|
|
||||||
|
return [attach_handle1, attach_handle2]
|
||||||
|
|
||||||
|
|
||||||
|
def _convert_from_dict_to_obj(ah_dict):
|
||||||
|
obj_ah = attach_handle.AttachHandle()
|
||||||
|
for field in ah_dict.keys():
|
||||||
|
obj_ah[field] = ah_dict[field]
|
||||||
|
return obj_ah
|
||||||
|
|
||||||
|
|
||||||
|
def _convert_to_db_ah(ah_dict):
|
||||||
|
for name, field in objects.AttachHandle.fields.items():
|
||||||
|
if name in ah_dict:
|
||||||
|
continue
|
||||||
|
if field.nullable:
|
||||||
|
ah_dict[name] = None
|
||||||
|
elif field.default != fields.UnspecifiedDefault:
|
||||||
|
ah_dict[name] = field.default
|
||||||
|
else:
|
||||||
|
raise Exception('fake_db_attach_handle needs help with %s' % name)
|
||||||
|
return ah_dict
|
||||||
|
|
||||||
|
|
||||||
|
def get_db_attach_handles():
|
||||||
|
ahs_list = get_fake_attach_handle_as_dict()
|
||||||
|
db_ahs = list(map(_convert_to_db_ah, ahs_list))
|
||||||
|
return db_ahs
|
||||||
|
|
||||||
|
|
||||||
|
def get_fake_attach_handle_objs():
|
||||||
|
ahs_list = get_fake_attach_handle_as_dict()
|
||||||
|
obj_ahs = list(map(_convert_from_dict_to_obj, ahs_list))
|
||||||
|
return obj_ahs
|
|
@ -21,6 +21,7 @@ from cyborg.common import constants
|
||||||
from cyborg.common import exception
|
from cyborg.common import exception
|
||||||
from cyborg import objects
|
from cyborg import objects
|
||||||
from cyborg.tests.unit.db import base
|
from cyborg.tests.unit.db import base
|
||||||
|
from cyborg.tests.unit import fake_attach_handle
|
||||||
from cyborg.tests.unit import fake_deployable
|
from cyborg.tests.unit import fake_deployable
|
||||||
from cyborg.tests.unit import fake_device_profile
|
from cyborg.tests.unit import fake_device_profile
|
||||||
from cyborg.tests.unit import fake_extarq
|
from cyborg.tests.unit import fake_extarq
|
||||||
|
@ -33,6 +34,7 @@ class TestExtARQObject(base.DbTestCase):
|
||||||
self.fake_db_extarqs = fake_extarq.get_fake_db_extarqs()
|
self.fake_db_extarqs = fake_extarq.get_fake_db_extarqs()
|
||||||
self.fake_obj_extarqs = fake_extarq.get_fake_extarq_objs()
|
self.fake_obj_extarqs = fake_extarq.get_fake_extarq_objs()
|
||||||
self.fake_obj_fpga_extarqs = fake_extarq.get_fake_fpga_extarq_objs()
|
self.fake_obj_fpga_extarqs = fake_extarq.get_fake_fpga_extarq_objs()
|
||||||
|
self.fake_obj_ahs = fake_attach_handle.get_fake_attach_handle_objs()
|
||||||
self.deployable_uuids = ['0acbf8d6-e02a-4394-aae3-57557d209498']
|
self.deployable_uuids = ['0acbf8d6-e02a-4394-aae3-57557d209498']
|
||||||
|
|
||||||
@mock.patch('cyborg.objects.ExtARQ._from_db_object')
|
@mock.patch('cyborg.objects.ExtARQ._from_db_object')
|
||||||
|
@ -334,6 +336,39 @@ class TestExtARQObject(base.DbTestCase):
|
||||||
obj_extarq._allocate_attach_handle, self.context, fake_dep)
|
obj_extarq._allocate_attach_handle, self.context, fake_dep)
|
||||||
mock_log.assert_called_once_with(
|
mock_log.assert_called_once_with(
|
||||||
msg, obj_extarq.arq.uuid, fake_dep.uuid, str(e))
|
msg, obj_extarq.arq.uuid, fake_dep.uuid, str(e))
|
||||||
|
mock_check_state.assert_called_once_with(
|
||||||
|
self.context, constants.ARQ_BIND_FAILED)
|
||||||
|
|
||||||
|
@mock.patch('cyborg.objects.ExtARQ.update_check_state')
|
||||||
|
@mock.patch('cyborg.objects.attach_handle.AttachHandle.get_by_id')
|
||||||
|
@mock.patch('cyborg.objects.attach_handle.AttachHandle.deallocate')
|
||||||
|
def test_deallocate_attach_handle(
|
||||||
|
self, mock_deallocate, mock_ah, mock_check_state):
|
||||||
|
obj_extarq = self.fake_obj_extarqs[0]
|
||||||
|
mock_ah.return_value = self.fake_obj_ahs[0]
|
||||||
|
obj_extarq._deallocate_attach_handle(self.context, mock_ah.id)
|
||||||
|
mock_check_state.assert_not_called()
|
||||||
|
|
||||||
|
@mock.patch('logging.LoggerAdapter.error')
|
||||||
|
@mock.patch('cyborg.objects.ExtARQ.update_check_state')
|
||||||
|
@mock.patch('cyborg.objects.attach_handle.AttachHandle.get_by_id')
|
||||||
|
@mock.patch('cyborg.objects.attach_handle.AttachHandle.deallocate')
|
||||||
|
def test_deallocate_attach_handle_with_error_log(
|
||||||
|
self, mock_ah, mock_deallocate, mock_check_state, mock_log):
|
||||||
|
obj_extarq = self.fake_obj_extarqs[0]
|
||||||
|
mock_ah.return_value = self.fake_obj_ahs[0]
|
||||||
|
e = exception.ResourceNotFound(
|
||||||
|
resource='AttachHandle', msg="Just for Test")
|
||||||
|
msg = ("Failed to deallocate attach handle %s for ARQ %s."
|
||||||
|
"Reason: %s")
|
||||||
|
mock_deallocate.side_effect = e
|
||||||
|
self.assertRaises(
|
||||||
|
exception.ResourceNotFound,
|
||||||
|
obj_extarq._deallocate_attach_handle, self.context, mock_ah.id)
|
||||||
|
mock_log.assert_called_once_with(
|
||||||
|
msg, mock_ah.id, obj_extarq.arq.uuid, str(e))
|
||||||
|
mock_check_state.assert_called_once_with(
|
||||||
|
self.context, constants.ARQ_UNBIND_FAILED)
|
||||||
|
|
||||||
@mock.patch('cyborg.objects.ExtARQ.get')
|
@mock.patch('cyborg.objects.ExtARQ.get')
|
||||||
@mock.patch('cyborg.objects.ExtARQ._from_db_object')
|
@mock.patch('cyborg.objects.ExtARQ._from_db_object')
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add ``ARQ_UNBIND_FAILED`` status for Accelerator Requests (arq) unbind process. Nowdays the status is
|
||||||
|
needed to accurate record the arq status.
|
Loading…
Reference in New Issue