Skip to content

Commit d4adc1a

Browse files
authored
Add baremetal dump command to output deployment playbook (#1812)
This adds a new 'baremetal dump <hostname>' command that outputs the deployment playbook for a given baremetal node to the console. The command reuses the playbook generation logic from BaremetalDeploy including NetBox integration for local_context_data, netplan_parameters, and frr_parameters. Usage: osism baremetal dump <hostname> osism manage baremetal dump <hostname> AI-assisted: Claude Code Signed-off-by: Christian Berendt <[email protected]>
1 parent 9fe1457 commit d4adc1a

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

osism/commands/baremetal.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,118 @@ def take_action(self, parsed_args):
284284
continue
285285

286286

287+
class BaremetalDump(Command):
288+
def get_parser(self, prog_name):
289+
parser = super(BaremetalDump, self).get_parser(prog_name)
290+
291+
parser.add_argument(
292+
"name",
293+
type=str,
294+
help="Dump deployment playbook for given baremetal node",
295+
)
296+
return parser
297+
298+
def take_action(self, parsed_args):
299+
name = parsed_args.name
300+
301+
# Check if NetBox connection is available
302+
if not utils.nb:
303+
logger.error("NetBox connection not available")
304+
return
305+
306+
try:
307+
# Try to find device by name first
308+
device = utils.nb.dcim.devices.get(name=name)
309+
310+
# If not found by name, try by inventory_hostname custom field
311+
if not device:
312+
devices = utils.nb.dcim.devices.filter(cf_inventory_hostname=name)
313+
if devices:
314+
device = devices[0]
315+
316+
# If device not found, error out
317+
if not device:
318+
logger.error(f"Could not find device {name} in NetBox")
319+
return
320+
321+
# Get default vars from NetBox local_context_data if available
322+
default_vars = {}
323+
if hasattr(device, "local_context_data") and device.local_context_data:
324+
default_vars = device.local_context_data
325+
logger.info(f"Using NetBox local_context_data for device {device.name}")
326+
else:
327+
logger.debug(
328+
f"No local_context_data found for device {device.name} in NetBox"
329+
)
330+
331+
playbook = []
332+
play = {
333+
"name": "Run bootstrap",
334+
"hosts": "localhost",
335+
"connection": "local",
336+
"gather_facts": True,
337+
"vars": default_vars.copy(),
338+
"roles": [
339+
"osism.commons.hostname",
340+
"osism.commons.hosts",
341+
"osism.commons.operator",
342+
],
343+
"tasks": [
344+
{
345+
"name": "Restart rsyslog service after hostname change",
346+
"ansible.builtin.systemd": {
347+
"name": "rsyslog",
348+
"state": "restarted",
349+
},
350+
}
351+
],
352+
}
353+
play["vars"].update(
354+
{"hostname_name": device.name, "hosts_type": "template"}
355+
)
356+
357+
# Get netplan_parameters from NetBox custom fields (already a dict, no JSON parsing needed)
358+
if (
359+
"netplan_parameters" in device.custom_fields
360+
and device.custom_fields["netplan_parameters"]
361+
):
362+
play["vars"].update(
363+
{
364+
"network_allow_service_restart": True,
365+
}
366+
)
367+
play["vars"].update(device.custom_fields["netplan_parameters"])
368+
play["roles"].append("osism.commons.network")
369+
370+
# Get frr_parameters from NetBox custom fields (already a dict, no JSON parsing needed)
371+
if (
372+
"frr_parameters" in device.custom_fields
373+
and device.custom_fields["frr_parameters"]
374+
):
375+
play["vars"].update(
376+
{
377+
"frr_dummy_interface": "loopback0",
378+
}
379+
)
380+
play["vars"].update(device.custom_fields["frr_parameters"])
381+
play["roles"].append("osism.services.frr")
382+
383+
playbook.append(play)
384+
385+
# Output playbook to stdout
386+
print(
387+
yaml.dump(
388+
playbook,
389+
default_flow_style=False,
390+
explicit_start=True,
391+
indent=2,
392+
sort_keys=False,
393+
)
394+
)
395+
except Exception as exc:
396+
logger.error(f"Failed to generate playbook for {name}: {exc}")
397+
398+
287399
class BaremetalUndeploy(Command):
288400
def get_parser(self, prog_name):
289401
parser = super(BaremetalUndeploy, self).get_parser(prog_name)

setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ osism.commands:
4242
baremetal burnin = osism.commands.baremetal:BaremetalBurnIn
4343
baremetal delete = osism.commands.baremetal:BaremetalDelete
4444
baremetal deploy = osism.commands.baremetal:BaremetalDeploy
45+
baremetal dump = osism.commands.baremetal:BaremetalDump
4546
baremetal list = osism.commands.baremetal:BaremetalList
4647
baremetal maintenance set = osism.commands.baremetal:BaremetalMaintenanceSet
4748
baremetal maintenance unset = osism.commands.baremetal:BaremetalMaintenanceUnset
@@ -97,6 +98,7 @@ osism.commands:
9798
manage baremetal burnin = osism.commands.baremetal:BaremetalBurnIn
9899
manage baremetal delete = osism.commands.baremetal:BaremetalDelete
99100
manage baremetal deploy = osism.commands.baremetal:BaremetalDeploy
101+
manage baremetal dump = osism.commands.baremetal:BaremetalDump
100102
manage baremetal list = osism.commands.baremetal:BaremetalList
101103
manage baremetal maintenance set = osism.commands.baremetal:BaremetalMaintenanceSet
102104
manage baremetal maintenance unset = osism.commands.baremetal:BaremetalMaintenanceUnset

0 commit comments

Comments
 (0)