示例#1
0
文件: test_views.py 项目: wuwx/netbox
    def setUp(self):

        self.client = Client()

        site = Site(name='Site 1', slug='site-1')
        site.save()

        manufacturer = Manufacturer(name='Manufacturer 1',
                                    slug='manufacturer-1')
        manufacturer.save()

        devicetype = DeviceType(model='Device Type 1',
                                manufacturer=manufacturer)
        devicetype.save()

        devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
        devicerole.save()

        device1 = Device(name='Device 1',
                         site=site,
                         device_type=devicetype,
                         device_role=devicerole)
        device1.save()
        device2 = Device(name='Device 2',
                         site=site,
                         device_type=devicetype,
                         device_role=devicerole)
        device2.save()

        iface1 = Interface(device=device1,
                           name='Interface 1',
                           form_factor=IFACE_FF_1GE_FIXED)
        iface1.save()
        iface2 = Interface(device=device1,
                           name='Interface 2',
                           form_factor=IFACE_FF_1GE_FIXED)
        iface2.save()
        iface3 = Interface(device=device1,
                           name='Interface 3',
                           form_factor=IFACE_FF_1GE_FIXED)
        iface3.save()
        iface4 = Interface(device=device2,
                           name='Interface 1',
                           form_factor=IFACE_FF_1GE_FIXED)
        iface4.save()
        iface5 = Interface(device=device2,
                           name='Interface 2',
                           form_factor=IFACE_FF_1GE_FIXED)
        iface5.save()
        iface6 = Interface(device=device2,
                           name='Interface 3',
                           form_factor=IFACE_FF_1GE_FIXED)
        iface6.save()

        Cable(termination_a=iface1, termination_b=iface4,
              type=CABLE_TYPE_CAT6).save()
        Cable(termination_a=iface2, termination_b=iface5,
              type=CABLE_TYPE_CAT6).save()
        Cable(termination_a=iface3, termination_b=iface6,
              type=CABLE_TYPE_CAT6).save()
示例#2
0
文件: test_views.py 项目: xcdr/netbox
    def test_trace(self):
        device = create_test_device('Device 1')

        circuittermination = CircuitTermination.objects.first()
        interface = Interface.objects.create(device=device, name='Interface 1')
        Cable(termination_a=circuittermination, termination_b=interface).save()

        response = self.client.get(
            reverse('circuits:circuittermination_trace',
                    kwargs={'pk': circuittermination.pk}))
        self.assertHttpStatus(response, 200)
示例#3
0
    def create_and_connect_surges(self, site, rack, pp, pole_setup):
        # surge_config will be of format <pole no>:<num surges>[ <pole no>:<num surges> [...]]
        # So first split by spaces to get a single pole config and then iterate of surge at this pole.
        # The RearPort of the 1st surge protector of the 1st pole will be connected to PP port 1 then
        # continuing upwards.
        surge_type = DeviceType.objects.get(manufacturer__name='Ubnt',
                                            model='Surge Protector')

        pp_port = 1
        for pole_config in pole_setup.split():
            pole_no, num_surges = pole_config.split(':')

            for n in range(1, int(num_surges) + 1):
                # Create surge
                surge_name = "sp-%s-mast%s-%s" % (site.slug.lower(), pole_no,
                                                  n)
                surge = Device(
                    device_type=surge_type,
                    device_role=DeviceRole.objects.get(name='Surge Protector'),
                    name=surge_name,
                    status=DeviceStatusChoices.STATUS_PLANNED,
                    site=site)

                surge.save()

                # Link RearPort of SP to next free panel port
                cable = Cable(termination_a=RearPort.objects.get(
                    device=pp, name=str(pp_port)),
                              termination_b=RearPort.objects.get(device=surge,
                                                                 name=str(1)),
                              status=CableStatusChoices.STATUS_PLANNED)

                cable.save()
                self.log_success(
                    "Created surge protector %s and linked it to patch panel port %s."
                    % (surge, pp_port))

                pp_port += 1
