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 __unicode__(self): return u"%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 __unicode__(self): return u"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 __unicode__(self): host = "host %s - " % self.host.name if self.host else "" return u"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 __unicode__(self): return u"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 __unicode__(self): p = "p" if self.pingable else "!p" r = "r" if self.reachable else "!r" return u"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 __unicode__(self): return u"%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 __unicode__(self): return u"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 __unicode__(self): return u"%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)