def test_duplicate_global_unique(self): IPAddress.objects.create(address=netaddr.IPNetwork('192.0.2.1/24')) duplicate_ip = IPAddress(address=netaddr.IPNetwork('192.0.2.1/24')) self.assertRaises(ValidationError, duplicate_ip.clean)
def store_original_ipaddress(instance: IPAddress, **_kwargs): instance.before_save = IPAddress.objects.filter(pk=instance.pk).first()
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))
def test_duplicate_global(self): IPAddress.objects.create(address=netaddr.IPNetwork('192.0.2.1/24')) duplicate_ip = IPAddress(address=netaddr.IPNetwork('192.0.2.1/24')) self.assertIsNone(duplicate_ip.clean())
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))
def sync_interfaces(device, interfaces): """ Syncing interfaces :param device: object NetBox Device :param interfaces: list of lists interfaces: interface['NAME'] - Name of interface interface['MAC'] - Mac-Address interface['IP'] - List of IP-address interface['MTU'] - MTU interface['DESCR'] - Description of interfaces interface['TYPE'] - Physical type of interface (Default 1G-cooper - cannot get from linux) interface['STATE'] - UP|DOWN :return: status: bool, message: string """ # Updated interface counter count = 0 # Init interfaces filter iface_filter = device.cf().get('Interfaces filter') try: iface_regex = re.compile(iface_filter) except Exception as e: logger.warning("Cannot parse regex for interface filter: {}".format(e)) iface_regex = re.compile('.*') for interface in interfaces: name = interface.get('NAME') mac = interface.get('MAC') ips = interface.get('IP') mtu = interface.get('MTU') description = interface.get('DESCR') iface_type = interface.get('TYPE') iface_state = interface.get('STATE') # TODO: add a bonding support iface_master = interface.get('BOND') # Check interface filter if not iface_regex.match(name): logger.debug("Iface {} not match with regex".format(name)) continue # Get interface from device - for check if exist ifaces = device.interfaces.filter(name=name) if ifaces: logger.info( "Interface {} is exist on device {}, will update".format( name, device.name)) # TODO: I think, that only one item will be in filter, but need to add check for it iface = ifaces[0] else: logger.info( "Interface {} is not exist on device {}, will create new". format(name, device.name)) iface = Interface(name=name) iface.device = device logger.info( "Will be save next parameters: Name:{name}, MAC: {mac}, MTU: {mtu}, Descr: {description}" .format(name=name, mac=mac, mtu=mtu, description=description)) if description: iface.description = description else: iface.description = '' iface.mac_address = mac # MTU should be less 32767 if int(mtu) < MAX_MTU: iface.mtu = mtu logger.info("Interface state is {}".format(iface_state)) iface.enabled = 'up' in iface_state.lower() iface.form_factor = _get_interface_type(name) try: iface.save() except Exception as e: logger.error("Cannot save interface, error is {}".format(e)) else: count += 1 logger.info("Interface {} was succesfully saved".format( name, device.name)) try: _connect_interface(iface) except: logger.error("Problem with connection function") # IP syncing if len(ips) > 0: for address in ips: addr = IPAddress() addr.interface = iface logger.info("Address is: {}".format(addr)) # TODO: Need a test ipv6 addresses try: # tries to determine is this address exist if iface.ip_addresses.filter(address=address): continue addr.address = IPNetwork(address) addr.save() except: logger.warning( "Cannot set address {} on interface".format(address)) if count == 0: return False, "Can't update any interface, see a log for details" return True, "Successfully updated {} interfaces".format(count)
def setUpTestData(cls): cluster_types = ( ClusterType(name='Cluster Type 1', slug='cluster-type-1'), ClusterType(name='Cluster Type 2', slug='cluster-type-2'), ClusterType(name='Cluster Type 3', slug='cluster-type-3'), ) ClusterType.objects.bulk_create(cluster_types) cluster_groups = ( ClusterGroup(name='Cluster Group 1', slug='cluster-group-1'), ClusterGroup(name='Cluster Group 2', slug='cluster-group-2'), ClusterGroup(name='Cluster Group 3', slug='cluster-group-3'), ) ClusterGroup.objects.bulk_create(cluster_groups) regions = ( Region(name='Test Region 1', slug='test-region-1'), Region(name='Test Region 2', slug='test-region-2'), Region(name='Test Region 3', slug='test-region-3'), ) for r in regions: r.save() site_groups = ( SiteGroup(name='Site Group 1', slug='site-group-1'), SiteGroup(name='Site Group 2', slug='site-group-2'), SiteGroup(name='Site Group 3', slug='site-group-3'), ) for site_group in site_groups: site_group.save() sites = ( Site(name='Test Site 1', slug='test-site-1', region=regions[0], group=site_groups[0]), Site(name='Test Site 2', slug='test-site-2', region=regions[1], group=site_groups[1]), Site(name='Test Site 3', slug='test-site-3', region=regions[2], group=site_groups[2]), ) Site.objects.bulk_create(sites) clusters = ( Cluster(name='Cluster 1', type=cluster_types[0], group=cluster_groups[0], site=sites[0]), Cluster(name='Cluster 2', type=cluster_types[1], group=cluster_groups[1], site=sites[1]), Cluster(name='Cluster 3', type=cluster_types[2], group=cluster_groups[2], site=sites[2]), ) Cluster.objects.bulk_create(clusters) platforms = ( Platform(name='Platform 1', slug='platform-1'), Platform(name='Platform 2', slug='platform-2'), Platform(name='Platform 3', slug='platform-3'), ) Platform.objects.bulk_create(platforms) roles = ( DeviceRole(name='Device Role 1', slug='device-role-1'), DeviceRole(name='Device Role 2', slug='device-role-2'), DeviceRole(name='Device Role 3', slug='device-role-3'), ) DeviceRole.objects.bulk_create(roles) tenant_groups = ( TenantGroup(name='Tenant group 1', slug='tenant-group-1'), TenantGroup(name='Tenant group 2', slug='tenant-group-2'), TenantGroup(name='Tenant group 3', slug='tenant-group-3'), ) for tenantgroup in tenant_groups: tenantgroup.save() tenants = ( Tenant(name='Tenant 1', slug='tenant-1', group=tenant_groups[0]), Tenant(name='Tenant 2', slug='tenant-2', group=tenant_groups[1]), Tenant(name='Tenant 3', slug='tenant-3', group=tenant_groups[2]), ) Tenant.objects.bulk_create(tenants) vms = ( VirtualMachine(name='Virtual Machine 1', cluster=clusters[0], platform=platforms[0], role=roles[0], tenant=tenants[0], status=VirtualMachineStatusChoices.STATUS_ACTIVE, vcpus=1, memory=1, disk=1, local_context_data={"foo": 123}), VirtualMachine(name='Virtual Machine 2', cluster=clusters[1], platform=platforms[1], role=roles[1], tenant=tenants[1], status=VirtualMachineStatusChoices.STATUS_STAGED, vcpus=2, memory=2, disk=2), VirtualMachine(name='Virtual Machine 3', cluster=clusters[2], platform=platforms[2], role=roles[2], tenant=tenants[2], status=VirtualMachineStatusChoices.STATUS_OFFLINE, vcpus=3, memory=3, disk=3), ) VirtualMachine.objects.bulk_create(vms) interfaces = ( VMInterface(virtual_machine=vms[0], name='Interface 1', mac_address='00-00-00-00-00-01'), VMInterface(virtual_machine=vms[1], name='Interface 2', mac_address='00-00-00-00-00-02'), VMInterface(virtual_machine=vms[2], name='Interface 3', mac_address='00-00-00-00-00-03'), ) VMInterface.objects.bulk_create(interfaces) # Assign primary IPs for filtering ipaddresses = ( IPAddress(address='192.0.2.1/24', assigned_object=interfaces[0]), IPAddress(address='192.0.2.2/24', assigned_object=interfaces[1]), ) IPAddress.objects.bulk_create(ipaddresses) VirtualMachine.objects.filter(pk=vms[0].pk).update( primary_ip4=ipaddresses[0]) VirtualMachine.objects.filter(pk=vms[1].pk).update( primary_ip4=ipaddresses[1])
def run(self, data, commit): services_list = [ { 'id_s': 's2', 'port': 22, 'name': 'SSHv2', 'protocol': 'tcp' }, { 'id_s': 's1', 'port': 22, 'name': 'SSHv1', 'protocol': 'tcp' }, { 'id_s': 't', 'port': 23, 'name': 'Telnet', 'protocol': 'tcp' }, { 'id_s': 'y', 'port': 443, 'name': 'YANG', 'protocol': 'tcp' }, { 'id_s': 'r', 'port': 443, 'name': 'REST', 'protocol': 'tcp' }, ] dev_role = DeviceRole.objects.get(slug='access-switch') device_new = Device( name=data['dev_name'], device_type=data['dev_model'], site=data['site'], rack=data['rack'], position=data['position'], device_role=dev_role, serial=data['dev_serial'], ) device_new.save() device_new.custom_field_data['fMonitoring'] = data['monitoring'] device_new.custom_field_data['fBackup'] = data['backup'] device_new.save() output = [] for iServ in data['services']: output.append(iServ) print(output) res = [row for row in services_list if row['id_s'] == iServ] s1 = Service( device=device_new, name=res[0]['name'], ports=[res[0]['port']], protocol=res[0]['protocol'], ) s1.save() dev_mgmt_int = Interface( device=device_new, name=data['mgmt_int_name'], type='virtual', ) dev_mgmt_int.save() ipa_type = ContentType.objects.get(app_label='dcim', model='interface') ipa = IPAddress( address=data['mgmt_int_ip'], assigned_object_id=dev_mgmt_int.id, assigned_object_type=ipa_type, ) ipa.save() device_new.primary_ip4 = ipa device_new.save() self.log_success(f"Created new Juniper device: {device_new}") return ''.join(output)
def run(self, data): host = data['vcenter_host'] user = data['vcenter_user'] password = data['vcenter_password'] vmCount = 0 ipCount = 0 intCount = 0 si = SmartConnectNoSSL(host=host, user=user, pwd=password, port=int(443)) if si: self.log_success("Connected to vCenter!") if not si: self.log_failure( "Couldn't connect to vCenter with the given credentials.") return -1 atexit.register(Disconnect, si) content = si.RetrieveContent() children = content.rootFolder.childEntity for child in children: dc = child vmdata[dc.name] = {} clusters = dc.hostFolder.childEntity for cluster in clusters: self.log_info(f"Found Cluster: {cluster}") vmdata[dc.name][cluster.name] = {} hosts = cluster.host for host in hosts: self.log_info(f"Found Host: {host}") hostname = host.summary.config.name vmdata[dc.name][cluster.name][hostname] = {} vms = host.vm self.log_info(f"DC Name: {vmdata[dc.name]}") self.log_info( f"Cluster Name: {vmdata[dc.name][cluster.name]}") for vm in vms: newVM = VirtualMachine( name=vm.summary.config.name, cluster=data['cluster'], status=DEVICE_STATUS_ACTIVE, vcpus=str(vm.summary.config.numCpu), memory=vm.summary.config.memorySizeMB, disk=str( int( float("%.2f" % (vm.summary.storage.committed / 1024**3))))) newVM.save() vmResult = VirtualMachine.objects.get( name=vm.summary.config.name) self.log_success("Created new VM: {}".format(newVM)) vmCount = vmCount + 1 nics = {} num = 1 for nic in vm.guest.net: if nic.network: if nic.ipConfig is not None and nic.ipConfig.ipAddress is not None: ipconf = nic.ipConfig.ipAddress i = 0 for ip in ipconf: if ":" not in ip.ipAddress: ipv4c = f"{ip.ipAddress}/{ip.prefixLength}" nicDescription = nic.network nicName = f"NIC{num}" newInt = Interface( virtual_machine=vmResult, name=nicName, description=nicDescription, type=IFACE_TYPE_VIRTUAL, mac_address=nic.macAddress) newInt.save() intCount = intCount + 1 intResult = Interface.objects.get( name=nicName, mac_address=nic.macAddress) self.log_info( f"Created new interface: {newInt} - {nic.macAddress}" ) newIP = IPAddress( family='4', address=ipv4c, description= f"{vm.summary.config.name} - {nicName}", interface=intResult) newIP.save() ipCount = ipCount + 1 num = num + 1 self.log_info( f"Created new IP: {newIP} - {nicName} - {nicDescription}" ) i = i + 1 self.log_info( f"Created {vmCount} VMs, {ipCount} IPs, and {intCount} interfaces." )
def test_duplicate_nonunique_role_nonrole(self): IPAddress.objects.create(address=IPNetwork('192.0.2.1/24'), role=IPAddressRoleChoices.ROLE_VIP) duplicate_ip = IPAddress(address=IPNetwork('192.0.2.1/24')) self.assertRaises(ValidationError, duplicate_ip.clean)
def test_duplicate_vrf_unique(self): vrf = VRF.objects.create(name='Test', rd='1:1', enforce_unique=True) IPAddress.objects.create(vrf=vrf, address=IPNetwork('192.0.2.1/24')) duplicate_ip = IPAddress(vrf=vrf, address=IPNetwork('192.0.2.1/24')) self.assertRaises(ValidationError, duplicate_ip.clean)
def test_duplicate_vrf(self): vrf = VRF.objects.create(name='Test', rd='1:1', enforce_unique=False) IPAddress.objects.create(vrf=vrf, address=IPNetwork('192.0.2.1/24')) duplicate_ip = IPAddress(vrf=vrf, address=IPNetwork('192.0.2.1/24')) self.assertIsNone(duplicate_ip.clean())
def setUpTestData(cls): vrfs = ( VRF(name='VRF 1', rd='65000:100'), VRF(name='VRF 2', rd='65000:200'), VRF(name='VRF 3', rd='65000:300'), ) VRF.objects.bulk_create(vrfs) site = Site.objects.create(name='Site 1', slug='site-1') manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1') device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1') devices = ( Device(device_type=device_type, name='Device 1', site=site, device_role=device_role), Device(device_type=device_type, name='Device 2', site=site, device_role=device_role), Device(device_type=device_type, name='Device 3', site=site, device_role=device_role), ) Device.objects.bulk_create(devices) clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1') cluster = Cluster.objects.create(type=clustertype, name='Cluster 1') virtual_machines = ( VirtualMachine(name='Virtual Machine 1', cluster=cluster), VirtualMachine(name='Virtual Machine 2', cluster=cluster), VirtualMachine(name='Virtual Machine 3', cluster=cluster), ) VirtualMachine.objects.bulk_create(virtual_machines) interfaces = ( Interface(device=devices[0], name='Interface 1'), Interface(device=devices[1], name='Interface 2'), Interface(device=devices[2], name='Interface 3'), Interface(virtual_machine=virtual_machines[0], name='Interface 1'), Interface(virtual_machine=virtual_machines[1], name='Interface 2'), Interface(virtual_machine=virtual_machines[2], name='Interface 3'), ) Interface.objects.bulk_create(interfaces) tenant_groups = ( TenantGroup(name='Tenant group 1', slug='tenant-group-1'), TenantGroup(name='Tenant group 2', slug='tenant-group-2'), TenantGroup(name='Tenant group 3', slug='tenant-group-3'), ) TenantGroup.objects.bulk_create(tenant_groups) tenants = ( Tenant(name='Tenant 1', slug='tenant-1', group=tenant_groups[0]), Tenant(name='Tenant 2', slug='tenant-2', group=tenant_groups[1]), Tenant(name='Tenant 3', slug='tenant-3', group=tenant_groups[2]), ) Tenant.objects.bulk_create(tenants) ipaddresses = ( IPAddress(family=4, address='10.0.0.1/24', tenant=None, vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-a'), IPAddress(family=4, address='10.0.0.2/24', tenant=tenants[0], vrf=vrfs[0], interface=interfaces[0], status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-b'), IPAddress(family=4, address='10.0.0.3/24', tenant=tenants[1], vrf=vrfs[1], interface=interfaces[1], status=IPAddressStatusChoices.STATUS_RESERVED, role=IPAddressRoleChoices.ROLE_VIP, dns_name='ipaddress-c'), IPAddress(family=4, address='10.0.0.4/24', tenant=tenants[2], vrf=vrfs[2], interface=interfaces[2], status=IPAddressStatusChoices.STATUS_DEPRECATED, role=IPAddressRoleChoices.ROLE_SECONDARY, dns_name='ipaddress-d'), IPAddress(family=4, address='10.0.0.1/25', tenant=None, vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE), IPAddress(family=6, address='2001:db8::1/64', tenant=None, vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-a'), IPAddress(family=6, address='2001:db8::2/64', tenant=tenants[0], vrf=vrfs[0], interface=interfaces[3], status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-b'), IPAddress(family=6, address='2001:db8::3/64', tenant=tenants[1], vrf=vrfs[1], interface=interfaces[4], status=IPAddressStatusChoices.STATUS_RESERVED, role=IPAddressRoleChoices.ROLE_VIP, dns_name='ipaddress-c'), IPAddress(family=6, address='2001:db8::4/64', tenant=tenants[2], vrf=vrfs[2], interface=interfaces[5], status=IPAddressStatusChoices.STATUS_DEPRECATED, role=IPAddressRoleChoices.ROLE_SECONDARY, dns_name='ipaddress-d'), IPAddress(family=6, address='2001:db8::1/65', tenant=None, vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE), ) IPAddress.objects.bulk_create(ipaddresses)
def handle(self, *args, **options): # First, query for the device by name. try: device = Device.objects.get(name=options['device_name']) except Device.DoesNotExist: self.stdout.write(f"Unable to find device: {options['device_name']}") return # Determine the information needed to connect to the device. mgmt_ip = device.primary_ip4 onepw_host = settings.PLUGINS_CONFIG['sidekick'].get('1pw_connect_host', None) onepw_token_path = settings.PLUGINS_CONFIG['sidekick'].get('1pw_connect_token_path', None) onepw_vault = settings.PLUGINS_CONFIG['sidekick'].get('1pw_connect_readonly_vault', None) # If all of the connection information was found, # attempt to decrypt the connection credentials, # connect to the device, and inventory the interfaces. if mgmt_ip is not None and \ onepw_host is not None and \ onepw_token_path is not None and \ onepw_vault is not None: _mgmt_ip = "%s" % (mgmt_ip.address.ip) try: snmp = decrypt_1pw_secret(onepw_token_path, onepw_host, onepw_vault, f"{device}", 'snmp') except Exception as e: self.stdout.write(f"Unable to decrypt snmp secret: {e}") if snmp is None: self.stdout.write(f"Unable to find snmp secret for {device}") return try: device_info = snmpwalk_bulk(_mgmt_ip, snmp) # device_info = get_device_info_via_snmp(_mgmt_ip, snmp) except Exception as e: self.stdout.write(f"Error querying device {device}: {e}") return # If we're able to connect, # build a list of interface names already on the device. existing_interfaces = {} for i in device.vc_interfaces(): existing_interfaces[i.name] = i # Obtain the list of interfaces. # For each device that is not supposed to be ignored, # add that interface to the device if it doesn't already exist. for iface_index, iface_details in device_info.items(): iface_name = iface_details.get('ifName', None) if iface_name is None: continue # self.stdout.write(f"{iface_details['name']}: {iface_details['oper_status']}") # continue if not any(i in iface_details['ifName'] for i in VALID_INTERFACE_NAMES): continue iface_type = InterfaceTypeChoices.TYPE_VIRTUAL if iface_details['ifHighSpeed'] == 1000: iface_type = InterfaceTypeChoices.TYPE_1GE_FIXED if iface_details['ifHighSpeed'] == 10000: iface_type = InterfaceTypeChoices.TYPE_10GE_FIXED if iface_details['ifHighSpeed'] == 'ieee8023adLag': iface_type = InterfaceTypeChoices.TYPE_LAG # TODO: VLAN management is incomplete right now. # _vlan = None iface_mode = InterfaceModeChoices.MODE_TAGGED if '.' in iface_name: iface_mode = InterfaceModeChoices.MODE_ACCESS # _vlan = iface_name.split('.')[1] if 'Vlan' in iface_name: iface_mode = InterfaceModeChoices.MODE_ACCESS # m = RE_ARISTA_VLAN.search(iface_name) # if m: # _vlan = m.group(1) iface_untagged_vlan = None # if _vlan is not None: # try: # iface_untagged_vlan = VLAN.objects.get(vid=_vlan) # except VLAN.MultipleObjectsReturned: # self.stdout.write(f"WARNING: Multiple results found for VLAN {_vlan}. Not setting VLAN.") # except VLAN.DoesNotExist: # self.stdout.write(f"WARNING: No results found for VLAN {_vlan}. Not setting VLAN.") # If the interface already exists, update a few fields. # We do not update the interface type because that could have # been updated in NetBox directly to something more specific/better # than what SNMP can can determine. if iface_name in existing_interfaces.keys(): existing_interface = existing_interfaces[iface_name] changed = False _descr = iface_details['ifAlias'].strip() if existing_interface.description != _descr: existing_interface.description = _descr changed = True admin_status = f"{iface_details['ifAdminStatus']}" if admin_status == "up": admin_status = 1 if admin_status == "down": admin_status = 0 iface_status = False oper_status = iface_details['ifOperStatus'] if admin_status == 1 and oper_status == 1: iface_status = True if existing_interface.enabled != iface_status: existing_interface.enabled = iface_status changed = True if existing_interface.untagged_vlan != iface_untagged_vlan: existing_interface.untagged_vlan = iface_untagged_vlan changed = True if changed is True: if options['dry_run']: self.stdout.write(f"Would have updated {iface_name}") else: existing_interface.save() if iface_name not in existing_interfaces.keys(): if options['dry_run']: self.stdout.write(f"Would have added {iface_name}") else: admin_status = f"{iface_details['ifAdminStatus']}" if admin_status == "down": admin_status = False if admin_status == "up": admin_status = True mtu = iface_details.get('ifMtu', 0) if 'No more variables' in f"{mtu}": mtu = 0 iface = Interface( device=device, description=iface_details.get('ifDescr', None), name=iface_name, type=iface_type, enabled=admin_status, mac_address=iface_details.get('ifPhysAddress', None), mtu=mtu, mode=iface_mode, untagged_vlan=iface_untagged_vlan, ) iface.save() # To account for one or more new interfaces being added, # build a list of interface names already on the device. existing_interfaces = {} for i in device.vc_interfaces(): existing_interfaces[i.name] = i # Obtain the list of IP addresses on each interface. # For each interface that is not supposed to be ignored, # add the IP address to the interface if it doesn't already exist. for iface_index, iface_details in device_info.items(): iface_name = iface_details.get('ifName', None) if iface_name is None: continue if not any(i in iface_name for i in VALID_INTERFACE_NAMES): continue if iface_name not in existing_interfaces.keys(): continue existing_interface = existing_interfaces[iface_name] existing_ip_addresses = existing_interface.ip_addresses.all() for version, family in IP_VERSIONS.items(): if version not in iface_details.keys(): continue if iface_details[version] is None: continue # Check if an IP was removed from the device. # If so, then delete it from NetBox. for existing_ip in existing_ip_addresses: if existing_ip.family == family: if f"{existing_ip}" not in iface_details[version]: if options['dry_run']: self.stdout.write( f"Would have removed {existing_ip} from {iface_name}") else: existing_ip.assigned_object = None existing_ip.description = f"Previously assigned to {options['device_name']} on interface {iface_name}" existing_ip.save() # Check if an IP needs to be added to NetBox. for interface_ip in iface_details[version]: # If the IP polled from the device is not in the NetBox device interface... if not any(interface_ip == f"{_ip}" for _ip in existing_ip_addresses): try: ip = IPAddress.objects.get(address=interface_ip) if ip.assigned_object is not None and ip.assigned_object.id != existing_interface.id: # If the IP being reported is the management IP, then ignore. # This is because we want to standardize on the name of the # management interface, even if the IP address is on a different # interface. This isn't ideal and should be improved in the # future. if ip == mgmt_ip: continue # Also ignore private IP addresses since they can be # reused in different locations. Again, this isn't ideal and # should be improved in the future. if f"{ip}".startswith("10.") or f"{ip}".startswith("172.") or f"{ip}".startswith("192."): continue # If the IP assignment is on the same device, we will assume # a reconfiguration was made. In this case, we reassign the # IP. if ip.assigned_object.device.name == existing_interface.device.name: ip.assigned_object = existing_interface ip.save() continue self.stdout.write( f"IP Address {interface_ip} is already assigned to " f"{ip.assigned_object.name} on {ip.assigned_object.device.name}. " f"Will not assign to {existing_interface.name} on " f"{existing_interface.device.name}") continue # Otherwise, add the IP to the interface. else: if options['dry_run']: self.stdout.write( f"Would have added {interface_ip} to {existing_interface.name}") else: if ip.description != existing_interface.description: ip.description = existing_interface.description ip.assigned_object = existing_interface ip.save() except IPAddress.MultipleObjectsReturned: self.stdout.write(f"WARNING: Multiple results found for IP {interface_ip}. Skipping.") continue except IPAddress.DoesNotExist: if options['dry_run']: self.stdout.write( f"Would have created IP address {interface_ip} and added it to " + f"{existing_interface.name}") else: ip = IPAddress( address=interface_ip, description=existing_interface.description) ip.save() existing_interface.ip_address = ip existing_interface.save() # Obtain the counters on each interface. # For each interface that is not supposed to be ignored, # store the counters as a NIC object. for iface_index, iface_details in device_info.items(): iface_name = iface_details.get('ifName', None) if iface_name is None: continue if not any(i in iface_name for i in VALID_INTERFACE_NAMES): continue if iface_name not in existing_interfaces.keys(): continue existing_interface = existing_interfaces[iface_name] if options['dry_run']: self.stdout.write(f"Would have updated counters for {existing_interface.name}: {iface_details}") else: admin_status = iface_details.get('ifAdminStatus', 0) if 'No more variables' in f"{admin_status}": admin_status = 0 oper_status = iface_details.get('ifOperStatus', 0) if 'No more variables' in f"{oper_status}": oper_status = 0 out_octets = iface_details.get('ifHCOutOctets', 0) if 'No more variables' in f"{out_octets}": out_octets = 0 in_octets = iface_details.get('ifHCInOctets', 0) if 'No more variables' in f"{in_octets}": in_octets = 0 out_unicast_packets = iface_details.get('ifHCOutUcastPkts', 0) if 'No more variables' in f"{out_unicast_packets}": out_unicast_packets = 0 in_unicast_packets = iface_details.get('ifHCInUcastPkts', 0) if 'No more variables' in f"{in_unicast_packets}": in_unicast_packets = 0 out_nunicast_packets = iface_details.get('ifOutNUcastPkts', 0) if 'No more variables' in f"{out_nunicast_packets}": out_nunicast_packets = 0 in_nunicast_packets = iface_details.get('ifInNUcastPkts', 0), if 'No more variables' in f"{in_nunicast_packets}": in_nunicast_packets = 0 out_errors = iface_details.get('ifOutErrors', 0) if 'No more variables' in f"{out_errors}": out_errors = 0 in_errors = iface_details.get('ifInErrors', 0) if 'No more variables' in f"{in_errors}": in_errors = 0 nic = NIC( interface=existing_interface, interface_id=existing_interface.id, admin_status=admin_status, oper_status=oper_status, out_octets=out_octets, in_octets=in_octets, out_unicast_packets=out_unicast_packets, in_unicast_packets=in_unicast_packets, out_nunicast_packets=out_nunicast_packets, in_nunicast_packets=in_unicast_packets, out_errors=out_errors, in_errors=in_errors, ) if 'in_rate' in iface_details: nic.in_rate = iface_details['in_rate'] if 'out_rate' in iface_details: nic.out_rate = iface_details['out_rate'] nic.save() # Send the metrics to Graphite if graphite_host has been set. graphite_host = settings.PLUGINS_CONFIG['sidekick'].get('graphite_host', None) if graphite_host is not None: graphyte.init(graphite_host) # Determine the difference between the last two updates. # This is because Cybera's metrics were previously stored in RRD # files which only retains the derivative and not what the actual # counters were. previous_entries = NIC.objects.filter( interface_id=existing_interface.id).order_by('-last_updated') if len(previous_entries) < 2: continue e1 = previous_entries[0] e2 = previous_entries[1] total_seconds = (e1.last_updated - e2.last_updated).total_seconds() graphite_prefix = "{}.{}".format( e1.graphite_device_name(), e1.graphite_interface_name()) for cat in METRIC_CATEGORIES: m1 = getattr(e1, cat, None) m2 = getattr(e2, cat, None) if m1 is not None and m2 is not None: diff = (m1 - m2) if diff != 0: diff = diff / total_seconds graphite_name = f"{graphite_prefix}.{cat}" if options['dry_run']: self.stdout.write(f"{graphite_name} {diff} {total_seconds}") else: graphyte.send(graphite_name, diff) # Determine if the interface is part of a member's network service. # If so, send a second set of metrics to Graphite with a prefix # dedicated to that service. try: nsd = NetworkServiceDevice.objects.get( device=device, interface=existing_interface.name, network_service__active=True) except NetworkServiceDevice.MultipleObjectsReturned: self.stdout.write(f"Multiple results found for network service using " f"{device} {existing_interface.name}") continue except NetworkServiceDevice.DoesNotExist: continue ns = nsd.network_service service_prefix = f"{ns.graphite_service_name()}.{graphite_prefix}" for cat in ['in_octets', 'out_octets']: graphite_name = f"{service_prefix}.{cat}" m1 = getattr(e1, cat, None) m2 = getattr(e2, cat, None) if m1 is not None and m2 is not None: diff = (m1 - m2) if diff != 0: diff = diff / total_seconds graphyte.send(graphite_name, diff)
def handle(self, *args, **options): # First, query for the device by name. try: device = Device.objects.get(name=options['name']) except Device.DoesNotExist: self.stdout.write(f"Unable to find device: {options['name']}") return # If an IP address was specified, then configure the device with it. _ip = options['ip'] if _ip is not None: # Make sure there's an interface named "mgmt" # If there isn't, then create one. mgmt_iface = next( (True for iface in device.vc_interfaces() if iface.name == 'mgmt'), None) if not mgmt_iface: if options['dry_run']: self.stdout.write( 'Would have created a managment interface called mgmt') else: mgmt_iface = Interface( device=device, name='mgmt', type=InterfaceTypeChoices.TYPE_VIRTUAL) mgmt_iface.save() # Make sure the specific IP address exists and is on the mgmt interface. try: _ip = options['ip'] mgmt_ip = IPAddress.objects.get(address=_ip) # If the IP exists, make sure it's currently not assigned to another interface. if mgmt_ip.interface is not None: if mgmt_ip.interface.name != 'mgmt' and mgmt_ip.interface.device.id != device.id: self.stdout.write( f"IP Address {_ip} is already assigned to {mgmt_ip.interface.device.name}" ) return # Otherwise, add the IP to the interface. else: if options['dry_run']: self.stdout.write( f"Would have added {mgmt_ip} to the mgmt interface" ) else: mgmt_ip.interface = mgmt_iface mgmt_ip.save() except IPAddress.DoesNotExist: # If the IP doesn't exist, create it and link it to the mgmt interfae. if options['dry_run']: self.stdout.write( f"Would have created IP address {options['ip']} and assigned it to the mgmt interface" ) else: mgmt_ip = IPAddress(address=options['ip'], interface=mgmt_iface) mgmt_ip.save() # Ensure the primary IP address of the device is set to the mgmt IP. if device.primary_ip4 is None or device.primary_ip4.id != mgmt_ip.id: if options['dry_run']: self.stdout.write( f"Would have assigned {mgmt_ip} as the primary IP of the device" ) else: device.primary_ip4 = mgmt_ip device.save()
def test_address_vrf_ordering(self): """ This function tests ordering with the inclusion of vrfs """ # Setup VRFs vrfa, vrfb, vrfc = self.vrfs # Setup Addresses addresses = ( IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.0.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.0.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.0.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.0.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.0.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.1.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.1.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.1.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.1.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.1.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.2.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.2.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.2.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.2.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.2.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.16.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.16.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.16.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.16.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.16.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.17.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.17.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.17.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.17.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.17.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.5.1/24')), ) IPAddress.objects.bulk_create(addresses) # Test self._compare(IPAddress.objects.all(), addresses)
def test_duplicate_vrf(self): vrf = VRF.objects.create(name='Test', rd='1:1', enforce_unique=False) IPAddress.objects.create(vrf=vrf, address=netaddr.IPNetwork('192.0.2.1/24')) duplicate_ip = IPAddress(vrf=vrf, address=netaddr.IPNetwork('192.0.2.1/24')) self.assertIsNone(duplicate_ip.clean())
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