def received (self): consumed_data = False for process in list(self._process): try: proc = self._process[process] # proc.poll returns None if the process is still fine # -[signal], like -15, if the process was terminated if proc.poll() is not None and self.reactor.respawn: raise ValueError('child died') r,_,_ = select.select([proc.stdout,],[],[],0) if r: try: while True: line = proc.stdout.next().rstrip() consumed_data = True self.logger.processes("Command from process %s : %s " % (process,line)) yield (process,formated(line)) except IOError,exc: if not exc.errno or exc.errno in error.fatal: # if the program exists we can get an IOError with errno code zero ! self.logger.processes("Issue with the process' PIPE, terminating it and restarting it") self._terminate(process) self._start(process) elif exc.errno in error.block: # we often see errno.EINTR: call interrupted and # we most likely have data, we will try to read them a the next loop iteration pass else: self.logger.processes("unexpected errno received from forked process (%s)" % errstr(exc)) except StopIteration: if not consumed_data: self.logger.processes("The process died, trying to respawn it") self._terminate(process) self._start(process)
def parse_api_vpls (self,command,peers,action): tokens = formated(command).split(' ')[1:] if len(tokens) < 4: return False if tokens[0] != 'vpls': return False changes = [] if 'self' in command: for peer,nexthop in peers.iteritems(): scope = [{}] self._nexthopself = nexthop if not self._single_l2vpn_vpls(scope,tokens[1:]): self._nexthopself = None return False for change in scope[0]['announce']: changes.append((peer,change)) self._nexthopself = None else: scope = [{}] if not self._single_l2vpn_vpls(scope,tokens[1:]): return False for peer in peers: for change in scope[0]['announce']: changes.append((peer,change)) if action == 'withdraw': for (peer,change) in changes: change.nlri.action = OUT.withdraw # pylint: disable=E1101 return changes
def api_vpls (self, command, peers, action): tokens = formated(command).split(' ')[1:] if len(tokens) < 4: return False if tokens[0] != 'vpls': return False changes = [] if 'self' in command: for peer,nexthop in peers.iteritems(): scope = [{}] self._nexthopself = nexthop if not self._single_l2vpn_vpls(scope,tokens[1:]): self._nexthopself = None return False for change in scope[0]['announce']: changes.append((peer,change)) self._nexthopself = None else: scope = [{}] if not self._single_l2vpn_vpls(scope,tokens[1:]): return False for peer in peers: for change in scope[0]['announce']: changes.append((peer,change)) if action == 'withdraw': for (peer,change) in changes: change.nlri.action = OUT.WITHDRAW return changes
def api_refresh (self, command): tokens = formated(command).split(' ')[2:] if len(tokens) != 2: return False afi = AFI.value(tokens.pop(0)) safi = SAFI.value(tokens.pop(0)) if afi is None or safi is None: return False return RouteRefresh(afi,safi)
def parse_api_refresh (self,command): tokens = formated(command).split(' ')[2:] if len(tokens) != 2: return False afi = AFI.value(tokens.pop(0)) safi = SAFI.value(tokens.pop(0)) if afi is None or safi is None: return False return RouteRefresh(afi,safi)
def parse_api_operational(self, command): tokens = formated(command).split(' ', 2) scope = [{}] if len(tokens) != 3: return False operational = tokens[0].lower() what = tokens[1].lower() if operational != 'operational': return False if what == 'asm': if not self._single_operational(Advisory.ASM, scope, ['afi', 'safi', 'advisory'], tokens[2]): return False elif what == 'adm': if not self._single_operational(Advisory.ADM, scope, ['afi', 'safi', 'advisory'], tokens[2]): return False elif what == 'rpcq': if not self._single_operational( Query.RPCQ, scope, ['afi', 'safi', 'sequence'], tokens[2]): return False elif what == 'rpcp': if not self._single_operational( Response.RPCP, scope, ['afi', 'safi', 'sequence', 'counter'], tokens[2]): return False elif what == 'apcq': if not self._single_operational( Query.APCQ, scope, ['afi', 'safi', 'sequence'], tokens[2]): return False elif what == 'apcp': if not self._single_operational( Response.APCP, scope, ['afi', 'safi', 'sequence', 'counter'], tokens[2]): return False elif what == 'lpcq': if not self._single_operational( Query.LPCQ, scope, ['afi', 'safi', 'sequence'], tokens[2]): return False elif what == 'lpcp': if not self._single_operational( Response.LPCP, scope, ['afi', 'safi', 'sequence', 'counter'], tokens[2]): return False else: return False operational = scope[0]['operational'][0] return operational
def parse_api_flow (self,command,action): self._tokens = self._tokenise(' '.join(formated(command).split(' ')[2:]).split('\\n')) scope = [{}] if not self._dispatch(scope,'flow',['route',],[],['root']): return False if not self._check_flow_route(scope): return False changes = scope[0]['announce'] if action == 'withdraw': for change in changes: change.nlri.action = OUT.withdraw # pylint: disable=E1101 return changes
def parse_api_flow (self, command, action): self._tokens = self._tokenise(' '.join(formated(command).split(' ')[2:]).split('\\n')) scope = [{}] if not self._dispatch(scope,'flow',['route',],[],['root']): return False if not self._check_flow_route(scope): return False changes = scope[0]['announce'] if action == 'withdraw': for change in changes: change.nlri.action = OUT.WITHDRAW return changes
def api_flow (self, command, action): tokens = formated(command).split(' ',2)[2].replace('\\n','\n').replace('{','{\n').replace('}','}\n').replace(';',';\n').replace('\n\n','\n') self.tokens.set_text(tokens) scope = [{}] if not self._dispatch(scope,'flow',['route',],[],['root']): return False if not self._check_flow_route(scope): return False changes = scope[0]['announce'] if action == 'withdraw': for change in changes: change.nlri.action = OUT.WITHDRAW return changes
def received(self): consumed_data = False for process in list(self._process): try: proc = self._process[process] # proc.poll returns None if the process is still fine # -[signal], like -15, if the process was terminated if proc.poll() is not None and self.reactor.respawn: raise ValueError('child died') r, _, _ = select.select([ proc.stdout, ], [], [], 0) if r: try: while True: # Calling next() on Linux and OSX works perfectly well # but not on OpenBSD where it always raise StopIteration # and only readline() works raw = proc.stdout.readline() line = raw.rstrip() consumed_data = True self.logger.processes( "Command from process %s : %s " % (process, line)) if raw == '': raise IOError('Child process died') yield (process, formated(line)) except IOError, exc: if not exc.errno or exc.errno in error.fatal: # if the program exists we can get an IOError with errno code zero ! self.logger.processes( "Issue with the process' PIPE, terminating it and restarting it" ) self._terminate(process) self._start(process) elif exc.errno in error.block: # we often see errno.EINTR: call interrupted and # we most likely have data, we will try to read them a the next loop iteration pass else: self.logger.processes( "unexpected errno received from forked process (%s)" % errstr(exc)) except StopIteration: if not consumed_data: self.logger.processes( "The process died, trying to respawn it") self._terminate(process) self._start(process)
def _tokenise (self,iterator): for line in iterator: replaced = formated(line) if not replaced: continue if replaced.startswith('#'): continue command = replaced[:3] if command in ('md5','asm'): string = line.strip()[3:].strip() if string[-1] == ';': string = string[:-1] yield [command,string,';'] elif replaced[:3] == 'run': yield [t for t in replaced[:-1].split(' ',1) if t] + [replaced[-1]] else: yield [t.lower() for t in replaced[:-1].split(' ') if t] + [replaced[-1]]
def parse_api_flow(self, command, action): command = command.replace('{', '{\\n').replace('}', '}\\n').replace( ';', ';\\n').replace('\\n\\n', '\\n') self._tokens = self._tokenise(' '.join( formated(command).split(' ')[2:]).split('\\n')) scope = [{}] if not self._dispatch(scope, 'flow', [ 'route', ], [], ['root']): return False if not self._check_flow_route(scope): return False changes = scope[0]['announce'] if action == 'withdraw': for change in changes: change.nlri.action = OUT.WITHDRAW return changes
def api_eor (self, command): tokens = formated(command).split(' ')[2:] number = len(tokens) if not number: return Family(1,1) if number != 2: return False afi = AFI.fromString(tokens[0]) if afi == AFI.undefined: return False safi = SAFI.fromString(tokens[1]) if safi == SAFI.undefined: return False return Family(afi,safi)
def parse_api_eor (self,command): tokens = formated(command).split(' ')[2:] number = len(tokens) if not number: return Family(1,1) if number != 2: return False afi = AFI.fromString(tokens[0]) if afi == AFI.undefined: return False safi = SAFI.fromString(tokens[1]) if safi == SAFI.undefined: return False return Family(afi,safi)
def api_operational (self, command): tokens = formated(command).split(' ',2) scope = [{}] if len(tokens) != 3: return False operational = tokens[0].lower() what = tokens[1].lower() if operational != 'operational': return False if what == 'asm': if not self._single_operational(Advisory.ASM,scope,['afi','safi','advisory'],tokens[2]): return False elif what == 'adm': if not self._single_operational(Advisory.ADM,scope,['afi','safi','advisory'],tokens[2]): return False elif what == 'rpcq': if not self._single_operational(Query.RPCQ,scope,['afi','safi','sequence'],tokens[2]): return False elif what == 'rpcp': if not self._single_operational(Response.RPCP,scope,['afi','safi','sequence','counter'],tokens[2]): return False elif what == 'apcq': if not self._single_operational(Query.APCQ,scope,['afi','safi','sequence'],tokens[2]): return False elif what == 'apcp': if not self._single_operational(Response.APCP,scope,['afi','safi','sequence','counter'],tokens[2]): return False elif what == 'lpcq': if not self._single_operational(Query.LPCQ,scope,['afi','safi','sequence'],tokens[2]): return False elif what == 'lpcp': if not self._single_operational(Response.LPCP,scope,['afi','safi','sequence','counter'],tokens[2]): return False else: return False operational = scope[0]['operational'][0] return operational
def parse_api_route (self,command,peers,action): tokens = formated(command).split(' ')[1:] number = len(tokens) if number < 1: return False message = tokens[0] if message not in ('route',): return False if number == 2 and action == 'withdraw' and 'next-hop' not in tokens: tokens.extend(['next-hop','0.0.0.0']) changes = [] if 'self' in command: for peer,nexthop in peers.iteritems(): scope = [{}] self._nexthopself = nexthop if not self._single_static_route(scope,tokens[1:]): self._nexthopself = None return False for change in scope[0]['announce']: changes.append((peer,change)) self._nexthopself = None else: scope = [{}] if not self._single_static_route(scope,tokens[1:]): return False for peer in peers: for change in scope[0]['announce']: changes.append((peer,change)) if action == 'withdraw': for (peer,change) in changes: change.nlri.action = OUT.withdraw # pylint: disable=E1101 return changes
def api_route (self, command, peers, action): tokens = formated(command).split(' ')[1:] number = len(tokens) if number < 1: return False message = tokens[0] if message not in ('route',): return False if number == 2 and action == 'withdraw' and 'next-hop' not in tokens: tokens.extend(['next-hop','0.0.0.0']) changes = [] if 'self' in command: for peer,nexthop in peers.iteritems(): scope = [{}] self._nexthopself = nexthop if not self._single_static_route(scope,tokens[1:]): self._nexthopself = None return False for change in scope[0]['announce']: changes.append((peer,change)) self._nexthopself = None else: scope = [{}] if not self._single_static_route(scope,tokens[1:]): return False for peer in peers: for change in scope[0]['announce']: changes.append((peer,change)) if action == 'withdraw': for (peer,change) in changes: change.nlri.action = OUT.WITHDRAW return changes
def _single_operational (self, klass, scope, parameters, value): def utf8 (string): return string.encode('utf-8')[1:-1] convert = { 'afi': AFI.value, 'safi': SAFI.value, 'sequence': int, 'counter': long, 'advisory': utf8 } def valid (_): return True def u32 (_): return int(_) <= 0xFFFFFFFF def u64 (_): return long(_) <= 0xFFFFFFFFFFFFFFFF def advisory (_): return len(_.encode('utf-8')) <= MAX_ADVISORY + 2 # the two quotes validate = { 'afi': AFI.value, 'safi': SAFI.value, 'sequence': u32, 'counter': u64, } number = len(parameters)*2 tokens = formated(value).split(' ',number-1) if len(tokens) != number: return self.error.set('invalid operational syntax, wrong number of arguments') return False data = {} while tokens and parameters: command = tokens.pop(0).lower() value = tokens.pop(0) if command == 'router-id': if isipv4(value): data['routerid'] = RouterID(value) else: return self.error.set('invalid operational value for %s' % command) return False continue expected = parameters.pop(0) if command != expected: return self.error.set('invalid operational syntax, unknown argument %s' % command) return False if not validate.get(command,valid)(value): return self.error.set('invalid operational value for %s' % command) return False data[command] = convert[command](value) if tokens or parameters: return self.error.set('invalid advisory syntax, missing argument(s) %s' % ', '.join(parameters)) return False if 'routerid' not in data: data['routerid'] = None if 'operational-message' not in scope[-1]: scope[-1]['operational-message'] = [] # iterate on each family for the peer if multiprotocol is set. scope[-1]['operationa-messagel'].append(klass(**data)) return True