|
1 | 1 | # SPDX-License-Identifier: Apache-2.0 |
2 | 2 |
|
| 3 | +import ipaddress |
3 | 4 | import json |
4 | 5 | import re |
5 | 6 | import textwrap |
|
27 | 28 | "osism-ipa-as": "frr_local_as", |
28 | 29 | "osism-ipa-ipv4": "frr_loopback_v4", |
29 | 30 | "osism-ipa-ipv6": "frr_loopback_v6", |
| 31 | + "osism-ipa-metalbox": None, # resolved via metalbox lookup |
30 | 32 | }, |
31 | 33 | } |
32 | 34 |
|
@@ -59,6 +61,45 @@ def _derive_as_from_hostname_yrzn(hostname): |
59 | 61 | return f"42001{t}{rack}{server}" |
60 | 62 |
|
61 | 63 |
|
| 64 | +def _get_metalbox_primary_ip4(device): |
| 65 | + """Get the primary IPv4 address of the metalbox managing this device. |
| 66 | +
|
| 67 | + Finds the metalbox whose interface shares the same subnet as the |
| 68 | + device's OOB IP address, then returns that metalbox's primary_ip4. |
| 69 | +
|
| 70 | + Args: |
| 71 | + device: NetBox device object |
| 72 | +
|
| 73 | + Returns: |
| 74 | + str: The metalbox's primary IPv4 address (without prefix), or None |
| 75 | + """ |
| 76 | + from osism import utils |
| 77 | + |
| 78 | + oob_ip_result = get_device_oob_ip(device) |
| 79 | + if not oob_ip_result: |
| 80 | + return None |
| 81 | + |
| 82 | + oob_ip, _ = oob_ip_result |
| 83 | + oob_addr = ipaddress.ip_address(oob_ip) |
| 84 | + |
| 85 | + metalboxes = utils.nb.dcim.devices.filter(role="metalbox") |
| 86 | + for metalbox in metalboxes: |
| 87 | + interfaces = utils.nb.dcim.interfaces.filter(device_id=metalbox.id) |
| 88 | + for interface in interfaces: |
| 89 | + ip_addresses = utils.nb.ipam.ip_addresses.filter( |
| 90 | + assigned_object_id=interface.id, |
| 91 | + ) |
| 92 | + for ip_addr in ip_addresses: |
| 93 | + if ip_addr.address: |
| 94 | + network = ipaddress.ip_network(ip_addr.address, strict=False) |
| 95 | + if oob_addr in network: |
| 96 | + if metalbox.primary_ip4: |
| 97 | + return str(metalbox.primary_ip4).split("/")[0] |
| 98 | + return None |
| 99 | + |
| 100 | + return None |
| 101 | + |
| 102 | + |
62 | 103 | driver_params = { |
63 | 104 | "ipmi": { |
64 | 105 | "address": "ipmi_address", |
@@ -184,6 +225,10 @@ def _prepare_node_attributes(device, get_ironic_parameters): |
184 | 225 | for kap_name, frr_key in SUPPORTED_IPA_TYPES[ipa_type].items(): |
185 | 226 | if kap_name == "osism-ipa-as" and derived_as: |
186 | 227 | kap += f" {kap_name}={derived_as}" |
| 228 | + elif kap_name == "osism-ipa-metalbox": |
| 229 | + metalbox_ip = _get_metalbox_primary_ip4(device) |
| 230 | + if metalbox_ip: |
| 231 | + kap += f" {kap_name}={metalbox_ip}" |
187 | 232 | elif frr_key in frr: |
188 | 233 | kap += f" {kap_name}={frr[frr_key]}" |
189 | 234 | node_attributes["instance_info"]["kernel_append_params"] = kap |
|
0 commit comments