示例#4
0
    def setUpTestData(cls):

        sites = (
            Site(name='Site 1', slug='site-1'),
            Site(name='Site 2', slug='site-2'),
            Site(name='Site 3', slug='site-3'),
        )
        Site.objects.bulk_create(sites)

        circuit_types = (
            CircuitType(name='Circuit Type 1', slug='circuit-type-1'),
        )
        CircuitType.objects.bulk_create(circuit_types)

        providers = (
            Provider(name='Provider 1', slug='provider-1'),
        )
        Provider.objects.bulk_create(providers)

        provider_networks = (
            ProviderNetwork(name='Provider Network 1', provider=providers[0]),
            ProviderNetwork(name='Provider Network 2', provider=providers[0]),
            ProviderNetwork(name='Provider Network 3', provider=providers[0]),
        )
        ProviderNetwork.objects.bulk_create(provider_networks)

        circuits = (
            Circuit(provider=providers[0], type=circuit_types[0], cid='Circuit 1'),
            Circuit(provider=providers[0], type=circuit_types[0], cid='Circuit 2'),
            Circuit(provider=providers[0], type=circuit_types[0], cid='Circuit 3'),
            Circuit(provider=providers[0], type=circuit_types[0], cid='Circuit 4'),
            Circuit(provider=providers[0], type=circuit_types[0], cid='Circuit 5'),
            Circuit(provider=providers[0], type=circuit_types[0], cid='Circuit 6'),
        )
        Circuit.objects.bulk_create(circuits)

        circuit_terminations = ((
            CircuitTermination(circuit=circuits[0], site=sites[0], term_side='A', port_speed=1000, upstream_speed=1000, xconnect_id='ABC'),
            CircuitTermination(circuit=circuits[0], site=sites[1], term_side='Z', port_speed=1000, upstream_speed=1000, xconnect_id='DEF'),
            CircuitTermination(circuit=circuits[1], site=sites[1], term_side='A', port_speed=2000, upstream_speed=2000, xconnect_id='GHI'),
            CircuitTermination(circuit=circuits[1], site=sites[2], term_side='Z', port_speed=2000, upstream_speed=2000, xconnect_id='JKL'),
            CircuitTermination(circuit=circuits[2], site=sites[2], term_side='A', port_speed=3000, upstream_speed=3000, xconnect_id='MNO'),
            CircuitTermination(circuit=circuits[2], site=sites[0], term_side='Z', port_speed=3000, upstream_speed=3000, xconnect_id='PQR'),
            CircuitTermination(circuit=circuits[3], provider_network=provider_networks[0], term_side='A'),
            CircuitTermination(circuit=circuits[4], provider_network=provider_networks[1], term_side='A'),
            CircuitTermination(circuit=circuits[5], provider_network=provider_networks[2], term_side='A'),
        ))
        CircuitTermination.objects.bulk_create(circuit_terminations)

        Cable(termination_a=circuit_terminations[0], termination_b=circuit_terminations[1]).save()
示例#5
0
    def run(self, data, commit):
        device_a = data["device_a"]
        device_b = data["device_b"]
        ports_a = getattr(device_a, data["termination_type_a"]).all()
        ports_b = getattr(device_b, data["termination_type_b"]).all()

        terms_a = expand_pattern(data["termination_name_a"])
        terms_b = expand_pattern(data["termination_name_b"])
        if len(terms_a) != len(terms_b):
            return self.log_failure(
                f'Mismatched number of ports: {len(terms_a)} (A) versus {len(terms_b)} (B)'
            )
        labels = expand_pattern(data["cable_label"])
        if len(labels) == 1:
            labels = [labels[0] for i in range(len(terms_a))]
        elif len(labels) != len(terms_a):
            return self.log_failure(
                f'Mismatched number of labels: {len(labels)} labels versus {len(terms_a)} ports'
            )

        for i in range(len(terms_a)):
            term_a = [x for x in ports_a if x.name == terms_a[i]]
            if len(term_a) != 1:
                self.log_failure(
                    f'Unable to find "{terms_a[i]}" in {data["termination_type_a"]} on device A ({device_a.name})'
                )
                continue
            term_b = [x for x in ports_b if x.name == terms_b[i]]
            if len(term_b) != 1:
                self.log_failure(
                    f'Unable to find "{terms_b[i]}" in {data["termination_type_b"]} on device B ({device_b.name})'
                )
                continue
            cable = Cable(
                termination_a=term_a[0],
                termination_b=term_b[0],
                type=data["cable_type"],
                status=data["cable_status"],
                tenant=data["cable_tenant"],
                label=labels[i],
                color=data["cable_color"],
                length=data["cable_length"],
                length_unit=data["cable_length_unit"],
            )
            try:
                with transaction.atomic():
                    cable.full_clean()
                    cable.save()
                    cable.tags.set(data["cable_tags"])
            except Exception as e:
                self.log_failure(
                    f'Unable to connect {device_a.name}:{terms_a[i]} to {device_b.name}:{terms_b[i]}: {e}'
                )
                continue
            self.log_success(
                f'Created cable from {device_a.name}:{terms_a[i]} to {device_b.name}:{terms_b[i]}'
            )
示例#6
0
def _connect_interface(interface):
    ''' Get iface connection from iface description
        Description should be like "server|port"
    '''
    desc_regex = "^(.*)+\|(.*)+"
    desc_regex = re.compile(desc_regex)

    iface_descr = interface.description

    if desc_regex.match(iface_descr):
        asset_tag, server_port = iface_descr.split('|')

        server = Device.objects.filter(asset_tag=asset_tag)
        if server:
            server = server[0]
            server_name = server.name

            # Find and compare ports
            for iface in server.interfaces.all():
                if _compare_interfaces(iface.name, server_port):
                    port = iface
                else:
                    port = None

            port = server.interfaces.filter(name=server_port)
            if port:
                cable = Cable()
                cable.termination_a = interface
                cable.termination_b = port[0]
                try:
                    cable.save()
                except Exception as e:
                    logger.error(
                        "Cannot do a connection {} to {} on {} - error is {}".
                        format(interface.name, server_name, server_port, e))
                    return
                logger.info(
                    "Successfully connected interface {} to server {} on port {}"
                    .format(interface.name, server_name, server_port))
            else:
                logger.warning("Cannot found interface {} on server {}".format(
                    server_port, server_name))
        else:
            logger.warning(
                "Cannot find server by AssetTag {}".format(asset_tag))
    else:
        logger.info(
            "Incorrect or None description on interface {} - cannot connect anything"
            .format(interface.name))
示例#7
0
    def setUp(self):
        user = create_test_user(permissions=['dcim.view_cable'])
        self.client = Client()
        self.client.force_login(user)

        site = Site(name='Site 1', slug='site-1')
        site.save()

        manufacturer = Manufacturer(name='Manufacturer 1',
                                    slug='manufacturer-1')
        manufacturer.save()

        devicetype = DeviceType(model='Device Type 1',
                                manufacturer=manufacturer)
        devicetype.save()

        devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
        devicerole.save()

        device1 = Device(name='Device 1',
                         site=site,
                         device_type=devicetype,
                         device_role=devicerole)
        device1.save()
        device2 = Device(name='Device 2',
                         site=site,
                         device_type=devicetype,
                         device_role=devicerole)
        device2.save()

        iface1 = Interface(device=device1,
                           name='Interface 1',
                           type=IFACE_TYPE_1GE_FIXED)
        iface1.save()
        iface2 = Interface(device=device1,
                           name='Interface 2',
                           type=IFACE_TYPE_1GE_FIXED)
        iface2.save()
        iface3 = Interface(device=device1,
                           name='Interface 3',
                           type=IFACE_TYPE_1GE_FIXED)
        iface3.save()
        iface4 = Interface(device=device2,
                           name='Interface 1',
                           type=IFACE_TYPE_1GE_FIXED)
        iface4.save()
        iface5 = Interface(device=device2,
                           name='Interface 2',
                           type=IFACE_TYPE_1GE_FIXED)
        iface5.save()
        iface6 = Interface(device=device2,
                           name='Interface 3',
                           type=IFACE_TYPE_1GE_FIXED)
        iface6.save()

        Cable(termination_a=iface1, termination_b=iface4,
              type=CABLE_TYPE_CAT6).save()
        Cable(termination_a=iface2, termination_b=iface5,
              type=CABLE_TYPE_CAT6).save()
        Cable(termination_a=iface3, termination_b=iface6,
              type=CABLE_TYPE_CAT6).save()
    def run(self, data, commit):
        # Create the device
        device = Device(name=data['business_name'],
                        device_role_id=self.DEVICE_ROLE_ID,
                        device_type_id=data["hardware_choice"],
                        platform_id=self.PLATFORM_ID,
                        site_id=self.SITE_ID)
        device.save()

        interfaces = Interface.objects.filter(device_id=device.id)
        enabled_interfaces = []
        mgmt_intf = interfaces.get(name="b107")
        enabled_interfaces.append(mgmt_intf)
        uplk_intf = interfaces.get(name="ether10")
        enabled_interfaces.append(uplk_intf)
        uplk_intf.mode = "tagged"
        uplk_intf.tagged_vlans.set([self.INET_VLAN, self.MGMT_VLAN])
        uplk_intf.description = "Uplink"
        uplk_intf.save()
        inet_intf = interfaces.get(name="ether1")
        enabled_interfaces.append(inet_intf)
        inet_intf.description = "Internet"
        inet_intf.mode = "access"
        inet_intf.untagged_vlan = self.INET_VLAN
        inet_intf.save()
        mgmt_intf.save()
        for intf in interfaces:
            intf.enabled = False
            intf.save()
        for intf in enabled_interfaces:
            intf.enabled = True
            intf.mtu = 1500
            intf.save()
        available_ip = Prefix.objects.get(
            vlan=self.MGMT_VLAN).get_first_available_ip()
        ip = IPAddress(
            address=available_ip,
            assigned_object_type=ContentType.objects.get_for_model(Interface),
            assigned_object_id=mgmt_intf.id)
        ip.save()
        device.primary_ip4_id = ip.id
        device.primary_ip_id = ip.id
        device.comments = data['comments']
        device.save()

        # ############
        if (not data["skip_zabbix"] and commit):

            # Post to Zabbix API to create host in mikrotik group and ICMP
            # template
            try:
                hostid = self.ZAPI.host.create(
                    host=data["business_name"],
                    interfaces=dict(type=2,
                                    main=1,
                                    useip=1,
                                    ip=available_ip.replace("/24", ""),
                                    port=161,
                                    dns="",
                                    details=dict(
                                        version="1",
                                        bulk="0",
                                        community=self.SNMP_COMMUNITY)),
                    groups=dict(groupid=15),
                    templates=dict(templateid=10186))
                self.log_info("zabbix configured successfully")
            except Exception as e:
                self.log_info("failed to configure zabbix {0}".format(e))

        if (not data["skip_uplink_port"] and commit):
            try:
                agg_switches = Device.objects.filter(
                    site=data["uplink_site"],
                    device_role_id=self.AGG_ROLE_ID,
                    status="active")
                selected_interface = ""
                for agg_switch in agg_switches:
                    interfaces = Interface.objects.filter(
                        device_id=agg_switch.id)
                    for interface in interfaces:
                        if (interface.connection_status is not True
                                and interface.enabled is True
                                and interface.description == ''
                                and interface.type == '1000base-x-sfp'):
                            selected_interface = interface
                            break
                    if selected_interface != "":
                        selected_interface.enabled = True
                        selected_interface.description = device.name
                        selected_interface.mode = "tagged"
                        selected_interface.tagged_vlans.set(
                            [self.INET_VLAN, self.MGMT_VLAN])
                        selected_interface.save()
                        cable = Cable(
                            termination_a=uplk_intf,
                            termination_b=selected_interface,
                        )
                        cable.save()
                        self.log_info(
                            "uplink switch chosen. Port {0} on {1}".format(
                                selected_interface.name, agg_switch.name))
                        break
                if selected_interface == "":
                    self.log_failure("No available aggregate port found. \
                        No aggregate port assigned.")

            except BaseException:
                self.log("failed to document uplink switch")

        self.log_success("Created {0}".format(device.name))
