Skip to content

Commit

Permalink
Update Nautobot Interface not Device for provisioning mode
Browse files Browse the repository at this point in the history
We used to flip a bit on the nautobot Device object for “connected_to_network”
when changing a device from/to “provisioning” and “tenant” settings.

We need this to be interface specific.  Because of Ironic's knowlege of the
interface that is being used for PXE boot, we are called with a server interface
UUID.

We update the nautobot status field of connected switch interface.

This tells undersync which mode the port should be in - provisioning or
tenant (normal).

We also make a change to the switch IDs that are passed to undersync.  This used
to represnt the set of all switches to which the server is connected.  This is
sub-optimal if there are multiple fabrics connected to the same server.   We
drop this logic and instead just pass a single switch ID, which is the switch
where PXE is happening.  Undersync will always update both switches in the VPC
pair (VLAN GROUP) in any case - passing the extra switch IDs was redundant.
  • Loading branch information
Steve Keay committed Aug 30, 2024
1 parent bdaf263 commit 26aa1aa
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,40 @@

logger = setup_logger(__name__)

network_name_status = {
"tenant": "Active",
"provisioning": "Provisioning Interface"
}

def update_nautobot(args) -> list[str]:
device_uuid = args.device_id
field_name = "connected_to_network"
field_value = args.network_name
nb_url = args.nautobot_url
def update_nautobot(args) -> UUID:
device_id = args.device_id
interface_id = args.interface_id
network_name = args.network_name

nb_url = args.nautobot_url
nb_token = args.nautobot_token or credential("nb-token", "token")

new_status = network_name_status[args.network_name]

nautobot = Nautobot(nb_url, nb_token, logger=logger)
logger.info(
f"Updating Device {device_uuid} and moving it to '{field_value}' network."
)
nautobot.update_cf(device_uuid, field_name, field_value)
logger.debug(f"Updated Device.{field_name} to {field_value}")
switches = nautobot.uplink_switches(device_uuid)
logger.info(f"Obtained switch IDs: {switches}")
return switches
logger.info(f"Updating Nautobot {device_id=!s} {interface_id=!s} {network_name=}")
interface = nautobot.update_switch_interface_status(interface_id, new_status)
logger.info(f"Updated Nautobot {device_id=!s} {interface_id=!s} {network_name=}")

switch_id = interface.device.id
logger.info(f"Interface connected to switch {switch_id!s}")
return switch_id


def call_undersync(args, switches):
def call_undersync(args, switch_id: UUID):
undersync_token = credential("undersync", "token")
if not undersync_token:
logger.error("Please provide auth token for Undersync.")
sys.exit(1)
undersync = Undersync(undersync_token)

try:
return undersync.sync_devices(switches, dry_run=args.dry_run, force=args.force)
return undersync.sync_devices([switch_id], dry_run=args.dry_run, force=args.force)
except Exception as error:
logger.error(error)
sys.exit(2)
Expand All @@ -54,7 +60,7 @@ def argument_parser():
"--interface-id", type=UUID, required=True, help="Nautobot interface UUID"
)
parser.add_argument(
"--device-id", type=UUID, required=True, help="Nautobot device UUID"
"--device-id", type=UUID, required=False, help="Nautobot device UUID"
)
parser.add_argument("--network-name", required=True)
parser = parser_nautobot_args(parser)
Expand Down Expand Up @@ -83,8 +89,8 @@ def main():
"""
args = argument_parser().parse_args()

switches = update_nautobot(args)
response = call_undersync(args, switches)
switch_id = update_nautobot(args)
response = call_undersync(args, switch_id)
logger.info(f"Undersync returned: {response.json()}")


Expand Down
23 changes: 23 additions & 0 deletions python/understack-workflows/understack_workflows/nautobot.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ def device_by_id(self, device_id: UUID) -> NautobotDevice:
self.exit_with_error(f"Device {device_id!s} not found in Nautobot")
return device

def interface_by_id(self, interface_id: UUID) -> NautobotInterface:
interface = self.session.dcim.interfaces.get(interface_id)
if not interface:
self.exit_with_error(f"Interface {interface_id!s} not found in Nautobot")
return interface


def device_interfaces(self, device_id: UUID):
return self.session.dcim.interfaces.filter(device_id=device_id)

Expand All @@ -120,6 +127,22 @@ def update_cf(self, device_id: UUID, field_name: str, field_value: str):
self.logger.info(f"save result: {response}")
return response

def update_switch_interface_status(self, server_interface_id: UUID, new_status: str) -> NautobotInterface:
server_interface = self.interface_by_id(server_interface_id)
connected_endpoint = server_interface.connected_endpoint
if not connected_endpoint:
raise Exception("Interface {server_interface_id} not connected in Nautobot")
switch_interface_id = connected_endpoint.id
self.logger.debug(f"Int {server_interface_id} connects to {switch_interface_id}")
switch_interface = self.interface_by_id(switch_interface_id)
switch_interface.status = new_status
result = switch_interface.save()

self.logger.debug(
f"Interface {switch_interface_id} updated to Status {new_status} {result=}"
)
return switch_interface

def update_device_status(self, device_id: UUID, device_status: str):
device = self.device_by_id(device_id)
device.status = device_status
Expand Down

0 comments on commit 26aa1aa

Please sign in to comment.