Merge "Fix volume deletion on newer iDRACs"
This commit is contained in:
commit
3f6f693ee8
|
@ -0,0 +1,4 @@
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fixes 'Unsupported parameter name @Redfish.OperationApplyTime' error
|
||||||
|
on iDRAC firmware version 6.00.02.00 or newer when deleting volumes.
|
|
@ -136,8 +136,22 @@ class Volume(base.ResourceBase):
|
||||||
if (payload and payload.get(_OAT_PROP)
|
if (payload and payload.get(_OAT_PROP)
|
||||||
== res_cons.ApplyTime.IMMEDIATE.value):
|
== res_cons.ApplyTime.IMMEDIATE.value):
|
||||||
blocking = True
|
blocking = True
|
||||||
r = self._conn.delete(self._path, data=payload, blocking=blocking,
|
try:
|
||||||
timeout=timeout)
|
r = self._conn.delete(self._path, data=payload,
|
||||||
|
blocking=blocking, timeout=timeout)
|
||||||
|
except exceptions.ServerSideError as exc:
|
||||||
|
if (_OAT_PROP in str(exc.message)
|
||||||
|
and 'SYS029' in str(exc.message)):
|
||||||
|
LOG.debug('Retry volume delete without %(prop)s for %(path)s '
|
||||||
|
'because got error: %(err)s',
|
||||||
|
{'prop': _OAT_PROP,
|
||||||
|
'path': self._path,
|
||||||
|
'err': exc})
|
||||||
|
payload.pop(_OAT_PROP)
|
||||||
|
r = self._conn.delete(self._path, data=payload,
|
||||||
|
blocking=blocking, timeout=timeout)
|
||||||
|
else:
|
||||||
|
raise exc
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def delete(self, payload=None, apply_time=None, timeout=500):
|
def delete(self, payload=None, apply_time=None, timeout=500):
|
||||||
|
|
|
@ -16,6 +16,7 @@ from unittest import mock
|
||||||
from dateutil import parser
|
from dateutil import parser
|
||||||
|
|
||||||
import sushy
|
import sushy
|
||||||
|
from sushy import exceptions
|
||||||
from sushy.resources import constants as res_cons
|
from sushy.resources import constants as res_cons
|
||||||
from sushy.resources.system.storage import constants as store_cons
|
from sushy.resources.system.storage import constants as store_cons
|
||||||
from sushy.resources.system.storage import volume
|
from sushy.resources.system.storage import volume
|
||||||
|
@ -106,6 +107,84 @@ class VolumeTestCase(base.TestCase):
|
||||||
self.assertEqual(task_mon.task_monitor_uri,
|
self.assertEqual(task_mon.task_monitor_uri,
|
||||||
'/redfish/v1/taskmon/4608f7e6')
|
'/redfish/v1/taskmon/4608f7e6')
|
||||||
|
|
||||||
|
@mock.patch.object(volume.LOG, 'debug', autospec=True)
|
||||||
|
def test_delete_retry_on_501_sys029_apply_time(self, mock_debug):
|
||||||
|
payload = {}
|
||||||
|
_OAT_PROP = '@Redfish.OperationApplyTime'
|
||||||
|
payload[_OAT_PROP] = 'Immediate'
|
||||||
|
target_uri = '/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1'
|
||||||
|
response_info = {"error": {"@Message.ExtendedInfo": [
|
||||||
|
{'Message': '@Redfish.OperationApplyTime.',
|
||||||
|
'MessageId': 'IDRAC.2.7.SYS029'}]}}
|
||||||
|
mock_error = mock.Mock()
|
||||||
|
mock_error.status_code = 501
|
||||||
|
mock_error.json.return_value = response_info
|
||||||
|
mock_success = mock.Mock()
|
||||||
|
mock_success.status_code = 201
|
||||||
|
self.conn.delete.side_effect = [exceptions.ServerSideError(
|
||||||
|
method='DELETE', url=target_uri, response=mock_error),
|
||||||
|
mock_success]
|
||||||
|
|
||||||
|
resource = self.stor_volume.delete(
|
||||||
|
payload=payload, apply_time=res_cons.ApplyTime.IMMEDIATE)
|
||||||
|
|
||||||
|
self.assertIsNone(resource)
|
||||||
|
self.assertEqual(2, self.stor_volume._conn.delete.call_count)
|
||||||
|
expected_calls = [
|
||||||
|
mock.call(self.stor_volume._path, data=payload, blocking=True,
|
||||||
|
timeout=500),
|
||||||
|
mock.call(self.stor_volume._path, data={}, blocking=True,
|
||||||
|
timeout=500)
|
||||||
|
]
|
||||||
|
self.stor_volume._conn.delete.assert_has_calls(expected_calls)
|
||||||
|
mock_debug.assert_called_once()
|
||||||
|
|
||||||
|
@mock.patch.object(volume.LOG, 'debug', autospec=True)
|
||||||
|
def test_delete_retry_on_501_sys029_other(self, mock_debug):
|
||||||
|
payload = {}
|
||||||
|
_OAT_PROP = '@Redfish.OperationApplyTime'
|
||||||
|
payload[_OAT_PROP] = 'Immediate'
|
||||||
|
target_uri = '/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1'
|
||||||
|
response_info = {"error": {"@Message.ExtendedInfo": [
|
||||||
|
{'Message': '@Redfish.SomethingElse.',
|
||||||
|
'MessageId': 'IDRAC.2.7.SYS029'}]}}
|
||||||
|
mock_error = mock.Mock()
|
||||||
|
mock_error.status_code = 501
|
||||||
|
mock_error.json.return_value = response_info
|
||||||
|
mock_success = mock.Mock()
|
||||||
|
mock_success.status_code = 201
|
||||||
|
self.conn.delete.side_effect = [exceptions.ServerSideError(
|
||||||
|
method='DELETE', url=target_uri, response=mock_error),
|
||||||
|
mock_success]
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.ServerSideError, self.stor_volume.delete,
|
||||||
|
payload=payload,
|
||||||
|
apply_time=res_cons.ApplyTime.IMMEDIATE)
|
||||||
|
self.stor_volume._conn.delete.assert_called_once_with(
|
||||||
|
self.stor_volume._path, data=payload, blocking=True, timeout=500)
|
||||||
|
mock_debug.assert_not_called()
|
||||||
|
|
||||||
|
@mock.patch.object(volume.LOG, 'debug', autospec=True)
|
||||||
|
def test_delete_raise_on_501_other(self, mock_debug):
|
||||||
|
payload = {}
|
||||||
|
_OAT_PROP = '@Redfish.OperationApplyTime'
|
||||||
|
payload[_OAT_PROP] = 'Immediate'
|
||||||
|
target_uri = '/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1'
|
||||||
|
response_info = {"error": {"@Message.ExtendedInfo": [
|
||||||
|
{'Message': 'Other message.'}]}}
|
||||||
|
mock_error = mock.Mock()
|
||||||
|
mock_error.status_code = 501
|
||||||
|
mock_error.json.return_value = response_info
|
||||||
|
self.conn.delete.side_effect = [exceptions.ServerSideError(
|
||||||
|
method='DELETE', url=target_uri, response=mock_error)]
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.ServerSideError, self.stor_volume.delete,
|
||||||
|
payload=payload,
|
||||||
|
apply_time=res_cons.ApplyTime.IMMEDIATE)
|
||||||
|
self.stor_volume._conn.delete.assert_called_once_with(
|
||||||
|
self.stor_volume._path, data=payload, blocking=True, timeout=500)
|
||||||
|
mock_debug.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
class VolumeCollectionTestCase(base.TestCase):
|
class VolumeCollectionTestCase(base.TestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue