Update export system configuration

- Add optional parameters export_use and include_in_export to private
export system configuration method.
- Add public export_system_configuration method.

Story: 2003594
Task: 41575

Change-Id: Id8d66cdec203308771ab4cb8909505f96b984296
This commit is contained in:
Aija Jauntēva 2020-10-23 07:42:44 -04:00 committed by Richard G. Pioso
parent 1020e805d3
commit 03278551f1
4 changed files with 259 additions and 8 deletions

View File

@ -58,3 +58,56 @@ IMPORT_SHUTDOWN_NO_REBOOT = 'no shutdown'
No shutdown performed. Explicit reboot is necessary to apply changes. No shutdown performed. Explicit reboot is necessary to apply changes.
""" """
# ExportUse in ExportSystemConfiguration
EXPORT_USE_DEFAULT = 'Default'
"""Default export type
Leaves some attributes commented out and requires user to enable them before
they can be applied during import.
"""
EXPORT_USE_CLONE = 'Clone'
"""Clone export type suitable for cloning a 'golden' configuration.
Compared to Default export type, more attributes are enabled and
storage settings adjusted to aid in cloning process.
"""
EXPORT_USE_REPLACE = 'Replace'
"""Replace export type suited for retiring or replacing complete configuration.
Compared to Clone export type, most attributes are enabled and storage settings
adjusted to aid in the replace process.
"""
# IncludeInExport in ExportSystemConfiguration
INCLUDE_EXPORT_DEFAULT = 'Default'
"""Default for what to include in export.
Does not include read-only attributes, and depending on Export Use, passwords
are marked as ****** (for Default) or are set to default password values (for
Clone and Replace).
"""
INCLUDE_EXPORT_READ_ONLY = 'Include read only attributes'
"""Includes read-only attributes.
In addition to values included by Default option, this also includes read-only
attributes that cannot be changed via Import and are provided for informational
purposes only.
"""
INCLUDE_EXPORT_PASSWORD_HASHES = 'Include password hash values'
"""Include password hashes.
When using Clone or Replace, include password hashes, instead of default
password. Can be used to replicate passwords across systems.
"""
INCLUDE_EXPORT_READ_ONLY_PASSWORD_HASHES = ('Include read only attributes and '
'password hash values')
"""Includes both read-only attributes and password hashes.
INCLUDE_EXPORT_READ_ONLY and INCLUDE_EXPORT_PASSWORD_HASHES combined
"""

View File

@ -47,6 +47,10 @@ class SharedParameters(base.CompositeField):
class ExportActionField(common.ActionField): class ExportActionField(common.ActionField):
shared_parameters = SharedParameters('ShareParameters') shared_parameters = SharedParameters('ShareParameters')
allowed_export_use_values = base.Field(
'ExportUse@Redfish.AllowableValues', adapter=list)
allowed_include_in_export_values = base.Field(
'IncludeInExport@Redfish.AllowableValues', adapter=list)
class ImportActionField(common.ActionField): class ImportActionField(common.ActionField):
@ -270,18 +274,60 @@ VFDD\
set(mgr_maps.EXPORT_CONFIG_VALUE_MAP). set(mgr_maps.EXPORT_CONFIG_VALUE_MAP).
intersection(allowed_values)]) intersection(allowed_values)])
def _export_system_configuration(self, target): def get_allowed_export_use_values(self):
"""Get allowed export use values of export system configuration.
:returns: A set of allowed export use values.
"""
export_action = self._actions.export_system_configuration
allowed_values = export_action.allowed_export_use_values
if not allowed_values:
LOG.warning('Could not figure out the allowed values for the '
'export use of export system configuration at %s',
self.path)
return set(mgr_maps.EXPORT_USE_VALUE_MAP_REV)
return set([mgr_maps.EXPORT_USE_VALUE_MAP[value] for value in
set(mgr_maps.EXPORT_USE_VALUE_MAP).
intersection(allowed_values)])
def get_allowed_include_in_export_values(self):
"""Get allowed include in export values of export system configuration.
:returns: A set of allowed include in export values.
"""
export_action = self._actions.export_system_configuration
allowed_values = export_action.allowed_include_in_export_values
if not allowed_values:
LOG.warning('Could not figure out the allowed values for the '
'include in export of export system configuration at '
'%s', self.path)
return set(mgr_maps.INCLUDE_EXPORT_VALUE_MAP_REV)
return set([mgr_maps.INCLUDE_EXPORT_VALUE_MAP[value] for value
in set(mgr_maps.INCLUDE_EXPORT_VALUE_MAP).
intersection(allowed_values)])
def _export_system_configuration(
self, target, export_use=mgr_cons.EXPORT_USE_DEFAULT,
include_in_export=mgr_cons.INCLUDE_EXPORT_DEFAULT):
"""Export system configuration. """Export system configuration.
It exports system configuration for specified target It exports system configuration for specified target like NIC, BIOS,
like NIC, BIOS, RAID. RAID and allows to configure purpose for export and what to include.
:param target: Component of the system to export the :param target: Component of the system to export the
configuration from. Can be the entire system. configuration from. Can be the entire system.
Valid values can be gotten from Valid values can be gotten from
`get_allowed_export_target_values`. `get_allowed_export_system_config_values`.
:returns: a response object containing configuration details for :param export_use: Export use. Optional, defaults to "Default".
the specified target. Valid values can be gotten from `get_allowed_export_use_values`.
:param include_in_export: What to include in export. Optional. Defaults
to "Default". Valid values can be gotten from
`get_allowed_include_in_export_values`.
:returns: Response object containing configuration details.
:raises: InvalidParameterValueError on invalid target. :raises: InvalidParameterValueError on invalid target.
:raises: ExtensionError on failure to perform requested :raises: ExtensionError on failure to perform requested
operation operation
@ -292,13 +338,30 @@ VFDD\
parameter='target', value=target, parameter='target', value=target,
valid_values=valid_allowed_targets) valid_values=valid_allowed_targets)
allowed_export_use = self.get_allowed_export_use_values()
if export_use not in allowed_export_use:
raise sushy.exceptions.InvalidParameterValueError(
parameter='export_use', value=export_use,
valid_values=allowed_export_use)
allowed_include_in_export = self.get_allowed_include_in_export_values()
if include_in_export not in allowed_include_in_export:
raise sushy.exceptions.InvalidParameterValueError(
parameter='include_in_export', value=include_in_export,
valid_values=allowed_include_in_export)
target = mgr_maps.EXPORT_CONFIG_VALUE_MAP_REV[target] target = mgr_maps.EXPORT_CONFIG_VALUE_MAP_REV[target]
export_use = mgr_maps.EXPORT_USE_VALUE_MAP_REV[export_use]
include_in_export =\
mgr_maps.INCLUDE_EXPORT_VALUE_MAP_REV[include_in_export]
action_data = { action_data = {
'ShareParameters': { 'ShareParameters': {
'Target': target 'Target': target
}, },
'ExportFormat': "JSON" 'ExportFormat': "JSON",
'ExportUse': export_use,
'IncludeInExport': include_in_export
} }
try: try:
@ -318,6 +381,21 @@ VFDD\
LOG.error('Dell OEM export system configuration failed : %s', exc) LOG.error('Dell OEM export system configuration failed : %s', exc)
raise raise
def export_system_configuration(self):
"""Export system configuration.
Exports ALL targets for cloning and includes password hashes.
:returns: Response object containing configuration details.
:raises: InvalidParameterValueError on invalid target.
:raises: ExtensionError on failure to perform requested
operation
"""
return self._export_system_configuration(
mgr_cons.EXPORT_TARGET_ALL,
export_use=mgr_cons.EXPORT_USE_CLONE,
include_in_export=mgr_cons.INCLUDE_EXPORT_PASSWORD_HASHES)
def get_pxe_port_macs_bios(self, ethernet_interfaces_mac): def get_pxe_port_macs_bios(self, ethernet_interfaces_mac):
"""Get a list of pxe port MAC addresses for BIOS. """Get a list of pxe port MAC addresses for BIOS.

View File

@ -41,3 +41,23 @@ IMPORT_SHUTDOWN_VALUE_MAP = {
IMPORT_SHUTDOWN_VALUE_MAP_REV =\ IMPORT_SHUTDOWN_VALUE_MAP_REV =\
utils.revert_dictionary(IMPORT_SHUTDOWN_VALUE_MAP) utils.revert_dictionary(IMPORT_SHUTDOWN_VALUE_MAP)
EXPORT_USE_VALUE_MAP = {
'Default': mgr_cons.EXPORT_USE_DEFAULT,
'Clone': mgr_cons.EXPORT_USE_CLONE,
'Replace': mgr_cons.EXPORT_USE_REPLACE
}
EXPORT_USE_VALUE_MAP_REV = utils.revert_dictionary(EXPORT_USE_VALUE_MAP)
INCLUDE_EXPORT_VALUE_MAP = {
'Default': mgr_cons.INCLUDE_EXPORT_DEFAULT,
'IncludeReadOnly': mgr_cons.INCLUDE_EXPORT_READ_ONLY,
'IncludePasswordHashValues':
mgr_cons.INCLUDE_EXPORT_PASSWORD_HASHES,
'IncludeReadOnly,IncludePasswordHashValues':
mgr_cons.INCLUDE_EXPORT_READ_ONLY_PASSWORD_HASHES
}
INCLUDE_EXPORT_VALUE_MAP_REV =\
utils.revert_dictionary(INCLUDE_EXPORT_VALUE_MAP)

View File

@ -100,7 +100,26 @@ class ManagerTestCase(BaseTestCase):
'/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager' '/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager'
'.ExportSystemConfiguration', data={'ShareParameters': '.ExportSystemConfiguration', data={'ShareParameters':
{'Target': 'ALL'}, {'Target': 'ALL'},
'ExportFormat': 'JSON'}) 'ExportFormat': 'JSON',
'ExportUse': 'Default',
'IncludeInExport': 'Default'})
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test__export_system_configuration_nondefault(self):
oem = self.manager.get_oem_extension('Dell')
oem._export_system_configuration(
target=mgr_cons.EXPORT_TARGET_RAID,
export_use=mgr_cons.EXPORT_USE_CLONE,
include_in_export=mgr_cons.INCLUDE_EXPORT_READ_ONLY)
self.conn.post.assert_called_once_with(
'/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager'
'.ExportSystemConfiguration', data={'ShareParameters':
{'Target': 'RAID'},
'ExportFormat': 'JSON',
'ExportUse': 'Clone',
'IncludeInExport':
'IncludeReadOnly'})
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test__export_system_configuration_invalid_target(self): def test__export_system_configuration_invalid_target(self):
@ -109,6 +128,87 @@ class ManagerTestCase(BaseTestCase):
self.assertRaises(sushy.exceptions.InvalidParameterValueError, self.assertRaises(sushy.exceptions.InvalidParameterValueError,
oem._export_system_configuration, target) oem._export_system_configuration, target)
def test__export_system_configuration_invalid_export_use(self):
oem = self.manager.get_oem_extension('Dell')
self.assertRaises(sushy.exceptions.InvalidParameterValueError,
oem._export_system_configuration, "RAID",
export_use="ABC")
def test__export_system_configuration_invalid_include_in_export(self):
oem = self.manager.get_oem_extension('Dell')
self.assertRaises(sushy.exceptions.InvalidParameterValueError,
oem._export_system_configuration, "RAID",
include_in_export="ABC")
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_get_allowed_export_use_values(self):
oem = self.manager.get_oem_extension('Dell')
expected_values = {mgr_cons.EXPORT_USE_DEFAULT,
mgr_cons.EXPORT_USE_CLONE,
mgr_cons.EXPORT_USE_REPLACE}
allowed_values = oem.get_allowed_export_use_values()
self.assertIsInstance(allowed_values, set)
self.assertEqual(expected_values, allowed_values)
@mock.patch.object(oem_manager, 'LOG', autospec=True)
def test_get_allowed_export_use_values_missing(self, mock_log):
oem = self.manager.get_oem_extension('Dell')
export_action = ('OemManager.v1_0_0'
'#OemManager.ExportSystemConfiguration')
oem.json['Actions']['Oem'][export_action].pop(
'ExportUse@Redfish.AllowableValues')
oem.refresh()
expected_values = {mgr_cons.EXPORT_USE_DEFAULT,
mgr_cons.EXPORT_USE_CLONE,
mgr_cons.EXPORT_USE_REPLACE}
allowed_values = oem.get_allowed_export_use_values()
self.assertIsInstance(allowed_values, set)
self.assertEqual(expected_values, allowed_values)
mock_log.warning.assert_called_once()
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_get_allowed_include_in_export_values(self):
oem = self.manager.get_oem_extension('Dell')
expected_values = {mgr_cons.INCLUDE_EXPORT_DEFAULT,
mgr_cons.INCLUDE_EXPORT_READ_ONLY,
mgr_cons.INCLUDE_EXPORT_PASSWORD_HASHES,
mgr_cons.INCLUDE_EXPORT_READ_ONLY_PASSWORD_HASHES}
allowed_values = oem.get_allowed_include_in_export_values()
self.assertIsInstance(allowed_values, set)
self.assertEqual(expected_values, allowed_values)
@mock.patch.object(oem_manager, 'LOG', autospec=True)
def test_get_allowed_include_in_export_values_missing(self, mock_log):
oem = self.manager.get_oem_extension('Dell')
export_action = ('OemManager.v1_0_0'
'#OemManager.ExportSystemConfiguration')
oem.json['Actions']['Oem'][export_action].pop(
'IncludeInExport@Redfish.AllowableValues')
oem.refresh()
expected_values = {mgr_cons.INCLUDE_EXPORT_DEFAULT,
mgr_cons.INCLUDE_EXPORT_READ_ONLY,
mgr_cons.INCLUDE_EXPORT_PASSWORD_HASHES,
mgr_cons.INCLUDE_EXPORT_READ_ONLY_PASSWORD_HASHES}
allowed_values = oem.get_allowed_include_in_export_values()
self.assertIsInstance(allowed_values, set)
self.assertEqual(expected_values, allowed_values)
mock_log.warning.assert_called_once()
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_export_system_configuration(self):
oem = self.manager.get_oem_extension('Dell')
oem._export_system_configuration = mock.Mock()
mock_response = mock.Mock()
oem._export_system_configuration.return_value = mock_response
response = oem.export_system_configuration()
self.assertEqual(mock_response, response)
oem._export_system_configuration.assert_called_once_with(
mgr_cons.EXPORT_TARGET_ALL,
export_use=mgr_cons.EXPORT_USE_CLONE,
include_in_export=mgr_cons.INCLUDE_EXPORT_PASSWORD_HASHES)
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_get_pxe_port_macs_bios(self): def test_get_pxe_port_macs_bios(self):
oem = self.manager.get_oem_extension('Dell') oem = self.manager.get_oem_extension('Dell')