Skip to content

Commit

Permalink
add and address review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
sujinmkang committed Nov 12, 2020
1 parent 11526df commit 5f42bbe
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 26 deletions.
101 changes: 82 additions & 19 deletions fwutil/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import shutil
import socket
import subprocess
import sys
import time
import tarfile
import urllib
Expand All @@ -34,9 +35,11 @@
NA = "N/A"
NEWLINE = "\n"
PLATFORM_COMPONENTS_FILE = "platform_components.json"
FWUPDATE_FWUPDATE_DIR = "/tmp/firmwareupdate/"
FWUPDATE_FWPACKAGE_DIR = os.path.join(FWUPDATE_FWUPDATE_DIR, "fwpackage/")
FWUPDATE_AU_TASK_FILE = "*_fw_auto_update"
FIRMWARE_UPDATE_DIR = "/tmp/firmwareupdate/"
FWUPDATE_FWPACKAGE_DIR = os.path.join(FIRMWARE_UPDATE_DIR, "fwpackage/")
FW_AU_TASK_FILE_REGEX = "*_fw_auto_update"
FW_AU_STATUS_FILE = "fw_auto_update_status"
FW_AU_STATUS_FILE_PATH = os.path.join(FIRMWARE_UPDATE_DIR, FW_AU_STATUS_FILE)

# ========================= Variables ==========================================

Expand Down Expand Up @@ -292,8 +295,8 @@ class FWPackage(object):

def __init__(self, fwpackage):
self.fwupdate_package_name = fwpackage
if not os.path.isdir(FWUPDATE_FWUPDATE_DIR):
os.mkdir(FWUPDATE_FWUPDATE_DIR)
if not os.path.isdir(FIRMWARE_UPDATE_DIR):
os.mkdir(FIRMWARE_UPDATE_DIR)
if os.path.isdir(FWUPDATE_FWPACKAGE_DIR):
shutil.rmtree(FWUPDATE_FWPACKAGE_DIR)
os.mkdir(FWUPDATE_FWPACKAGE_DIR)
Expand All @@ -311,7 +314,7 @@ def get_fw_package_path(self):
for file in f:
if PLATFORM_COMPONENTS_FILE in file:
self.fwupdate_fwimage_dir = os.path.join(r, os.path.dirname(file))
click.echo("fwupdate_fwimage_dir: {}".format(self.fwupdate_fwimage_dir))
log_helper.print_warning("fwupdate_fwimage_dir: {}".format(self.fwupdate_fwimage_dir))
return self.fwupdate_fwimage_dir

