Skip to end of metadata
Go to start of metadata

Итак, я лентяй, я лучше напишу кратенький скриптик, чтоб он за меня пробежался по всем адресам и вбил им FQDN, чем буду делать это нудно и печально.

Шаблон.... Определимся с шаблоном таким образом:

Vlan 5, SVI 50, GigabitEthernet 2/1, FastIron 400 = v5-50g2-1-fi4-1-<place>.rt.domain.net

Как это можно автоматизировать?

По ip мы можем найти svi, через него узнать VLAN и managed_object(хотя, зачастую можно managed_object выдрать и напрямую из Ip). Зная VLAN и managed_object можно попробовать найти порт, на котором этот влан p2p-линка болтается.

Проверку проводим в пределах определенного префикса, допустим - 127.0.0.1/24 . Начинаем:

./noc shell
from noc.ip.models import *
from noc.inv.models import *
prf=Prefix.objects.get(prefix='127.0.0.1/24') # здесь мы выбираем из всех префиксов IPAM нужный нам
adrs=prf.nested_address_set # здесь мы выбираем все IP адреса из нашего префикса. Даже если это адреса из префикса уровнем ниже, все-равно они попадут в выбор
for a in adrs:
	sub = SubInterface.objects.filter(ipv4_addresses__contains=a.address + '/') # Из сабинтерфейсов мы выбираем те, которые имеют нужный нам адрес. Я склеил a.address и '/' для того, чтоб в выборку попали только те сабы, которые имеют адрес ИМЕННО 127.0.0.х . Если этого не сделать, то под запрос попадут и 127.0.0.1 и 127.0.0.10, 127.0.0.100 и так далее.
	sub, a.address # здесь мы выводим список сабов и адрес. Сабы именуются по шаблону "устройство сабинтерфейс"

Если это все, только без комментов аккуратно скопировать, поменять префикс на нужный, попробовать выполнить - питон остановится на многоточии. Жмите еще раз Enter - цикл начнет выполняться. По результату можно увидеть, что какой-то адрес есть на нескольких устройствах. Это может случиться, если сабинтерфейс забыли зачистить при переносе линка. Такое лучше зачистить.

Саб мы нашли... Продолжаем разговор(дописываем цикл дальше):

	for s in sub:
		s, s.vlan_ids, s.untagged_vlan, s.tagged_vlans # для каждого сабинтерфейса смотрим, какие вланы у него есть тегом, антегом и вообще.

Дальше начинается магия. По логике IGetInterfaces на L3 SVI должен быть определен только vlan_ids. После того, как мы получили к нему доступ - мы берем и фильтруем все оставшиеся subinterfaces по tagged_vlans и untagged_vlan(должны равняться s.vlan_ids). Полученный результат пробегаем по одиночке. Если вдруг у этого саба поле interface.type будет physical  - это наш нужный порт.

В итоге получаем такую хрень(нужно дополнительно импортнуть string):

for a in adrs:
 sub = SubInterface.objects.filter(ipv4_addresses__contains=a.address + '/')
 sub, a.address
 for s in sub:
  s, s.vlan_ids, s.untagged_vlan, s.tagged_vlans,s.interface.type
  ports = SubInterface.objects.filter(managed_object=s.managed_object.id).filter(Q(untagged_vlan=s.vlan_ids[0])|Q(tagged_vlans__contains=s.vlan_ids[0]))
  for p in ports:
   if p.interface.type=='physical':
    p.name,p.interface.type
    fqn=str(s.vlan_ids[0])+'-'+s.name+'-'+p.name+'-'+s.managed_object.name+'.domain.com'
    fqn=string.replace(fqn," ","")
    fqn=string.replace(fqn,"/","-")
    fqn

fqn будет содержать в результате тот самый FQDN на основании vlan, svi, port, object_name.

Зачищаем отладочные выводы, прихорашиваем, получаем результат:

from noc.ip.models import *
from noc.inv.models import *
import string
prf=Prefix.objects.get(prefix='127.0.0.0/24')
adrs=prf.nested_address_set
for a in adrs:
 sub = SubInterface.objects.filter(ipv4_addresses__contains=a.address + '/')
 for s in sub:
  ports = SubInterface.objects.filter(managed_object=s.managed_object.id).filter(Q(untagged_vlan=s.vlan_ids[0])|Q(tagged_vlans__contains=s.vlan_ids[0]))
  for p in ports:
   if p.interface.type=='physical':
    fqn=str(s.vlan_ids[0])+'-'+s.name+'-'+p.name+'-'+s.managed_object.name+'.domain.com'
    fqn=string.replace(fqn," ","")
    fqn=string.replace(fqn,"/","-")
    fqn

Очевидно, что если поменять местами что-то в строке 

    fqn=str(s.vlan_ids[0])+'-'+s.name+'-'+p.name+'-'+s.managed_object.name+'.domain.com'

то изменится формат/шаблон FQDN. В завершение можно добавить строки (вместо одиноко стоящей fqn)

    a.fqdn=fqn
    a.save()

Запустить, дождаться завершения, зайти в IPAM. Убедиться, что внутри префикса все переименовано.

Да, могут быть баги, может быть ругань, не забывайте бекапиться перед тем, как будете менять объекты.

 

PS:

Что можно со всего этого поиметь - скрипт, который кладется в ./scripts/ или pyRule, которое будет запускаться шедулером. Можно даже Job, но зачем? (smile)

15:20:58] <dvolodin> # -*- coding: utf-8 -*-
[15:21:05] <dvolodin> import set_env
[15:21:05] <dvolodin> set_env.setup(use_django=True)
[15:21:16] <dvolodin> дальше -- обычный скрипт
[15:21:25] <mikevlz> на две строчки больше...
[15:21:28] <dvolodin> с полным доступом ко всем объектам NOC
[15:21:30] <dvolodin> да
[15:21:42] <dvolodin> зато пускается ./scripts/myscript
[15:21:47] <dvolodin> и можно параметры парсить
[15:21:52] <mikevlz> лучше расскажи, как из этого сделать джоб или еще что-нить, чтоб оно само по расписанию крутилось
[15:22:00] <dvolodin> pyrule
[15:22:01] <mikevlz> прям там, внутрях нока
[15:22:04] <dvolodin> и на scheduler
[15:22:24] <mikevlz> я почему-то так и думал :)
[15:22:49] <dvolodin> в правиле
[15:22:52] <dvolodin> @pyrule
[15:22:52] <dvolodin> def rule(timeout=None):
[15:22:52] <dvolodin> .....
[15:23:10] <dvolodin> интерфейс у него - IPeriodicTask
[15:23:39] <dvolodin> есть еще одна афромагия
[15:24:20] <dvolodin> в noc'овский scheduler приехал lib/scheduler.py
[15:24:26] <dvolodin> со всеми потрохами
[15:24:33] <mikevlz> ну мне эти упражнения показали, что часть оборудования надо донастроить, подчистить конфиги... потом сделаю, запущу
[15:24:35] <dvolodin> он теперь умеет и job'ы запускать