Blog

Записки новичка: консервируем МО

У нас нередко коммутатор получает "вторую жизнь".

По каким-либо причинам мы его демонтируем, помещаем на склад, а спустя некоторое время он возвращается в сеть, как новый объект.

Для NOC`а, однако, это не совсем новый объект, некоторые его свойства он помнит для его предыдущей реинкарнации.

Я правлю это так:

./noc shell
from noc.inv.models.discoveryid import DiscoveryID
from noc.inv.models import *
from noc.sa.models import *
MO = {'MO1', 'MO2'}
for m in MO:
    id = ManagedObject.objects.get(name = m).id
    try:
        chassis = DiscoveryID.objects.get(object = id)
        print "chassis:", chassis.object, chassis.chassis_mac, chassis.id         
        # delete chassis 
        chassis.delete()
        chassis.save()
    except:
        print "chassis not found:", m
    for i in Interface.objects.filter(managed_object = id):
        if i.link:
            try:
                l = Link.objects.get(interfaces = i)
                print "link:", i.link
                # delete link
                l.delete()
                l.save()
            except:
                print "link not found:", i
        # delete interface
        i.delete()
        i.save()
quit()

Для добавления железок используются ип адреса из address space managment-assignet addresses. Там же нужно проставить tag. Вот сам скрипт

 

from noc.sa.models import *
from noc.inv.models import *
from noc.ip.models import *
from noc.main.models import SystemNotification
import string
import commands
for i in range(1,10):                          #задаем диапазон сеток
  prf=Prefix.objects.filter(prefix='10.10.'+str(i)+'.0/24',vrf='1') #делим диапазон на сети /24 (10.10.1.0/24 по 10.10.10.0/24)
  for p in prf:
    if p.tags:
      tags1= ','.join(str(v) for v in p.tags)     #ищем тег сетки 
      adrs=p.nested_address_set                   #поиск найденных адресов
      print tags1
      for a in adrs:
        addpr=False
        mo=ManagedObject.objects.filter(address=a.address)  #проверка на наличие mo
        if mo:
           for o in mo:
            print o.name
            addpr=False
        else:
           print a.address
           ring="ring"+str(int(str(a.address).split('.')[3])//20)                          #доп тег
           cmd="snmpget -v 2c -c public " + str(a.address) + " 1.3.6.1.2.1.1.2.0 -O Uvqn"  #вендор
           cmd2="snmpget -v 2c -c public " + str(a.address) + " 1.3.6.1.2.1.1.5.0 -O Uvqn" #hostname - будущее имя mo
           x=str(commands.getoutput(cmd))
           name=commands.getoutput(cmd2).replace('"', '')
           if x == ".1.3.6.1.4.1.2011.2.23.92":               #различные вендоры
            type1="Huawei.VRP"#s2326
            type2="s2300"
            addpr=True
           if x == ".1.3.6.1.4.1.259.6.10.94":
            type1="EdgeCore.ES"
            type2="edge"
            addpr=True
           if x == ".1.3.6.1.4.1.2011.2.23.96":            #железку не добавляем
            type1="Huawei.VRP"
            addpr=False
            continue
           if x == ".1.3.6.1.4.1.2011.2.23.229":
            type1="Huawei.VRP" #s2328
            type2="s2300"
            addpr=True
           if x.startswith("Timeout"):
            addpr=False
            continue
           if addpr:
            tags2 = [tags1,ring,type2]
            print tags2
            print addpr
            print name
            m = ManagedObject(name=name.format(a.address),is_managed=True,administrative_domain=AdministrativeDomain.objects.get(name="default"),activator = Activator.objects.get(name='default'),profile_name = type1, tags = tags2, snmp_ro = 'public', object_profile = ManagedObjectProfile.objects.get(name='test1'), scheme = 0, address = a.address, user = 'user', password = 'pass')
            m.save()                           #запись нового mo
            a.managed_object = m  

Работает через ./noc shell. На выходе куча железок в sa-mo, в которых проставлены вендоры, теги и тд, те сразу начинается сбор статистики.

Код далек от идеала. Например, выдет ошибку, если у мо 2 ип (это поправимо).

  1. Как запихнуть этот код в пируль?
  2. При переносе железки с изменением ип, хотелось бы старый мо удалить и создать новый.
  3. Как применить несколько snmp community?

(Canned BeefNOC-1429)

Есть у меня в использовании несколько коммутаторов DLink DGS-3100-24TG.

Они чуть более исключительные, чем остальные DES-DGS, и для них сделан отдельный профиль DGS3100.

Я допилил для указанного профиля обработку портчэналов, доработка коснулась скриптов get_portchannel и get_interfaces.

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

В NOC'е для этого реализован механизм работы с "тушенкой", возможность собрать данные с коммутатора и затем тестировать работу скриптов в отсутствии самого железа.

Обновим "тушенку" из публичного репо:

noc@noc:/opt/noc$ ./noc beef --pull
[sa_public]
pulling from https://bitbucket.org/nocproject/noc-sa-beef-public
searching for changes
no changes found

Тестируем скрипты:

noc@noc:/opt/noc$ ./noc test --beef-filter=DLink.DGS3100.get_portchannel noc.stop
Ran 0 tests in 0.000s
OK
noc@noc:/opt/noc$ ./noc test --beef-filter=DLink.DGS3100.get_interfaces noc.stop
Ran 0 tests in 0.000s
OK

Ноль тестов? Проверяем, есть ли "тушенка" для наших скриптов.

Данные лежат в /opt/noc/local/

noc@noc:/opt/noc/local/repos/sa/sa_public/DLink/DGS3100$ ls -l
drwxrwxr-x 2 noc noc 4096 Oct 20 14:41 get_chassis_id
drwxrwxr-x 2 noc noc 4096 Oct 20 14:41 get_dom_status
drwxrwxr-x 2 noc noc 4096 Oct 20 14:41 get_interface_status
drwxrwxr-x 2 noc noc 4096 Oct 20 14:41 get_lldp_neighbors
drwxrwxr-x 2 noc noc 4096 Oct 20 14:41 get_mac_address_table
drwxrwxr-x 2 noc noc 4096 Oct 20 14:41 get_version
drwxrwxr-x 2 noc noc 4096 Oct 20 14:41 get_vlans

Видим, что для get_portchannel и get_interfaces нет каталогов.

Значит сделаем локальный репо и протестируем на своих данных.

Пишем где будет наш репо:

etc/beef.conf

[my_repo]
enabled = true
type = sa
private = true
repo = /srv/noc/my_repo

Проверяем:

noc@noc:/opt/noc$ ./noc beef --list-repo
E P T  Name                 Repo
+ N sa sa_public            https://bitbucket.org/nocproject/noc-sa-beef-public
+ N sa my_repo              /srv/noc/my_repo

Готовим "тушенку":

./noc debug-script get_portchannel router1 -o output.json
./noc debug-script get_interfaces  router1 -o output.json

(DLink DGS-3100 — предварительно сделанный селектор)

 

./noc shell
from noc.sa.models import *
SELECTOR = "DLink DGS-3100"
mos = ManagedObjectSelector.objects.filter(name=SELECTOR)[0]
if mos is not None:
    for m in mos.managed_objects:
        #print m.name, m.platform, m.get_attr("version","")
        txt  = "./noc debug-script get_portchannel " 
        txt += m.name + " -o /home/noc/" 
        txt += m.name.split(".")[0] + "_get_portchannel_" 
        txt += m.get_attr("version","") + ".json"
        print txt
if mos is not None:
    for m in mos.managed_objects:
        txt  = "./noc debug-script get_interfaces " 
        txt += m.name + " -o /home/noc/" 
        txt += m.name.split(".")[0] + "_get_interfaces_" 
        txt += m.get_attr("version","") + ".json"
        print txt
quit()

получаю строки вида:
./noc debug-script get_portchannel router1 -o /home/noc/s2-5-8_get_portchannel_3.60.44.json
./noc debug-script get_interfaces router1 -o /home/noc/s2-5-8_get_interfaces_3.60.44.json

затем кучей вываливаю их в консоль и через некоторое время получаю "тушенку" в /home/noc/

 


Делаем каталоги  get_portchannel и get_interfaces в /srv/noc/my_repo, копируем в них полученные файлы json. (json в репо помещается не совсем так, буду корректировать)

Тестируем на наших данных:

noc@noc:/opt/noc$ ./noc test --beef=/srv/noc/my_repo/ noc.stop
Ran 28 tests in 0.014s
OK

Или так:

./noc test --beef=/srv/noc/my_repo/ --beef-filter=DLink.DGS3100.get_portchannel noc.stop
./noc test --beef=/srv/noc/my_repo/ --beef-filter=DLink.DGS3100.get_interfaces noc.stop

Или так, на всей доступной тушенке: и нашей и публичной:

./noc test --beef-filter=DLink.DGS3100.get_portchannel noc.stop
./noc test --beef-filter=DLink.DGS3100.get_interfaces noc.stop

 

Ура, скрипты корректно работают на всех DGS-3100, которые есть у меня в NOC`е.

 