def cleanup_tmp_fwpackage(self):
Expand Down Expand Up @@ -391,7 +394,7 @@ def __parse_component_section(self, section, component, is_module_component=Fals
self.__module_component_map[section][key1] = OrderedDict()

if value1:
if len(value1) != 1 and len(value1) != 2:
if len(value1) < 1 or len(value1) > 3:
self.__parser_component_fail("unexpected number of records: key={}".format(key1))

if self.FIRMWARE_KEY not in value1:
Expand All @@ -400,6 +403,9 @@ def __parse_component_section(self, section, component, is_module_component=Fals
elif len(value1) == 2 and self.VERSION_KEY not in value1:
missing_key = self.VERSION_KEY
break
elif len(value1) == 3 and self.UTILITY_KEY not in value1:
missing_key = self.UTILITY_KEY
break

for key2, value2 in value1.items():
if not self.__is_str(value2):
Expand All @@ -410,7 +416,7 @@ def __parse_component_section(self, section, component, is_module_component=Fals
else:
self.__module_component_map[section][key1] = value1

if missing_key is not None:
if missing_key is not None and missing_key is not self.UTILITY_KEY:
self.__parser_component_fail("\"{}\" key hasn't been found".format(missing_key))

def __parse_chassis_section(self, chassis):
Expand Down Expand Up @@ -530,6 +536,7 @@ class ComponentUpdateProvider(PlatformDataProvider):
ComponentUpdateProvider
"""
STATUS_HEADER = [ "Chassis", "Module", "Component", "Firmware", "Version (Current/Available)", "Status" ]
AU_STATUS_HEADER = [ "Component", "Status", "Info", "Boot" ]
FORMAT = "simple"

FW_STATUS_UPDATE_REQUIRED = "update is required"
Expand Down Expand Up @@ -792,14 +799,63 @@ def update_firmware(self, chassis_name, module_name, component_name):
log_helper.log_fw_update_end(component_path, firmware_path, False, e)
raise

def auto_update_firmware(self, component, boot):
is_chassis_component = component[0]
chassis_name = component[1]
module_name = component[2]
component_name = component[3]
utility = component[6]
def update_au_status_file(self, au_info_data, filename=FW_AU_STATUS_FILE_PATH):
with open(filename, 'w') as f:
json.dump(au_info_data, f)

def read_au_status_file_if_exists(self, filename=FW_AU_STATUS_FILE_PATH):
data = None
if os.path.exists(filename):
with open(filename) as au_status_file:
data = json.load(au_status_file)
return data

def set_firmware_auto_update_status(self, component_path, boot, status, info):
data = self.read_au_status_file_if_exists(FW_AU_STATUS_FILE_PATH)
if data is None:
data = {}
if boot not in data:
data[boot] = []

au_status = data[boot]

comp_au_status = {}
comp_au_status['comp'] = component_path
comp_au_status['status'] = status
comp_au_status['info'] = info

au_status.append(comp_au_status)

self.update_au_status_file(data, FW_AU_STATUS_FILE_PATH)

def get_au_status(self):
au_status = []
auto_updated_status_table = []
data = self.read_au_status_file_if_exists(FW_AU_STATUS_FILE_PATH)

if data is None:
return None

boot_type = list(data.keys())[0]
click.echo("Firmware auto-update performed for {} reboot".format(boot_type))

au_status = data[boot_type]
for comp_au_status in au_status:
r = []
r.append(comp_au_status['comp'] if 'comp' in comp_au_status else "")
r.append(comp_au_status['status'] if 'status' in comp_au_status else "")
r.append(comp_au_status['info'] if 'info' in comp_au_status else "")
auto_updated_status_table.append(r)

return tabulate(auto_updated_status_table, self.AU_STATUS_HEADER, tablefmt=self.FORMAT)

def auto_update_firmware(self, component_au_info, boot):
is_chassis_component = component_au_info[0]
chassis_name = component_au_info[1]
module_name = component_au_info[2]
component_name = component_au_info[3]
utility = component_au_info[6]

click.echo("{} {} {} {}".format(is_chassis_component, chassis_name, module_name, boot))
if is_chassis_component:
component = self.chassis_component_map[chassis_name][component_name]
parser = self.__pcp.chassis_component_map[chassis_name][component_name]
Expand All @@ -821,7 +877,7 @@ def auto_update_firmware(self, component, boot):
utility = self.__root_path + utility

try:
click.echo("{} firmware auto-update: {} with boot_type {}".format(component, firmware_path, boot))
click.echo("{} firmware auto-update starting: {} with boot_type {}".format(component_path, firmware_path, boot))
log_helper.log_fw_auto_update_start(component_path, firmware_path, boot)
if os.path.isfile(utility) and os.access(utility, os.X_OK):
cmd = "{} -a {} {}".format(
Expand All @@ -832,7 +888,8 @@ def auto_update_firmware(self, component, boot):
status, info = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode(sys.stdout.encoding).strip().split(":")
else:
status, info = component.auto_update_firmware(firmware_path, boot).decode(sys.stdout.encoding).strip().split(":")
click.echo("{} firmware auto-update status : {} with {}".format(component_name, status, info))
self.set_firmware_auto_update_status(component_path, boot, status, info)
click.echo("{} firmware auto-update status: {} with {}".format(component_path, status, info))
log_helper.log_fw_auto_update_end(component_path, firmware_path, boot, status, info)
except KeyboardInterrupt:
log_helper.log_fw_auto_update_end(component_path, firmware_path, boot, False, "Keyboard interrupt")
Expand All @@ -841,13 +898,19 @@ def auto_update_firmware(self, component, boot):
log_helper.log_fw_auto_update_end(component_path, firmware_path, boot, False, e)
raise


def is_first_auto_update(self, boot):
task_file = None
for task_file in glob.glob(os.path.join(FWUPDATE_FWUPDATE_DIR, FWUPDATE_AU_TASK_FILE)):
status_file = None
for task_file in glob.glob(os.path.join(FIRMWARE_UPDATE_DIR, FW_AU_TASK_FILE_REGEX)):
if task_file is not None:
click.echo("{} firmware auto-update is already performed, {} firmware auto update is not allowed any more".format(task_file, boot))
return False
click.echo("firmware auto-update for boot_type {} is allowed".format(boot))
for status_file in glob.glob(os.path.join(FIRMWARE_UPDATE_DIR, FW_AU_STATUS_FILE)):
if status_file is not None:
click.echo("{} firmware auto-update is already performed, {} firmware auto update is not allowed any more".format(task_file, boot))
return False
click.echo("Firmware auto-update for boot_type {} is allowed".format(boot))
return True

def is_firmware_update_available(self, chassis_name, module_name, component_name):
Expand Down
28 changes: 21 additions & 7 deletions fwutil/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,13 +379,15 @@ def fw_auto_update(ctx, boot, image=None, fw_image=None):
cup = ComponentUpdateProvider()

if cup is not None:
if cup.is_first_auto_update(boot):
component_list = cup.get_update_available_components()
if component_list:
for component in component_list:
cup.auto_update_firmware(component, boot)
else:
log_helper.print_warning("All components: {}".format(cup.FW_STATUS_UP_TO_DATE))
au_component_list = cup.get_update_available_components()
if au_component_list:
if cup.is_first_auto_update(boot):
for au_component in au_component_list:
cup.auto_update_firmware(au_component, boot)
log_helper.print_warning("All firmware auto-update has been performed")
click.echo("All firmware auto-update has been performed")
else:
log_helper.print_warning("All components: {}".format(cup.FW_STATUS_UP_TO_DATE))
else:
log_helper.print_warning("compoenet update package is not available")
finally:
Expand Down Expand Up @@ -460,6 +462,18 @@ def status(ctx):
cli_abort(ctx, str(e))


# 'auto_update_status' subcommand
@show.command()
@click.pass_context
def auto_update_status(ctx):
"""Show platform components auto firmware update status"""
try:
cup = ComponentUpdateProvider()
click.echo(cup.get_au_status())
except Exception as e:
cli_abort(ctx, str(e))


# 'version' subcommand
@show.command()
def version():
Expand Down

0 comments on commit 5f42bbe

Please sign in to comment.