def ovs_intfopts(self): popts = '' iopts = '' if is_some(self.tag): popts += ' vlan_mode=access tag={}'.format(self.tag) else: popts += ' vlan_mode=trunk tag=[] trunks=[]' if is_some(self.intf_type): iopts += ' type={0}'.format(self.intf_type) if is_some(self.ofport): iopts += ' ofport_request={0}'.format(self.ofport) is_valid = lambda (k, v): is_somestr(k) and is_somestr(v) opt_to_str = lambda (k, v): '{0}={1}'.format(k, v) valid_opts = list(filter(is_valid, self.intf_opts.iteritems())) if len(valid_opts) == 1: single_opt = valid_opts[0] iopts += ' options:' + opt_to_str(single_opt) elif len(valid_opts) > 0: iopts += ' options:{' iopts += ','.join(map(opt_to_str, valid_opts)) iopts += '}' if len(iopts) > 0: iopts = ' -- set Interface {} {}'.format(self.name, iopts) return popts + iopts
def get_address( host, port ): if is_some( host ) and is_some( port ): host = resolve( host ) port = as_int( port, minim=1, maxim=65535, name='port' ) return ( host, port ) else: return None
def is_valid_node( mn, node ): if node in mn.hosts: return is_some( node.IP() ) elif node in mn.switches: return is_some( node.dpid ) else: return False
def __init__(self, name, ip=None, port=None, **params): super(ControllerConfig, self).__init__(name, ip=ip, port=port, **params) self.ip = as_str(ip, name='ip') if is_some(ip) else None self.port = as_int(port, minim=1, maxim=65535, name='port') if is_some(port) else None
def _do_read_cmd( self, sock ): ctype_raw = recv_bytes( sock, 1, exit_check=self.is_shutdown ) if not is_some( ctype_raw ): return ( None, None ) else: ctype = _IOUtils.unpack_byte( ctype_raw ) cmd = _IOUtils.recv_string( sock, exit_check=self.is_shutdown ) if not is_some( cmd ): return ( None, None ) else: return ( ctype, cmd )
def add_local_sdncontroller(self, name='flood', sudo=None, **params): if is_some(self.controller): raise RuntimeError('only one controller is supported') if self.use_netcontroller: self.controller = self.mr.add_network_controller(name, **params) else: varanus_home = self.local_varanus_home if not is_some(varanus_home): raise RuntimeError( 'VARANUS home is not defined, cannot add sdncontroller') self.controller = self.mr.add_local_varanus_sdncontroller( name, varanus_home, sudo=sudo, **params)
def check_valid_node( mn, node ): if node in mn.hosts: if is_some( node.IP() ): return node else: raise ValueError( 'invalid host node (must have a defined IP address)' ) elif node in mn.switches: if is_some( node.dpid ): return node else: raise ValueError( 'invalid switch node (must have a defined DPID)' ) else: raise ValueError( 'unknown node with name \'{}\''.format( node.name ) )
def _handle_connection( self, sock ): with closing( sock ): while not self.is_shutdown(): ctype, cmd = self._do_read_cmd( sock ) if is_some( ctype ) and is_some( cmd ): if ctype == _RCLIServer._PYTHON_CMD_TYPE: code, res = self._do_exec_python_cmd( cmd ) elif ctype == _RCLIServer._SHELL_CMD_TYPE: code, res = self._do_exec_shell_cmd( cmd ) else: raise IOError( 'received invalid command type' ) self._do_write_cmd_result( sock, ctype, code, res )
def __handle_gencfg(self): if self.gencfg: with open(self.gencfg_file, 'w') as f: f.write('# ==== SDNCONTROLLER CFG ====') f.write('\n') self.__write_sdncontroller_config(f) f.write('\n') f.write('# ==== COLLECTOR CFG ====') f.write('\n') self.__write_collector_config(f) return True else: if self.autocfg and is_some(self.local_varanus_home): sdncontroller_file = os.path.join( self.local_varanus_home, VaranusTopo._SDNCONTROLLER_CFG_FILE) with open(sdncontroller_file, 'w') as f: self.__write_sdncontroller_config(f, multiline=False) collector_file = os.path.join(self.local_varanus_home, VaranusTopo._COLLECTOR_CFG_FILE) with open(collector_file, 'w') as f: self.__write_collector_config(f, multiline=False) return False
def _do_exec_shell_cmd( self, shell_cmd ): try: shell_cmd = _IOUtils.decode_str( shell_cmd ) op, key, node, host, port, cmd = self._do_parse_shell_cmd_args( shell_cmd ) if op == 'start' or op == 'start_no_output': if key in self.shell_handlers: raise ValueError( 'cannot start command for active key {}'.format( key ) ) else: handler = _ShellCommandHandler( key, node, host, port, cmd ) self.shell_handlers[key] = handler handler.start() return ( _RCLIServer._SHELL_RESULT_OK_CODE, None ) elif op == 'stop' or op == 'stop_custom': if key not in self.shell_handlers: raise ValueError( 'cannot stop command for inactive key {}'.format( key ) ) else: handler = self.shell_handlers[key] del self.shell_handlers[key] if is_some( cmd ): handler.stop_custom( cmd ) else: handler.terminate() return ( _RCLIServer._SHELL_RESULT_OK_CODE, None ) else: raise AssertionError( 'should never happen' ) except Exception as e: e = _IOUtils.encode_str( e ) return ( _RCLIServer._SHELL_RESULT_ERROR_CODE, e )
def hip( mn, ip_addr ): ip_addr = some( ip_addr, name='IP address' ) host = next( ( h for h in mn.hosts if h.IP() == ip_addr ), None ) if is_some( host ): return host else: raise ValueError( 'no host matches the provided IP address' )
def sid( mn, dpid ): dpid = some( dpid, name='DPID' ) switch = next( ( s for s in mn.switches if int( s.dpid ) == dpid ), None ) if is_some( switch ): return switch else: raise ValueError( 'no switch matches the provided DPID' )
def _do_write_cmd_result( self, sock, ctype, code, res ): ctype_raw = _IOUtils.pack_byte( ctype ) if send_bytes( sock, ctype_raw, exit_check=self.is_shutdown ): code_raw = _IOUtils.pack_byte( code ) if send_bytes( sock, code_raw, exit_check=self.is_shutdown ): if is_some( res ): _IOUtils.send_string( sock, res, exit_check=self.is_shutdown )
def _new_node(self, node_builder, name, **params): node_builder = as_callable(node_builder, name='node_builder') num = self._next_node_num() name = as_str( name, name='name') if is_some(name) else self._next_node_name(num) return as_a(node_builder(self.ringnum, num, name, **params), instance_of=NodeConfig, name='created node')
def stop_rcli(): srv = _RCLIServer._ACTIVE_SERVER if is_some( srv ) and srv.is_active(): srv.shutdown() _RCLIServer._ACTIVE_SERVER = None return True else: return False
def _run( self ): try: sock = self._accept_single_connection() if is_some( sock ): self._handle_connection( sock ) except IOError as e: error( newline( 'IO error:', e ) ) finally: self._active_thread = None
def recv_string( sock, exit_check=None, exit_on_timeout=False ): slen_raw = recv_bytes( sock, 4, exit_check=exit_check, exit_on_timeout=exit_on_timeout ) if not is_some( slen_raw ): return None else: slen = _IOUtils.unpack_int( slen_raw ) if slen < 0: raise IOError( 'Received invalid string length' ) else: return recv_bytes( sock, slen, exit_check=exit_check, exit_on_timeout=exit_on_timeout )
def add_local_collector(self, c_name, cid, **params): varanus_home = self.local_varanus_home if not is_some(varanus_home): raise RuntimeError( 'VARANUS home is not defined, cannot add collector') c_name = as_str(c_name, name='c_name') cid = as_int(cid, name='cid') self.__add_local_collector(c_name, varanus_home, cid, **params)
def __getqos_intf( intf ): qos = QOS_CACHE.get( intf ) if is_some( qos ): return qos elif __check_iface_is_available( intf ): qos = __get_bandwidth_and_netem( intf ) QOS_CACHE.put( intf, qos ) return qos else: return ( None, None )
def __set_tc_netem( intf, netem ): if is_some( netem ) and len( netem ) > 0: cmd = 'tc qdisc add dev {i} parent 1:1 handle 10: netem {n}'.format( i=intf, n=netem ) res = NodeUtils.run_cmd( intf.node, cmd ) if len( res ) == 0: return True else: raise RuntimeError( 'tc error while setting netem: ' + res ) else: return True
def create_port(self, node): node = as_a(node, instance_of=NodeConfig, name='node') if is_some(self.name): portname = self.name else: portname = node.name + '-e' + str(self.portnum) return node.add_port(self.portnum, name=portname, is_virtual=self.is_virtual, **self.params)
def _run( self ): if is_some( self.addr ): with closing( socket.socket( socket.AF_INET, socket.SOCK_STREAM ) ) as sock: sock.connect( self.addr ) sock.settimeout( self.sock_timeout ) output( newline( '< Shell command client with key', self.key, 'connected to', self.addr, '>' ) ) while not self.cmd_proc.is_finished(): line = self.cmd_proc.readline( block=True, timeout=self.line_timeout ) if is_some( line ): debug( newline( '== Sending output line ===============================' ) ) debug( newline( line ) ) debug( newline( '======================================================' ) ) line = _IOUtils.encode_str( line ) self._do_write_output_line( sock, line ) else: self.cmd_proc.wait_to_finish() debug( newline( '== Command output ======================================' ) ) debug( multiline( self.cmd_proc.read_available_lines() ) ) debug( newline( '========================================================' ) )
def __init__(self, ringnum, prefix='n', port1_cfg=None, port2_cfg=None, link_builder=None): self.ringnum = as_int(ringnum, minim=0, name='ringnum') self.prefix = as_str(prefix, allow_empty=True, name='prefix') self.port1_cfg = as_a(port1_cfg, instance_of=PortConfig, name='port1_cfg') if is_some(port1_cfg) else None self.port2_cfg = as_a(port2_cfg, instance_of=PortConfig, name='port2_cfg') if is_some(port2_cfg) else None self.link_builder = as_callable( link_builder, name='link_builder') if is_some(link_builder) else None self.nodes = [] self.links = []
def stop(self, *args, **kwargs): if self._is_active: self.stopcmd(self, *args, **kwargs) self._is_active = False deleteIntfs = kwargs.get('deleteIntfs') if is_some(deleteIntfs): super(CustomNodeMixin, self).stop(deleteIntfs=deleteIntfs) else: super(CustomNodeMixin, self).stop() else: warn(newline('<! Cannot stop the inactive node', self.name, '!>'))
def __get_tc_bandwidth( intf ): cmd = 'tc class show dev {i} | grep -E "htb 1:1"'.format( i=intf ) res = NodeUtils.run_cmd( intf.node, cmd ) if len( res ) == 0: return None else: re_res = re.search( r'ceil ([^ ]+)', res ) if is_some( re_res ): return re_res.group( 1 ) else: raise RuntimeError( 'unexpected "tc class show" output for bandwidth' )
def _do_exec_python_cmd( self, python_cmd ): try: python_cmd = _IOUtils.decode_str( python_cmd ) res = self._eval_cmd( python_cmd ) if is_some( res ): res = _IOUtils.encode_str( res ) return ( _RCLIServer._PYTHON_RESULT_NONNULL_CODE, res ) else: return ( _RCLIServer._PYTHON_RESULT_NULL_CODE, None ) except Exception as e: e = _IOUtils.encode_str( e ) return ( _RCLIServer._PYTHON_RESULT_EXCEPTION_CODE, e )
def __get_tc_netem( intf ): cmd = 'tc qdisc show dev {i} | grep -E "netem"'.format( i=intf ) res = NodeUtils.run_cmd( intf.node, cmd ) if len( res ) == 0: return None else: re_res = re.search( r'limit [^ ]+(.*)', res ) if is_some( re_res ): return re_res.group( 1 ).strip() else: raise RuntimeError( 'unexpected "tc qdisc show" output for netem' )
def _new_link(self, node1, port1_cfg, node2, port2_cfg, link_builder): if is_some(port1_cfg): port1_cfg = as_a(port1_cfg, instance_of=PortConfig, name='port1_cfg') elif is_some(self.port1_cfg): port1_cfg = self.port1_cfg else: port1_cfg = PortConfig(2) if is_some(port2_cfg): port2_cfg = as_a(port2_cfg, instance_of=PortConfig, name='port2_cfg') elif is_some(self.port2_cfg): port2_cfg = self.port2_cfg else: port2_cfg = PortConfig(1) if is_some(link_builder): link_builder = as_callable(link_builder, name='link_builder') elif is_some(self.link_builder): link_builder = self.link_builder else: raise ValueError( 'no default link builder is available; must provide one') port1 = port1_cfg.create_port(node1) port2 = port2_cfg.create_port(node2) return as_a(link_builder(port1, port2), instance_of=LinkConfig, name='created link')
def start_rcli( listenport, mn ): listenport = as_int( listenport, minim=1, maxim=65535, name='listenport' ) srv = _RCLIServer._ACTIVE_SERVER if is_some( srv ) and srv.is_active(): return False else: # Specialized eval() function with specific globals and locals eval_cmd = _build_eval_func( mn ) srv = _RCLIServer( listenport, eval_cmd, mn ) srv.start() _RCLIServer._ACTIVE_SERVER = srv return True
def __set_ovs_qos( intf, band ): if is_some( band ) and len( band ) > 0: cmd_fmt = 'ovs-vsctl -- set Port {i} qos=@newqos' + \ ' -- --id=@newqos create QoS type=linux-htb other-config:max-rate={b} queues=0=@q0' + \ ' -- --id=@q0 create Queue other-config:min-rate={b} other-config:max-rate={b}' cmd = cmd_fmt.format( i=intf, b=band ) else: cmd_fmt = 'ovs-vsctl -- set Port {i} qos=@newqos' + \ ' -- --id=@newqos create QoS type=linux-htb queues=0=@q0' + \ ' -- --id=@q0 create Queue other-config={{}}' cmd = cmd_fmt.format( i=intf ) _res = NodeUtils.run_cmd( intf.node, cmd ) return True