示例#9
0
    def setup_bbr(self, site, rack, vlan, site_no, node_id, asset_tag, sw):
        bbr_name = "bbr-%s.in.ffho.net" % site.slug

        try:
            bbr = Device.objects.get(name=bbr_name)
            self.log_info("Backbone router %s already present, carrying on." %
                          bbr_name)

            return bbr
        except Device.DoesNotExist:
            pass

        bbr_type = DeviceType.objects.get(manufacturer__name='PCEngines',
                                          model='APU2c4-19"')

        bbr = Device(
            device_type=bbr_type,
            device_role=DeviceRole.objects.get(name='Backbone router'),
            platform=Platform.objects.get(name='Linux'),
            name=bbr_name,
            asset_tag=asset_tag,
            status=DeviceStatusChoices.STATUS_PLANNED,
            site=site,
            rack=rack,
            position=rack.u_height - 4,
            face=DeviceFaceChoices.FACE_FRONT,
        )

        bbr.save()
        self.log_success("Created backbone router %s" % bbr)

        # Set bond0 mode to tagged-all, bundle enp<n>s0 into it and connect enp<n>s0  to switchport 10 + n
        bbr_bond0 = Interface.objects.get(device=bbr, name="bond0")
        bbr_bond0.mode = InterfaceModeChoices.MODE_TAGGED_ALL
        bbr_bond0.save()

        # Link enp1s0 and enp2s0 to switch port 10 and 11 respectivly
        for n in [1, 2]:
            bbr_port = Interface.objects.get(device=bbr, name="enp%ds0" % n)
            sw_port = Interface.objects.get(device=sw, name=str(10 + n))
            cable = Cable(termination_a=sw_port,
                          termination_b=bbr_port,
                          status=CableStatusChoices.STATUS_PLANNED)
            cable.save()

            bbr_port.lag = bbr_bond0
            bbr_port.save()

        self.log_success("Linked %s to %s" % (bbr, sw))

        # Disable enp3s0
        enp3s0 = Interface.objects.get(device=bbr, name="enp3s0")
        enp3s0.enabled = False
        enp3s0.save()

        # Set up Mgmt vlan interface + IP
        bbr_mgmt_iface = Interface(
            device=bbr,
            name="vlan%d" % vlan.vid,
            type=InterfaceTypeChoices.TYPE_VIRTUAL,
        )
        bbr_mgmt_iface.save()

        bbr_mgmt_ip = IPAddress(address="172.30.%d.1/24" % site_no,
                                interface=bbr_mgmt_iface)
        bbr_mgmt_ip.save()

        self.log_success("Configured %s on interface %s of %s" %
                         (bbr_mgmt_ip, bbr_mgmt_iface, bbr))

        # Set up loopback IPs
        bbr_lo_iface = Interface.objects.get(device=bbr, name="lo")
        ipv4 = IPAddress(address="10.132.255.%s/32" % node_id,
                         interface=bbr_lo_iface)
        ipv4.save()

        ipv6 = IPAddress(address="2a03:2260:2342:ffff::%s/128" % node_id,
                         interface=bbr_lo_iface)
        ipv6.save()

        bbr.primary_ip4 = ipv4
        bbr.primary_ip6 = ipv6
        bbr.save()
        self.log_success("Configured %s + %s on lo interface of %s" %
                         (ipv4, ipv6, bbr))
