📄 netbox.py
字号:
# -*- coding: ISO8859-1 -*-# Copyright 2002-2005 Norwegian University of Science and Technology# Copyright 2006 UNINETT AS## This file is part of Network Administration Visualized (NAV)## NAV is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## NAV is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with NAV; if not, write to the Free Software# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA### Authors: Magnus Nordseth <magnun@itea.ntnu.no># Stian Soiland <stain@itea.ntnu.no># Stein Magnus Jodal <stein.magnus.jodal@uninett.no>#"""Top level view of a netbox.Includes generic information (hostname, ip), ping statistics, switchmodules, statistics (RRD), services monitored, network connectivity,vlans, etc."""import sysimport timeimport IPyfrom mod_python import apacheimport forgetHTML as htmlimport refrom mx import DateTimeimport nav.dbfrom nav.db import managefrom nav.web import urlbuilderfrom nav.errors import *from nav.rrd import presenterfrom nav.web import tableviewimport modulefrom nav.web.devBrowser.servicetable import ServiceTablefrom nav.event import EventQ, Eventimport logginglogger = logging.getLogger("nav.web.devBrowser.netbox")_statusTranslator = {'y':'Up', 'n':'Down', 's':'Shadow' }def distance(a,b): """ Calculates the Levenshtein distance between a and b. """ n, m = len(a), len(b) if n > m: a,b = b,a n,m = m,n current = range(n+1) for i in range(1,m+1): previous, current = current, [i]+[0]*m for j in range(1,n+1): add, delete = previous[j]+1, current[j-1]+1 change = previous[j-1] if a[j-1] != b[i-1]: change = change + 1 current[j] = min(add, delete, change) return current[n]import typesdef getChildrenIterator(self, forgetter, field=None, where=None, orderBy=None, useObject=None): """Mimics forgetSQL forgetters' getChildren, except that it returns an iterator, like getAllIterator. """ if type(where) in (types.StringType, types.UnicodeType): where = (where,) if not field: for (i_field, i_class) in forgetter._userClasses.items(): if isinstance(self, i_class): field = i_field break # first one found is ok :=) if not field: raise "No field found, check forgetter's _userClasses" sqlname = forgetter._sqlFields[field] myID = self._getID()[0] # assuming single-primary ! whereList = ["%s='%s'" % (sqlname, myID)] if where: whereList.extend(where) return forgetter.getAllIterator(whereList, useObject=useObject, orderBy=orderBy)# Dirrty hack to extend forgetSQL for perfomance reasonsimport forgetSQLif not hasattr(forgetSQL.Forgetter, 'getChildrenIterator'): forgetSQL.Forgetter.getChildrenIterator = getChildrenIteratordef findNetboxes(hostname): """ Finds a netbox from sysname or partial sysname. Returns a list of netboxes in which hostname is a substring of their sysname. huh """ netbox = manage.getNetbox(hostname) if netbox: return [netbox] # Now we can try to see if hostname is a substing of # a real sysname matches = [nb for nb in manage.Netbox.getAllIterator( where="sysname like %s" % nav.db.escape('%'+hostname+'%')) ] if len(matches) == 1: raise RedirectError, urlbuilder.createUrl(matches[0]) elif matches: return [(match, None) for match in matches] # try mr. levenshtein... a=hostname.count('.') for nb in manage.Netbox.getAllIterator(): try: IPy.IP(nb.sysname) except ValueError: # Only accept non-IP sysnames shortname = '.'.join(nb.sysname.split('.')[:a+1]) matches.append((distance(hostname, shortname), nb)) matches.sort() result = [] for match in matches: dist, nb = match # 5 seems to be a reasonable distance... if dist < 5: result.append((nb, dist)) else: break # If no matches have low enough Levenstein, just show the five closest # matches if len(result) == 0: for i, match in enumerate(matches): if i < 5: dist, nb = match result.append((nb, dist)) i += 1 else: break if len(result) == 1: raise RedirectError, urlbuilder.createUrl(result[0][0]) return result #return [(manage.getNetbox(x[1]),x[0]) for x in matches[:20]] raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND def showMatches(netboxes): result = html.Division() heading = html.Header("Listing %s closest matches" % len(netboxes), level=2) result.append(heading) for match in netboxes: netbox, distance = match line = html.Division() line.append("%s (%s)" % (urlbuilder.createLink(netbox), distance)) result.append(line) return result def process(request): args = request['args'] fields = request['fields'] if 'sort' in fields: sortBy = fields.getfirst('sort') try: sortBy = int(sortBy) except: sortBy = 2 hostname = request.get("hostname","") if not hostname: # How did we get here? return showIndex() netboxes = findNetboxes(hostname) # returns a list of tuples; [(netbox, distance),] if len(netboxes) > 1: return showMatches(netboxes) elif len(netboxes) == 1: netbox = netboxes[0] else: raise "Dette burde ikke skje" request['templatePath'].append((str(netbox), None)) #for i in netbox._sqlFields.keys(): # line = "%s: %s\n" % (i, getattr(netbox, i)) # result.append(html.Division(line)) if 'refresh' in request['fields']: refresh = RefreshHandler(request, netbox) if not refresh.isDone(): return refresh.process() # Ok, instanciate our NetboxInfo using netbox info = NetboxInfo(netbox) result = html.Division() result.append(info.showInfo()) actions = html.Paragraph() actions.append(urlbuilder.createLink(netbox, subsystem='editdb', content="[Edit]")) actions.append(urlbuilder.createLink(netbox, subsystem='maintenance', content='[Schedule maintenance]')) result.append(actions) interval = fields.getfirst('interval', '30') interval = interval.isdigit() and int(interval) or 30 ports = info.showPorts(activePerspective= fields.getfirst('perspective', 'standard'), interval=interval) if ports: result.append(ports) services = info.showServices(sortBy) if services: result.append(services) rrds = info.showRrds() if rrds: result.append(rrds)## links = info.showLinks() ## if links:## result.append(links) return resultclass RefreshHandler: refreshVar = 'devBrowseRefresh' def __init__(self, request, netbox): self.request = request self.netbox = netbox self.session = self.request['session'] self.postRefresh() def postRefresh(self): if self.refreshVar not in self.session: # Post the event here refreshTime = time.time() refreshId = '%d%d' % (self.netbox.netboxid,refreshTime) refreshId = long(refreshId) % sys.maxint event = Event(source='devBrowse', target='getDeviceData', netboxid=self.netbox.netboxid, subid=refreshId, eventtypeid='notification') event['command'] = 'runNetbox' req = self.request['request'] logger.debug("Posting refresh event for IP Device %s, " "refreshID=%s", self.netbox.sysname, refreshId) event.post() self.session[self.refreshVar] = (refreshId, refreshTime) self.session.save() def cancelRefresh(self): if self.refreshVar in self.session: del self.session[self.refreshVar] result = html.Division() result.append(html.Paragraph('Refresh cancelled...')) backUrl = urlbuilder.createUrl(division='netbox', id=self.netbox.netboxid) refreshMeta = '<meta http-equiv="refresh" content="0;url=%s" />\n' self.request['template'].additionalMeta = lambda: refreshMeta % backUrl return result def isDone(self): "If received, consume reply event and return true" req = self.request['request'] def deleteStale(events): staleMinutes = 5 staleTime = DateTime.now() - DateTime.oneMinute * staleMinutes stale = [event for event in events if event.time < staleTime \ and event['command'] == 'runNetboxDone'] for event in stale: age = (DateTime.now() - event.time).minutes logger.debug("Deleting stale refresh reply event " "%s (%.01f minutes old)", event.eventqid, age) event.dispose() # Only check for replies if we actually know that we've posted an event if self.refreshVar in self.session:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -