Prompt for IOM1 or IOM2 in serial configure workflow

Previously hardcoded to IOM1. Now asks which IOM the serial cable is
connected to after login, and threads that choice through all Redfish
paths in fetch_current_config and collect_network_config. apply_configuration
and print_summary already used cfg.iom1.iom for paths so needed no changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-16 11:39:34 -04:00
parent edc1b35a62
commit d8a74f02dc
2 changed files with 45 additions and 33 deletions

View File

@@ -39,12 +39,12 @@ modules/
## Workflows
### 1 — Serial Network Configuration (`workflow_serial.py`)
5-step workflow using the USB serial cable. **Serial access is limited to IOM1 only** — the cable connects to IOM1's console port; IOM2 cannot be queried or configured this way.
5-step workflow using the USB serial cable. The serial cable connects to one IOM's console port at a time — the user is prompted to select IOM1 or IOM2 after login, and all Redfish paths use that selection.
1. Detect USB serial device (`/dev/ttyUSB*`, `/dev/ttyACM*`, `/dev/ttyU*`)
2. Open 115200-baud 8N1 connection and wake the IOM console
3. Query IOM1 current network settings via Redfish (`GET` over `127.0.0.1`)
4. Collect new settings from user (Static IP or DHCP) for IOM1
5. Apply via Redfish `PATCH` over `127.0.0.1` to IOM1
3. Prompt for IOM1 or IOM2, then query current network settings via Redfish (`GET` over `127.0.0.1`)
4. Collect new settings from user (Static IP or DHCP)
5. Apply via Redfish `PATCH` over `127.0.0.1`
### 2 — Firmware Update (`workflow_firmware.py`)
Updates IOM firmware and/or Fabric Card firmware over the network:

View File

@@ -340,20 +340,19 @@ def open_serial_connection(device: str) -> Optional[SerialPort]:
# ── Step 3: Fetch & display current IOM network settings ─────────────────────
def fetch_current_config(cfg: ShelfConfig, ser: SerialPort) -> bool:
def fetch_current_config(cfg: ShelfConfig, ser: SerialPort, iom: str) -> bool:
"""
Query Redfish for the current network config of IOM1 via curl over the
serial console session. Only IOM1 is reachable — the serial cable
connects to IOM1's console port; IOM2 cannot be queried this way.
Populates cfg.iom1 with live data.
Returns True if IOM1 responded successfully.
Query Redfish for the current network config of the connected IOM via curl
over the serial console session. Only the IOM whose console port the serial
cable is plugged into is reachable.
Populates cfg.iom1 with live data (regardless of whether IOM1 or IOM2).
Returns True if the IOM responded successfully.
"""
rule("Step 3 of 5 -- Current IOM1 Network Settings")
info("Querying IOM1 Redfish API via serial console...")
info("Note: only IOM1 is reachable over the serial connection.")
rule(f"Step 3 of 5 -- Current {iom} Network Settings")
info(f"Querying {iom} Redfish API via serial console...")
print()
path = "/redfish/v1/Managers/IOM1/EthernetInterfaces/1"
path = f"/redfish/v1/Managers/{iom}/EthernetInterfaces/1"
ok_flag, data = _serial_redfish_request(ser, cfg.password, "GET", path)
if ok_flag and isinstance(data, dict):
@@ -373,7 +372,7 @@ def fetch_current_config(cfg: ShelfConfig, ser: SerialPort) -> bool:
ip = gateway = netmask = "--"
cfg.iom1 = IOMConfig(
iom = "IOM1",
iom = iom,
dhcp = dhcp_enabled,
ip = ip if ip != "--" else "",
gateway = gateway if gateway != "--" else "",
@@ -383,26 +382,26 @@ def fetch_current_config(cfg: ShelfConfig, ser: SerialPort) -> bool:
mode_str = _c(C.CYN, "DHCP") if dhcp_enabled else _c(C.GRN, "Static")
draw_table(
["IOM", "Mode", "IP Address", "Gateway", "Subnet Mask"],
[["IOM1", mode_str, ip, gateway, netmask]],
[[iom, mode_str, ip, gateway, netmask]],
[5, 8, 15, 15, 15],
)
print()
return True
else:
draw_table(
["IOM", "Mode", "Origin", "IP Address", "Gateway", "Subnet Mask"],
[["IOM1", _c(C.RED, "No response"), "--", "--", "--", "--"]],
[5, 10, 8, 16, 16, 16],
["IOM", "Mode", "IP Address", "Gateway", "Subnet Mask"],
[[iom, _c(C.RED, "No response"), "--", "--", "--"]],
[5, 8, 15, 15, 15],
)
print()
error(f"IOM1 query failed: {data}")
error("Check that the serial cable is connected and IOM1 is booted.")
error(f"{iom} query failed: {data}")
error(f"Check that the serial cable is connected and {iom} is booted.")
print()
return False
# ── Step 4: Prompt user — change config or exit ───────────────────────────────
def collect_network_config(cfg: ShelfConfig) -> bool:
def collect_network_config(cfg: ShelfConfig, iom: str) -> bool:
"""
Show current settings, ask user what to do.
Returns True to proceed with applying changes, False to skip.
@@ -425,7 +424,7 @@ def collect_network_config(cfg: ShelfConfig) -> bool:
# ── User wants to change settings ─────────────────────────────────────────
print()
print(" How should IOM1 be configured?")
print(f" How should {iom} be configured?")
print(f" {_c(C.BOLD, '1')} Static IP address")
print(f" {_c(C.BOLD, '2')} DHCP")
print()
@@ -440,16 +439,16 @@ def collect_network_config(cfg: ShelfConfig) -> bool:
print()
if use_dhcp:
cfg.iom1 = IOMConfig("IOM1", dhcp=True)
ok("IOM1 will be set to DHCP.")
cfg.iom1 = IOMConfig(iom, dhcp=True)
ok(f"{iom} will be set to DHCP.")
return True
# Static — IOM1
info(f"Static network details for {_c(C.BOLD, 'IOM1')}:")
iom1_ip = prompt_ip(" IOM1 IP address ")
iom1_gw = prompt_ip(" IOM1 Gateway ")
iom1_nm = prompt_ip(" IOM1 Subnet Mask")
cfg.iom1 = IOMConfig("IOM1", dhcp=False, ip=iom1_ip, gateway=iom1_gw, netmask=iom1_nm)
# Static
info(f"Static network details for {_c(C.BOLD, iom)}:")
ip = prompt_ip(f" {iom} IP address ")
gw = prompt_ip(f" {iom} Gateway ")
nm = prompt_ip(f" {iom} Subnet Mask")
cfg.iom1 = IOMConfig(iom, dhcp=False, ip=ip, gateway=gw, netmask=nm)
return True
@@ -598,11 +597,24 @@ def configure_shelf() -> bool:
time.sleep(2)
return True
# Prompt for which IOM the serial cable is connected to
print()
print(" Which IOM is the serial cable connected to?")
print(f" {_c(C.BOLD, '1')} IOM1")
print(f" {_c(C.BOLD, '2')} IOM2")
print()
while True:
iom_choice = prompt("Select [1/2]")
if iom_choice in ("1", "2"):
break
warn("Please enter 1 or 2.")
iom = "IOM1" if iom_choice == "1" else "IOM2"
# 3 — Fetch & display current settings
fetch_current_config(cfg, ser)
fetch_current_config(cfg, ser, iom)
# 4 — Ask user: change or leave alone?
apply_changes = collect_network_config(cfg)
apply_changes = collect_network_config(cfg, iom)
# 5 — Apply if requested
changed = False