P.S.

Бывает, что "test" ругается на данные, а мы видим, что скрипт корректно отдает данные. В моем случае ругалось на ответ скрипта "[]".

Корректируем данные так:

./noc test --beef=/srv/noc/my_repo/ --fixed-beef-base=/srv/noc/fixed-beef yes

в /srv/noc/fixed-beef будут сформированы файлы, в которых найдена и поправлена ошибка. Копируем эти файлы в репо (нужно угадать какие файлы были ошибочные) и снова тестируемся.


Файлы "тушенки" отправляем на beef@nocproject.org и если все корректно, то их разместят в публичном репо.

 

 

Записки новичка: закрытие аварий

Как подсказал zi_rus:

 

09:36 misak, noc shell в помощь
09:36 from noc.fm.models import *
09:36 ac = AlarmClass.objects.get(name='Network | EIGRP | Neighbor Down')
09:36 alarms = ActiveAlarm.objects.filter(alarm_class=ac)
09:36 
09:36 for a in alarms:
09:36 a.clear_alarm("close")
09:36 from noc.fm.models import *
09:36 alarms = ActiveAlarm.objects.filter(vars__peer__in=['195.98.32.86'])
09:36 for a in alarms:
09:36 a.clear_alarm("close")
09:36  или так
09:36 from noc.fm.models import *
09:36 from noc.sa.models import *
09:36 alarms = ActiveAlarm.objects.filter(managed_object=ManagedObject.objects.get(name="bb-zmile").id)
09:36 for a in alarms:
09:36 a.clear_alarm("close")
09:36 5 строк

