Last active
September 19, 2024 01:54
-
-
Save noslin005/5e5e0f7a99f93b1cfbd58cf4570d49c0 to your computer and use it in GitHub Desktop.
Perform the BIOS/BMC update on multiple Gigabyte nodes using GbUtility.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import argparse | |
import multiprocessing | |
import os | |
import shutil | |
import subprocess | |
__author__ = 'Nilson Lopes <[email protected]>' | |
def update_firmware(host, user, password, asset_tag, update_type, file_path, verbose): | |
""" | |
Update the BIOS or BMC on a single node. | |
Args: | |
host (str): The host of the BMC node. | |
user (str): The username for authentication. | |
password (str): The password for authentication. | |
asset_tag (str): The asset tag of the node. | |
update_type (str): The type of update (bios or bmc). | |
file_path (str): The path to the BIOS/BMC update file. | |
verbose (bool): Whether to display the command output. | |
Returns: | |
tuple: A tuple containing the asset tag and a boolean indicating | |
whether the update was successful (asset_tag, success). | |
""" | |
# Create a folder with the asset tag name | |
folder_path = os.path.join(os.getcwd(), asset_tag) | |
os.makedirs(folder_path, exist_ok=True) | |
# Copy the BIOS/BMC update file to the asset tag folder | |
destination_path = os.path.join(folder_path, os.path.basename(file_path)) | |
shutil.copyfile(file_path, destination_path) | |
gbtutil_jar = "/opt/gsmcli/GbtUtility-2.1.60.jar" | |
command = (f"java -jar {gbtutil_jar} -H {host} -U {user} " | |
f"-P {password} update {update_type} auto {destination_path}") | |
process = subprocess.Popen(command, | |
shell=True, | |
stdout=subprocess.PIPE, | |
stderr=subprocess.PIPE) | |
# Output file path for the current asset tag | |
output_file = os.path.join(folder_path, f"{asset_tag}.txt") | |
while True: | |
output = process.stdout.readline().decode().strip() | |
if output: | |
print(f"Node {asset_tag} is running ...") | |
if verbose: | |
print(f"Node: {asset_tag} - {output}") | |
with open(output_file, "a") as file: | |
file.write(f"{output}\n") | |
if process.poll() is not None: | |
break | |
if process.returncode == 0: | |
return asset_tag, True | |
else: | |
return asset_tag, False | |
def main(update_type, file_path, nodes_file, verbose): | |
""" | |
Perform the BIOS/BMC update on multiple nodes. | |
Args: | |
update_type (str): The type of update (bios or bmc). | |
file_path (str): The path to the BIOS/BMC update file. | |
nodes_file (str): The path to the file containing the list of BMC nodes. | |
verbose (bool): Whether to display the command output at the end. | |
""" | |
# Read the list of BMC nodes from the specified text file | |
with open(nodes_file, 'r') as file: | |
nodes = [line.strip().split() for line in file.readlines()] | |
pool = multiprocessing.Pool(processes=len(nodes)) | |
results = [pool.apply_async(update_firmware, | |
(host, | |
user, | |
password, | |
asset_tag, | |
update_type, | |
file_path, | |
verbose)) | |
for host, user, password, asset_tag in nodes] | |
pool.close() | |
pool.join() | |
success_nodes = [] | |
failed_nodes = [] | |
for result in results: | |
asset_tag, success = result.get() | |
if success: | |
success_nodes.append(asset_tag) | |
else: | |
failed_nodes.append(asset_tag) | |
print("\n--- Nodes updated successfully ---") | |
for asset_tag in success_nodes: | |
print(asset_tag) | |
print("\n--- Nodes failed to update ---") | |
for asset_tag in failed_nodes: | |
print(asset_tag) | |
# Display the command output if verbose mode is enabled | |
if verbose: | |
print("\n--- Command Output ---") | |
for asset_tag in success_nodes + failed_nodes: | |
output_file = os.path.join(asset_tag, f"{asset_tag}.txt") | |
with open(output_file, "r", encoding='utf-8') as file: | |
print(f"Node: {asset_tag}") | |
print(file.read()) | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser( | |
description='Update BIOS or BMC on multiple nodes.') | |
parser.add_argument('file_path', | |
help='Path to the BIOS/BMC update file') | |
parser.add_argument('-u', | |
'--update_type', | |
action='store', | |
choices=['bios', 'bmc'], | |
required=True, | |
help='Update type (bios or bmc)') | |
parser.add_argument('-l', | |
'--nodes_file', | |
default='nodes.txt', | |
action='store', | |
required=True, | |
help='Path to the file containing the list of' | |
' BMC nodes (default: nodes.txt)') | |
parser.add_argument('-v', | |
'--verbose', | |
action='store_true', | |
help='Display the command output at the end') | |
args = parser.parse_args() | |
main(args.update_type, args.file_path, args.nodes_file, args.verbose) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment