"Fossies" - the Fresh Open Source Software Archive

Member "ironic-16.0.3/ironic/tests/unit/drivers/modules/redfish/test_management.py" (18 Jan 2021, 55175 Bytes) of package /linux/misc/openstack/ironic-16.0.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "test_management.py": 16.0.2_vs_16.0.3.

    1 # Copyright 2017 Red Hat, Inc.
    2 # All Rights Reserved.
    3 #
    4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
    5 #    not use this file except in compliance with the License. You may obtain
    6 #    a copy of the License at
    7 #
    8 #         http://www.apache.org/licenses/LICENSE-2.0
    9 #
   10 #    Unless required by applicable law or agreed to in writing, software
   11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   13 #    License for the specific language governing permissions and limitations
   14 #    under the License.
   15 
   16 import datetime
   17 from unittest import mock
   18 
   19 from oslo_utils import importutils
   20 
   21 from ironic.common import boot_devices
   22 from ironic.common import boot_modes
   23 from ironic.common import components
   24 from ironic.common import exception
   25 from ironic.common import indicator_states
   26 from ironic.common import states
   27 from ironic.conductor import task_manager
   28 from ironic.conductor import utils as manager_utils
   29 from ironic.drivers.modules import deploy_utils
   30 from ironic.drivers.modules.redfish import management as redfish_mgmt
   31 from ironic.drivers.modules.redfish import utils as redfish_utils
   32 from ironic.tests.unit.db import base as db_base
   33 from ironic.tests.unit.db import utils as db_utils
   34 from ironic.tests.unit.objects import utils as obj_utils
   35 
   36 sushy = importutils.try_import('sushy')
   37 
   38 INFO_DICT = db_utils.get_test_redfish_info()
   39 
   40 
   41 class RedfishManagementTestCase(db_base.DbTestCase):
   42 
   43     def setUp(self):
   44         super(RedfishManagementTestCase, self).setUp()
   45         self.config(enabled_hardware_types=['redfish'],
   46                     enabled_power_interfaces=['redfish'],
   47                     enabled_boot_interfaces=['redfish-virtual-media'],
   48                     enabled_management_interfaces=['redfish'],
   49                     enabled_inspect_interfaces=['redfish'],
   50                     enabled_bios_interfaces=['redfish'])
   51         self.node = obj_utils.create_test_node(
   52             self.context, driver='redfish', driver_info=INFO_DICT)
   53 
   54         self.system_uuid = 'ZZZ--XXX-YYY'
   55         self.chassis_uuid = 'XXX-YYY-ZZZ'
   56         self.drive_uuid = 'ZZZ-YYY-XXX'
   57 
   58     @mock.patch.object(redfish_mgmt, 'sushy', None)
   59     def test_loading_error(self):
   60         self.assertRaisesRegex(
   61             exception.DriverLoadError,
   62             'Unable to import the sushy library',
   63             redfish_mgmt.RedfishManagement)
   64 
   65     def test_get_properties(self):
   66         with task_manager.acquire(self.context, self.node.uuid,
   67                                   shared=True) as task:
   68             properties = task.driver.get_properties()
   69             for prop in redfish_utils.COMMON_PROPERTIES:
   70                 self.assertIn(prop, properties)
   71 
   72     @mock.patch.object(redfish_utils, 'parse_driver_info', autospec=True)
   73     def test_validate(self, mock_parse_driver_info):
   74         with task_manager.acquire(self.context, self.node.uuid,
   75                                   shared=True) as task:
   76             task.driver.management.validate(task)
   77             mock_parse_driver_info.assert_called_once_with(task.node)
   78 
   79     def test_get_supported_boot_devices(self):
   80         with task_manager.acquire(self.context, self.node.uuid,
   81                                   shared=True) as task:
   82             supported_boot_devices = (
   83                 task.driver.management.get_supported_boot_devices(task))
   84             self.assertEqual(list(redfish_mgmt.BOOT_DEVICE_MAP_REV),
   85                              supported_boot_devices)
   86 
   87     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
   88     def test_set_boot_device(self, mock_get_system):
   89         fake_system = mock.Mock()
   90         mock_get_system.return_value = fake_system
   91         with task_manager.acquire(self.context, self.node.uuid,
   92                                   shared=False) as task:
   93             expected_values = [
   94                 (boot_devices.PXE, sushy.BOOT_SOURCE_TARGET_PXE),
   95                 (boot_devices.DISK, sushy.BOOT_SOURCE_TARGET_HDD),
   96                 (boot_devices.CDROM, sushy.BOOT_SOURCE_TARGET_CD),
   97                 (boot_devices.BIOS, sushy.BOOT_SOURCE_TARGET_BIOS_SETUP)
   98             ]
   99 
  100             for target, expected in expected_values:
  101                 task.driver.management.set_boot_device(task, target)
  102 
  103                 # Asserts
  104                 fake_system.set_system_boot_options.assert_has_calls(
  105                     [mock.call(expected,
  106                                enabled=sushy.BOOT_SOURCE_ENABLED_ONCE),
  107                      mock.call(mode=sushy.BOOT_SOURCE_MODE_BIOS)])
  108                 mock_get_system.assert_called_with(task.node)
  109                 self.assertNotIn('redfish_boot_device',
  110                                  task.node.driver_internal_info)
  111 
  112                 # Reset mocks
  113                 fake_system.set_system_boot_options.reset_mock()
  114                 mock_get_system.reset_mock()
  115 
  116     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  117     def test_set_boot_device_persistency(self, mock_get_system):
  118         fake_system = mock.Mock()
  119         mock_get_system.return_value = fake_system
  120         with task_manager.acquire(self.context, self.node.uuid,
  121                                   shared=False) as task:
  122             expected_values = [
  123                 (True, sushy.BOOT_SOURCE_ENABLED_CONTINUOUS),
  124                 (False, sushy.BOOT_SOURCE_ENABLED_ONCE)
  125             ]
  126 
  127             for target, expected in expected_values:
  128                 task.driver.management.set_boot_device(
  129                     task, boot_devices.PXE, persistent=target)
  130 
  131                 fake_system.set_system_boot_options.assert_has_calls(
  132                     [mock.call(sushy.BOOT_SOURCE_TARGET_PXE,
  133                                enabled=expected),
  134                      mock.call(mode=sushy.BOOT_SOURCE_MODE_BIOS)])
  135                 mock_get_system.assert_called_with(task.node)
  136                 self.assertNotIn('redfish_boot_device',
  137                                  task.node.driver_internal_info)
  138 
  139                 # Reset mocks
  140                 fake_system.set_system_boot_options.reset_mock()
  141                 mock_get_system.reset_mock()
  142 
  143     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  144     def test_set_boot_device_persistency_no_change(self, mock_get_system):
  145         fake_system = mock.Mock()
  146         mock_get_system.return_value = fake_system
  147         with task_manager.acquire(self.context, self.node.uuid,
  148                                   shared=False) as task:
  149             expected_values = [
  150                 (True, sushy.BOOT_SOURCE_ENABLED_CONTINUOUS),
  151                 (False, sushy.BOOT_SOURCE_ENABLED_ONCE)
  152             ]
  153 
  154             for target, expected in expected_values:
  155                 fake_system.boot.get.return_value = expected
  156 
  157                 task.driver.management.set_boot_device(
  158                     task, boot_devices.PXE, persistent=target)
  159 
  160                 fake_system.set_system_boot_options.assert_has_calls(
  161                     [mock.call(sushy.BOOT_SOURCE_TARGET_PXE, enabled=None),
  162                      mock.call(mode=sushy.BOOT_SOURCE_MODE_BIOS)])
  163                 mock_get_system.assert_called_with(task.node)
  164 
  165                 # Reset mocks
  166                 fake_system.set_system_boot_options.reset_mock()
  167                 mock_get_system.reset_mock()
  168 
  169     @mock.patch.object(sushy, 'Sushy', autospec=True)
  170     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  171     def test_set_boot_device_fail(self, mock_get_system, mock_sushy):
  172         fake_system = mock.Mock()
  173         fake_system.set_system_boot_options.side_effect = (
  174             sushy.exceptions.SushyError()
  175         )
  176         mock_get_system.return_value = fake_system
  177         with task_manager.acquire(self.context, self.node.uuid,
  178                                   shared=False) as task:
  179             self.assertRaisesRegex(
  180                 exception.RedfishError, 'Redfish set boot device',
  181                 task.driver.management.set_boot_device, task, boot_devices.PXE)
  182             fake_system.set_system_boot_options.assert_called_once_with(
  183                 sushy.BOOT_SOURCE_TARGET_PXE,
  184                 enabled=sushy.BOOT_SOURCE_ENABLED_ONCE)
  185             mock_get_system.assert_called_once_with(task.node)
  186             self.assertNotIn('redfish_boot_device',
  187                              task.node.driver_internal_info)
  188 
  189     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  190     def test_set_boot_device_fail_no_change(self, mock_get_system):
  191         fake_system = mock.Mock()
  192         fake_system.set_system_boot_options.side_effect = (
  193             sushy.exceptions.SushyError()
  194         )
  195         mock_get_system.return_value = fake_system
  196         with task_manager.acquire(self.context, self.node.uuid,
  197                                   shared=False) as task:
  198             expected_values = [
  199                 (True, sushy.BOOT_SOURCE_ENABLED_CONTINUOUS),
  200                 (False, sushy.BOOT_SOURCE_ENABLED_ONCE)
  201             ]
  202 
  203             for target, expected in expected_values:
  204                 fake_system.boot.get.return_value = expected
  205 
  206                 self.assertRaisesRegex(
  207                     exception.RedfishError, 'Redfish set boot device',
  208                     task.driver.management.set_boot_device, task,
  209                     boot_devices.PXE, persistent=target)
  210                 fake_system.set_system_boot_options.assert_called_once_with(
  211                     sushy.BOOT_SOURCE_TARGET_PXE, enabled=None)
  212                 mock_get_system.assert_called_once_with(task.node)
  213                 self.assertNotIn('redfish_boot_device',
  214                                  task.node.driver_internal_info)
  215 
  216                 # Reset mocks
  217                 fake_system.set_system_boot_options.reset_mock()
  218                 mock_get_system.reset_mock()
  219 
  220     @mock.patch.object(sushy, 'Sushy', autospec=True)
  221     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  222     def test_set_boot_device_persistence_fallback(self, mock_get_system,
  223                                                   mock_sushy):
  224         fake_system = mock.Mock()
  225         fake_system.set_system_boot_options.side_effect = [
  226             sushy.exceptions.SushyError(),
  227             None,
  228             None
  229         ]
  230         mock_get_system.return_value = fake_system
  231         with task_manager.acquire(self.context, self.node.uuid,
  232                                   shared=False) as task:
  233             task.driver.management.set_boot_device(
  234                 task, boot_devices.PXE, persistent=True)
  235             fake_system.set_system_boot_options.assert_has_calls([
  236                 mock.call(sushy.BOOT_SOURCE_TARGET_PXE,
  237                           enabled=sushy.BOOT_SOURCE_ENABLED_CONTINUOUS),
  238                 mock.call(sushy.BOOT_SOURCE_TARGET_PXE,
  239                           enabled=sushy.BOOT_SOURCE_ENABLED_ONCE)
  240             ])
  241             mock_get_system.assert_called_with(task.node)
  242 
  243             task.node.refresh()
  244             self.assertEqual(
  245                 sushy.BOOT_SOURCE_TARGET_PXE,
  246                 task.node.driver_internal_info['redfish_boot_device'])
  247 
  248     def test_restore_boot_device(self):
  249         fake_system = mock.Mock()
  250         with task_manager.acquire(self.context, self.node.uuid,
  251                                   shared=False) as task:
  252             task.node.driver_internal_info['redfish_boot_device'] = (
  253                 sushy.BOOT_SOURCE_TARGET_HDD
  254             )
  255 
  256             task.driver.management.restore_boot_device(task, fake_system)
  257 
  258             fake_system.set_system_boot_options.assert_called_once_with(
  259                 sushy.BOOT_SOURCE_TARGET_HDD,
  260                 enabled=sushy.BOOT_SOURCE_ENABLED_ONCE)
  261             # The stored boot device is kept intact
  262             self.assertEqual(
  263                 sushy.BOOT_SOURCE_TARGET_HDD,
  264                 task.node.driver_internal_info['redfish_boot_device'])
  265 
  266     def test_restore_boot_device_noop(self):
  267         fake_system = mock.Mock()
  268         with task_manager.acquire(self.context, self.node.uuid,
  269                                   shared=False) as task:
  270             task.driver.management.restore_boot_device(task, fake_system)
  271 
  272             self.assertFalse(fake_system.set_system_boot_options.called)
  273 
  274     @mock.patch.object(redfish_mgmt.LOG, 'warning', autospec=True)
  275     def test_restore_boot_device_failure(self, mock_log):
  276         fake_system = mock.Mock()
  277         fake_system.set_system_boot_options.side_effect = (
  278             sushy.exceptions.SushyError()
  279         )
  280         with task_manager.acquire(self.context, self.node.uuid,
  281                                   shared=False) as task:
  282             task.node.driver_internal_info['redfish_boot_device'] = (
  283                 sushy.BOOT_SOURCE_TARGET_HDD
  284             )
  285 
  286             task.driver.management.restore_boot_device(task, fake_system)
  287 
  288             fake_system.set_system_boot_options.assert_called_once_with(
  289                 sushy.BOOT_SOURCE_TARGET_HDD,
  290                 enabled=sushy.BOOT_SOURCE_ENABLED_ONCE)
  291             self.assertTrue(mock_log.called)
  292             # The stored boot device is kept intact
  293             self.assertEqual(
  294                 sushy.BOOT_SOURCE_TARGET_HDD,
  295                 task.node.driver_internal_info['redfish_boot_device'])
  296 
  297     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  298     def test_get_boot_device(self, mock_get_system):
  299         boot_attribute = {
  300             'target': sushy.BOOT_SOURCE_TARGET_PXE,
  301             'enabled': sushy.BOOT_SOURCE_ENABLED_CONTINUOUS
  302         }
  303         fake_system = mock.Mock(boot=boot_attribute)
  304         mock_get_system.return_value = fake_system
  305         with task_manager.acquire(self.context, self.node.uuid,
  306                                   shared=True) as task:
  307             response = task.driver.management.get_boot_device(task)
  308             expected = {'boot_device': boot_devices.PXE,
  309                         'persistent': True}
  310             self.assertEqual(expected, response)
  311 
  312     def test_get_supported_boot_modes(self):
  313         with task_manager.acquire(self.context, self.node.uuid,
  314                                   shared=True) as task:
  315             supported_boot_modes = (
  316                 task.driver.management.get_supported_boot_modes(task))
  317             self.assertEqual(list(redfish_mgmt.BOOT_MODE_MAP_REV),
  318                              supported_boot_modes)
  319 
  320     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  321     def test_set_boot_mode(self, mock_get_system):
  322         fake_system = mock.Mock()
  323         mock_get_system.return_value = fake_system
  324         with task_manager.acquire(self.context, self.node.uuid,
  325                                   shared=False) as task:
  326             expected_values = [
  327                 (boot_modes.LEGACY_BIOS, sushy.BOOT_SOURCE_MODE_BIOS),
  328                 (boot_modes.UEFI, sushy.BOOT_SOURCE_MODE_UEFI)
  329             ]
  330 
  331             for mode, expected in expected_values:
  332                 task.driver.management.set_boot_mode(task, mode=mode)
  333 
  334                 # Asserts
  335                 fake_system.set_system_boot_options.assert_called_once_with(
  336                     mode=mode)
  337                 mock_get_system.assert_called_once_with(task.node)
  338 
  339                 # Reset mocks
  340                 fake_system.set_system_boot_options.reset_mock()
  341                 mock_get_system.reset_mock()
  342 
  343     @mock.patch.object(sushy, 'Sushy', autospec=True)
  344     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  345     def test_set_boot_mode_fail(self, mock_get_system, mock_sushy):
  346         fake_system = mock.Mock()
  347         fake_system.set_system_boot_options.side_effect = (
  348             sushy.exceptions.SushyError)
  349         mock_get_system.return_value = fake_system
  350         with task_manager.acquire(self.context, self.node.uuid,
  351                                   shared=False) as task:
  352             self.assertRaisesRegex(
  353                 exception.RedfishError, 'Setting boot mode',
  354                 task.driver.management.set_boot_mode, task, boot_modes.UEFI)
  355             fake_system.set_system_boot_options.assert_called_once_with(
  356                 mode=boot_modes.UEFI)
  357             mock_get_system.assert_called_once_with(task.node)
  358 
  359     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  360     def test_get_boot_mode(self, mock_get_system):
  361         boot_attribute = {
  362             'target': sushy.BOOT_SOURCE_TARGET_PXE,
  363             'enabled': sushy.BOOT_SOURCE_ENABLED_CONTINUOUS,
  364             'mode': sushy.BOOT_SOURCE_MODE_BIOS,
  365         }
  366         fake_system = mock.Mock(boot=boot_attribute)
  367         mock_get_system.return_value = fake_system
  368         with task_manager.acquire(self.context, self.node.uuid,
  369                                   shared=True) as task:
  370             response = task.driver.management.get_boot_mode(task)
  371             expected = boot_modes.LEGACY_BIOS
  372             self.assertEqual(expected, response)
  373 
  374     def test__get_sensors_fan(self):
  375         attributes = {
  376             "identity": "XXX-YYY-ZZZ",
  377             "name": "CPU Fan",
  378             "status": {
  379                 "state": "enabled",
  380                 "health": "OK"
  381             },
  382             "reading": 6000,
  383             "reading_units": "RPM",
  384             "lower_threshold_fatal": 2000,
  385             "min_reading_range": 0,
  386             "max_reading_range": 10000,
  387             "serial_number": "SN010203040506",
  388             "physical_context": "CPU"
  389         }
  390 
  391         mock_chassis = mock.MagicMock(identity='ZZZ-YYY-XXX')
  392 
  393         mock_fan = mock.MagicMock(**attributes)
  394         mock_fan.name = attributes['name']
  395         mock_fan.status = mock.MagicMock(**attributes['status'])
  396         mock_chassis.thermal.fans = [mock_fan]
  397 
  398         with task_manager.acquire(self.context, self.node.uuid,
  399                                   shared=True) as task:
  400             sensors = task.driver.management._get_sensors_fan(mock_chassis)
  401 
  402         expected = {
  403             'XXX-YYY-ZZZ@ZZZ-YYY-XXX': {
  404                 'identity': 'XXX-YYY-ZZZ',
  405                 'max_reading_range': 10000,
  406                 'min_reading_range': 0,
  407                 'physical_context': 'CPU',
  408                 'reading': 6000,
  409                 'reading_units': 'RPM',
  410                 'serial_number': 'SN010203040506',
  411                 'health': 'OK',
  412                 'state': 'enabled'
  413             }
  414         }
  415 
  416         self.assertEqual(expected, sensors)
  417 
  418     def test__get_sensors_temperatures(self):
  419         attributes = {
  420             "identity": "XXX-YYY-ZZZ",
  421             "name": "CPU Temp",
  422             "status": {
  423                 "state": "enabled",
  424                 "health": "OK"
  425             },
  426             "reading_celsius": 62,
  427             "upper_threshold_non_critical": 75,
  428             "upper_threshold_critical": 90,
  429             "upperThresholdFatal": 95,
  430             "min_reading_range_temp": 0,
  431             "max_reading_range_temp": 120,
  432             "physical_context": "CPU",
  433             "sensor_number": 1
  434         }
  435 
  436         mock_chassis = mock.MagicMock(identity='ZZZ-YYY-XXX')
  437 
  438         mock_temperature = mock.MagicMock(**attributes)
  439         mock_temperature.name = attributes['name']
  440         mock_temperature.status = mock.MagicMock(**attributes['status'])
  441         mock_chassis.thermal.temperatures = [mock_temperature]
  442 
  443         with task_manager.acquire(self.context, self.node.uuid,
  444                                   shared=True) as task:
  445             sensors = task.driver.management._get_sensors_temperatures(
  446                 mock_chassis)
  447 
  448         expected = {
  449             'XXX-YYY-ZZZ@ZZZ-YYY-XXX': {
  450                 'identity': 'XXX-YYY-ZZZ',
  451                 'max_reading_range_temp': 120,
  452                 'min_reading_range_temp': 0,
  453                 'physical_context': 'CPU',
  454                 'reading_celsius': 62,
  455                 'sensor_number': 1,
  456                 'health': 'OK',
  457                 'state': 'enabled'
  458             }
  459         }
  460 
  461         self.assertEqual(expected, sensors)
  462 
  463     def test__get_sensors_power(self):
  464         attributes = {
  465             'identity': 0,
  466             'name': 'Power Supply 0',
  467             'power_capacity_watts': 1450,
  468             'last_power_output_watts': 650,
  469             'line_input_voltage': 220,
  470             'input_ranges': {
  471                 'minimum_voltage': 185,
  472                 'maximum_voltage': 250,
  473                 'minimum_frequency_hz': 47,
  474                 'maximum_frequency_hz': 63,
  475                 'output_wattage': 1450
  476             },
  477             'serial_number': 'SN010203040506',
  478             "status": {
  479                 "state": "enabled",
  480                 "health": "OK"
  481             }
  482         }
  483 
  484         mock_chassis = mock.MagicMock(identity='ZZZ-YYY-XXX')
  485         mock_power = mock_chassis.power
  486         mock_power.identity = 'Power'
  487         mock_psu = mock.MagicMock(**attributes)
  488         mock_psu.name = attributes['name']
  489         mock_psu.status = mock.MagicMock(**attributes['status'])
  490         mock_psu.input_ranges = mock.MagicMock(**attributes['input_ranges'])
  491         mock_power.power_supplies = [mock_psu]
  492 
  493         with task_manager.acquire(self.context, self.node.uuid,
  494                                   shared=True) as task:
  495             sensors = task.driver.management._get_sensors_power(mock_chassis)
  496 
  497         expected = {
  498             '0:Power@ZZZ-YYY-XXX': {
  499                 'health': 'OK',
  500                 'last_power_output_watts': 650,
  501                 'line_input_voltage': 220,
  502                 'maximum_frequency_hz': 63,
  503                 'maximum_voltage': 250,
  504                 'minimum_frequency_hz': 47,
  505                 'minimum_voltage': 185,
  506                 'output_wattage': 1450,
  507                 'power_capacity_watts': 1450,
  508                 'serial_number': 'SN010203040506',
  509                 'state': 'enabled'
  510             }
  511         }
  512 
  513         self.assertEqual(expected, sensors)
  514 
  515     def test__get_sensors_data_drive(self):
  516         attributes = {
  517             'name': '32ADF365C6C1B7BD',
  518             'manufacturer': 'IBM',
  519             'model': 'IBM 350A',
  520             'capacity_bytes': 3750000000,
  521             'status': {
  522                 'health': 'OK',
  523                 'state': 'enabled'
  524             }
  525         }
  526 
  527         mock_system = mock.MagicMock(identity='ZZZ-YYY-XXX')
  528         mock_drive = mock.MagicMock(**attributes)
  529         mock_drive.name = attributes['name']
  530         mock_drive.status = mock.MagicMock(**attributes['status'])
  531         mock_storage = mock.MagicMock()
  532         mock_storage.devices = [mock_drive]
  533         mock_storage.identity = 'XXX-YYY-ZZZ'
  534         mock_system.simple_storage.get_members.return_value = [mock_storage]
  535 
  536         with task_manager.acquire(self.context, self.node.uuid,
  537                                   shared=True) as task:
  538             sensors = task.driver.management._get_sensors_drive(mock_system)
  539 
  540         expected = {
  541             '32ADF365C6C1B7BD:XXX-YYY-ZZZ@ZZZ-YYY-XXX': {
  542                 'capacity_bytes': 3750000000,
  543                 'health': 'OK',
  544                 'name': '32ADF365C6C1B7BD',
  545                 'model': 'IBM 350A',
  546                 'state': 'enabled'
  547             }
  548         }
  549 
  550         self.assertEqual(expected, sensors)
  551 
  552     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  553     def test_get_sensors_data(self, mock_system):
  554         mock_chassis = mock.MagicMock()
  555         mock_system.return_value.chassis = [mock_chassis]
  556 
  557         with task_manager.acquire(self.context, self.node.uuid,
  558                                   shared=True) as task:
  559             sensors = task.driver.management.get_sensors_data(task)
  560 
  561         expected = {
  562             'Fan': {},
  563             'Temperature': {},
  564             'Power': {},
  565             'Drive': {}
  566         }
  567 
  568         self.assertEqual(expected, sensors)
  569 
  570     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  571     def test_inject_nmi(self, mock_get_system):
  572         fake_system = mock.Mock()
  573         mock_get_system.return_value = fake_system
  574         with task_manager.acquire(self.context, self.node.uuid,
  575                                   shared=False) as task:
  576             task.driver.management.inject_nmi(task)
  577             fake_system.reset_system.assert_called_once_with(sushy.RESET_NMI)
  578             mock_get_system.assert_called_once_with(task.node)
  579 
  580     @mock.patch.object(sushy, 'Sushy', autospec=True)
  581     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  582     def test_inject_nmi_fail(self, mock_get_system, mock_sushy):
  583         fake_system = mock.Mock()
  584         fake_system.reset_system.side_effect = (
  585             sushy.exceptions.SushyError)
  586         mock_get_system.return_value = fake_system
  587         with task_manager.acquire(self.context, self.node.uuid,
  588                                   shared=False) as task:
  589             self.assertRaisesRegex(
  590                 exception.RedfishError, 'Redfish inject NMI',
  591                 task.driver.management.inject_nmi, task)
  592             fake_system.reset_system.assert_called_once_with(
  593                 sushy.RESET_NMI)
  594             mock_get_system.assert_called_once_with(task.node)
  595 
  596     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  597     def test_get_supported_indicators(self, mock_get_system):
  598         fake_chassis = mock.Mock(
  599             uuid=self.chassis_uuid,
  600             indicator_led=sushy.INDICATOR_LED_LIT)
  601         fake_drive = mock.Mock(
  602             uuid=self.drive_uuid,
  603             indicator_led=sushy.INDICATOR_LED_LIT)
  604         fake_system = mock.Mock(
  605             uuid=self.system_uuid,
  606             chassis=[fake_chassis],
  607             simple_storage=mock.MagicMock(drives=[fake_drive]),
  608             indicator_led=sushy.INDICATOR_LED_LIT)
  609 
  610         mock_get_system.return_value = fake_system
  611 
  612         with task_manager.acquire(self.context, self.node.uuid,
  613                                   shared=True) as task:
  614 
  615             supported_indicators = (
  616                 task.driver.management.get_supported_indicators(task))
  617 
  618             expected = {
  619                 components.CHASSIS: {
  620                     'XXX-YYY-ZZZ': {
  621                         "readonly": False,
  622                         "states": [
  623                             indicator_states.BLINKING,
  624                             indicator_states.OFF,
  625                             indicator_states.ON
  626                         ]
  627                     }
  628                 },
  629                 components.SYSTEM: {
  630                     'ZZZ--XXX-YYY': {
  631                         "readonly": False,
  632                         "states": [
  633                             indicator_states.BLINKING,
  634                             indicator_states.OFF,
  635                             indicator_states.ON
  636                         ]
  637                     }
  638                 },
  639                 components.DISK: {
  640                     'ZZZ-YYY-XXX': {
  641                         "readonly": False,
  642                         "states": [
  643                             indicator_states.BLINKING,
  644                             indicator_states.OFF,
  645                             indicator_states.ON
  646                         ]
  647                     }
  648                 }
  649             }
  650 
  651             self.assertEqual(expected, supported_indicators)
  652 
  653     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  654     def test_set_indicator_state(self, mock_get_system):
  655         fake_chassis = mock.Mock(
  656             uuid=self.chassis_uuid,
  657             indicator_led=sushy.INDICATOR_LED_LIT)
  658         fake_drive = mock.Mock(
  659             uuid=self.drive_uuid,
  660             indicator_led=sushy.INDICATOR_LED_LIT)
  661         fake_system = mock.Mock(
  662             uuid=self.system_uuid,
  663             chassis=[fake_chassis],
  664             simple_storage=mock.MagicMock(drives=[fake_drive]),
  665             indicator_led=sushy.INDICATOR_LED_LIT)
  666 
  667         mock_get_system.return_value = fake_system
  668 
  669         with task_manager.acquire(self.context, self.node.uuid,
  670                                   shared=False) as task:
  671             task.driver.management.set_indicator_state(
  672                 task, components.SYSTEM, self.system_uuid, indicator_states.ON)
  673 
  674             fake_system.set_indicator_led.assert_called_once_with(
  675                 sushy.INDICATOR_LED_LIT)
  676 
  677             mock_get_system.assert_called_once_with(task.node)
  678 
  679     @mock.patch.object(redfish_utils, 'get_system', autospec=True)
  680     def test_get_indicator_state(self, mock_get_system):
  681         fake_chassis = mock.Mock(
  682             uuid=self.chassis_uuid,
  683             indicator_led=sushy.INDICATOR_LED_LIT)
  684         fake_drive = mock.Mock(
  685             uuid=self.drive_uuid,
  686             indicator_led=sushy.INDICATOR_LED_LIT)
  687         fake_system = mock.Mock(
  688             uuid=self.system_uuid,
  689             chassis=[fake_chassis],
  690             simple_storage=mock.MagicMock(drives=[fake_drive]),
  691             indicator_led=sushy.INDICATOR_LED_LIT)
  692 
  693         mock_get_system.return_value = fake_system
  694 
  695         with task_manager.acquire(self.context, self.node.uuid,
  696                                   shared=False) as task:
  697 
  698             state = task.driver.management.get_indicator_state(
  699                 task, components.SYSTEM, self.system_uuid)
  700 
  701             mock_get_system.assert_called_once_with(task.node)
  702 
  703             self.assertEqual(indicator_states.ON, state)
  704 
  705     @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
  706     @mock.patch.object(deploy_utils, 'get_async_step_return_state',
  707                        autospec=True)
  708     @mock.patch.object(deploy_utils, 'set_async_step_flags', autospec=True)
  709     @mock.patch.object(redfish_utils, 'get_update_service', autospec=True)
  710     def test_update_firmware(self, mock_get_update_service,
  711                              mock_set_async_step_flags,
  712                              mock_get_async_step_return_state,
  713                              mock_node_power_action):
  714         mock_task_monitor = mock.Mock()
  715         mock_task_monitor.task_monitor = '/task/123'
  716         mock_update_service = mock.Mock()
  717         mock_update_service.simple_update.return_value = mock_task_monitor
  718         mock_get_update_service.return_value = mock_update_service
  719         with task_manager.acquire(self.context, self.node.uuid,
  720                                   shared=False) as task:
  721             task.node.save = mock.Mock()
  722 
  723             task.driver.management.update_firmware(task,
  724                                                    [{'url': 'test1'},
  725                                                     {'url': 'test2'}])
  726 
  727             mock_get_update_service.assert_called_once_with(task.node)
  728             mock_update_service.simple_update.assert_called_once_with('test1')
  729             self.assertIsNotNone(task.node
  730                                  .driver_internal_info['firmware_updates'])
  731             self.assertEqual(
  732                 [{'task_monitor': '/task/123', 'url': 'test1'},
  733                  {'url': 'test2'}],
  734                 task.node.driver_internal_info['firmware_updates'])
  735             mock_set_async_step_flags.assert_called_once_with(
  736                 task.node, reboot=True, skip_current_step=True, polling=True)
  737             mock_get_async_step_return_state.assert_called_once_with(
  738                 task.node)
  739             mock_node_power_action.assert_called_once_with(task, states.REBOOT)
  740 
  741     @mock.patch.object(task_manager, 'acquire', autospec=True)
  742     def test__query_firmware_update_failed(self, mock_acquire):
  743         driver_internal_info = {
  744             'firmware_updates': [
  745                 {'task_monitor': '/task/123',
  746                  'url': 'test1'}]}
  747         self.node.driver_internal_info = driver_internal_info
  748         self.node.save()
  749         management = redfish_mgmt.RedfishManagement()
  750         mock_manager = mock.Mock()
  751         node_list = [(self.node.uuid, 'redfish', '', driver_internal_info)]
  752         mock_manager.iter_nodes.return_value = node_list
  753         task = mock.Mock(node=self.node,
  754                          driver=mock.Mock(management=management))
  755         mock_acquire.return_value = mock.MagicMock(
  756             __enter__=mock.MagicMock(return_value=task))
  757         management._clear_firmware_updates = mock.Mock()
  758 
  759         management._query_firmware_update_failed(mock_manager,
  760                                                  self.context)
  761 
  762         management._clear_firmware_updates.assert_called_once_with(self.node)
  763 
  764     @mock.patch.object(task_manager, 'acquire', autospec=True)
  765     def test__query_firmware_update_failed_not_redfish(self, mock_acquire):
  766         driver_internal_info = {
  767             'firmware_updates': [
  768                 {'task_monitor': '/task/123',
  769                  'url': 'test1'}]}
  770         self.node.driver_internal_info = driver_internal_info
  771         self.node.save()
  772         management = redfish_mgmt.RedfishManagement()
  773         mock_manager = mock.Mock()
  774         node_list = [(self.node.uuid, 'not-redfish', '', driver_internal_info)]
  775         mock_manager.iter_nodes.return_value = node_list
  776         task = mock.Mock(node=self.node,
  777                          driver=mock.Mock(management=mock.Mock()))
  778         mock_acquire.return_value = mock.MagicMock(
  779             __enter__=mock.MagicMock(return_value=task))
  780         management._clear_firmware_updates = mock.Mock()
  781 
  782         management._query_firmware_update_failed(mock_manager,
  783                                                  self.context)
  784 
  785         management._clear_firmware_updates.assert_not_called()
  786 
  787     @mock.patch.object(task_manager, 'acquire', autospec=True)
  788     def test__query_firmware_update_failed_no_firmware_upd(self, mock_acquire):
  789         driver_internal_info = {'something': 'else'}
  790         self.node.driver_internal_info = driver_internal_info
  791         self.node.save()
  792         management = redfish_mgmt.RedfishManagement()
  793         mock_manager = mock.Mock()
  794         node_list = [(self.node.uuid, 'redfish', '', driver_internal_info)]
  795         mock_manager.iter_nodes.return_value = node_list
  796         task = mock.Mock(node=self.node,
  797                          driver=mock.Mock(management=management))
  798         mock_acquire.return_value = mock.MagicMock(
  799             __enter__=mock.MagicMock(return_value=task))
  800         management._clear_firmware_updates = mock.Mock()
  801 
  802         management._query_firmware_update_failed(mock_manager,
  803                                                  self.context)
  804 
  805         management._clear_firmware_updates.assert_not_called()
  806 
  807     @mock.patch.object(redfish_mgmt.LOG, 'info', autospec=True)
  808     @mock.patch.object(task_manager, 'acquire', autospec=True)
  809     def test__query_firmware_update_failed_node_notfound(self, mock_acquire,
  810                                                          mock_log):
  811         driver_internal_info = {
  812             'firmware_updates': [
  813                 {'task_monitor': '/task/123',
  814                  'url': 'test1'}]}
  815         self.node.driver_internal_info = driver_internal_info
  816         self.node.save()
  817         management = redfish_mgmt.RedfishManagement()
  818         mock_manager = mock.Mock()
  819         node_list = [(self.node.uuid, 'redfish', '', driver_internal_info)]
  820         mock_manager.iter_nodes.return_value = node_list
  821         mock_acquire.side_effect = exception.NodeNotFound
  822         management._clear_firmware_updates = mock.Mock()
  823 
  824         management._query_firmware_update_failed(mock_manager,
  825                                                  self.context)
  826 
  827         management._clear_firmware_updates.assert_not_called()
  828         self.assertTrue(mock_log.called)
  829 
  830     @mock.patch.object(redfish_mgmt.LOG, 'info', autospec=True)
  831     @mock.patch.object(task_manager, 'acquire', autospec=True)
  832     def test__query_firmware_update_failed_node_locked(
  833             self, mock_acquire, mock_log):
  834         driver_internal_info = {
  835             'firmware_updates': [
  836                 {'task_monitor': '/task/123',
  837                  'url': 'test1'}]}
  838         self.node.driver_internal_info = driver_internal_info
  839         self.node.save()
  840         management = redfish_mgmt.RedfishManagement()
  841         mock_manager = mock.Mock()
  842         node_list = [(self.node.uuid, 'redfish', '', driver_internal_info)]
  843         mock_manager.iter_nodes.return_value = node_list
  844         mock_acquire.side_effect = exception.NodeLocked
  845         management._clear_firmware_updates = mock.Mock()
  846 
  847         management._query_firmware_update_failed(mock_manager,
  848                                                  self.context)
  849 
  850         management._clear_firmware_updates.assert_not_called()
  851         self.assertTrue(mock_log.called)
  852 
  853     @mock.patch.object(task_manager, 'acquire', autospec=True)
  854     def test__query_firmware_update_status(self, mock_acquire):
  855         driver_internal_info = {
  856             'firmware_updates': [
  857                 {'task_monitor': '/task/123',
  858                  'url': 'test1'}]}
  859         self.node.driver_internal_info = driver_internal_info
  860         self.node.save()
  861         management = redfish_mgmt.RedfishManagement()
  862         mock_manager = mock.Mock()
  863         node_list = [(self.node.uuid, 'redfish', '', driver_internal_info)]
  864         mock_manager.iter_nodes.return_value = node_list
  865         task = mock.Mock(node=self.node,
  866                          driver=mock.Mock(management=management))
  867         mock_acquire.return_value = mock.MagicMock(
  868             __enter__=mock.MagicMock(return_value=task))
  869         management._check_node_firmware_update = mock.Mock()
  870 
  871         management._query_firmware_update_status(mock_manager,
  872                                                  self.context)
  873 
  874         management._check_node_firmware_update.assert_called_once_with(task)
  875 
  876     @mock.patch.object(task_manager, 'acquire', autospec=True)
  877     def test__query_firmware_update_status_not_redfish(self, mock_acquire):
  878         driver_internal_info = {
  879             'firmware_updates': [
  880                 {'task_monitor': '/task/123',
  881                  'url': 'test1'}]}
  882         self.node.driver_internal_info = driver_internal_info
  883         self.node.save()
  884         management = redfish_mgmt.RedfishManagement()
  885         mock_manager = mock.Mock()
  886         node_list = [(self.node.uuid, 'not-redfish', '', driver_internal_info)]
  887         mock_manager.iter_nodes.return_value = node_list
  888         task = mock.Mock(node=self.node,
  889                          driver=mock.Mock(management=mock.Mock()))
  890         mock_acquire.return_value = mock.MagicMock(
  891             __enter__=mock.MagicMock(return_value=task))
  892         management._check_node_firmware_update = mock.Mock()
  893 
  894         management._query_firmware_update_status(mock_manager,
  895                                                  self.context)
  896 
  897         management._check_node_firmware_update.assert_not_called()
  898 
  899     @mock.patch.object(task_manager, 'acquire', autospec=True)
  900     def test__query_firmware_update_status_no_firmware_upd(self, mock_acquire):
  901         driver_internal_info = {'something': 'else'}
  902         self.node.driver_internal_info = driver_internal_info
  903         self.node.save()
  904         management = redfish_mgmt.RedfishManagement()
  905         mock_manager = mock.Mock()
  906         node_list = [(self.node.uuid, 'redfish', '', driver_internal_info)]
  907         mock_manager.iter_nodes.return_value = node_list
  908         task = mock.Mock(node=self.node,
  909                          driver=mock.Mock(management=management))
  910         mock_acquire.return_value = mock.MagicMock(
  911             __enter__=mock.MagicMock(return_value=task))
  912         management._check_node_firmware_update = mock.Mock()
  913 
  914         management._query_firmware_update_status(mock_manager,
  915                                                  self.context)
  916 
  917         management._check_node_firmware_update.assert_not_called()
  918 
  919     @mock.patch.object(redfish_mgmt.LOG, 'info', autospec=True)
  920     @mock.patch.object(task_manager, 'acquire', autospec=True)
  921     def test__query_firmware_update_status_node_notfound(self, mock_acquire,
  922                                                          mock_log):
  923         driver_internal_info = {
  924             'firmware_updates': [
  925                 {'task_monitor': '/task/123',
  926                  'url': 'test1'}]}
  927         self.node.driver_internal_info = driver_internal_info
  928         self.node.save()
  929         management = redfish_mgmt.RedfishManagement()
  930         mock_manager = mock.Mock()
  931         node_list = [(self.node.uuid, 'redfish', '', driver_internal_info)]
  932         mock_manager.iter_nodes.return_value = node_list
  933         mock_acquire.side_effect = exception.NodeNotFound
  934         management._check_node_firmware_update = mock.Mock()
  935 
  936         management._query_firmware_update_status(mock_manager,
  937                                                  self.context)
  938 
  939         management._check_node_firmware_update.assert_not_called()
  940         self.assertTrue(mock_log.called)
  941 
  942     @mock.patch.object(redfish_mgmt.LOG, 'info', autospec=True)
  943     @mock.patch.object(task_manager, 'acquire', autospec=True)
  944     def test__query_firmware_update_status_node_locked(
  945             self, mock_acquire, mock_log):
  946         driver_internal_info = {
  947             'firmware_updates': [
  948                 {'task_monitor': '/task/123',
  949                  'url': 'test1'}]}
  950         self.node.driver_internal_info = driver_internal_info
  951         self.node.save()
  952         management = redfish_mgmt.RedfishManagement()
  953         mock_manager = mock.Mock()
  954         node_list = [(self.node.uuid, 'redfish', '', driver_internal_info)]
  955         mock_manager.iter_nodes.return_value = node_list
  956         mock_acquire.side_effect = exception.NodeLocked
  957         management._check_node_firmware_update = mock.Mock()
  958 
  959         management._query_firmware_update_status(mock_manager,
  960                                                  self.context)
  961 
  962         management._check_node_firmware_update.assert_not_called()
  963         self.assertTrue(mock_log.called)
  964 
  965     @mock.patch.object(redfish_mgmt.LOG, 'warning', autospec=True)
  966     @mock.patch.object(redfish_utils, 'get_update_service', autospec=True)
  967     def test__check_node_firmware_update_redfish_conn_error(
  968             self, mock_get_update_services, mock_log):
  969         mock_get_update_services.side_effect = exception.RedfishConnectionError
  970         driver_internal_info = {
  971             'firmware_updates': [
  972                 {'task_monitor': '/task/123',
  973                  'url': 'test1'}]}
  974         self.node.driver_internal_info = driver_internal_info
  975         self.node.save()
  976 
  977         management = redfish_mgmt.RedfishManagement()
  978         with task_manager.acquire(self.context, self.node.uuid,
  979                                   shared=False) as task:
  980             management._check_node_firmware_update(task)
  981 
  982         self.assertTrue(mock_log.called)
  983 
  984     @mock.patch.object(redfish_mgmt.LOG, 'debug', autospec=True)
  985     @mock.patch.object(redfish_utils, 'get_update_service', autospec=True)
  986     def test__check_node_firmware_update_wait_elapsed(
  987             self, mock_get_update_service, mock_log):
  988         mock_update_service = mock.Mock()
  989         mock_get_update_service.return_value = mock_update_service
  990 
  991         wait_start_time = datetime.datetime.utcnow() -\
  992             datetime.timedelta(minutes=15)
  993         driver_internal_info = {
  994             'firmware_updates': [
  995                 {'task_monitor': '/task/123',
  996                  'url': 'test1',
  997                  'wait_start_time':
  998                     wait_start_time.isoformat(),
  999                  'wait': 1}]}
 1000         self.node.driver_internal_info = driver_internal_info
 1001         self.node.save()
 1002         management = redfish_mgmt.RedfishManagement()
 1003         management._continue_firmware_updates = mock.Mock()
 1004 
 1005         with task_manager.acquire(self.context, self.node.uuid,
 1006                                   shared=False) as task:
 1007             management._check_node_firmware_update(task)
 1008 
 1009             self.assertTrue(mock_log.called)
 1010             management._continue_firmware_updates.assert_called_once_with(
 1011                 task,
 1012                 mock_update_service,
 1013                 [{'task_monitor': '/task/123', 'url': 'test1'}])
 1014 
 1015     @mock.patch.object(redfish_mgmt.LOG, 'debug', autospec=True)
 1016     @mock.patch.object(redfish_utils, 'get_update_service', autospec=True)
 1017     def test__check_node_firmware_update_still_waiting(
 1018             self, mock_get_update_service, mock_log):
 1019         mock_update_service = mock.Mock()
 1020         mock_get_update_service.return_value = mock_update_service
 1021 
 1022         wait_start_time = datetime.datetime.utcnow() -\
 1023             datetime.timedelta(minutes=1)
 1024         driver_internal_info = {
 1025             'firmware_updates': [
 1026                 {'task_monitor': '/task/123',
 1027                  'url': 'test1',
 1028                  'wait_start_time':
 1029                      wait_start_time.isoformat(),
 1030                  'wait': 600}]}
 1031         self.node.driver_internal_info = driver_internal_info
 1032         self.node.save()
 1033         management = redfish_mgmt.RedfishManagement()
 1034         management._continue_firmware_updates = mock.Mock()
 1035 
 1036         with task_manager.acquire(self.context, self.node.uuid,
 1037                                   shared=False) as task:
 1038             management._check_node_firmware_update(task)
 1039 
 1040             self.assertTrue(mock_log.called)
 1041             management._continue_firmware_updates.assert_not_called()
 1042 
 1043     @mock.patch.object(redfish_mgmt.LOG, 'warning', autospec=True)
 1044     @mock.patch.object(redfish_utils, 'get_update_service', autospec=True)
 1045     def test__check_node_firmware_update_task_monitor_not_found(
 1046             self, mock_get_update_service, mock_log):
 1047         mock_update_service = mock.Mock()
 1048         mock_update_service.get_task_monitor.side_effect =\
 1049             sushy.exceptions.ResourceNotFoundError(
 1050                 method='GET', url='/task/123', response=mock.MagicMock())
 1051         mock_get_update_service.return_value = mock_update_service
 1052         driver_internal_info = {
 1053             'firmware_updates': [
 1054                 {'task_monitor': '/task/123',
 1055                  'url': 'test1'}]}
 1056         self.node.driver_internal_info = driver_internal_info
 1057         self.node.save()
 1058         management = redfish_mgmt.RedfishManagement()
 1059         management._continue_firmware_updates = mock.Mock()
 1060 
 1061         with task_manager.acquire(self.context, self.node.uuid,
 1062                                   shared=False) as task:
 1063             management._check_node_firmware_update(task)
 1064 
 1065             self.assertTrue(mock_log.called)
 1066             management._continue_firmware_updates.assert_called_once_with(
 1067                 task,
 1068                 mock_update_service,
 1069                 [{'task_monitor': '/task/123', 'url': 'test1'}])
 1070 
 1071     @mock.patch.object(redfish_mgmt.LOG, 'debug', autospec=True)
 1072     @mock.patch.object(redfish_utils, 'get_update_service', autospec=True)
 1073     def test__check_node_firmware_update_in_progress(self,
 1074                                                      mock_get_update_service,
 1075                                                      mock_log):
 1076         mock_task_monitor = mock.Mock()
 1077         mock_task_monitor.is_processing = True
 1078         mock_update_service = mock.Mock()
 1079         mock_update_service.get_task_monitor.return_value = mock_task_monitor
 1080         mock_get_update_service.return_value = mock_update_service
 1081         driver_internal_info = {
 1082             'firmware_updates': [
 1083                 {'task_monitor': '/task/123',
 1084                  'url': 'test1'}]}
 1085         self.node.driver_internal_info = driver_internal_info
 1086         self.node.save()
 1087         management = redfish_mgmt.RedfishManagement()
 1088 
 1089         with task_manager.acquire(self.context, self.node.uuid,
 1090                                   shared=False) as task:
 1091             management._check_node_firmware_update(task)
 1092 
 1093             self.assertTrue(mock_log.called)
 1094 
 1095     @mock.patch.object(manager_utils, 'cleaning_error_handler', autospec=True)
 1096     @mock.patch.object(redfish_utils, 'get_update_service', autospec=True)
 1097     def test__check_node_firmware_update_fail(self,
 1098                                               mock_get_update_service,
 1099                                               mock_cleaning_error_handler):
 1100         mock_sushy_task = mock.Mock()
 1101         mock_sushy_task.task_state = 'exception'
 1102         mock_message_unparsed = mock.Mock()
 1103         mock_message_unparsed.message = None
 1104         mock_message = mock.Mock()
 1105         mock_message.message = 'Firmware upgrade failed'
 1106         messages = mock.PropertyMock(side_effect=[[mock_message_unparsed],
 1107                                                   [mock_message]])
 1108         type(mock_sushy_task).messages = messages
 1109         mock_task_monitor = mock.Mock()
 1110         mock_task_monitor.is_processing = False
 1111         mock_task_monitor.get_task.return_value = mock_sushy_task
 1112         mock_update_service = mock.Mock()
 1113         mock_update_service.get_task_monitor.return_value = mock_task_monitor
 1114         mock_get_update_service.return_value = mock_update_service
 1115         driver_internal_info = {'something': 'else',
 1116                                 'firmware_updates': [
 1117                                     {'task_monitor': '/task/123',
 1118                                      'url': 'test1'}]}
 1119         self.node.driver_internal_info = driver_internal_info
 1120         self.node.save()
 1121         management = redfish_mgmt.RedfishManagement()
 1122         management._continue_firmware_updates = mock.Mock()
 1123 
 1124         with task_manager.acquire(self.context, self.node.uuid,
 1125                                   shared=False) as task:
 1126             task.upgrade_lock = mock.Mock()
 1127             task.process_event = mock.Mock()
 1128 
 1129             management._check_node_firmware_update(task)
 1130 
 1131             task.upgrade_lock.assert_called_once_with()
 1132             self.assertEqual({'something': 'else'},
 1133                              task.node.driver_internal_info)
 1134             mock_cleaning_error_handler.assert_called_once()
 1135             management._continue_firmware_updates.assert_not_called()
 1136 
 1137     @mock.patch.object(redfish_mgmt.LOG, 'info', autospec=True)
 1138     @mock.patch.object(redfish_utils, 'get_update_service', autospec=True)
 1139     def test__check_node_firmware_update_done(self,
 1140                                               mock_get_update_service,
 1141                                               mock_log):
 1142         mock_task = mock.Mock()
 1143         mock_task.task_state = sushy.TASK_STATE_COMPLETED
 1144         mock_task.task_status = sushy.HEALTH_OK
 1145         mock_message = mock.Mock()
 1146         mock_message.message = 'Firmware update done'
 1147         mock_task.messages = [mock_message]
 1148         mock_task_monitor = mock.Mock()
 1149         mock_task_monitor.is_processing = False
 1150         mock_task_monitor.get_task.return_value = mock_task
 1151         mock_update_service = mock.Mock()
 1152         mock_update_service.get_task_monitor.return_value = mock_task_monitor
 1153         mock_get_update_service.return_value = mock_update_service
 1154         driver_internal_info = {
 1155             'firmware_updates': [
 1156                 {'task_monitor': '/task/123',
 1157                  'url': 'test1'}]}
 1158         self.node.driver_internal_info = driver_internal_info
 1159         self.node.save()
 1160         management = redfish_mgmt.RedfishManagement()
 1161         management._continue_firmware_updates = mock.Mock()
 1162 
 1163         with task_manager.acquire(self.context, self.node.uuid,
 1164                                   shared=False) as task:
 1165             management._check_node_firmware_update(task)
 1166 
 1167             self.assertTrue(mock_log.called)
 1168             management._continue_firmware_updates.assert_called_once_with(
 1169                 task,
 1170                 mock_update_service,
 1171                 [{'task_monitor': '/task/123',
 1172                   'url': 'test1'}])
 1173 
 1174     @mock.patch.object(redfish_mgmt.LOG, 'debug', autospec=True)
 1175     def test__continue_firmware_updates_wait(self, mock_log):
 1176         mock_update_service = mock.Mock()
 1177 
 1178         management = redfish_mgmt.RedfishManagement()
 1179         with task_manager.acquire(self.context, self.node.uuid,
 1180                                   shared=False) as task:
 1181             management._continue_firmware_updates(
 1182                 task,
 1183                 mock_update_service,
 1184                 [{'task_monitor': '/task/123',
 1185                   'url': 'test1',
 1186                   'wait': 10,
 1187                   'wait_start_time': '20200901123045'},
 1188                  {'url': 'test2'}])
 1189 
 1190             self.assertTrue(mock_log.called)
 1191             # Wait start time has changed
 1192             self.assertNotEqual(
 1193                 '20200901123045',
 1194                 task.node.driver_internal_info['firmware_updates']
 1195                 [0]['wait_start_time'])
 1196 
 1197     @mock.patch.object(redfish_mgmt.LOG, 'info', autospec=True)
 1198     @mock.patch.object(manager_utils, 'notify_conductor_resume_clean',
 1199                        autospec=True)
 1200     def test__continue_firmware_updates_last_update(
 1201             self,
 1202             mock_notify_conductor_resume_clean,
 1203             mock_log):
 1204         mock_update_service = mock.Mock()
 1205         driver_internal_info = {
 1206             'something': 'else',
 1207             'firmware_updates': [
 1208                 {'task_monitor': '/task/123', 'url': 'test1'}]}
 1209         self.node.driver_internal_info = driver_internal_info
 1210         self.node.save()
 1211 
 1212         management = redfish_mgmt.RedfishManagement()
 1213         with task_manager.acquire(self.context, self.node.uuid,
 1214                                   shared=False) as task:
 1215             management._continue_firmware_updates(
 1216                 task,
 1217                 mock_update_service,
 1218                 [{'task_monitor': '/task/123', 'url': 'test1'}])
 1219 
 1220             self.assertTrue(mock_log.called)
 1221             mock_notify_conductor_resume_clean.assert_called_once_with(task)
 1222             self.assertEqual({'something': 'else'},
 1223                              task.node.driver_internal_info)
 1224 
 1225     @mock.patch.object(redfish_mgmt.LOG, 'debug', autospec=True)
 1226     @mock.patch.object(manager_utils, 'node_power_action', autospec=True)
 1227     def test__continue_firmware_updates_more_updates(self,
 1228                                                      mock_node_power_action,
 1229                                                      mock_log):
 1230         mock_task_monitor = mock.Mock()
 1231         mock_task_monitor.task_monitor = '/task/987'
 1232         mock_update_service = mock.Mock()
 1233         mock_update_service.simple_update.return_value = mock_task_monitor
 1234         driver_internal_info = {
 1235             'something': 'else',
 1236             'firmware_updates': [
 1237                 {'task_monitor': '/task/123', 'url': 'test1'},
 1238                 {'url': 'test2'}]}
 1239         self.node.driver_internal_info = driver_internal_info
 1240 
 1241         management = redfish_mgmt.RedfishManagement()
 1242         with task_manager.acquire(self.context, self.node.uuid,
 1243                                   shared=False) as task:
 1244             task.node.save = mock.Mock()
 1245 
 1246             management._continue_firmware_updates(
 1247                 task,
 1248                 mock_update_service,
 1249                 [{'task_monitor': '/task/123', 'url': 'test1'},
 1250                  {'url': 'test2'}])
 1251 
 1252             self.assertTrue(mock_log.called)
 1253             mock_update_service.simple_update.assert_called_once_with('test2')
 1254             self.assertIsNotNone(
 1255                 task.node.driver_internal_info['firmware_updates'])
 1256             self.assertEqual(
 1257                 [{'url': 'test2', 'task_monitor': '/task/987'}],
 1258                 task.node.driver_internal_info['firmware_updates'])
 1259             task.node.save.assert_called_once_with()
 1260             mock_node_power_action.assert_called_once_with(task, states.REBOOT)