# # Functions for interacting with the routes table in the database # from types import StringTypes import socket import struct from PLC.Faults import * from PLC.Parameter import Parameter from PLC.Filter import Filter from PLC.Debug import profile from PLC.Table import Row, Table from PLC.NetworkTypes import NetworkType, NetworkTypes from PLC.NetworkMethods import NetworkMethod, NetworkMethods from PLC.IpAddresses import SimpleAddress, Subnet import PLC.Nodes class Route(Row): """ Representation of a row in the routees table. To use, optionally instantiate with a dict of values. Update as you would a dict. Commit to the database with sync(). """ table_name = 'routes' primary_key = 'route_id' join_tables = [] fields = { 'route_id': Parameter(int, "Route identifier"), 'node_id': Parameter(int, "Node this route belongs to"), 'subnet': Parameter(str, "Subnet for this route", nullok = True), 'next_hop': Parameter(str, "IP address to send outgoing traffic"), 'interface_id': Parameter(int, "Interface to send outgoing traffic"), 'last_updated': Parameter(int, "Date and time when node entry was created", ro = True), } tags = {} # TODO - validate next_hop and subnet def validate_node_id(self, node_id): nodes = PLC.Nodes.Nodes(self.api, [node_id]) if not nodes: raise PLCInvalidArgument, "No such node %d"%node_id return node_id def validate_interface_id(self, interface_id): interfaces = PLC.Interfaces.Interfaces(self.api, [interface_id]) if not interfaces: raise PLCInvalidArgument, "No such interface %d"%interface_id if (interfaces[0]["node_id"] != self["node_id"]): raise PLCInvalidArgument, "Interface is not for the same node as this route" return interface_id def validate_subnet(self, subnet): Subnet(subnet) return subnet def validate_next_hop(self, next_hop): SimpleAddress(next_hop) return next_hop def validate(self): """ Flush changes back to the database. """ # Basic validation Row.validate(self) validate_last_updated = Row.validate_timestamp def update_timestamp(self, col_name, commit = True): """ Update col_name field with current time """ assert 'route_id' in self assert self.table_name self.api.db.do("UPDATE %s SET %s = CURRENT_TIMESTAMP " % (self.table_name, col_name) + \ " where route_id = %d" % (self['route_id']) ) self.sync(commit) def update_last_updated(self, commit = True): self.update_timestamp('last_updated', commit) class Routes(Table): """ Representation of row(s) from the routees table in the database. """ def __init__(self, api, route_filter = None, columns = None): Table.__init__(self, api, Route, columns) # the view that we're selecting upon: start with view_nodes view = "view_routes" # as many left joins as requested tags for tagname in self.tag_columns: view= "%s left join %s using (%s)"%(view,Route.tagvalue_view_name(tagname), Route.primary_key) sql = "SELECT %s FROM %s WHERE True" % \ (", ".join(self.columns.keys()+self.tag_columns.keys()),view) if route_filter is not None: if isinstance(route_filter, (list, tuple, set)): # Separate the list into integers and strings ints = filter(lambda x: isinstance(x, (int, long)), route_filter) route_filter = Filter(Route.fields, {'route_id': ints}) sql += " AND (%s) %s" % route_filter.sql(api, "OR") elif isinstance(route_filter, dict): allowed_fields=dict(Route.fields.items()+Route.tags.items()) route_filter = Filter(allowed_fields, route_filter) sql += " AND (%s) %s" % route_filter.sql(api) elif isinstance(route_filter, int): route_filter = Filter(Route.fields, {'route_id': [route_filter]}) sql += " AND (%s) %s" % route_filter.sql(api) else: raise PLCInvalidArgument, "Wrong route filter %r"%route_filter self.selectall(sql)