Add destructive field flag to export configuration

New optional parameter added to export configuration method to control
if destructive iDRAC settings, such as those that could cause loss of
network access, are exported. It is also unlikely that these fields
are necessary during import to replicate same static IP address
settings. User can still put these fields back during import.

Change-Id: Iad39267fedf1c1a7381d03152eb0cea0c114eede
This commit is contained in:
Aija Jauntēva 2021-11-04 07:08:13 -04:00
parent 797e085483
commit 8fb44bc93f
3 changed files with 227 additions and 2 deletions

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import json
import logging
import subprocess
import time
@ -42,6 +43,12 @@ _SYSTEM_CONFIG_TAG = "SystemConfiguration"
# Response Code Constant
_RESPONSE_OK_CODE = 200
# Structure {'Component FQDD': (tuple of beginning of Attribute keys)}
_DESTRUCTIVE_CONF_KEYS = {
'iDRAC.Embedded.1':
('IPv4Static', 'IPv6Static', 'IPv4.1#Enable', 'IPv4.1#DHCPEnable',
'IPv6.1#Enable', 'IPv6.1#AutoConfig')}
class SharedParameters(base.CompositeField):
allowed_target_values = base.Field('Target@Redfish.AllowableValues')
@ -411,23 +418,44 @@ VFDD\
LOG.error('Dell OEM export system configuration failed : %s', exc)
raise
def export_system_configuration(self):
def export_system_configuration(self, include_destructive_fields=True):
"""Export system configuration.
Exports ALL targets for cloning and includes password hashes and
read-only attributes.
:param include_destructive_fields: Whether includes settings such as
iDRAC static IP address that could lead to losing access to iDRAC
if importing this configuration into another system. Default to
True for backward compability. False recommended if unsure.
:returns: Response object containing configuration details.
:raises: InvalidParameterValueError on invalid target.
:raises: ExtensionError on failure to perform requested
operation
"""
include_in_export = mgr_cons.INCLUDE_EXPORT_READ_ONLY_PASSWORD_HASHES
return self._export_system_configuration(
response = self._export_system_configuration(
mgr_cons.EXPORT_TARGET_ALL,
export_use=mgr_cons.EXPORT_USE_CLONE,
include_in_export=include_in_export)
if (response.status_code == _RESPONSE_OK_CODE
and not include_destructive_fields):
conf = response.json()
if _SYSTEM_CONFIG_TAG in conf.keys():
for fqdd, values in _DESTRUCTIVE_CONF_KEYS.items():
for comp in conf[_SYSTEM_CONFIG_TAG]['Components']:
if comp['FQDD'] == fqdd:
attributes_copy = comp['Attributes'].copy()
for child in comp['Attributes']:
if child.get('Name').startswith(values):
attributes_copy.remove(child)
comp['Attributes'] = attributes_copy
response._content = json.dumps(conf).encode()
return response
def get_pxe_port_macs_bios(self, ethernet_interfaces_mac):
"""Get a list of pxe port MAC addresses for BIOS.

View File

@ -0,0 +1,174 @@
{ "SystemConfiguration": {
"Comments": [
{ "Comment": "Export type is Clone,RO,JSON,IncludeHash,Selective" },
{ "Comment": "Exported configuration may contain commented attributes. Attributes may be commented due to dependency, destructive nature, preserving server identity or for security reasons." }
],
"Model": "PowerEdge R640",
"ServiceTag": "ABC1234",
"TimeStamp": "Thu Nov 4 07:21:54 2021",
"Components": [
{ "FQDD": "iDRAC.Embedded.1",
"Attributes": [
{ "Name": "Info.1#Product",
"Value": "Integrated Dell Remote Access Controller",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "Info.1#Description",
"Value": "This system component provides a complete set of remote management functions for Dell PowerEdge Servers",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "Info.1#Version",
"Value": "5.00.10.20",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "Info.1#Build",
"Value": "01",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "Info.1#Name",
"Value": "iDRAC",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "Info.1#Type",
"Value": "14G Monolithic",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "Info.1#ServerGen",
"Value": "14G",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv4.1#Enable",
"Value": "Enabled",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv4.1#DHCPEnable",
"Value": "Disabled",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv6.1#Enable",
"Value": "Disabled",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv6.1#AutoConfig",
"Value": "Enabled",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv6.1#LinkLocalAddress",
"Value": "2001:db8:3333:4444:5555:6666:7777:8888",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address2",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address3",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address4",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address5",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address6",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address7",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address8",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address9",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address10",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address11",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address12",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address13",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address14",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#Address15",
"Value": "::",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#AddressState",
"Value": "Active",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv6.1#DUID",
"Value": "00:01:00:01:25:67:39:1b:f4:02:70:db:6c:88",
"Set On Import": "False",
"Comment": "Always Read Only" },
{ "Name": "IPv4Static.1#Address",
"Value": "192.168.88.13",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv4Static.1#Netmask",
"Value": "255.255.255.0",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv4Static.1#Gateway",
"Value": "192.168.88.1",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv4Static.1#DNS1",
"Value": "0.0.0.0",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv4Static.1#DNS2",
"Value": "0.0.0.0",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv4Static.1#DNSFromDHCP",
"Value": "Disabled",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv6Static.1#Address1",
"Value": "::",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv6Static.1#Gateway",
"Value": "::",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv6Static.1#PrefixLength",
"Value": "64",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv6Static.1#DNS1",
"Value": "::",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv6Static.1#DNS2",
"Value": "::",
"Set On Import": "True",
"Comment": "Read and Write" },
{ "Name": "IPv6Static.1#DNSFromDHCP6",
"Value": "Disabled",
"Set On Import": "True",
"Comment": "Read and Write" }
]}
]}
}

View File

@ -295,6 +295,29 @@ class ManagerTestCase(BaseTestCase):
export_use=mgr_cons.EXPORT_USE_CLONE,
include_in_export=include_in_export)
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_export_system_configuration_destructive_fields(self):
oem = self.manager.get_oem_extension('Dell')
oem._export_system_configuration = mock.Mock()
with open('sushy_oem_idrac/tests/unit/json_samples/'
'export_configuration_idrac.json') as f:
mock_response = oem._export_system_configuration.return_value
mock_response.json.return_value = json.load(f)
mock_response.status_code = 200
response = oem.export_system_configuration(
include_destructive_fields=False)
response_json = json.loads(response._content)
# From 40 items in test data 16 should be removed
self.assertEqual(24, len(response_json['SystemConfiguration']
['Components'][0]['Attributes']))
include_in_export = mgr_cons.INCLUDE_EXPORT_READ_ONLY_PASSWORD_HASHES
oem._export_system_configuration.assert_called_once_with(
mgr_cons.EXPORT_TARGET_ALL,
export_use=mgr_cons.EXPORT_USE_CLONE,
include_in_export=include_in_export)
@mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {})
def test_get_pxe_port_macs_bios(self):
oem = self.manager.get_oem_extension('Dell')