Changeset 280
- Timestamp:
- 06/25/15 14:27:54 (9 years ago)
- Location:
- etherws/trunk
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
etherws/trunk/README.rst
r279 r280 128 128 Advanced Usage 129 129 ============== 130 131 Proxy 132 ----- 133 You can create WebSocket tunnels via HTTP proxy. Proxy server's address and 134 port number are specified by generic environment variables: e.g. *$http_proxy* 135 136 See https://docs.python.org/library/urllib.html for more information about 137 environment variables for the proxy. 138 139 Logging 140 ------- 141 etherws uses standard logging library. You can customize the logger using the 142 *fileConfig* described in https://docs.python.org/library/logging.config.html 143 144 To run *etherws sw* with the custom logger:: 145 146 # etherws sw --logconf /path/to/logging.ini 147 148 etherws uses a logger stream named "etherws". And internally Tornado uses 149 some logger streams described in http://www.tornadoweb.org/en/stable/log.html 150 151 Note: etherws does not write debug logs even if you simply configure loglevel 152 DEBUG, to avoid performance degradation. To write debug logs, you can 153 specify *--debug* option. 130 154 131 155 Remote Control … … 203 227 ======= 204 228 1.3 229 - logging support 205 230 - http proxy support on client connection 206 231 - fix listport bug on tornado 4.0.x -
etherws/trunk/etherws.py
r278 r280 52 52 import operator 53 53 import argparse 54 import traceback 54 55 import logging 56 import logging.config 55 57 56 58 import tornado … … 65 67 66 68 67 class DebugMixIn(object):68 def dprintf(self, msg, func=lambda: ()):69 if self._debug:70 prefix = '[%s] %s - ' % (time.asctime(), self.__class__.__name__)71 sys.stderr.write(prefix + (msg % func()))72 73 74 69 class EthernetFrame(object): 75 70 def __init__(self, data): … … 107 102 108 103 109 class FDB( DebugMixIn):104 class FDB(object): 110 105 class Entry(object): 111 106 def __init__(self, port, ageout): … … 122 117 return self.age > self._ageout 123 118 124 def __init__(self, ageout, debug):119 def __init__(self, ageout, logger, debug): 125 120 self._ageout = ageout 121 self._logger = logger 126 122 self._debug = debug 127 123 self._table = {} … … 149 145 150 146 self._del_entry(vid, mac) 151 self.dprintf('aged out: port:%d; vid:%d; mac:%s\n', 152 lambda: (entry.port.number, vid, mac.encode('hex'))) 147 148 if self._debug: 149 self._logger.debug('fdb aged out: port:%d; vid:%d; mac:%s', 150 entry.port.number, vid, mac.encode('hex')) 153 151 154 152 def each(self): … … 169 167 vid = frame.vid 170 168 self._set_entry(vid, mac, port) 171 self.dprintf('learned: port:%d; vid:%d; mac:%s\n', 172 lambda: (port.number, vid, mac.encode('hex'))) 169 170 if self._debug: 171 self._logger.debug('fdb learned: port:%d; vid:%d; mac:%s', 172 port.number, vid, mac.encode('hex')) 173 173 174 174 def delete(self, port): … … 176 176 if entry.port.number == port.number: 177 177 self._del_entry(vid, mac) 178 self.dprintf('deleted: port:%d; vid:%d; mac:%s\n', 179 lambda: (port.number, vid, mac.encode('hex'))) 180 181 182 class SwitchingHub(DebugMixIn): 178 179 if self._debug: 180 self._logger.debug('fdb deleted: port:%d; vid:%d; mac:%s', 181 port.number, vid, mac.encode('hex')) 182 183 184 class SwitchingHub(object): 183 185 class Port(object): 184 186 def __init__(self, number, interface): … … 189 191 self.shut = False 190 192 191 def __init__(self, fdb, debug):193 def __init__(self, fdb, logger, debug): 192 194 self.fdb = fdb 195 self._logger = logger 193 196 self._debug = debug 194 197 self._table = {} … … 227 230 p.tx += 1 228 231 229 if ports:230 self. dprintf('sent: port:%s; vid:%d; %s -> %s\n',231 lambda: (','.join(str(p.number) for p in ports),232 233 234 frame.dst_mac.encode('hex')))232 if self._debug and ports: 233 self._logger.debug('sent: port:%s; vid:%d; %s -> %s', 234 ','.join(str(p.number) for p in ports), 235 frame.vid, 236 frame.src_mac.encode('hex'), 237 frame.dst_mac.encode('hex')) 235 238 236 239 def receive(self, src_interface, frame): … … 257 260 258 261 except: # ex. received invalid frame 259 traceback.print_exc() 262 self._logger.exception( 263 'caught error while forwarding frame: port:%d; frame:%s', 264 src_port.number, frame.data.encode('hex')) 260 265 261 266 def _privattr(self, name): 262 return '_%s_%s_%s' % ( self.__class__.__name__, id(self), name)267 return '_%s_%s_%s' % (type(self).__name__, id(self), name) 263 268 264 269 def _set_privattr(self, name, obj, value): … … 402 407 return do_execute() 403 408 except: 404 traceback.print_exc()409 self._logger.exception('caught error while doing authorization') 405 410 406 411 return auth_required() 407 412 408 413 409 class ServerHandler( DebugMixIn,BasicAuthMixIn, WebSocketHandler):414 class ServerHandler(BasicAuthMixIn, WebSocketHandler): 410 415 IFTYPE = 'server' 411 416 IFOP_ALLOWED = False 412 417 413 def __init__(self, app, req, switch, htpasswd, debug):418 def __init__(self, app, req, switch, htpasswd, logger, debug): 414 419 super(ServerHandler, self).__init__(app, req) 415 420 self._switch = switch 416 421 self._htpasswd = htpasswd 422 self._logger = logger 417 423 self._debug = debug 418 424 … … 421 427 conn = self.request.connection 422 428 if hasattr(conn, 'address'): 423 return ':'.join(str(e) for e in conn.address )429 return ':'.join(str(e) for e in conn.address[:2]) 424 430 if hasattr(conn, 'context'): 425 return ':'.join(str(e) for e in conn.context.address )431 return ':'.join(str(e) for e in conn.context.address[:2]) 426 432 return str(conn) 427 433 … … 430 436 return self._switch.register_port(self) 431 437 finally: 432 self. dprintf('connected: %s\n', lambda:self.request.remote_ip)438 self._logger.info('connected: %s', self.request.remote_ip) 433 439 434 440 def on_message(self, message): … … 437 443 def on_close(self): 438 444 self._switch.unregister_port(self) 439 self. dprintf('disconnected: %s\n', lambda:self.request.remote_ip)440 441 442 class BaseClientHandler( DebugMixIn):445 self._logger.info('disconnected: %s', self.request.remote_ip) 446 447 448 class BaseClientHandler(object): 443 449 IFTYPE = 'baseclient' 444 450 IFOP_ALLOWED = False 445 451 446 def __init__(self, ioloop, switch, target, debug, *args, **kwargs):452 def __init__(self, ioloop, switch, target, logger, debug, *args, **kwargs): 447 453 self._ioloop = ioloop 448 454 self._switch = switch 449 455 self._target = target 456 self._logger = logger 450 457 self._debug = debug 451 458 self._args = args … … 491 498 492 499 @property 500 def logger(self): 501 return self._logger 502 503 @property 493 504 def device(self): 494 505 return self._device … … 503 514 self.leave_switch() 504 515 self.unregister_device() 505 self. dprintf('disconnected: %s\n', lambda:self.target)516 self.logger.info('disconnected: %s', self.target) 506 517 507 518 def register_device(self, device): … … 524 535 return 525 536 except: 526 traceback.print_exc()537 self.logger.exception('caught error while receiving frame') 527 538 self.close() 528 539 … … 583 594 socket.PF_PACKET, socket.SOCK_RAW, socket.htons(self.ETH_P_ALL))) 584 595 self.device.bind((self.target, self.ETH_P_ALL)) 585 self. dprintf('connected: %s\n', lambda:self.target)596 self.logger.info('connected: %s', self.target) 586 597 return self.join_switch() 587 598 … … 659 670 self.register_device(TunTapDevice(self.target, IFF_TAP | IFF_NO_PI)) 660 671 self.device.up() 661 self. dprintf('connected: %s\n', lambda:self.target)672 self.logger.info('connected: %s', self.target) 662 673 return self.join_switch() 663 674 … … 702 713 self.register_device(websocket.WebSocket(sslopt=self._sslopt)) 703 714 self.device.connect(self.target, **self._options) 704 self. dprintf('connected: %s\n', lambda:self.target)715 self.logger.info('connected: %s', self.target) 705 716 return self.join_switch() 706 717 … … 736 747 737 748 738 class ControlServerHandler( DebugMixIn,BasicAuthMixIn, RequestHandler):749 class ControlServerHandler(BasicAuthMixIn, RequestHandler): 739 750 NAMESPACE = 'etherws.control' 740 751 IFTYPES = { … … 744 755 } 745 756 746 def __init__(self, app, req, ioloop, switch, htpasswd, debug):757 def __init__(self, app, req, ioloop, switch, htpasswd, logger, debug): 747 758 super(ControlServerHandler, self).__init__(app, req) 748 759 self._ioloop = ioloop 749 760 self._switch = switch 750 761 self._htpasswd = htpasswd 762 self._logger = logger 751 763 self._debug = debug 752 764 … … 758 770 'code': 0 - 32700, 759 771 'message': 'Parse error', 760 'data': '%s: %s' % ( e.__class__.__name__, str(e)),772 'data': '%s: %s' % (type(e).__name__, str(e)), 761 773 }) 762 774 … … 772 784 'code': 0 - 32600, 773 785 'message': 'Invalid Request', 774 'data': '%s: %s' % ( e.__class__.__name__, str(e)),786 'data': '%s: %s' % (type(e).__name__, str(e)), 775 787 }) 776 788 … … 784 796 'code': 0 - 32601, 785 797 'message': 'Method not found', 786 'data': '%s: %s' % ( e.__class__.__name__, str(e)),798 'data': '%s: %s' % (type(e).__name__, str(e)), 787 799 }) 788 800 … … 790 802 return self._jsonrpc_response(id_=id_, result=handler(params)) 791 803 except Exception as e: 792 traceback.print_exc()804 self._logger.exception('caught error while processing request') 793 805 return self._jsonrpc_response(id_=id_, error={ 794 806 'code': 0 - 32602, 795 807 'message': 'Invalid params', 796 'data': '%s: %s' % ( e.__class__.__name__, str(e)),808 'data': '%s: %s' % (type(e).__name__, str(e)), 797 809 }) 798 810 … … 816 828 opt = getattr(self, '_optparse_' + type_)(params.get('options', {})) 817 829 cls = self.IFTYPES[type_] 818 interface = cls(self._ioloop, self._switch, target, self._debug, **opt) 830 interface = cls(self._ioloop, self._switch, target, 831 self._logger, self._debug, **opt) 819 832 portnum = interface.open() 820 833 return {'entries': [self._portstat(self._switch.get_port(portnum))]} … … 971 984 raise ValueError('Invalid ageout: %s' % args.ageout) 972 985 986 setrealpath(args, 'logconf') 973 987 setrealpath(args, 'htpasswd', 'sslkey', 'sslcert') 974 988 setrealpath(args, 'ctlhtpasswd', 'ctlsslkey', 'ctlsslcert') … … 986 1000 sethtpasswd(args, 'ctlhtpasswd') 987 1001 1002 if args.logconf: 1003 logging.config.fileConfig(args.logconf) 1004 logger = logging.getLogger('etherws') 1005 else: 1006 logger = logging.getLogger('etherws') 1007 logger.setLevel(logging.DEBUG if args.debug else logging.INFO) 1008 988 1009 ioloop = IOLoop.instance() 989 fdb = FDB(args.ageout, args.debug)990 switch = SwitchingHub(fdb, args.debug)1010 fdb = FDB(args.ageout, logger, args.debug) 1011 switch = SwitchingHub(fdb, logger, args.debug) 991 1012 992 1013 if args.port == args.ctlport and args.host == args.ctlhost: … … 1002 1023 'switch': switch, 1003 1024 'htpasswd': args.htpasswd, 1025 'logger': logger, 1004 1026 'debug': args.debug, 1005 1027 }), … … 1008 1030 'switch': switch, 1009 1031 'htpasswd': args.ctlhtpasswd, 1032 'logger': logger, 1010 1033 'debug': args.debug, 1011 1034 }), … … 1018 1041 'switch': switch, 1019 1042 'htpasswd': args.htpasswd, 1043 'logger': logger, 1020 1044 'debug': args.debug, 1021 1045 })]) … … 1027 1051 'switch': switch, 1028 1052 'htpasswd': args.ctlhtpasswd, 1053 'logger': logger, 1029 1054 'debug': args.debug, 1030 1055 })]) … … 1199 1224 parser_sw.add_argument('--debug', action='store_true', default=False, 1200 1225 help='run as debug mode') 1226 parser_sw.add_argument('--logconf', 1227 help='path to logging config') 1201 1228 parser_sw.add_argument('--foreground', action='store_true', default=False, 1202 1229 help='run as foreground mode') … … 1326 1353 'code': 0 - 32603, 1327 1354 'message': 'Internal error', 1328 'data': '%s: %s' % ( e.__class__.__name__, str(e)),1355 'data': '%s: %s' % (type(e).__name__, str(e)), 1329 1356 }) 1330 1357
Note: See TracChangeset
for help on using the changeset viewer.