示例#10
0
    def setup_swtich(self, site, rack, pp, panel_ports, vlan, site_no,
                     asset_tag):
        sw_name = "sw-%s-01.in.ffho.net" % site.slug

        try:
            sw = Device.objects.get(name=sw_name)
            self.log_info("Switch %s already present, carrying on." % sw_name)

            return sw
        except Device.DoesNotExist:
            pass

        sw_type = DeviceType.objects.get(manufacturer__name='Netonix',
                                         model='WS-12-250-AC')

        sw = Device(device_type=sw_type,
                    device_role=DeviceRole.objects.get(name='Switch'),
                    platform=Platform.objects.get(name='Netonix'),
                    name=sw_name,
                    asset_tag=asset_tag,
                    status=DeviceStatusChoices.STATUS_PLANNED,
                    site=site,
                    rack=rack,
                    position=rack.u_height - 2,
                    face=DeviceFaceChoices.FACE_FRONT)

        sw.save()
        self.log_success("Created switch %s" % sw)

        # Link switch ports for panel ports
        for n in range(1, int(panel_ports) + 1):
            cable = Cable(termination_a=Interface.objects.get(device=sw,
                                                              name=str(n)),
                          termination_b=FrontPort.objects.get(device=pp,
                                                              name=str(n)),
                          status=CableStatusChoices.STATUS_PLANNED)
            cable.save()

        # Disable interfaces which aren't connected
        unused_ifaces = [13, 14]
        if panel_ports < 10:
            unused_ifaces.extend(list(range(int(panel_ports + 1), 10)))
        unused_ifaces = [str(x) for x in sorted(unused_ifaces)]
        for n in unused_ifaces:
            iface = Interface.objects.get(device=sw, name=n)
            iface.enabled = False
            iface.save()

        self.log_success("Disabled switch unsued ports %s" %
                         ",".join(unused_ifaces))

        # Set up Mgmt port
        sw_mgmt_port = Interface.objects.get(device=sw, name="10")
        sw_mgmt_port.mode = InterfaceModeChoices.MODE_ACCESS
        sw_mgmt_port.untagged_vlan = vlan
        sw_mgmt_port.description = "Mgmt"
        sw_mgmt_port.save()

        self.log_success("Set mgmt interface 10 to untagged VLAN %s" % vlan)

        # Set po1 tagged-all and bundle ports 11 + 12 into it
        sw_po1 = Interface.objects.get(device=sw, name='po1')
        sw_po1.mode = InterfaceModeChoices.MODE_TAGGED_ALL
        sw_po1.save()

        for n in [11, 12]:
            sw_port = Interface.objects.get(device=sw, name=str(n))
            sw_port.lag = sw_po1
            sw_port.save()

        self.log_success("Linked first %s ports of %s to %s" %
                         (panel_ports, sw, pp))

        # Set up Mgmt vlan interface + IP
        sw_mgmt_iface = Interface(
            device=sw,
            name="vlan%d" % vlan.vid,
            type=InterfaceTypeChoices.TYPE_VIRTUAL,
        )
        sw_mgmt_iface.save()

        sw_mgmt_ip = IPAddress(address="172.30.%d.10/24" % site_no,
                               interface=sw_mgmt_iface)
        sw_mgmt_ip.save()

        sw.primary_ip4 = sw_mgmt_ip
        sw.save()

        self.log_success("Configured %s on interface %s of %s" %
                         (sw_mgmt_ip, sw_mgmt_iface, sw))

        return sw
