+++ /dev/null
-#!/usr/bin/env python2
-
-# pcepdump - Display messages from PCCs
-#
-# Copyright (c) 2012,2013 Cisco Systems, Inc. and others. All rights reserved.
-#
-# This program and the accompanying materials are made available under the
-# terms of the Eclipse Public License v1.0 which accompanies this distribution,
-# and is available at http://www.eclipse.org/legal/epl-v10.html
-#
-import sys
-import datetime
-
-# Temporary hack
-sys.path.append('..')
-
-import argparse
-import logging
-import code
-import pcepy.peer as _P
-import pcepy.session as _S
-import pcepy.message as _M
-from pcepy.message import object as _O
-
-_LOGGER = logging.getLogger('pcepy.peer')
-
-DEFAULT_IP = '0.0.0.0'
-KEEPALIVE = 30
-
-class PcepDumper(_P.Context):
- """A manager for a PCEP connection.
-
- PcepDumper can be PCC or PCE and it main function it to listen in and
- print incoming messages. It aslo provide interface for sending messages.
- This class should not be used directly, use one of subclasses instead.
- """
-
- def __init__(self, config, loglevel):
- super(PcepDumper, self).__init__(config)
- self.logger = logging.getLogger()
- handler = logging.StreamHandler()
- handler.setFormatter(
- logging.Formatter(
- "%(asctime)s: %(levelname)s;%(message)s",
- "%Y-%m-%d %H:%M:%S",
- )
- )
- self.logger.addHandler(handler)
- self.loglevel = loglevel
- self.enabled = True
-
- @property
- def loglevel(self):
- return self.logger.getEffectiveLevel()
-
- @loglevel.setter
- def loglevel(self, level):
- "Set the log level of root logger"
- self.logger.setLevel(level)
-
- def shutdown(self):
- self.logger.info("Bringing PCE down")
- self.peer.shutdown()
- self.bus.stop()
-
- def exit(self):
- if not self.peer:
- return 0
- try:
- self.shutdown()
- if self.peer.active:
- self.logger.info('Waiting on bus stop')
- self.bus.join()
-
- self.logger.info("All connections are down.")
- return 0
- except Exception as err:
- self.logger.exception("Clean shutdown failed: %s" % err)
- return 1
-
- def on_message(self, session, eventargs):
- # Get date and time
- dt = datetime.datetime.now()
- # Dont print KeepAlive messages in quiet mode
- if self.loglevel == logging.WARN and \
- isinstance(eventargs['message'], _M.Keepalive):
-
- return
- else:
- print("=======\n%s: Message on %s:\n%s\n=======" % (
- dt.strftime("%Y-%m-%d %H:%M:%S"), eventargs['session'],
- eventargs['message'].show(
- {
- 'msg_sep':'\n', 'obj_sep':'\n',
- 'item_sep':'\n', 'data':'\n'
- },
- prefix=''
- )
- ))
-
-class ManualOpener(_P.base.Opener):
- def on_connect(self, peer, eventargs):
- # Copy paste from peer.base.Opener, only difference is that we don't
- # send Open message
- session = eventargs['session']
- if session.is_server():
- return
-
- # TODO: duplicate sessions -> send err 9 close
- session[_P.base.Opener.STATE_STATE] = _P.base.Opener.OS_OPENWAIT
- session[_P.base.Opener.STATE_PCEPTYPE] = \
- self._get_pceptype(peer, session)
- session[_P.base.Opener.STATE_SESSIONID] = \
- self._get_sessionid(peer, session)
- session[_P.base.Keeper.STATE_KEEPALIVE] = self._get_keepalive(peer, session)
- session[_P.base.Keeper.STATE_DEADTIMER] = self._get_deadtimer(peer, session)
- session[_P.base.Opener.STATE_OPENWAIT] = \
- _P.base.resolve_timeout(_P.base.Opener.OPENWAIT)
-
- def on_message(self, peer, eventargs):
- session = eventargs['session']
- message = eventargs['message']
- state = session[_P.base.Opener.STATE_STATE]
-
- is_open = isinstance(message, _M.Open)
-
- if is_open:
- open = message.get(_O.Open)
- if state == _P.base.Opener.OS_OPENWAIT:
- if not open:
- _LOGGER.error('Open message without Open object received')
- return
-
- session[_P.base.Opener.STATE_REMOTE_OPEN] = open
- accept_open = self._accept_open(peer, session, open)
-
- if accept_open is True:
- del session[_P.base.Opener.STATE_OPENWAIT]
- session[_P.base.Opener.STATE_REMOTE_OK] = True
- session[_P.base.Opener.STATE_STATE] = \
- _P.base.Opener.OS_KEEPWAIT
-
- else:
- _LOGGER.error('Open message received in %s state' % state)
-
- elif isinstance(message, _M.Keepalive):
- if state == _P.base.Opener.OS_KEEPWAIT:
- del session[_P.base.Opener.STATE_KEEPWAIT]
- self.ka_rec = True
- elif state != _P.base.Opener.OS_UP:
- _LOGGER.error('Keepalive message received in %s state' % state)
-
-
- def send_open(self, keepalive, deadtimer, session_id):
- send(_M.Open(_O.Open(
- keealive=keepalive,
- deaedtimer=deadtimer,
- session_id=session_id
- )))
- self.open_sended = True
-
- def send_keepalive(self, peer, session):
- send(_M.Keepalive())
- self._session_open(peer, session)
- session[_P.base.Opener.STATE_STATE] = _P.base.Opener.OS_UP
-
-
-class PccDumper(PcepDumper):
- """ PCC manager. See PcepDumper for more info. """
- def __init__(self, config, loglevel, manual_open):
- super(PccDumper, self).__init__(config, loglevel)
- self.peer = _P.Pcc('PDE', self)
- self.peer.add_handler(self)
- self.role = _S.Node.ROLE_PCC
-
- if manual_open:
- self.peer.remove_handler(_P.base.Opener)
- self.opener = ManualOpener()
- self.peer.add_handler(self.opener)
-
- def send_open(keepalive=30, deadtimer=120, session_id=1):
- self.opener.send_open(keepalive, deadtimer, session_id)
-
- def send_keepalive():
- self.opener.send_keepalive(self.peer, self.peer.sessions[0])
-
- self.send_open = send_open
- self.send_keepalive = send_keepalive
-
- def start(self, address, port):
- self.logger.info("Starting dumper on %s:%s" % (address, port))
- address = self.address_from(address)
-
- local = '::' if self.address_is_ipv6(address) else '0.0.0.0'
- self.peer_node = self.get_node(self.role, 'DumpNode',
- self.address_from(local)
- )
- self.mark_node = self.get_node(self.role, 'MarkNode',
- self.address_from(address), port
- )
- self.peer.create_session(self.peer_node, self.mark_node)
-
- if not self.bus.is_alive():
- self.bus.start()
-
- def send_open(self, keepalive=30, deadtimer=120, session_id=1):
- send(_M.Open(_O.Open(
- keepalive=keepalive,
- deadtimer=deadtimer,
- session_id=session_id
- )))
- self.opened = True
-
- def send_keepalive(self):
- send(_M.Keepalive())
-
-class PceDumper(PcepDumper):
- """ PCE manager. See PcepDumper for more info. """
- def __init__(self, config, loglevel):
- super(PceDumper, self).__init__(config, loglevel)
- self.peer = _P.Pce('PDE', self)
- self.peer.add_handler(self)
- self.role = _S.Node.ROLE_PCE
-
- def start(self, address, port):
- self.logger.info("Starting dumper on %s:%s" % (address, port))
- address = self.address_from(address)
-
- self.peer_node = self.get_node(self.role, 'DumpNode', address, port)
- self.peer.create_server(self.peer_node)
-
- if not self.bus.is_alive():
- self.bus.start()
-
-def ipaddr_port_type(data):
- try:
- ip, port = data.split('@')
- except ValueError:
- ip = data
- port = _S.PCEP_PORT
-
- try:
- ip = _P.Context.address_from(ip)
- except ValueError:
- raise argparse.ArgumentTypeError('Invalid IP address: %s' % ip)
-
- try:
- port = int(port)
- except ValueError:
- raise argparse.ArgumentTypeError('Invalid port: %s' % port)
-
- return ip, port
-
-def exit():
- sys.exit(dumper.exit())
-
-def process_arguments(arguments):
- """ Initialize command line arguments parser. """
-
- parser = argparse.ArgumentParser(
- description='Command line utility for running PCE or PCC and printing \
- incomming messages',
- version='%(prog)s 0.1 Copyright (c) 2012,2013 Cisco Systems, Inc. and others. All rights reserved.',
- usage='%(prog)s [OPTION]...',
- )
-
- group_type = parser.add_argument_group()
-
- group_type.add_argument(
- '-c', '--pcc',
- action='store_const',
- dest='pcc',
- const=True,
- default=False,
- help='Enable PCC mode (PCE is default)',
- )
-
- group_parameters = parser.add_argument_group()
-
- group_parameters.add_argument(
- '-a', '--address',
- action='store',
- type=ipaddr_port_type,
- dest='ip_port',
- default=(_P.Context.address_from(DEFAULT_IP), _S.PCEP_PORT),
- metavar='IP@PORT',
- help='the ip address and port to which is this server bound'
- )
-
- group_parameters.add_argument(
- '-i', '--id',
- action='store',
- type=int,
- dest=_P.base.Opener.CONFIG_NODE_ID,
- metavar='ID',
- help='the node ID for PCE',
- )
-
- group_parameters.add_argument(
- '-k', '-ka', '--keepalive',
- action='store',
- type=int,
- dest=_P.base.Keeper.CONFIG_KEEPALIVE,
- default=KEEPALIVE,
- metavar='TIMEOUT',
- help='in seconds, value of the desired KeepAlive timer'
- )
-
- group_parameters.add_argument(
- '-d', '--deadtimer',
- action='store',
- type=int,
- dest=_P.base.Keeper.CONFIG_DEADTIMER,
- default=None,
- metavar='TIMEOUT',
- help='in seconds, value of the desired deadtimer'
- )
-
- group_open = parser.add_argument_group()
-
- group_open.add_argument(
- '-o', '--open',
- action='store_const',
- const=True,
- dest='open',
- default=False,
- help='Force manual session opening (pcc only)'
- )
-
- group_mode = parser.add_argument_group()
-
- # TODO: Maybe raise error when specified more of these?
- # Now, last one specified is used.
- group_mode.add_argument(
- '--stateful',
- action='store_const',
- const=_P.base.Opener.PCEPTYPE_STATEFUL,
- dest=_P.base.Opener.CONFIG_PCEPTYPE,
- default=_P.base.Opener.PCEPTYPE_STATELESS,
- help='passive stateful'
- )
-
- group_mode.add_argument(
- '--active',
- action='store_const',
- const=_P.base.Opener.PCEPTYPE_STATEFULA,
- dest=_P.base.Opener.CONFIG_PCEPTYPE,
- default=_P.base.Opener.PCEPTYPE_STATELESS,
- help='active stateful'
- )
-
- group_mode.add_argument(
- '--versioned',
- action='store',
- dest=_P.base.Opener.CONFIG_DB_VERSION,
- type=int,
- default=0,
- metavar='VERSION',
- help='version number for versioned stateful'
- )
-
- group_output = parser.add_argument_group()
-
- group_output.add_argument(
- '--quiet',
- action='store_const',
- const=logging.WARN,
- dest='loglevel',
- default=logging.INFO,
- help='Suppres WARN log level (INFO is default)',
- )
-
- group_output.add_argument(
- '--debug',
- action='store_const',
- const=logging.DEBUG,
- dest='loglevel',
- default=logging.INFO,
- help='Suppres DEBUG log level (INFO is default)',
- )
-
- # Parse arguments and create dict
- parsed_args = vars(parser.parse_args(arguments))
-
- # If keepalive timer was set and deadtimer was not, reset it to
- # 4 times keepalive (max value is 255)
- parsed_args[_P.base.Keeper.CONFIG_DEADTIMER] = \
- parsed_args[_P.base.Keeper.CONFIG_DEADTIMER]or \
- parsed_args[_P.base.Keeper.CONFIG_KEEPALIVE] * 4 if \
- parsed_args[_P.base.Keeper.CONFIG_KEEPALIVE] * 4 < 255 else \
- 255
-
- # Print warning, if user forces deadtimer other than keepalive * 4
- if parsed_args[_P.base.Keeper.CONFIG_DEADTIMER] != \
- parsed_args[_P.base.Keeper.CONFIG_KEEPALIVE] * 4:
- sys.stderr.write('Warrning: deadtimer (%s) should be 4 times bigger '\
- 'than keepalive (%s)\n' \
- % (parsed_args[_P.base.Keeper.CONFIG_DEADTIMER],
- parsed_args[_P.base.Keeper.CONFIG_KEEPALIVE]))
-
- # Set stateful type if versioned and stateless
- if parsed_args[_P.base.Opener.CONFIG_DB_VERSION] and \
- parsed_args[_P.base.Opener.CONFIG_PCEPTYPE] == \
- _P.base.Opener.PCEPTYPE_STATELESS:
-
- parsed_args[_P.base.Opener.CONFIG_PCEPTYPE] = \
- _P.base.Opener.PCEPTYPE_STATEFUL
-
- return parsed_args
-
-def send(msg, session=0):
- """ UI function for messages sending. """
- try:
- dumper.peer.sessions[session].send(msg)
- except(IndexError):
- sys.stderr.write('Could not send message, ' + \
- 'sessions %s doesn\'t exists\n' % session)
-
-def quit():
- exit()
-
-if __name__ == '__main__':
- args = process_arguments(sys.argv[1:])
-
- # Determine role (PCE or PCC)
- role = _S.Node.ROLE_PCC if args['pcc'] else _S.Node.ROLE_PCE
- del args['pcc']
-
- # Log level
- log_level = args['loglevel']
- del args['loglevel']
-
- manual_open = args['open']
- del args['open']
-
- # Additional arguments are used for config construction
- config_session = _P.pce.Pce.CONFIG_SESSION_CONFIG if \
- role == _S.Node.ROLE_PCE else _P.pcc.Pcc.CONFIG_SESSION_CONFIG
-
- config = {
- config_session:
- { key : value for key, value in args.iteritems() if \
- value is not None },
- }
-
- # Create and start dumper
- if role == _S.Node.ROLE_PCC:
- dumper = PccDumper(config, log_level, manual_open)
- else:
- dumper = PceDumper(config, log_level)
-
- dumper.start(args['ip_port'][0], args['ip_port'][1])
-
- code.interact(banner=None, local=globals())
- sys.exit(dumper.exit())
- print "Done."