Adds steps 'apply_configuration' and 'flash_firmware_sum'
Following inband deploy steps are added: 1. 'apply_configuration' is added for 'raid' interface. 2. 'flash_firmware_sum' is added for 'management' interface. Change-Id: I42e153aaa52befb13d0471a2a1f0a2401684aaea
This commit is contained in:
parent
6e03a55374
commit
5dc26eb950
@ -15,8 +15,48 @@
|
||||
from ironic_python_agent import hardware
|
||||
|
||||
from proliantutils.hpssa import manager as hpssa_manager
|
||||
from proliantutils import log
|
||||
from proliantutils.sum import sum_controller
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
|
||||
_RAID_APPLY_CONFIGURATION_ARGSINFO = {
|
||||
"raid_config": {
|
||||
"description": "The RAID configuration to apply.",
|
||||
"required": True,
|
||||
},
|
||||
"delete_existing": {
|
||||
"description": (
|
||||
"Setting this to 'True' indicates to delete existing RAID "
|
||||
"configuration prior to creating the new configuration. "
|
||||
"Default value is 'True'."
|
||||
),
|
||||
"required": False,
|
||||
}
|
||||
}
|
||||
|
||||
_FIRMWARE_UPDATE_SUM_ARGSINFO = {
|
||||
'url': {
|
||||
'description': (
|
||||
"The image location for SPP (Service Pack for Proliant) ISO."
|
||||
),
|
||||
'required': True,
|
||||
},
|
||||
'checksum': {
|
||||
'description': (
|
||||
"The md5 checksum of the SPP image file."
|
||||
),
|
||||
'required': True,
|
||||
},
|
||||
'components': {
|
||||
'description': (
|
||||
"The list of firmware component filenames. If not specified, "
|
||||
"SUM updates all the firmware components."
|
||||
),
|
||||
'required': False,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ProliantHardwareManager(hardware.GenericHardwareManager):
|
||||
|
||||
@ -36,22 +76,96 @@ class ProliantHardwareManager(hardware.GenericHardwareManager):
|
||||
:returns: A list of dictionaries, each item containing the step name,
|
||||
interface and priority for the clean step.
|
||||
"""
|
||||
return [{'step': 'create_configuration',
|
||||
return [
|
||||
{
|
||||
'step': 'create_configuration',
|
||||
'interface': 'raid',
|
||||
'priority': 0},
|
||||
{'step': 'delete_configuration',
|
||||
'priority': 0,
|
||||
'reboot_requested': False,
|
||||
},
|
||||
{
|
||||
'step': 'delete_configuration',
|
||||
'interface': 'raid',
|
||||
'priority': 0},
|
||||
{'step': 'erase_devices',
|
||||
'priority': 0,
|
||||
'reboot_requested': False,
|
||||
},
|
||||
{
|
||||
'step': 'erase_devices',
|
||||
'interface': 'deploy',
|
||||
'priority': 0},
|
||||
{'step': 'update_firmware_sum',
|
||||
'priority': 0,
|
||||
'reboot_requested': False,
|
||||
},
|
||||
{
|
||||
'step': 'update_firmware_sum',
|
||||
'interface': 'management',
|
||||
'priority': 0}]
|
||||
'priority': 0,
|
||||
'reboot_requested': False,
|
||||
},
|
||||
]
|
||||
|
||||
def get_deploy_steps(self, node, ports):
|
||||
"""Return the deploy steps supported by this hardware manager.
|
||||
|
||||
This method returns the deploy steps that are supported by
|
||||
proliant hardware manager. This method is invoked on every
|
||||
hardware manager by Ironic Python Agent to give this information
|
||||
back to Ironic.
|
||||
|
||||
:param node: A dictionary of the node object
|
||||
:param ports: A list of dictionaries containing information of ports
|
||||
for the node
|
||||
:returns: A list of dictionaries, each item containing the step name,
|
||||
interface, priority, reboot_requested and
|
||||
argsinfo for the deploy step.
|
||||
"""
|
||||
return [
|
||||
{
|
||||
'step': 'apply_configuration',
|
||||
'interface': 'raid',
|
||||
'priority': 0,
|
||||
'reboot_requested': False,
|
||||
'argsinfo': _RAID_APPLY_CONFIGURATION_ARGSINFO,
|
||||
},
|
||||
{
|
||||
'step': 'flash_firmware_sum',
|
||||
'interface': 'management',
|
||||
'priority': 0,
|
||||
'reboot_requested': False,
|
||||
'argsinfo': _FIRMWARE_UPDATE_SUM_ARGSINFO,
|
||||
},
|
||||
]
|
||||
|
||||
def evaluate_hardware_support(cls):
|
||||
return hardware.HardwareSupport.SERVICE_PROVIDER
|
||||
|
||||
def apply_configuration(self, node, ports, raid_config,
|
||||
delete_existing=True):
|
||||
"""Apply RAID configuration.
|
||||
|
||||
:param node: A dictionary of the node object.
|
||||
:param ports: A list of dictionaries containing information
|
||||
of ports for the node.
|
||||
:param raid_config: The configuration to apply.
|
||||
:param delete_existing: Whether to delete the existing configuration.
|
||||
:returns: The current RAID configuration of the below format.
|
||||
raid_config = {
|
||||
'logical_disks': [{
|
||||
'size_gb': 100,
|
||||
'raid_level': 1,
|
||||
'physical_disks': [
|
||||
'5I:0:1',
|
||||
'5I:0:2'],
|
||||
'controller': 'Smart array controller'
|
||||
},
|
||||
]
|
||||
}
|
||||
"""
|
||||
if delete_existing:
|
||||
self.delete_configuration(node, ports)
|
||||
LOG.debug("Creating raid with configuration %(raid_config)s",
|
||||
{'raid_config': raid_config})
|
||||
return hpssa_manager.create_configuration(raid_config=raid_config)
|
||||
|
||||
def create_configuration(self, node, ports):
|
||||
"""Create RAID configuration on the bare metal.
|
||||
|
||||
@ -75,6 +189,12 @@ class ProliantHardwareManager(hardware.GenericHardwareManager):
|
||||
}
|
||||
"""
|
||||
target_raid_config = node.get('target_raid_config', {}).copy()
|
||||
if not target_raid_config:
|
||||
LOG.debug("No target_raid_config found")
|
||||
return {}
|
||||
|
||||
LOG.debug("Creating raid with configuration %(raid_config)s",
|
||||
{'raid_config': target_raid_config})
|
||||
return hpssa_manager.create_configuration(
|
||||
raid_config=target_raid_config)
|
||||
|
||||
@ -114,10 +234,40 @@ class ProliantHardwareManager(hardware.GenericHardwareManager):
|
||||
|
||||
This method performs firmware update on all or some of the firmware
|
||||
components on the bare metal node.
|
||||
|
||||
:param node: A dictionary of the node object.
|
||||
:param port: A list of dictionaries containing information of ports
|
||||
for the node.
|
||||
:returns: A string with return code and the statistics of
|
||||
updated/failed components.
|
||||
:raises: SUMOperationError, when the SUM based firmware update
|
||||
operation on the node fails.
|
||||
"""
|
||||
return sum_controller.update_firmware(node)
|
||||
url = node['clean_step']['args'].get('url')
|
||||
checksum = node['clean_step']['args'].get('checksum')
|
||||
components = node['clean_step']['args'].get('components')
|
||||
return sum_controller.update_firmware(node, url, checksum,
|
||||
components=components)
|
||||
|
||||
def flash_firmware_sum(self, node, port, url,
|
||||
checksum, components=None):
|
||||
"""Performs SUM based firmware update on the bare metal node.
|
||||
|
||||
This method performs firmware update on all or some of the firmware
|
||||
components on the bare metal node.
|
||||
:param node: A dictionary of the node object.
|
||||
:param port: A list of dictionaries containing information of ports
|
||||
for the node.
|
||||
:param url: URL of SPP (Service Pack for Proliant) ISO.
|
||||
:param checksum: MD5 checksum of SPP ISO to verify the image.
|
||||
:param components: List of filenames of the firmware components to be
|
||||
flashed. If not provided, the firmware update is performed on all
|
||||
the firmware components.
|
||||
:returns: A string with return code and the statistics of
|
||||
updated/failed components.
|
||||
:raises: SUMOperationError, when the SUM based firmware update
|
||||
operation on the node fails.
|
||||
"""
|
||||
LOG.debug("Flashing firmware from %(url)s for components %(comp)s",
|
||||
{'url': url, 'comp': components})
|
||||
return sum_controller.update_firmware(node, url, checksum,
|
||||
components=components)
|
||||
|
@ -155,25 +155,28 @@ def _parse_sum_ouput(exit_code):
|
||||
return "UPDATE STATUS: UNKNOWN"
|
||||
|
||||
|
||||
def update_firmware(node):
|
||||
def update_firmware(node, url, checksum, components=None):
|
||||
"""Performs SUM based firmware update on the node.
|
||||
|
||||
This method performs SUM firmware update by mounting the
|
||||
SPP ISO on the node. It performs firmware update on all or
|
||||
some of the firmware components.
|
||||
|
||||
:param node: A node object of type dict.
|
||||
:param node: A dictionary of the node object.
|
||||
:param url: URL of SPP (Service Pack for Proliant) ISO.
|
||||
:param checksum: MD5 checksum of SPP ISO to verify the image.
|
||||
:param components: List of filenames of the firmware components to be
|
||||
flashed. If not provided, the firmware update is performed on all
|
||||
the firmware components.
|
||||
:returns: Operation Status string.
|
||||
:raises: SUMOperationError, when the vmedia device is not found or
|
||||
when the mount operation fails or when the image validation fails.
|
||||
:raises: IloConnectionError, when the iLO connection fails.
|
||||
:raises: IloError, when vmedia eject or insert operation fails.
|
||||
"""
|
||||
sum_update_iso = node['clean_step']['args'].get('url')
|
||||
|
||||
# Validates the http image reference for SUM update ISO.
|
||||
try:
|
||||
utils.validate_href(sum_update_iso)
|
||||
utils.validate_href(url)
|
||||
except exception.ImageRefValidationFailed as e:
|
||||
raise exception.SUMOperationError(reason=e)
|
||||
|
||||
@ -181,9 +184,9 @@ def update_firmware(node):
|
||||
# is identified by matching its label.
|
||||
time.sleep(WAIT_TIME_DISK_LABEL_TO_BE_VISIBLE)
|
||||
vmedia_device_dir = "/dev/disk/by-label/"
|
||||
for file in os.listdir(vmedia_device_dir):
|
||||
if fnmatch.fnmatch(file, 'SPP*'):
|
||||
vmedia_device_file = os.path.join(vmedia_device_dir, file)
|
||||
for fname in os.listdir(vmedia_device_dir):
|
||||
if fnmatch.fnmatch(fname, 'SPP*'):
|
||||
vmedia_device_file = os.path.join(vmedia_device_dir, fname)
|
||||
|
||||
if not os.path.exists(vmedia_device_file):
|
||||
msg = "Unable to find the virtual media device for SUM"
|
||||
@ -191,9 +194,8 @@ def update_firmware(node):
|
||||
|
||||
# Validates the SPP ISO image for any file corruption using the checksum
|
||||
# of the ISO file.
|
||||
expected_checksum = node['clean_step']['args'].get('checksum')
|
||||
try:
|
||||
utils.verify_image_checksum(vmedia_device_file, expected_checksum)
|
||||
utils.verify_image_checksum(vmedia_device_file, checksum)
|
||||
except exception.ImageRefValidationFailed as e:
|
||||
raise exception.SUMOperationError(reason=e)
|
||||
|
||||
@ -215,7 +217,6 @@ def update_firmware(node):
|
||||
if not os.path.exists(sum_file_path):
|
||||
sum_file_path = os.path.join(vmedia_mount_point, HPSUM_LOCATION)
|
||||
|
||||
components = node['clean_step']['args'].get('components')
|
||||
result = _execute_sum(sum_file_path, vmedia_mount_point,
|
||||
components=components)
|
||||
|
||||
|
@ -28,24 +28,54 @@ class ProliantHardwareManagerTestCase(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.hardware_manager = hardware_manager.ProliantHardwareManager()
|
||||
self.info = {'ilo_address': '1.2.3.4',
|
||||
'ilo_password': '12345678',
|
||||
'ilo_username': 'admin'}
|
||||
clean_step = {
|
||||
'interface': 'management',
|
||||
'step': 'update_firmware_sum',
|
||||
'args': {'url': 'http://1.2.3.4/SPP.iso',
|
||||
'checksum': '1234567890'}}
|
||||
self.node = {'driver_info': self.info,
|
||||
'clean_step': clean_step}
|
||||
super(ProliantHardwareManagerTestCase, self).setUp()
|
||||
|
||||
def test_get_clean_steps(self):
|
||||
self.assertEqual(
|
||||
[{'step': 'create_configuration',
|
||||
'interface': 'raid',
|
||||
'priority': 0},
|
||||
'priority': 0,
|
||||
'reboot_requested': False},
|
||||
{'step': 'delete_configuration',
|
||||
'interface': 'raid',
|
||||
'priority': 0},
|
||||
'priority': 0,
|
||||
'reboot_requested': False},
|
||||
{'step': 'erase_devices',
|
||||
'interface': 'deploy',
|
||||
'priority': 0},
|
||||
'priority': 0,
|
||||
'reboot_requested': False},
|
||||
{'step': 'update_firmware_sum',
|
||||
'interface': 'management',
|
||||
'priority': 0}],
|
||||
'priority': 0,
|
||||
'reboot_requested': False}],
|
||||
self.hardware_manager.get_clean_steps("", ""))
|
||||
|
||||
def test_get_deploy_steps(self):
|
||||
self.assertEqual(
|
||||
[{'step': 'apply_configuration',
|
||||
'interface': 'raid',
|
||||
'reboot_requested': False,
|
||||
'priority': 0,
|
||||
'argsinfo': (
|
||||
hardware_manager._RAID_APPLY_CONFIGURATION_ARGSINFO)},
|
||||
{'step': 'flash_firmware_sum',
|
||||
'interface': 'management',
|
||||
'reboot_requested': False,
|
||||
'priority': 0,
|
||||
'argsinfo': (
|
||||
hardware_manager._FIRMWARE_UPDATE_SUM_ARGSINFO)}],
|
||||
self.hardware_manager.get_deploy_steps("", []))
|
||||
|
||||
@mock.patch.object(hpssa_manager, 'create_configuration')
|
||||
def test_create_configuration(self, create_mock):
|
||||
create_mock.return_value = 'current-config'
|
||||
@ -55,6 +85,40 @@ class ProliantHardwareManagerTestCase(testtools.TestCase):
|
||||
create_mock.assert_called_once_with(raid_config={'foo': 'bar'})
|
||||
self.assertEqual('current-config', ret)
|
||||
|
||||
@mock.patch.object(hpssa_manager, 'create_configuration')
|
||||
def test_create_configuration_no_target_config(self, create_mock):
|
||||
create_mock.return_value = 'current-config'
|
||||
manager = self.hardware_manager
|
||||
node = {'target_raid_config': {}}
|
||||
manager.create_configuration(node, [])
|
||||
create_mock.assert_not_called()
|
||||
|
||||
@mock.patch.object(hardware_manager.ProliantHardwareManager,
|
||||
'delete_configuration')
|
||||
@mock.patch.object(hpssa_manager, 'create_configuration')
|
||||
def test_apply_configuration_with_delete(self, create_mock, delete_mock):
|
||||
create_mock.return_value = 'current-config'
|
||||
manager = self.hardware_manager
|
||||
raid_config = {'foo': 'bar'}
|
||||
ret = manager.apply_configuration("", [], raid_config,
|
||||
delete_existing=True)
|
||||
delete_mock.assert_called_once_with("", [])
|
||||
create_mock.assert_called_once_with(raid_config={'foo': 'bar'})
|
||||
self.assertEqual('current-config', ret)
|
||||
|
||||
@mock.patch.object(hardware_manager.ProliantHardwareManager,
|
||||
'delete_configuration')
|
||||
@mock.patch.object(hpssa_manager, 'create_configuration')
|
||||
def test_apply_configuration_no_delete(self, create_mock, delete_mock):
|
||||
create_mock.return_value = 'current-config'
|
||||
manager = self.hardware_manager
|
||||
raid_config = {'foo': 'bar'}
|
||||
ret = manager.apply_configuration("", [], raid_config,
|
||||
delete_existing=False)
|
||||
create_mock.assert_called_once_with(raid_config={'foo': 'bar'})
|
||||
delete_mock.assert_not_called()
|
||||
self.assertEqual('current-config', ret)
|
||||
|
||||
@mock.patch.object(hpssa_manager, 'delete_configuration')
|
||||
def test_delete_configuration(self, delete_mock):
|
||||
delete_mock.return_value = 'current-config'
|
||||
@ -96,7 +160,22 @@ class ProliantHardwareManagerTestCase(testtools.TestCase):
|
||||
@mock.patch.object(sum_controller, 'update_firmware')
|
||||
def test_update_firmware_sum(self, update_mock):
|
||||
update_mock.return_value = "log files"
|
||||
node = {'foo': 'bar'}
|
||||
ret = self.hardware_manager.update_firmware_sum(node, "")
|
||||
update_mock.assert_called_once_with(node)
|
||||
url = self.node['clean_step']['args'].get('url')
|
||||
csum = self.node['clean_step']['args'].get('checksum')
|
||||
comp = self.node['clean_step']['args'].get('components')
|
||||
ret = self.hardware_manager.update_firmware_sum(self.node, "")
|
||||
update_mock.assert_called_once_with(self.node, url, csum,
|
||||
components=comp)
|
||||
self.assertEqual('log files', ret)
|
||||
|
||||
@mock.patch.object(sum_controller, 'update_firmware')
|
||||
def test_flash_firmware_sum(self, update_mock):
|
||||
update_mock.return_value = "log files"
|
||||
url = self.node['clean_step']['args'].get('url')
|
||||
csum = self.node['clean_step']['args'].get('checksum')
|
||||
comp = self.node['clean_step']['args'].get('components')
|
||||
ret = self.hardware_manager.flash_firmware_sum(self.node, "", url,
|
||||
csum, components=comp)
|
||||
update_mock.assert_called_once_with(self.node, url, csum,
|
||||
components=comp)
|
||||
self.assertEqual('log files', ret)
|
||||
|
@ -16,6 +16,7 @@ import os
|
||||
import shutil
|
||||
import tarfile
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
import mock
|
||||
from oslo_concurrency import processutils
|
||||
@ -152,6 +153,7 @@ class SUMFirmwareUpdateTest(testtools.TestCase):
|
||||
os.remove(file_object.name)
|
||||
os.remove(tar_file.name)
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(utils, 'validate_href')
|
||||
@mock.patch.object(utils, 'verify_image_checksum')
|
||||
@mock.patch.object(sum_controller, '_execute_sum')
|
||||
@ -164,21 +166,23 @@ class SUMFirmwareUpdateTest(testtools.TestCase):
|
||||
def test_update_firmware(self, execute_mock, mkdir_mock,
|
||||
exists_mock, mkdtemp_mock, rmtree_mock,
|
||||
listdir_mock, execute_sum_mock,
|
||||
verify_image_mock, validate_mock):
|
||||
verify_image_mock, validate_mock, sleep_mock):
|
||||
execute_sum_mock.return_value = 'SUCCESS'
|
||||
listdir_mock.return_value = ['SPP_LABEL']
|
||||
mkdtemp_mock.return_value = "/tempdir"
|
||||
null_output = ["", ""]
|
||||
exists_mock.side_effect = [True, False]
|
||||
execute_mock.side_effect = [null_output, null_output]
|
||||
|
||||
ret_val = sum_controller.update_firmware(self.node)
|
||||
url = "http://a.b.c.d/spp.iso"
|
||||
checksum = "12345678"
|
||||
components = ['abc', 'pqr']
|
||||
ret_val = sum_controller.update_firmware(self.node, url, checksum,
|
||||
components)
|
||||
|
||||
execute_mock.assert_any_call('mount', "/dev/disk/by-label/SPP_LABEL",
|
||||
"/tempdir")
|
||||
execute_sum_mock.assert_any_call('/tempdir/hp/swpackages/hpsum',
|
||||
'/tempdir',
|
||||
components=None)
|
||||
'/tempdir', components=components)
|
||||
calls = [mock.call("/dev/disk/by-label/SPP_LABEL"),
|
||||
mock.call("/tempdir/packages/smartupdate")]
|
||||
exists_mock.assert_has_calls(calls, any_order=False)
|
||||
@ -187,6 +191,7 @@ class SUMFirmwareUpdateTest(testtools.TestCase):
|
||||
rmtree_mock.assert_called_once_with("/tempdir", ignore_errors=True)
|
||||
self.assertEqual('SUCCESS', ret_val)
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(utils, 'validate_href')
|
||||
@mock.patch.object(utils, 'verify_image_checksum')
|
||||
@mock.patch.object(sum_controller, '_execute_sum')
|
||||
@ -199,17 +204,22 @@ class SUMFirmwareUpdateTest(testtools.TestCase):
|
||||
def test_update_firmware_sum(self, execute_mock, mkdir_mock,
|
||||
exists_mock, mkdtemp_mock, rmtree_mock,
|
||||
listdir_mock, execute_sum_mock,
|
||||
verify_image_mock, validate_mock):
|
||||
verify_image_mock, validate_mock, sleep_mock):
|
||||
execute_sum_mock.return_value = 'SUCCESS'
|
||||
listdir_mock.return_value = ['SPP_LABEL']
|
||||
mkdtemp_mock.return_value = "/tempdir"
|
||||
null_output = ["", ""]
|
||||
exists_mock.side_effect = [True, True]
|
||||
execute_mock.side_effect = [null_output, null_output]
|
||||
exists_mock.side_effect = [True, True, True, True]
|
||||
execute_mock.side_effect = [null_output, null_output,
|
||||
null_output, null_output]
|
||||
url = "http://a.b.c.d/spp.iso"
|
||||
checksum = "12345678"
|
||||
|
||||
ret_val = sum_controller.update_firmware(self.node)
|
||||
ret_val = sum_controller.update_firmware(
|
||||
self.node, url, checksum)
|
||||
|
||||
execute_mock.assert_any_call('mount', "/dev/disk/by-label/SPP_LABEL",
|
||||
execute_mock.assert_any_call('mount',
|
||||
"/dev/disk/by-label/SPP_LABEL",
|
||||
"/tempdir")
|
||||
execute_sum_mock.assert_any_call('/tempdir/packages/smartupdate',
|
||||
'/tempdir',
|
||||
@ -226,41 +236,54 @@ class SUMFirmwareUpdateTest(testtools.TestCase):
|
||||
def test_update_firmware_throws_for_nonexistent_file(self,
|
||||
validate_href_mock):
|
||||
invalid_file_path = '/some/invalid/file/path'
|
||||
url = "http://a.b.c.d/spp.iso"
|
||||
checksum = "12345678"
|
||||
components = ['abc', 'pqr']
|
||||
value = ("Got HTTP code 503 instead of 200 in response to "
|
||||
"HEAD request.")
|
||||
validate_href_mock.side_effect = exception.ImageRefValidationFailed(
|
||||
reason=value, image_href=invalid_file_path)
|
||||
|
||||
exc = self.assertRaises(exception.SUMOperationError,
|
||||
sum_controller.update_firmware, self.node)
|
||||
sum_controller.update_firmware, self.node,
|
||||
url, checksum, components)
|
||||
self.assertIn(value, str(exc))
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(utils, 'validate_href')
|
||||
@mock.patch.object(os.path, 'exists')
|
||||
@mock.patch.object(os, 'listdir')
|
||||
def test_update_firmware_device_file_not_found(self,
|
||||
listdir_mock, exists_mock,
|
||||
validate_mock):
|
||||
validate_mock, sleep_mock):
|
||||
listdir_mock.return_value = ['SPP_LABEL']
|
||||
exists_mock.return_value = False
|
||||
url = "http://a.b.c.d/spp.iso"
|
||||
checksum = "12345678"
|
||||
components = ['abc', 'pqr']
|
||||
|
||||
msg = ("An error occurred while performing SUM based firmware "
|
||||
"update, reason: Unable to find the virtual media device "
|
||||
"for SUM")
|
||||
exc = self.assertRaises(exception.SUMOperationError,
|
||||
sum_controller.update_firmware, self.node)
|
||||
sum_controller.update_firmware, self.node,
|
||||
url, checksum, components=components)
|
||||
self.assertEqual(msg, str(exc))
|
||||
exists_mock.assert_called_once_with("/dev/disk/by-label/SPP_LABEL")
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(utils, 'validate_href')
|
||||
@mock.patch.object(utils, 'verify_image_checksum')
|
||||
@mock.patch.object(os, 'listdir')
|
||||
@mock.patch.object(os.path, 'exists')
|
||||
def test_update_firmware_invalid_checksum(self, exists_mock,
|
||||
listdir_mock, verify_image_mock,
|
||||
validate_mock):
|
||||
validate_mock, sleep_mock):
|
||||
listdir_mock.return_value = ['SPP_LABEL']
|
||||
exists_mock.side_effect = [True, False]
|
||||
url = "http://1.2.3.4/SPP.iso"
|
||||
checksum = "1234567890"
|
||||
components = ['abc', 'pqr']
|
||||
|
||||
value = ("Error verifying image checksum. Image "
|
||||
"http://1.2.3.4/SPP.iso failed to verify against checksum "
|
||||
@ -270,12 +293,14 @@ class SUMFirmwareUpdateTest(testtools.TestCase):
|
||||
reason=value, image_href='http://1.2.3.4/SPP.iso')
|
||||
|
||||
self.assertRaisesRegex(exception.SUMOperationError, value,
|
||||
sum_controller.update_firmware, self.node)
|
||||
sum_controller.update_firmware, self.node,
|
||||
url, checksum, components=components)
|
||||
|
||||
verify_image_mock.assert_called_once_with(
|
||||
'/dev/disk/by-label/SPP_LABEL', '1234567890')
|
||||
exists_mock.assert_called_once_with("/dev/disk/by-label/SPP_LABEL")
|
||||
|
||||
@mock.patch.object(time, 'sleep')
|
||||
@mock.patch.object(utils, 'validate_href')
|
||||
@mock.patch.object(utils, 'verify_image_checksum')
|
||||
@mock.patch.object(processutils, 'execute')
|
||||
@ -286,16 +311,20 @@ class SUMFirmwareUpdateTest(testtools.TestCase):
|
||||
def test_update_firmware_mount_fails(self, listdir_mock,
|
||||
exists_mock, mkdir_mock,
|
||||
mkdtemp_mock, execute_mock,
|
||||
verify_image_mock, validate_mock):
|
||||
verify_image_mock, validate_mock,
|
||||
sleep_mock):
|
||||
listdir_mock.return_value = ['SPP_LABEL']
|
||||
exists_mock.return_value = True
|
||||
mkdtemp_mock.return_value = "/tempdir"
|
||||
execute_mock.side_effect = processutils.ProcessExecutionError
|
||||
url = "http://a.b.c.d/spp.iso"
|
||||
checksum = "12345678"
|
||||
|
||||
msg = ("Unable to mount virtual media device "
|
||||
"/dev/disk/by-label/SPP_LABEL")
|
||||
exc = self.assertRaises(exception.SUMOperationError,
|
||||
sum_controller.update_firmware, self.node)
|
||||
sum_controller.update_firmware, self.node,
|
||||
url, checksum)
|
||||
self.assertIn(msg, str(exc))
|
||||
exists_mock.assert_called_once_with("/dev/disk/by-label/SPP_LABEL")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user