mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Fix to handle Redfish Gen2 Firmware upgrade (#8444)
* Fix to handle Redfish Gen2 Firmware upgrade * Fixed sanity checks and unit test cases * Added change log gragment * Updated change log fragment * Updated review comments --------- Co-authored-by: Adarsh Manjunath <adarsh.manjunath@wdc.com>
This commit is contained in:
parent
45972c23d4
commit
feb1ecbfcd
3 changed files with 62 additions and 12 deletions
2
changelogs/fragments/8444-fix-redfish-gen2-upgrade.yaml
Normal file
2
changelogs/fragments/8444-fix-redfish-gen2-upgrade.yaml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- wdc_redfish_command - minor change to handle upgrade file for Redfish WD platforms (https://github.com/ansible-collections/community.general/pull/8444).
|
|
@ -11,6 +11,7 @@ import datetime
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import tarfile
|
import tarfile
|
||||||
|
import os
|
||||||
|
|
||||||
from ansible.module_utils.urls import fetch_file
|
from ansible.module_utils.urls import fetch_file
|
||||||
from ansible_collections.community.general.plugins.module_utils.redfish_utils import RedfishUtils
|
from ansible_collections.community.general.plugins.module_utils.redfish_utils import RedfishUtils
|
||||||
|
@ -79,19 +80,25 @@ class WdcRedfishUtils(RedfishUtils):
|
||||||
return response
|
return response
|
||||||
return self._find_updateservice_additional_uris()
|
return self._find_updateservice_additional_uris()
|
||||||
|
|
||||||
def _is_enclosure_multi_tenant(self):
|
def _is_enclosure_multi_tenant_and_fetch_gen(self):
|
||||||
"""Determine if the enclosure is multi-tenant.
|
"""Determine if the enclosure is multi-tenant.
|
||||||
|
|
||||||
The serial number of a multi-tenant enclosure will end in "-A" or "-B".
|
The serial number of a multi-tenant enclosure will end in "-A" or "-B".
|
||||||
|
Fetching enclsoure generation.
|
||||||
|
|
||||||
:return: True/False if the enclosure is multi-tenant or not; None if unable to determine.
|
:return: True/False if the enclosure is multi-tenant or not and return enclosure generation;
|
||||||
|
None if unable to determine.
|
||||||
"""
|
"""
|
||||||
response = self.get_request(self.root_uri + self.service_root + "Chassis/Enclosure")
|
response = self.get_request(self.root_uri + self.service_root + "Chassis/Enclosure")
|
||||||
if response['ret'] is False:
|
if response['ret'] is False:
|
||||||
return None
|
return None
|
||||||
pattern = r".*-[A,B]"
|
pattern = r".*-[A,B]"
|
||||||
data = response['data']
|
data = response['data']
|
||||||
return re.match(pattern, data['SerialNumber']) is not None
|
if 'EnclVersion' not in data:
|
||||||
|
enc_version = 'G1'
|
||||||
|
else:
|
||||||
|
enc_version = data['EnclVersion']
|
||||||
|
return re.match(pattern, data['SerialNumber']) is not None, enc_version
|
||||||
|
|
||||||
def _find_updateservice_additional_uris(self):
|
def _find_updateservice_additional_uris(self):
|
||||||
"""Find & set WDC-specific update service URIs"""
|
"""Find & set WDC-specific update service URIs"""
|
||||||
|
@ -180,15 +187,44 @@ class WdcRedfishUtils(RedfishUtils):
|
||||||
To determine if the bundle is multi-tenant or not, it looks inside the .bin file within the tarfile,
|
To determine if the bundle is multi-tenant or not, it looks inside the .bin file within the tarfile,
|
||||||
and checks the appropriate byte in the file.
|
and checks the appropriate byte in the file.
|
||||||
|
|
||||||
|
If not tarfile, the bundle is checked for 2048th byte to determine whether it is Gen2 bundle.
|
||||||
|
Gen2 is always single tenant at this time.
|
||||||
|
|
||||||
:param str bundle_uri: HTTP URI of the firmware bundle.
|
:param str bundle_uri: HTTP URI of the firmware bundle.
|
||||||
:return: Firmware version number contained in the bundle, and whether or not the bundle is multi-tenant.
|
:return: Firmware version number contained in the bundle, whether or not the bundle is multi-tenant
|
||||||
Either value will be None if unable to determine.
|
and bundle generation. Either value will be None if unable to determine.
|
||||||
:rtype: str or None, bool or None
|
:rtype: str or None, bool or None
|
||||||
"""
|
"""
|
||||||
bundle_temp_filename = fetch_file(module=self.module,
|
bundle_temp_filename = fetch_file(module=self.module,
|
||||||
url=bundle_uri)
|
url=bundle_uri)
|
||||||
|
bundle_version = None
|
||||||
|
is_multi_tenant = None
|
||||||
|
gen = None
|
||||||
|
|
||||||
|
# If not tarfile, then if the file has "MMG2" or "DPG2" at 2048th byte
|
||||||
|
# then the bundle is for MM or DP G2
|
||||||
if not tarfile.is_tarfile(bundle_temp_filename):
|
if not tarfile.is_tarfile(bundle_temp_filename):
|
||||||
return None, None
|
cookie1 = None
|
||||||
|
with open(bundle_temp_filename, "rb") as bundle_file:
|
||||||
|
file_size = os.path.getsize(bundle_temp_filename)
|
||||||
|
if file_size >= 2052:
|
||||||
|
bundle_file.seek(2048)
|
||||||
|
cookie1 = bundle_file.read(4)
|
||||||
|
# It is anticipated that DP firmware bundle will be having the value "DPG2"
|
||||||
|
# for cookie1 in the header
|
||||||
|
if cookie1 and cookie1.decode("utf8") == "MMG2" or cookie1.decode("utf8") == "DPG2":
|
||||||
|
file_name, ext = os.path.splitext(str(bundle_uri.rsplit('/', 1)[1]))
|
||||||
|
# G2 bundle file name: Ultrastar-Data102_3000_SEP_1010-032_2.1.12
|
||||||
|
parsedFileName = file_name.split('_')
|
||||||
|
if len(parsedFileName) == 5:
|
||||||
|
bundle_version = parsedFileName[4]
|
||||||
|
# MM G2 is always single tanant
|
||||||
|
is_multi_tenant = False
|
||||||
|
gen = "G2"
|
||||||
|
|
||||||
|
return bundle_version, is_multi_tenant, gen
|
||||||
|
|
||||||
|
# Bundle is for MM or DP G1
|
||||||
tf = tarfile.open(bundle_temp_filename)
|
tf = tarfile.open(bundle_temp_filename)
|
||||||
pattern_pkg = r"oobm-(.+)\.pkg"
|
pattern_pkg = r"oobm-(.+)\.pkg"
|
||||||
pattern_bin = r"(.*\.bin)"
|
pattern_bin = r"(.*\.bin)"
|
||||||
|
@ -205,8 +241,9 @@ class WdcRedfishUtils(RedfishUtils):
|
||||||
bin_file.seek(11)
|
bin_file.seek(11)
|
||||||
byte_11 = bin_file.read(1)
|
byte_11 = bin_file.read(1)
|
||||||
is_multi_tenant = byte_11 == b'\x80'
|
is_multi_tenant = byte_11 == b'\x80'
|
||||||
|
gen = "G1"
|
||||||
|
|
||||||
return bundle_version, is_multi_tenant
|
return bundle_version, is_multi_tenant, gen
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def uri_is_http(uri):
|
def uri_is_http(uri):
|
||||||
|
@ -267,15 +304,16 @@ class WdcRedfishUtils(RedfishUtils):
|
||||||
# Check the FW version in the bundle file, and compare it to what is already on the IOMs
|
# Check the FW version in the bundle file, and compare it to what is already on the IOMs
|
||||||
|
|
||||||
# Bundle version number
|
# Bundle version number
|
||||||
bundle_firmware_version, is_bundle_multi_tenant = self._get_bundle_version(bundle_uri)
|
bundle_firmware_version, is_bundle_multi_tenant, bundle_gen = self._get_bundle_version(bundle_uri)
|
||||||
if bundle_firmware_version is None or is_bundle_multi_tenant is None:
|
if bundle_firmware_version is None or is_bundle_multi_tenant is None or bundle_gen is None:
|
||||||
return {
|
return {
|
||||||
'ret': False,
|
'ret': False,
|
||||||
'msg': 'Unable to extract bundle version or multi-tenant status from update image tarfile'
|
'msg': 'Unable to extract bundle version or multi-tenant status or generation from update image file'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_enclosure_multi_tenant, enclosure_gen = self._is_enclosure_multi_tenant_and_fetch_gen()
|
||||||
|
|
||||||
# Verify that the bundle is correctly multi-tenant or not
|
# Verify that the bundle is correctly multi-tenant or not
|
||||||
is_enclosure_multi_tenant = self._is_enclosure_multi_tenant()
|
|
||||||
if is_enclosure_multi_tenant != is_bundle_multi_tenant:
|
if is_enclosure_multi_tenant != is_bundle_multi_tenant:
|
||||||
return {
|
return {
|
||||||
'ret': False,
|
'ret': False,
|
||||||
|
@ -285,6 +323,16 @@ class WdcRedfishUtils(RedfishUtils):
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Verify that the bundle is compliant with the target enclosure
|
||||||
|
if enclosure_gen != bundle_gen:
|
||||||
|
return {
|
||||||
|
'ret': False,
|
||||||
|
'msg': 'Enclosure generation is {0} but bundle is of {1}'.format(
|
||||||
|
enclosure_gen,
|
||||||
|
bundle_gen,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
# Version number installed on IOMs
|
# Version number installed on IOMs
|
||||||
firmware_inventory = self.get_firmware_inventory()
|
firmware_inventory = self.get_firmware_inventory()
|
||||||
if not firmware_inventory["ret"]:
|
if not firmware_inventory["ret"]:
|
||||||
|
|
|
@ -289,7 +289,7 @@ def mock_get_firmware_inventory_version_1_2_3(*args, **kwargs):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ERROR_MESSAGE_UNABLE_TO_EXTRACT_BUNDLE_VERSION = "Unable to extract bundle version or multi-tenant status from update image tarfile"
|
ERROR_MESSAGE_UNABLE_TO_EXTRACT_BUNDLE_VERSION = "Unable to extract bundle version or multi-tenant status or generation from update image file"
|
||||||
ACTION_WAS_SUCCESSFUL_MESSAGE = "Action was successful"
|
ACTION_WAS_SUCCESSFUL_MESSAGE = "Action was successful"
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue