def _start(self, process): try: if process in self._process: self.logger.processes("process already running") return if not process in self.reactor.configuration.process: self.logger.processes( "Can not start process, no configuration for it (anymore ?)" ) return # Prevent some weird termcap data to be created at the start of the PIPE # \x1b[?1034h (no-eol) (esc) os.environ['TERM'] = 'dumb' run = self.reactor.configuration.process[process].get('run', '') if run: api = self.reactor.configuration.process[process]['encoder'] self._api_encoder[process] = JSON( '2.0') if api == 'json' else Text('1.0') self._process[process] = subprocess.Popen( run, stdin=subprocess.PIPE, stdout=subprocess.PIPE, preexec_fn=preexec_helper # This flags exists for python 2.7.3 in the documentation but on on my MAC # creationflags=subprocess.CREATE_NEW_PROCESS_GROUP ) fcntl.fcntl(self._process[process].stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) self.logger.processes("Forked process %s" % process) around_now = int(time.time()) & self.respawn_timemask if process in self._respawning: if around_now in self._respawning[process]: self._respawning[process][around_now] += 1 # we are respawning too fast if self._respawning[process][ around_now] > self.respawn_number: self.logger.processes( "Too many respawn for %s (%d) terminating program" % (process, self.respawn_number), 'critical') raise ProcessError() else: # reset long time since last respawn self._respawning[process] = {around_now: 1} else: # record respawing self._respawning[process] = {around_now: 1} neighbor = self.reactor.configuration.process[process]['neighbor'] self._neighbor_process.setdefault(neighbor, []).append(process) except (subprocess.CalledProcessError, OSError, ValueError), e: self._broken.append(process) self.logger.processes("Could not start process %s" % process) self.logger.processes("reason: %s" % str(e))
def setup(self, env, ip, port): self.handle = { Message.ROUTE_MONITORING: self._route, Message.STATISTICS_REPORT: self._statistics, Message.PEER_DOWN_NOTIFICATION: self._peer, } self.asn4 = env.bmp.asn4 self.use_json = env.bmp.json self.fd = env.fd self.ip = ip self.port = port self.json = JSON('3.4.8') return self
# This does not take the BGP header - let's assume we will not break that :) update = Update.unpack_message(injected,negotiated) except KeyboardInterrupt: raise except Notify,exc: logger.parser('could not parse the message','error') logger.parser(str(exc),'error') return False except Exception,exc: logger.parser('could not parse the message','error') logger.parser(str(exc),'error') return False logger.parser('') # new line for number in range(len(update.nlris)): change = Change(update.nlris[number],update.attributes) logger.parser('decoded %s %s %s' % (decoding,change.nlri.action,change.extensive())) logger.parser('update json %s' % JSON('3.4.0').update(p,update,'','')) return True # ================================================================= check_update # def check_notification (raw): notification = Notification.unpack_message(raw[18:],None) # XXX: FIXME: should be using logger here print notification return True
raise except Notify, e: logger.parser('could not parse the message') logger.parser(str(e)) return False except Exception, e: logger.parser('could not parse the message') logger.parser(str(e)) return False logger.parser('') # new line for number in range(len(update.nlris)): change = Change(update.nlris[number], update.attributes) logger.parser('decoded %s %s %s' % (decoding, change.nlri.action, change.extensive())) logger.parser('update json %s' % JSON('3.4.0').update(p, update, '', '')) return True # ================================================================= check_update # def check_notification(raw): notification = Notification.unpack_message(raw[18:], None) # XXX: FIXME: should be using logger here print notification return True
except Notify, exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False except Exception, exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False logger.parser('') # new line for number in range(len(update.nlris)): change = Change(update.nlris[number], update.attributes) logger.parser('decoded %s %s %s' % (decoding, change.nlri.action, change.extensive())) logger.parser( 'update json %s' % JSON(json_version).update(p.neighbor, 'in', update, '', '')) return True # ================================================================= check_update # def check_notification(raw): notification = Notification.unpack_message(raw[18:], None) # XXX: FIXME: should be using logger here print notification return True
raise except Notify, exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False except Exception, exc: logger.parser('could not parse the message') logger.parser(str(exc)) return False logger.parser('') # new line for number in range(len(update.nlris)): change = Change(update.nlris[number], update.attributes) logger.parser('decoded %s %s %s' % (decoding, change.nlri.action, change.extensive())) logger.parser('update json %s' % JSON(json_version).update(p, update, '', '')) return True # ================================================================= check_update # def check_notification(raw): notification = Notification.unpack_message(raw[18:], None) # XXX: FIXME: should be using logger here print notification return True
class Transcoder(object): seen_open = { 'send': None, 'receive': None, } negotiated = None json = JSON(json_version) def __init__(self, src='json', dst='json'): if src != 'json': raise RuntimeError('left as an exercise to the reader') if dst != 'json': raise RuntimeError('left as an exercise to the reader') self.convert = self._from_json self.encoder = self.json def _state(self): self.seen_open['send'] = None self.seen_open['receive'] = None self.negotiated = None def _open(self, direction, message): self.seen_open[direction] = message if all(self.seen_open.values()): self.negotiated = Negotiated(None) self.negotiated.sent(self.seen_open['send']) self.negotiated.received(self.seen_open['receive']) def _from_json(self, string): try: parsed = json.loads(string) except ValueError: print >> sys.stderr, 'invalid JSON message' sys.exit(1) if parsed.get('exabgp', '0.0.0') != json_version: print >> sys.stderr, 'invalid json version', string sys.exit(1) content = parsed.get('type', '') if not content: print >> sys.stderr, 'invalid json content', string sys.exit(1) neighbor = _FakeNeighbor( parsed['neighbor']['address']['local'], parsed['neighbor']['address']['peer'], parsed['neighbor']['asn']['local'], parsed['neighbor']['asn']['peer'], ) if content == 'state': self._state() return string direction = parsed['neighbor']['direction'] category = parsed['neighbor']['message']['category'] header = parsed['neighbor']['message']['header'] body = parsed['neighbor']['message']['body'] raw = ''.join( chr(int(body[_:_ + 2], 16)) for _ in range(0, len(body), 2)) if content == 'open': message = Open.unpack_message(raw) self._open(direction, message) return self.encoder.open(neighbor, direction, message, header, body) if content == 'keapalive': return self.encoder.keepalive(neighbor, direction, header, body) if content == 'notification': return self.encoder.notification(neighbor, direction, ord(message[0]), ord(message[1]), message[2:], header, body) if not self.negotiated: print >> sys.stderr, 'invalid message sequence, open not exchange not complete', string sys.exit(1) message = Message.unpack(category, raw, self.negotiated) if content == 'update': return self.encoder.update(neighbor, direction, message, header, body) if content == 'eor': # XXX: Should not be required return self.encoder.update(neighbor, direction, message, header, body) if content == 'refresh': return self.json.refresh(neighbor, direction, message, header, body) if content == 'operational': return self.json.refresh(neighbor, direction, message, header, body) raise RuntimeError( 'the programer is a monkey and forgot a JSON message type')