Закроем такие:

# закрыть 'Network | IMPB | Unauthenticated IP-MAC' с IP = '0.0.0.0'
from noc.fm.models import *
ac = AlarmClass.objects.get(name='Network | IMPB | Unauthenticated IP-MAC')
alarms = ActiveAlarm.objects.filter(alarm_class=ac)
for a in alarms:
    if a['vars']['ip']=='0.0.0.0':
        a.clear_alarm("close")

Решил поиграться с графитом. Цель была- понять, можно ли механизмом активаторов собирать и слать данные во внешнюю систему в больших объемах. Все выродилось в два pyRule:

  1. IReduceTask, именно он собранные данные шлет наружу - в графит по простому текстовому протоколу. Мне кажется, проблема моей ДНК где-то в этом коде. Именно отсюда растут тормоза.
# -*- coding: utf-8 -*-
##----------------------------------------------------------------------
## ResultReport
##----------------------------------------------------------------------
## INTERFACE: IReduceTask
##----------------------------------------------------------------------
## DESCRIPTION:
## Display reduce task result
##----------------------------------------------------------------------
## Copyright (C) 2007-2010 The NOC Project
## See LICENSE for details
##----------------------------------------------------------------------
import pprint
##
## 
##
@pyrule
def result_report_graphite(task):
    out=""
    import time
    from noc.lib.nbsocket import *
    sf=SocketFactory()
    gp=sf.connect_tcp('graphite.host',2003,ConnectedTCPSocket)
    sf.loop()
    gp.create_socket()
    sf.loop()
    gp.handle_connect()
    sf.loop()
    for mt in task.maptask_set.all():
      if mt.script_result:
        for k,v in mt.script_result:
            t=int(time.time())
            out+="crc.%s.%s %s %s\n"%(mt.managed_object.address, k.split(".")[-1],v,t)
            gp.write("crc.%s.%s %s %s\n"%(mt.managed_object.address, k.split(".")[-1],v,t))
            sf.loop()
  #          for i in xrange(10):
   #          sf.loop()
            #gp.close(True)
#    out+=["<TR><TD>%s</TD><TD>%s</TD><TD><PRE>%s</PRE></TD></TR>"%(mt.managed_object.name,mt.status,pprint.pformat(mt.script_result))\
#        for mt in task.maptask_set.all()]
 #   out+=["</tbody>","</table>"]
    sf.shutdown()
    return out