示例#11
0
    def run(self, data, commit: bool):
        """The main method of the script that will be run when pressing the Run Script button

        1. Grabs the data from Netbox about devices containing the devices by regex input by the user
        2. Loops through the devices, and makes a NAPALM `get_lldp_neighbors` call to gather local and their remote interfaces
        3. Loops through all LLDP provided local interfaces.
        4. If a mac_address is any kind of empty or null, it makes sure to set it to python None
        5. Makes sure the local interface can be found in Netbox
        6. If a cable is found, it moves to the next iteration and if the remote interface is correct, goes to next iteration
        7. If a cable is found but the remote interface is not the same, makes sure to mark the cable for deletion (Netbox only allows 1 to 1 cable connections)
        8. Makes sure the remote device and interface can be found in Netbox
        9. Deletes the cable if one was found
        10. Creates a new cable using the local and remote interface pair
        11. Calls function to remove cables no longer found in LLDP

        Args:
            data (dict): a dict that has the variables for user input. Defined using class variables
            commit (bool): a bool that determines to commit or not to commit the changes to database
                        (since Netbox automatically reverts database changes on commit = False, we don't use it)

        Returns:
            str: output for the Output tab
        """
        output = ""
        devices = Device.objects.filter(name__regex=data["device_name"])

        for device in devices:
            napalm_lldp_neighbors = napalm_call("get_lldp_neighbors",
                                                device.id, self.request)

            lldp_interface_names = []
            for local_interface_name, remote_interface in napalm_lldp_neighbors.items(
            ):
                remote_device_name = remote_interface[0]["hostname"]
                remote_interface_name = remote_interface[0]["port"]

                lldp_interface_names.append(local_interface_name)
                try:
                    netbox_local_interface = Interface.objects.get(
                        device=device.id, name=local_interface_name)
                except Interface.DoesNotExist:
                    if data["non_existent"]:
                        self.log_warning(
                            f"""`[{device.name}]` Local interface **({local_interface_name})** for device **({device.name})** could not be found in Netbox.  
                            Please run the interface update script to have all the interfaces for a device generated"""
                        )
                    continue

                delete_cable = False
                if netbox_local_interface.cable is not None:
                    if (netbox_local_interface._cable_peer.name
                            == remote_interface_name
                            and netbox_local_interface._cable_peer.device.name
                            == remote_device_name):
                        # Cable already exists so we continue on
                        continue
                    else:  # A Netbox cable is connected but not to the interface the device is reporting
                        delete_cable = True  # Don't delete the cable immediately as the remote interface might not be there

                try:
                    remote_device = Device.objects.get(name=remote_device_name)
                    netbox_remote_interface = Interface.objects.get(
                        device=remote_device.id, name=remote_interface_name)
                except Device.DoesNotExist:
                    if data["non_existent"]:
                        self.log_info(
                            f"""`[{device.name}]` Remote device **({remote_device_name})** could not be found in Netbox  
                            Create the device in Netbox and add the **({remote_interface_name})** interface for a cable to be connected"""
                        )
                    continue
                except Interface.DoesNotExist:
                    if data["non_existent"]:
                        self.log_info(
                            f"""`[{device.name}]` Remote Interface **({remote_interface_name})** for device **({remote_device_name})** could not be found in Netbox  
                            Create the interface in Netbox for a cable to be connected"""
                        )
                    continue

                if delete_cable:
                    # Delete a cable that doesn't exist
                    netbox_local_interface.cable.delete()
                    self.log_success(
                        f"`[{device.name}]` Deleting a no longer existing cable: "
                        f"**{netbox_local_interface.name}** "
                        f"({netbox_local_interface.device.name})"
                        " <-> "
                        f"**{netbox_local_interface._cable_peer.name}** "
                        f"({netbox_local_interface._cable_peer.device.name})")

                # Create a new cable
                dcim_interface_type = ContentType.objects.get(
                    app_label="dcim", model="interface")
                new_cable = Cable(
                    termination_a_type=dcim_interface_type,
                    termination_a_id=netbox_local_interface.id,
                    termination_b_type=dcim_interface_type,
                    termination_b_id=netbox_remote_interface.id,
                )
                new_cable.save()

                self.log_success(f"`[{device.name}]` Creating a new cable: "
                                 f"**{netbox_local_interface.name}** "
                                 f"({netbox_local_interface.device.name})"
                                 " <-> "
                                 f"**{netbox_remote_interface.name}** "
                                 f"({netbox_remote_interface.device.name})")
            self.remove_old_cables(device, lldp_interface_names)

        return output