diff --git a/gso/services/netbox_client.py b/gso/services/netbox_client.py index 1ed7f82f1ac813e6946851077e93adb9dfceab14..8269c5e36f58ff38cffc6e00913f0db6e13389e7 100644 --- a/gso/services/netbox_client.py +++ b/gso/services/netbox_client.py @@ -188,7 +188,11 @@ class NetboxClient: # Get LAG lag = self.netbox.dcim.interfaces.get(name=lag_name, device_id=device.id) - # Assign interface to LAG + # Assign interface to LAG, ensuring it doesn't already belong to a LAG + if iface.lag: + raise WorkflowStateError( + f"The interface: {iface_name} on device: {device_name} already belongs to a LAG: {iface.lag.name}.") + iface.lag = lag.id # Set description if provided @@ -220,27 +224,6 @@ class NetboxClient: return interface - def free_interface(self, device_name: str, iface_name: str) -> Interfaces: - """Reserve an interface by enabling it.""" - - # First get interface from device - device = self.get_device_by_name(device_name) - interface = self.netbox.dcim.interfaces.get(device_id=device.id, name=iface_name) - - # Check if interface exists - if interface is None: - raise NotFoundError(f"Interface: {iface_name} on device: {device_name} not found.") - - # Ensure that interface is reserved - if not interface.enabled: - raise WorkflowStateError(f"The interface: {iface_name} on device: {device_name} is not reserved.") - - # Free interface by disabling it - interface.enabled = False - interface.save() - - return interface - def allocate_interface(self, device_name: str, iface_name: str) -> Interfaces: """Allocate an interface by marking it as connected.""" diff --git a/utils/netboxcli.py b/utils/netboxcli.py index 6b2a1c9500d52de970c3e338c016280a5965d201..6eeae3730014fd1832c1cf1564f56d706ce78da6 100644 --- a/utils/netboxcli.py +++ b/utils/netboxcli.py @@ -157,7 +157,7 @@ def action() -> None: @action.command() -@click.option("--fqdn", help="Device name where to get interface to edit") +@click.option("--fqdn", help="Device name from where to get interface to edit") @click.option("--iface", help="Interface name to edit") def reserve_interface(fqdn: str, iface: str) -> None: click.echo(f"Reserving interface: device ={fqdn}, interface name={iface}") @@ -166,7 +166,7 @@ def reserve_interface(fqdn: str, iface: str) -> None: @action.command() -@click.option("--fqdn", help="Device name where to get interface to edit") +@click.option("--fqdn", help="Device name from where to get interface to edit") @click.option("--iface", help="Interface name to edit") def free_interface(fqdn: str, iface: str) -> None: click.echo(f"Freeing interface: device={fqdn}, interface name={iface}") @@ -175,7 +175,7 @@ def free_interface(fqdn: str, iface: str) -> None: @action.command() -@click.option("--fqdn", help="Device name where to get interface to edit") +@click.option("--fqdn", help="Device name from where to get interface to edit") @click.option("--iface", help="Interface name to edit") def allocate_interface(fqdn: str, iface: str) -> None: click.echo(f"Allocating interface: device={fqdn}, interface name={iface}") @@ -184,7 +184,7 @@ def allocate_interface(fqdn: str, iface: str) -> None: @action.command() -@click.option("--fqdn", help="Device name where to get interface to edit") +@click.option("--fqdn", help="Device name from where to get interface to edit") @click.option("--iface", help="Interface name to edit") def deallocate_interface(fqdn: str, iface: str) -> None: click.echo(f"Deallocating interface: device={fqdn}, interface name={iface}") @@ -192,10 +192,32 @@ def deallocate_interface(fqdn: str, iface: str) -> None: click.echo(deallocated_iface) +@action.command() +@click.option("--fqdn", help="Device name from where to get physical interface to attach LAG") +@click.option("--lag", help="LAG name to attach physical interface to") +@click.option("--iface", help="Interface name to attach to LAG") +def attach_interface_to_lag(fqdn: str, lag: str, iface: str) -> None: + click.echo(f"Attaching LAG to physical interface: device={fqdn}, LAG name={lag}, interface name={iface}") + attached_iface = NetBoxClient().attach_interface_to_lag(fqdn, lag, iface) + click.echo(attached_iface) + + +@action.command() +@click.option("--fqdn", help="Device name from where to get physical interface to unattach LAG") +@click.option("--lag", help="LAG name to unattach from physical interface") +@click.option("--iface", help="Interface name to unattach LAG from") +def unattach_interface_from_lag(fqdn: str, lag: str, iface: str) -> None: + click.echo(f"Unattaching LAG from physical interface: device={fqdn}, LAG name={lag}, interface name={iface}") + unattached_iface = NetBoxClient().unattach_interface_from_lag(fqdn, lag, iface) + click.echo(unattached_iface) + + action.add_command(reserve_interface) action.add_command(free_interface) action.add_command(allocate_interface) action.add_command(deallocate_interface) +action.add_command(attach_interface_to_lag) +action.add_command(unattach_interface_from_lag) if __name__ == "__main__":