2. IPeriodicTask - собственно, пируль, который запускает сбор данных. Просто для всех железяк опрашивается ноковским getnext ветка CRCErrors

# -*- coding: utf-8 -*-
from noc.sa.models import *
from noc.inv.models import *
from noc.ip.models import *
from noc.main.models import SystemNotification
import string


@pyrule
def SendCRCtoGraphite(timeout= None):
 #mo=managed object to get counters from
 mo=ManagedObjectSelector.objects.get(name='All-DLINK')
 t=ReduceTask.create_task(mo,"pyrule:result_report_graphite","","get_snmp_getnext",{'oid':'1.3.6.1.2.1.16.1.1.1.8'},900)
 z=t.get_result()
 SystemNotification.notify(name="sa.version_inventory", subject="Managed Object discovered", body="Discovered %s"%z)
 return True

Для одного хоста укладывался секунд в 10 вместе с отправкой всех данных в графит. Для двух тысяч наступает понимание - что-то тут не так... Если будут сочувствующие, умные и вообще неплохие люди - могу поэкспериментировать(до среды или с 5 октября).

Да, код-ревью устраивать не надо,это черновик.

Записки новичка: грохнуть порты
./noc shell
# delete mo interface 
from noc.inv.models import *
mo = ManagedObject.objects.get(name='MO')
for i in Interface.objects.filter(managed_object=mo.id ): #, type='physical' , type='SVI' , name='1:9'
    print i.name, i.type, i.managed_object
    i.delete()
    i.save()
quit()

Революция, о необходимости которой так долго гооврили большевики, таки свершилась: NOC, как и подобает любой нормальной OSS, обзавелся своей адресной базой. Роль адресной базы часто ошибочно недооценивают, но тем не менее она является одним из краеугольных камней в фундаменте OSS. Без качественной адресной базы крайне сложно нормально организовать процессы капитального строительства и обслуживания массового сегмента (PSTN, ШПД, ЦТВ, КТВ и др), то есть почти все услуги фиксированной связи, оказываемые в жесткой привязке к конкретному адресу.

Структура и идеология адресной базы возникла не на ровном месте, а как обобщение многолетнего опыта работы в сфере OSS и анализе достоинств и недостатков различных подходов, применяющихся в различных компаниях.На мой взгляд, структура получилась с одной стороны простой до идиотизма, с другой - достаточно гибкой для применения во многих областях. Итак, вкратце об основной концепции базы.

 

