You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
6.3 KiB
192 lines
6.3 KiB
# This file is part of dnmapper, an AS--level mapping tool |
|
# Licensed under GNU General Public License v3 or later |
|
# Written by Sebastian Lohff (seba@someserver.de) |
|
|
|
from django.db import models |
|
from django.db.models import Q |
|
|
|
|
|
# Create your models here. |
|
class ConfigHost(models.Model): |
|
CHECK_CHOICES = ( |
|
('CMK', "Check MK"), |
|
('PLAIN', "Plain"), |
|
) |
|
|
|
# asno, ip, check method, |
|
name = models.CharField(max_length=50) |
|
number = models.IntegerField() |
|
ip = models.GenericIPAddressField() |
|
checkMethod = models.CharField(max_length=4, choices=CHECK_CHOICES) |
|
|
|
def __str__(self): |
|
return "%s (%s / %s)" % (self.name, self.number, self.ip) |
|
|
|
class CrawlRun(models.Model): |
|
# time start, time end, |
|
startTime = models.DateTimeField() |
|
endTime = models.DateTimeField(null=True, blank=True) |
|
|
|
hostsCrawled = models.ManyToManyField(ConfigHost, null=True, blank=True) |
|
|
|
asCount = models.IntegerField(default=0) |
|
asOnlineCount = models.IntegerField(default=0) |
|
asOfflineCount = models.IntegerField(default=0) |
|
peeringCount = models.IntegerField(default=0) |
|
|
|
def __str__(self): |
|
return "Run %d - %s to %s" % (self.pk, self.startTime, self.endTime if self.endTime else "?") |
|
|
|
def countAS(self): |
|
return self.asCount |
|
def countASOnline(self): |
|
return self.asOnlineCount |
|
def countASOffline(self): |
|
return self.asOfflineCount |
|
#return self.as_set.filter(online=False).count() |
|
def countPeerings(self): |
|
return self.peeringCount |
|
#return Peering.objects.filter(Q(as1__crawl=self)|Q(as2__crawl=self)).count() |
|
|
|
class CrawlLog(models.Model): |
|
INFO = 'INFO' |
|
ERROR = 'ERROR' |
|
DEBUG = 'DEBUG' |
|
WARN = 'WARN' |
|
SEVERITY = ( |
|
(INFO, 'info'), |
|
(ERROR, 'error'), |
|
(DEBUG, 'debug'), |
|
(WARN, 'warning'), |
|
) |
|
|
|
crawl = models.ForeignKey(CrawlRun) |
|
host = models.ForeignKey(ConfigHost, null=True, blank=True, on_delete=models.SET_NULL) |
|
logtime = models.DateTimeField(auto_now_add=True) |
|
severity = models.CharField(max_length=10, choices=SEVERITY) |
|
message = models.TextField() |
|
|
|
@staticmethod |
|
def log(crawl, msg, severity=None, host=None): |
|
if not severity: |
|
severity = CrawlLog.ERROR |
|
|
|
log = CrawlLog() |
|
log.crawl = crawl |
|
log.message = msg |
|
log.severity = severity |
|
log.host = host |
|
log.save() |
|
|
|
def __str__(self): |
|
host = "host %s - " % self.host.name if self.host else "" |
|
return "Log %s %s: %s%s" % (self.get_severity_display(), self.logtime, host, self.message) |
|
|
|
class AS(models.Model): |
|
# asno |
|
crawl = models.ForeignKey(CrawlRun) |
|
number = models.IntegerField(db_index=True) |
|
|
|
directlyCrawled = models.BooleanField(default=False) |
|
online = models.BooleanField(default=True, db_index=True) |
|
lastSeen = models.ForeignKey(CrawlRun, blank=True, null=True, default=None, related_name='as_lastseen') |
|
|
|
class Meta: |
|
unique_together = (('crawl', 'number'),) |
|
index_together = ( |
|
('crawl', 'number'), |
|
) |
|
|
|
def __str__(self): |
|
return "AS %s (crawl %d)" % (self.number, self.crawl.pk) |
|
|
|
def setOnline(self): |
|
if not self.online: |
|
self.online = True |
|
self.lastSeen = None |
|
self.save() |
|
|
|
def getPeerings(self): |
|
return Peering.objects.filter(Q(as1=self)|Q(as2=self)) |
|
|
|
def getAnnouncedPrefixes(self): |
|
return list(set(map(lambda _x: "%(ip)s/%(prefix)s" % _x, self.announcement_set.all().values('ip', 'prefix')))) |
|
|
|
def formatLastSeen(self): |
|
if self.lastSeen: |
|
return self.lastSeen.startTime.strftime("%d.%m.%Y %H:%I") |
|
|
|
class BorderRouter(models.Model): |
|
# as id, ip, check method, pingable, reachable |
|
# unique: (crawl_id, asno, as id) |
|
AS = models.ForeignKey(AS) |
|
routerID = models.GenericIPAddressField() |
|
|
|
pingable = models.BooleanField(default=False) |
|
reachable = models.BooleanField(default=False) |
|
|
|
def __str__(self): |
|
p = "p" if self.pingable else "!p" |
|
r = "r" if self.reachable else "!r" |
|
return "Router %s (AS %s, %s%s)" % (self.routerID, self.AS.number, p, r) |
|
|
|
class Announcement(models.Model): |
|
router = models.ForeignKey(BorderRouter) |
|
|
|
ip = models.GenericIPAddressField() |
|
prefix = models.IntegerField() |
|
|
|
# NOTE: increase length for longer pathes (currently supports a length of ~85) |
|
ASPath = models.CharField(max_length=512) |
|
nextHop = models.GenericIPAddressField() |
|
originAS = models.ForeignKey(AS, null=True) |
|
crawlAS = models.ForeignKey(AS, related_name='crawl_as', null=True) |
|
|
|
def __str__(self): |
|
return "%s/%s via %s (crawl %s)" % (self.ip, self.prefix, self.ASPath, self.router.AS.crawl.pk) |
|
|
|
class Peering(models.Model): |
|
DIRECT = 'direct' |
|
PATH = 'path' |
|
|
|
ORIGIN = ( |
|
(PATH, 'BGP Path'), |
|
(DIRECT, 'Direct Connection'), |
|
) |
|
|
|
index_together = ( |
|
('as1', 'as2'), |
|
) |
|
|
|
as1 = models.ForeignKey(AS, related_name='peering1') |
|
as2 = models.ForeignKey(AS, related_name='peering2') |
|
origin = models.CharField(max_length=10, choices=ORIGIN) |
|
|
|
def __str__(self): |
|
return "AS %s <--> AS %s (%s, crawl %s)" % (self.as1.number, self.as2.number, self.get_origin_display(), self.as1.crawl.pk) |
|
|
|
def containsAS(self, AS): |
|
return AS in (self.as1, self.as2) |
|
|
|
@staticmethod |
|
def getPeering(as1, as2): |
|
""" Find matching peering """ |
|
try: |
|
return Peering.objects.get(as1=as1, as2=as2) |
|
except Peering.DoesNotExist: |
|
return Peering.objects.get(as1=as2, as2=as1) |
|
|
|
class BorderRouterPair(models.Model): |
|
peering = models.ForeignKey(Peering) |
|
router1 = models.ForeignKey(BorderRouter, default=None, blank=True, null=True, related_name='routerpair1') |
|
router2 = models.ForeignKey(BorderRouter, default=None, blank=True, null=True, related_name='routerpair2') |
|
|
|
def __str__(self): |
|
return "%s <--> %s (crawl %d)" % (self.router1, self.router2, self.router1.AS.crawl.pk) |
|
|
|
@staticmethod |
|
def getPairing(peering, router1, router2): |
|
try: |
|
return BorderRouterPair.objects.get(peering=peering, router1=router1, router2=router2) |
|
except BorderRouterPair.DoesNotExist: |
|
return BorderRouterPair.objects.get(peering=peering, router1=router2, router2=router1)
|
|
|