Skip to content
Snippets Groups Projects

Feature/Netbox integration terminate ip trunk

Merged Neda Moeini requested to merge feature/netbox_integration_terminate_ip_trunk into develop
8 files
+ 169
77
Compare changes
  • Side-by-side
  • Inline
Files
8
@@ -3,7 +3,6 @@ from uuid import UUID
import pydantic
import pynetbox
from infoblox_client.objects import Interface
from pynetbox.models.dcim import Devices, DeviceTypes, Interfaces
from gso.products.product_types.router import Router
@@ -63,12 +62,22 @@ class NetboxClient:
)
def get_device_by_name(self, device_name: str) -> Devices:
"""Return the device object by name from netbox, or ``None`` if not found."""
return self.netbox.dcim.devices.get(name=device_name)
"""Return the device object by name from netbox, or raise not found."""
device = self.netbox.dcim.devices.get(name=device_name)
if device is None:
raise NotFoundError(f"Device: {device_name} not found.")
return device
def get_interfaces_by_device(self, device_name: str, speed: str) -> list[Interfaces]:
"""Get all interfaces of a device by name and speed."""
def get_interface_by_name_and_device(self, iface_name: str, device_name: str) -> Interfaces:
"""Return the interface lists by name and device name from netbox."""
device = self.get_device_by_name(device_name)
interface = self.netbox.dcim.interfaces.get(device_id=device.id, name=iface_name)
if interface is None:
raise NotFoundError(f"Interface: {iface_name} on device with id: {device.id} not found.")
return interface
def get_interfaces_by_device(self, device_name: str, speed: str) -> list[Interfaces]:
"""Get all interfaces of a device by name and speed that are not reserved and not allocated."""
device = self.get_device_by_name(device_name)
return list(
self.netbox.dcim.interfaces.filter(device_id=device.id, enabled=False, mark_connected=False, speed=speed)
@@ -84,6 +93,7 @@ class NetboxClient:
Returns the new interface object as dict.
"""
device = self.get_device_by_name(device_name)
return self.netbox.dcim.interfaces.create(
name=iface_name,
type=type,
@@ -96,8 +106,7 @@ class NetboxClient:
def delete_interface(self, device_name: str, iface_name: str) -> None:
"""Delete an interface from a device by name."""
device = self.get_device_by_name(device_name)
interface = self.netbox.dcim.interfaces.get(device_id=device.id, name=iface_name)
interface = self.get_interface_by_name_and_device(iface_name, device_name)
return interface.delete()
def create_device_type(self, manufacturer: str, model: str, slug: str) -> DeviceTypes:
@@ -131,7 +140,7 @@ class NetboxClient:
return int("".join(filter(str.isdigit, type_parts[0]))) * 1000000
return None
def create_device(self, router_name: str, site_tier: str) -> Devices:
def create_device(self, device_name: str, site_tier: str) -> Devices:
"""Create a new device in Netbox."""
# Get device type id
@@ -146,7 +155,7 @@ class NetboxClient:
# Create new device
device = self.netbox.dcim.devices.create(
name=router_name, device_type=device_type.id, role=device_role.id, site=device_site.id
name=device_name, device_type=device_type.id, role=device_role.id, site=device_site.id
)
module_bays = list(self.netbox.dcim.module_bays.filter(device_id=device.id))
card_type = self.netbox.dcim.module_types.get(model=tier_info.module_type)
@@ -168,8 +177,9 @@ class NetboxClient:
return device
def delete_device(self, router_name: str) -> None:
self.netbox.dcim.devices.get(name=router_name).delete()
def delete_device(self, device_name: str) -> None:
"""Delete device by name."""
self.netbox.dcim.devices.get(name=device_name).delete()
return
def attach_interface_to_lag(
@@ -179,16 +189,16 @@ class NetboxClient:
Returns the interface object after assignment.
"""
# Get device id
device = self.get_device_by_name(device_name)
# Get interface for device
iface = self.netbox.dcim.interfaces.get(name=iface_name, device_id=device.id)
iface = self.get_interface_by_name_and_device(iface_name, device_name)
# Get LAG
lag = self.netbox.dcim.interfaces.get(name=lag_name, device_id=device.id)
lag = self.get_interface_by_name_and_device(lag_name, device_name)
# 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
@@ -196,19 +206,13 @@ class NetboxClient:
iface.description = description
iface.save()
return iface
def reserve_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)
# Reserve interface by enabling it
if interface is None:
raise NotFoundError(f"Interface: {iface_name} on device: {device_name} not found.")
interface = self.get_interface_by_name_and_device(iface_name, device_name)
# Check if interface is reserved
if interface.enabled:
@@ -223,18 +227,14 @@ class NetboxClient:
def allocate_interface(self, device_name: str, iface_name: str) -> Interfaces:
"""Allocate an interface by marking it as connected."""
device = self.get_device_by_name(device_name)
interface = self.netbox.dcim.interfaces.get(device_id=device.id, name=iface_name)
# Check if interface is available
if interface is None:
raise NotFoundError(f"Interface: {iface_name} on device: {device_name} not found.")
# First get interface from device
interface = self.get_interface_by_name_and_device(iface_name, device_name)
# Check if interface is reserved
if interface.mark_connected:
raise WorkflowStateError(f"The interface: {iface_name} on device: {device_name} is already allocated.")
# allocate interface by mark as connected
# Allocate interface by marking it as connected
interface.mark_connected = True
interface.save()
@@ -243,13 +243,8 @@ class NetboxClient:
def free_interface(self, device_name: str, iface_name: str) -> Interfaces:
"""Free interface by marking disconnect and disable it."""
device = self.get_device_by_name(device_name)
interface = self.netbox.dcim.interfaces.get(device_id=device.id, name=iface_name)
# Check if interface is available
if interface is None:
raise NotFoundError(f"Interface: {iface_name} on device: {device_name} not found.")
# First get interface from device
interface = self.get_interface_by_name_and_device(iface_name, device_name)
interface.mark_connected = False
interface.enabled = False
interface.description = ""
@@ -302,13 +297,3 @@ class NetboxClient:
return self.netbox.dcim.interfaces.filter(
device=device.name, enabled=False, mark_connected=False, speed=speed_bps
)
def get_interface_by_name_and_device(self, router_id: UUID, interface_name: str) -> Interface:
"""Return the interface object by name and device from netbox, or ``None`` if not found."""
router = Router.from_subscription(router_id).router.router_fqdn
device = self.get_device_by_name(router)
try:
return self.netbox.dcim.interfaces.get(device=device.name, name=interface_name)
except pynetbox.RequestError:
raise NotFoundError(f"Interface: {interface_name} on device: {device.name} not found.")
Loading