База описывает четыре основных сущности:

  • Дом, как объект недвижимости. Дома представляют для нас особый интерес в первую очередь тем, что в них имеют привычку селиться люди. Некоторые из этих замечательных людей являются нашими клиентами и платят за услуги фиксированной связи. Другие, не менее замечательные – спят и видят, как мы их подключим и сделаем своими клиентами, устранив тем самым вселенскую несправедливость. В любом случае, при работе на массовом сегменте, подключение разбивается на два независимых этапа – подключение собственно дома (капитальное строительство, создание технической возможности), и подключение жильца или конторы в доме. Чем больше мы знаем про подключенные дома, тем лучше. Чем больше мы знаем про дома, которые можно подключить - тем еще лучше.
  • Если сильно упрощать, дома имеют привычку сбиваться в кучки и организовываться в различные образования. Совсем маленькие кучки становятся хуторами, чуть более крупные - деревнями и селами, если домов сбежалось слишком много, то появляются поселки и города. Когда домов в городе становится слишком много, их начинают разбивать на кучки помельче и возникают городские районы. Когда город разрастается до неприличных размеров, то районы начинают группировать в более крупные формации, вроде городских округов. На более крупном уровне возникают группировки в области и федеральные округа, а еще выше – в страны. Возникает строго иерархическая система деления - от страны к федеральным округам, далее - к областям, потом идут районы, сельсоветы и многочисленные деревни Гадюкино. Так как подобное разбиение обусловленно, в основном, административными причинами и осуществляется по принципу территорий, его называют Административно-территориальное деление, а его элементы - административно-территориальным образованием (АТО). ATO является не единственным делением, параллельно могут существовать деления по участкам обслуживания, финансовой привлекательности, и другим причинам. Общее у них то, что на самом нижнем уровне идет Дом
  • Далее возникает вопрос, как отличать один дом от другого. Когда домов в деревне с десяток, и различать нечего, в общем: вот тот на краю - деда Пахома, в соседнем Прасковьи Петровны, далее, с покосившейся крышей, Марфы Захаровной, которая, дура, в позапрошлом году в город уехала. С ростом деревни, Санта-Барбара начинает крепчать и пухнуть на глазах, появляются дома на выселках за Новонедоделовкой, которая через речку от Старододелова, где в позапрошлом году два порося в луже утопилось, пока Марфа, дура, в городе гужевалась, а при царе Горохе мельница была. В общем, мозг от насилия нужно как-то спасать и от местного колорита избавляться. Решили, ту тропинку, по которой дед Пахом на дрожке за дровами через всю деревню в лес чешет, а барин Игнат Савельевич на черном крузаке распахивает, и где по весне лужи по колено, в которых два порося потонуло, торжественно назвать улицей, а лучше прешпектом. А прешпект, соответсвенно, назвать Поросячим. И закипело дело: дом деда Пахома стал первым домом по Поросячему прешпекту, Петровны - вторым, а лучше сразу третьим, Марфа - хоть и дура, пятая по счету и все это в селе Старододелове, что в Моршанском уезде Тамбовской губернии. Повесил дед Пахом табличку 1 на дом, глянул на двор и закручинился: на сортир табличку уже и не повесишь, отдельное строение. Почесал дед Пахом лысину и решил - быть сортиру домом 1 строением 1. А пристройке летней у дома быть корпусом 2. Увидел, что это хорошо, а значит так тому и быть. Испытал нужду большую и пошел по адресу Поросячий п-т, д 1 к 1, там его облегчение и настигло.
    А мы в результате получили две новые проблемы – улицы и адреса, как номера домов по улицам. Относятся ли улицы к АТО? На самом деле и да и нет. С одной стороны, улица может проходить через несколько районов и при этом иметь сквозную нумерацию домов. С другой – обычно улица все-таки связана с населенным пунктом. Как связаны дома с улицами: с одной стороны - дом имеет какой-то номер по улице. С другой – если вокруг дома деда Пахома кабаны тропы протоптали, а бары колею раскатали, то быть ему угловым сразу на всех четырех улицах и везде под разными номерами. Таким образом - у дома может быть несколько адресов. Адреса также имеют склонность к ветренности и имеют привычку внезапно меняться, доводя ситуацию до полного абсурда, как описано по ссылке.

 

Таким образом, если мы хотим устранить цифровое неравенство в сортире деда Пахома, наша адресная база должна работать с четыремя основными элементами: Дом (сортир), административным деленим (Тамбовская губерния, Моршанский уезд, село Старододелово, в котором расположен сортир), улицей (Поросячий п-т) и адресом (д. 1. к. 1 по Поросячему прешпекту).

А как жить с этим богатством, мы обсудим в следующей статье

Отчет по топологии своими рукам

Понадобилось тут проверить, а что за железки выпали из дерева топологии. Естественно, у задачи есть минимум два решения. А был бы ерл вместо питона - было бы по пять вариантов написания каждого из двух решений и одно решение в виде ASCII-art. Ну да ладно. Не о том речь. Речь о том, до чего именно я докатился в своем падении.

Сейчас можно сделать отчет тремя путями:

  1. сгенерировать скелет отчета с помощью механизма newapp у консольного приложения noc.
  2. скопировать любой понравившийся отчет в новый каталоги, удалить лишнее, исправить код
  3. взять карту местности, на которой отмечен крестиком ближайший лес... Ой, то есть сделать типовое приложение Ext на базе нужного класса с нуля.

 

Я не стал выпендриваться с приложением с нуля. Лазить по коду и вспоминать ключи(Дима, привет, хорошо что в хелпе консольных команд есть пример использования, там же все очевидно) командной строки.. Я тупо скопировал отчет, подрихтовал его под себя и все у меня теперь работает.

Решения:

  1. Взять базу объектов, базу линков, ящик водки... Заправить базовым алгоритмом A*, ну или чем-то похожим... Если бы меня приперло, я бы и такое родил. Но я так делать не стал
  2. Установить пакет networkx. Версию не ниже 1.7, использовать написанный умными людьми код.

 

Во втором варианте решения все оказалось очень просто. Требовалось создать и заполнить граф связности(в данном случае неважно, какоие порты связаны, важно, что между устройствами есть линк в принципе), а дальше - простой перебор железок и проверка двух условий:

  • железки нет в графе(она однозначно выпала из дерева топологии
  • железка есть в графе, но нет пути, который бы соединял железку с центром сети.

Код отчета прилагаю ниже, там все относительно просто(файл views.py):

# -*- coding: utf-8 -*-
##----------------------------------------------------------------------
## inv.reportobjectsummary
##----------------------------------------------------------------------
## Copyright (C) 2007-2013 The NOC Project
## See LICENSE for details
##----------------------------------------------------------------------
## Python modules
from collections import defaultdict
import networkx as nx
## NOC modules
from noc.lib.app.simplereport import SimpleReport, TableColumn
from noc.inv.models import *
from noc.sa.models import *
class ReportTopoFailsApplication(SimpleReport):
    title = "Objects not in Topology tree"
    def gen_mgraph(self):
        G = nx.MultiGraph()
        for l in Link.objects.all():
            G.add_edge(l.interfaces[0].managed_object.id,l.interfaces[1].managed_object.id)
        return G
    def get_data(self, **kwargs):
        data = defaultdict(int)
        #Generate graph to search orphans
        G = self.gen_mgraph()
        for mo in ManagedObject.objects.all():
            if not mo.id in G.nodes():
                data[mo]=0
            else:
                if not nx.has_path(G,mo.id,664):
                    for nei in nx.all_neighbors(G,mo.id):
                        data[mo]+=1
        data = sorted(((k, data[k]) for k in data), key=lambda x: -x[1])
        return self.from_dataset(
            title=self.title,
            columns=[
                "Object",
                TableColumn("Neighbors Count", format="numeric", align="right")
            ],
            data=data
        )

Изменение порта web сервера NOC

Приветствую,

NOC Version 0.8dev9319 OS Ubuntu 12.4 Server

 

по умолчанию NOC работает на 80 порту, который потребовалось изменить

заходим в cd /etc/nginx/sites-enabled

Редактируем файл noc.conf

sudo nano noc.conf

 

Изменяем в разделе server в строке порт через который будем ходить --> listen 8383;

 

После этого рестрат noc и nginx

 

 

my "Hello world"

c "Божьей"  помощью, вот что получилось. Я очень очень буду рада комментариям, но убедительно прошу не сильно пинать ногами, т.к. мой опыт программирования равен 1 неделе, опыт программирования на python и того меньше.  Первая попытка, т.к. цель не достигнута код буду очень сильно модифицировать и часто. 

 

1
intname = "fastethernet0/45"
aclname = "BLOCK-" + intname
blockstring = "deny any any"
aclseek = False
import re
f = open('/srv/noc/repo/config/cisco1845conf', 'r')
m = re.search(r'(?P<int>interface (?P<intname>' + intname + ')(.+?)\!)', f.read(), re.IGNORECASE | re.DOTALL)
if m:
    interfaceconf = m.group('int')
    intname = m.group('intname')
    m = re.search(r'.+access-group (?P<aclname>.+) .+', interfaceconf)
    if m:
        aclname = m.group('aclname')
        aclseek = True
cmd = ""
acl = []
acl.append(blockstring)
if aclseek:
    f.seek(0)
    while True:
        line = f.readline()
        if not line: break
        m = re.search(r'access-list ' + aclname + ' (?P<acl>.+)', line)
        if m:
            cmd = "interface " + intname + "\n no access-group " + aclname + " in\n!\n"
            cmd = cmd + "no access-list " + aclname + "\n"
            acl.append(m.group('acl'))
f.close()
for line in acl:
    cmd = cmd + "access-list " + aclname + " " + line + "\n"
cmd = cmd + "!\ninterface " + intname + "\n" \
                                        " access-group " + aclname + " in\n"
print(cmd)
Записки новичка: Pyrule

По мотивам крайне полезного пируля, чуть его доработал:

# -*- coding: utf-8 -*-
##----------------------------------------------------------------------
## set interfaces profile
##----------------------------------------------------------------------
## INTERFACE: IPeriodicTask
##----------------------------------------------------------------------
## DESCRIPTION:
## set NNI or UNI inventory\interfaces profile
##----------------------------------------------------------------------
## Copyright (C) 2007-2014 The NOC Project
## See LICENSE for details
##----------------------------------------------------------------------
## http://kb.nocproject.org/pages/viewpage.action?pageId=11108392
import logging
from noc.inv.models import *
@pyrule
def set_interface_profile(timeout = None):
    current_profile_name = "default"
    new_profile_name = "default"
    interface = Interface.objects.filter(type="physical")
    for i in interface:
        current_profile_name = i.profile.name
        new_profile_name = current_profile_name
        untagged_vlan = SubInterface.objects.get(interface=i).untagged_vlan
        if i.link:
            new_profile_name = "NNI"
        else:
           if not i.description:
               new_profile_name = "default"
           elif i.profile.name == InterfaceProfile.objects.get(name="default").name:
               new_profile_name = "UNI"
        if untagged_vlan == 1:
               new_profile_name = "NNI" 
        if new_profile_name != current_profile_name:
            i.profile = InterfaceProfile.objects.get(name=new_profile_name).id
            i.save()
            logging.info("[pyrule.set_interfaces_profile] set interface.profile %s '%s'->'%s'" % (i, current_profile_name, new_profile_name))
    return True 

 

В лог noc-scheduler.log попадают записи об изменении профиля порта, примерно так

2014-03-07 09:13:57,080 [pyrule.set_interfaces_profile] set interface.profile s558.intt: 1:9 'default'->'NNI'

 

 

 

Связь NOC с Zabbix на уровне БД.
Представляю Вашему вниманию вариант организации связи NOC с Zabbix на уровне триггеров базы данных.
 
Версия PostgreSQL от 9.1
База Zabbix может быть как PostgreSQL так и MySQL.
Связь реализована на основе Foreign Data Wrappers (FDW) http://wiki.postgresql.org/wiki/Foreign_data_wrappers
 
Версия Zabbix 2.2.0, но это не принципиально.
Необходимо изменить только SQL с созданием внешних таблиц соответственно вашей версии Zabbix,
а в коде pgsql используются только id и переменные ROWTYPE.
 
Версия NOC значения не имеет, поскольку используются всего две таблицы:
- sa_managedobject поля NAME, ADDRESS
- sa_managedobjectattribute поля key (с содержимым 'platform'), value.
 
Порядок действий:
-----------------
Zabbix:
-----------------
1. Импортировать шаблоны. Хотя на самом деле можно использовать любые
только нужно заполнить таблицу соответствия в NOC (см. ниже).
2. Изменить тип индекса на уникальный для имени хоста ( runme_zabbix.sql ).
 

NOC:
-----------------
1. Пользователь noc должен быть суперюзером на время исполнения runme_noc.sql
Потом можно лишить его этой привилегии.
2. Перед тем как исполнить runme_noc.sql почитайте комментарии в скриптах.

В итоге при добавлении, изменении или удалении хоста в NOC
соответствующие изменения автоматически произойдут и в заббиксе.
Триггерная функция написана так, что при возникновении ошибки
транзакция в NOC безусловно произойдёт.

 

TAR c SQL скриптами и шаблонами для Zabbix доступен  http://yadi.sk/d/hhrJv1T6E5vGd

 

 

 

Сейчас пока нет морды для вот такой простой вещи

from noc.sa.models import ManagedObject
from lib.scheduler import utils
dev=ManagedObject.objects.filter(name__icontains='server')
for i in dev:
    utils.refresh_schedule("inv.discovery", "config_discovery", i.id)

этот кусочек позволяет пересчитать когда будет запущено задание.

Фактически переводить сбор на NOW.

в 4-ой строке можно задать какие именно железяки будут затронуты

все варианты аргументов.

Choices are: activator, address, address_set, administrative_domain, config, config_diff_filter_rule, config_filter_rule, config_validation_rule, description, id, is_configuration_managed, is_managed, managedobjectattribute, maptask, max_scripts, name, object_profile, password, port, profile_name, remote_path, repo_path, scheme, shape, snmp_ro, snmp_rw, super_password, tags, trap_community, trap_source_ip, user, vc_domain, vrf

использовать так

dev=ManagedObject.objects.filter(profile_name='Cisco.IOS')
Branched development

NOC's development had followed single-branch development model from a very start. It was single default branch, result of streamlined path of development. Releases were just a tags - simple milestones on the road, a points of relative stability. Simplicity always has own benefits:

  • Easy to understood
  • Easy to commit: Just test you changes and push to the repos
  • Easy to choose: Wait on stable milestone or dance over bleeding edge of tip

But sometimes, simplicity is worse than theft. Drawback of simple approach are obvious:

  • No hotfix releases. In order to fix critical bug you must leave the stable milestone
  • Feature development blocks release. You must freeze the development of new features when going into release process. Long-term feature development blocks release for a long time.
  • Hard to test single feature, they are all bundled in single branch
  • Expirements are expensive, it is hard to clean up results of unsuccessive experiment from main branch
  • Hard to share early work and demonstrate incomplete features
  • Hard to split development and Q&A

DCVSes offer the branches as the method of splitting development into semi-independed streams. Mercurial, used by NOC, has all necessary tools. But branching itself is not enough. Without strict policy branching will lead to greater mess, so we need a really good one.

Vincent Driessen's model is good starting point (See "A successful Git branching model"). The common idea is to define possible branch categories and define a policy of possible merging. Model define following branch types:

  • default - stable release branch. Releases denoted by tags. Direct commit into default branch are strictly prohibited
  • develop - contains tested features and bug fixes. develop is relatively stable and used as the base to start the feature branches. All changes from default must be merged into develop too. Although simple patches can be commited directly in develop, greater changes must be developed and tested in the dedicated feature/* branches.
  • release/* - when develop collects worth amount of features, the release process begun. First, separate release/* branch forked from develop one, and Q&A process begins. No new features may be commited into open release/* branch. When release/* branch is well-tested and polished, it is marked by release tag, merged into default and develop, then release/* branch closed
  • hotfix/* - Can be used to fix bugs leaked to release. hotfix/* branch forked from the point of release on default branch, after bug has been fixed hotfix got release tag and all changes return back to default and develop, then hotfix/* branch closed
  • feature/* - forked from develop. Most of development work done in feature/* branches, single branch per feature. Stable changes merged back to develop

Comparison table:

BranchNumberForked fromDirect commitsMerged toClosed
defaultone

-

NeverdevelopNever
developone-Small fixes and featuresfeature/*Never
release/*one per releasedevelopLast-minute fixes, release notes

default

develop

On release
hotfix/*one per hotfix releasedefaultPost-release fixes

default

develop

On release
feature/*one per featuredevelopNew features, improvements, large fixesdevelopOn feature complete

Upgrade process

Choose appropriative branch to follow:

  1. default - to receive stable releases and hot fixes for production use
  2. develop - to access latest tested features for early access testing
  3. feature/<name> - to get access to particular feature in development

Change etc/upgrade.conf and set BRANCH variable to appropriative branch. i. e.

BRANCH=feature/extjs-4.2.1

Then upgrade as usually

/opt/noc# ./scripts/upgrade

Developer's tools

hgflow extension used to maintain branch workflow.

To install extension grab latest hgflow release from download section and unpack distribution. Then enable hgflow in ~/.hgrc

[extensions]
....
flow = <path to hgflow.py>
 
[flow]
autoshelve = true

 

hg flow subcommand provides access to the extensions.

Common tasks:

Check, which is the name of active branch:

 
/opt/noc$ hg branch
develop

Get list of open feature branches 

/opt/noc$ hg flow feature list
flow: Open <feature> branches:
flow:   feature/NOC-1036
flow:   feature/OAM
flow:   feature/extjs-4.2.1
flow:   feature/fm-new-ui
flow:   feature/ip.show_maintained
flow:   feature/notification-center
flow:   feature/ranged-chassis-id

Switch to develop

/opt/noc$ hg flow develop

 

Start new feature branch 

/opt/noc$ hg flow develop
/opt/noc$ hg flow feature start myfeature

 

Switch to another feature branch

/opt/noc$ hg flow feature other feature

Push feature branch changes to repo

/opt/noc$ hg flow feature push
Массовое изменение параметров МО

Появилась задача - изменить/добавить параметры RO Community в настройках объекта.

За основу был взят пост Небольшие сниппеты, которые могут пригодиться

проконсультировавшись с автором получил следующее

from noc.sa.models import *
var = ManagedObjectSelector.objects.get(name='SL')
for mo in var.managed_objects:
    mo.snmp_ro = "public"
    mo.save()

 

Сначала выбираем все MO из селектора, в данном случае SL

Затем проставляем нужный нам комьюнити для snmp и сохраняем результат.

Все параметры которые можно изменять, и их называние, можно посмотреть в /opt/noc/sa/models/managedobject.py