Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 46 additions & 6 deletions stackbox/cli/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import time

import click
from requests import ConnectionError as RequestsConnectionError
from requests import HTTPError as RequestsHTTPError
from requests import Timeout as RequestsTimeout

from stackbox import __version__
from stackbox.core import builder
Expand Down Expand Up @@ -368,8 +371,6 @@ def init(
# Phase 7: Verify BMC can see VMs
click.echo("\n🔌 Verifying BMC configuration...")
try:
import requests

from stackbox.core import bmc

# Give sushy-tools a moment to discover VMs
Expand All @@ -396,7 +397,7 @@ def init(
click.echo(f" ⚠️ {node_name} not found in BMC", err=True)
click.echo(" This may resolve after services stabilize")

except requests.ConnectionError as e:
except RequestsConnectionError as e:
# Scenario 1: sushy-tools container not running or unreachable
click.echo(
f"\n❌ Cannot connect to BMC service at http://localhost:8000: {e}\n"
Expand All @@ -405,7 +406,7 @@ def init(
err=True,
)

except requests.Timeout as e:
except RequestsTimeout as e:
# Scenario 2: sushy-tools not responding
click.echo(
f"\n⚠️ BMC verification timeout: {e}\n"
Expand All @@ -414,7 +415,7 @@ def init(
err=True,
)

except requests.HTTPError as e:
except RequestsHTTPError as e:
# Scenario 3: HTTP error from sushy-tools (500, 404, etc.)
status_code = e.response.status_code if e.response else "unknown"

Expand All @@ -440,13 +441,52 @@ def init(
err=True,
)

# TODO: Phase 8 (Issue #10): Enroll node in Ironic
# Phase 8: Enroll nodes in Ironic
click.echo("\n📝 Enrolling node in Ironic...")
try:
from stackbox.core import enrollment

ironic_client = enrollment.IronicClient("http://localhost:6385")

# BMC address for container-to-container communication
bmc_address = "http://sushy-tools:8000"

# Enroll node
enrolled_node = enrollment.enroll_node(
ironic_client,
node_info,
bmc_address,
)

click.echo(f"✅ Node enrolled: {enrolled_node['uuid']}")

# Verify power control
click.echo("🔌 Verifying power control...")
if enrollment.verify_node_power_control(ironic_client, enrolled_node["uuid"]):
click.echo("✅ Power control verified")
else:
click.echo("⚠️ Power control verification failed", err=True)
click.echo(" Node is enrolled but power control may not work")

except RequestsConnectionError as e:
click.echo(
f"\n❌ Cannot connect to Ironic API at http://localhost:6385: {e}\n"
"Ironic API service is not running or unreachable.",
err=True,
)
sys.exit(1)

except RuntimeError as e:
click.echo(f"\n❌ Failed to enroll node: {e}", err=True)
sys.exit(1)

# TODO: Phase 9 (Issue #11): Configure Tempest

click.echo("\n✅ Initialization complete!")
click.echo(" Ironic API: http://localhost:6385")
click.echo(f" Virtual node: {node_name}")
click.echo(" BMC endpoint: http://localhost:8000/redfish/v1/")
click.echo(f" Enrolled in Ironic: {enrolled_node['uuid']}")

def rebuild(self, service: str, no_cache: bool) -> None:
"""Rebuild a service after code changes."""
Expand Down
Loading
Loading