def start( self ): """ Starts the Mininet object with the current topology (if not already started). """ if not self.built: raise RuntimeError( 'can only start after calling build() method once' ) elif not self.started: info( newline() ) info( newline( newline( '=== Starting Mininet...' ) ) ) self.net.start() self.started = True
def add_remote_varanus_collector( self, name, user, server, varanus_home, cid, **params ): """ Adds a remote VARANUS collector to the current topology and returns a RemoteCollectorConfig object representing it, or a NullNodeConfig if VARANUS usage is disabled. - name : a textual representation of the collector - user : the name of the user on the remote server - server : the IP address of the remote server - varanus_home: home directory of varanus project - cid : the collector identifier """ if self.enable_varanus: if self.built: raise RuntimeError( 'build() method was already called; cannot add any more collectors' ) name = as_str( name ) storage = self.hosts check_duplicate( storage, name ) c = self._new_remote_node( RemoteCollectorConfig, name, user, server, \ varanus_home=varanus_home, cid=cid, \ **params ) storage[ name ] = c info( newline( '=== Added remote VARANUS collector', c ) ) return c else: return self.add_null_host( name )
def add_link( self, port1, port2, **params ): """ Adds a new link to the current topology and returns a LinkConfig object representing it. If any of the ports is a null port then this method returns a NullLinkConfig object. - port1: a PortConfig object representing the port of the 1st node - port2: a PortConfig object representing the port of the 2nd node """ if self.built: raise RuntimeError( 'build() method was already called; cannot add any more links' ) if isinstance( port1, NullPortConfig ) or isinstance( port2, NullPortConfig ): return NullLinkConfig( port1, port2, **params ) if port1.is_virtual() and port2.is_virtual(): link_cls = VirLinkConfig elif not ( port1.is_virtual() or port2.is_virtual() ): link_cls = PhyLinkConfig else: raise RuntimeError( "link between virtual port and physical port is not supported" ) l = link_cls( port1, port2, **params ) self.links.append( l ) info( newline( '=== Added link', l ) ) return l
def start( self ): t = threading.Thread( target=self._run, name='ShellCommandHandler-{}-thread'.format( self.key ) ) t.daemon = True output( newline( '<', 'Starting shell command', self.cmd, '>' ) ) self.cmd_proc = NodeUtils.run_cmd_async( self.node, self.cmd ) t.start()
def add_custom_remote_host( self, name, user, server, \ startcmd, stopcmd, morecmds=None, \ **params ): """ Adds a custom remote host to the current topology and returns a CustomRemoteHostConfig object representing it. - name : a textual representation of the host - user : the name of the user on the remote server - server : the IP address of the remote server - startcmd: a function used to start the host when called - stopcmd : a function used to stop the host when called - morecmds: additional optional commands to define in the Mininet node """ if self.built: raise RuntimeError( 'build() method was already called; cannot add any more hosts' ) name = as_str( name ) storage = self.hosts check_duplicate( storage, name ) h = self._new_remote_node( CustomRemoteHostConfig, name, user, server, \ startcmd=startcmd, stopcmd=stopcmd, morecmds=morecmds, \ **params ) storage[ name ] = h info( newline( '=== Added custom remote host', h ) ) return h
def forward_OVS_ports( self, sw, src, dest ): if not isinstance( sw, LocalOVSSwitchConfig ) and \ not isinstance( sw, RemoteOVSSwitchConfig ): sw = self.switches[ sw ] sw.forward_ports( src, dest ) info( newline( '=== Forwarded OVS ports in switch', sw, \ '-', src, '-->', dest ) )
def start(self, *args, **kwargs): if not self._is_active: self.startcmd(self, *args, **kwargs) self._is_active = True else: warn( newline('<! Cannot start the already active node', self.name, '!>'))
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 _accept_single_connection( self ): with closing( socket.socket( socket.AF_INET, socket.SOCK_STREAM ) ) as srvsock: srvsock.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 ) srvsock.bind( ( "localhost", self._listenport ) ) srvsock.listen( 1 ) srvsock.settimeout( self._server_timeout ) output( newline( '< RCLI server was started on port', self._listenport, '>' ) ) while not self.is_shutdown(): try: sock, addr = srvsock.accept() output( newline( '< RCLI client connected at', addr, '>' ) ) sock.settimeout( self.sock_timeout ) return sock except socket.timeout: pass # try again else: return None
def start(self, *args, **kwargs): if not self._is_active: self.startcmd(self, *args, **kwargs) self._is_active = True # do not call Controller start method else: warn( newline('<! Cannot start the already active controller', self.name, '!>'))
def stop(self, *args, **kwargs): if self._is_active: self.stopcmd(self, *args, **kwargs) self._is_active = False # bypass Controller stop method Node.stop(self) else: warn( newline('<! Cannot stop the inactive controller', self.name, '!>'))
def add_console_command( self, name, cmd ): """ Adds a named command to be available to call when interacting with Mininet. - name: the name of the command - cmd : the function to be called when the command is executed """ name = as_str( name ) info ( newline( '=== Registered console command', '"' + name + '"' ) ) self.cli.register_command( name, cmd )
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 build( self ): """ Builds the Mininet objects for controllers, nodes and links. """ if self.built: raise RuntimeError( 'can only call build() method once' ) else: info( newline( '=== Building controllers...' ) ) for c in self.controllers.itervalues(): c.build( self.net ) info( newline( '=== Building hosts...' ) ) for h in self.hosts.itervalues(): h.build( self.net ) info( newline( '=== Building switches...' ) ) for s in self.switches.itervalues(): s.build( self.net ) info( newline( '=== Building links...' ) ) for l in self.links: l.build( self.net ) self.built = True
def add_local_host( self, name, **params ): """ Adds a new local host to the current topology and returns a LocalHostConfig object representing it. - name: a textual representation of the host """ if self.built: raise RuntimeError( 'build() method was already called; cannot add any more hosts' ) name = as_str( name ) storage = self.hosts check_duplicate( storage, name ) h = self._new_node( LocalHostConfig, name, **params ) storage[ name ] = h info( newline( '=== Added local host', h ) ) return h
def add_null_switch( self, name, **params ): """ Adds a dummy non-existent switch to the current topology and returns a NullNodeConfig object representing it. - name: a textual representation of the switch """ if self.built: raise RuntimeError( 'build() method was already called; cannot add any more switches' ) name = as_str( name ) storage = self.switches check_duplicate( storage, name ) s = self._new_node( NullNodeConfig, name, **params ) storage[ name ] = s info( newline( '=== Added null switch', s ) ) return s
def add_null_controller( self, name, **params ): """ Adds a dummy non-existent controller to the current topology and returns a NullControllerConfig object representing it. - name: a textual representation of the controller """ if self.built: raise RuntimeError( 'build() method was already called; cannot add any more controllers' ) name = as_str( name ) storage = self.controllers check_duplicate( storage, name ) c = self._new_node( NullControllerConfig, name, **params ) storage[ name ] = c info( newline( '=== Added null controller', c ) ) return c
def add_local_ovs_switch( self, name, **params ): """ Adds a new local OVS switch to the current topology and returns a LocalOVSSwitchConfig object representing it. - name: a textual representation of the switch """ if self.built: raise RuntimeError( 'build() method was already called; cannot add any more switches' ) name = as_str( name ) storage = self.switches check_duplicate( storage, name ) s = self._new_node( LocalOVSSwitchConfig, name, \ protocols=self.of_version, **params ) storage[ name ] = s info( newline( '=== Added local OVS switch', s ) ) return s
def add_remote_host( self, name, user, server, **params ): """ Adds a new remote host to the current topology and returns a RemoteHostConfig object representing it. - name : a textual representation of the host - user : the name of the user on the remote server - server: the IP address of the remote server """ if self.built: raise RuntimeError( 'build() method was already called; cannot add any more hosts' ) name = as_str( name ) storage = self.hosts check_duplicate( storage, name ) h = self._new_remote_node( RemoteHostConfig, name, user, server, **params ) storage[ name ] = h info( newline( '=== Added remote host', h ) ) return h
def interact( self ): """ Starts the Mininet object (if not started already), launches a console to interact with user and shutdowns Mininet when done. """ self.start() info( newline() ) info( newline( newline( '=== Interacting now with Mininet ===' ) ) ) result = self.cli.run_command_line( self.net ) info( newline() ) info( newline( newline( '=== Stopping Mininet...' ) ) ) self.net.stop() return result
def add_pica8_switch( self, name, user, server, **params ): """ Adds a new pica8 switch (remote) to the current topology and returns a Pica8SwitchConfig object representing it. - name : a textual representation of the switch - user : the name of the user on the remote server - server: the IP address of the remote server """ if self.built: raise RuntimeError( 'build() method was already called; cannot add any more switches' ) name = as_str( name ) storage = self.switches check_duplicate( storage, name ) s = self._new_remote_node( Pica8SwitchConfig, name, user, server, \ protocols=self.of_version, \ **params ) storage[ name ] = s info( newline( '=== Added Pica8 switch', s ) ) return s
def add_custom_local_controller( self, name, startcmd, stopcmd, morecmds=None, \ **params ): """ Adds a custom local controller to the current topology and returns a CustomLocalControllerConfig object representing it. - name : a textual representation of the controller - startcmd: a function used to start the controller when called - stopcmd : a function used to stop the controller when called - morecmds: additional optional commands to define in the Mininet node """ if self.built: raise RuntimeError( 'build() method was already called; cannot add any more controllers' ) name = as_str( name ) storage = self.controllers check_duplicate( storage, name ) c = self._new_node( CustomLocalControllerConfig, name, \ startcmd=startcmd, stopcmd=stopcmd, morecmds=morecmds, \ **params ) storage[ name ] = c info( newline( '=== Added custom local controller', c ) ) return c
def add_local_varanus_sdncontroller( self, name, varanus_home, sudo=None, **params ): """ Adds a local VARANUS SDN controller to the current topology and returns a LocalSDNControllerConfig object representing it, or a NullControllerConfig if VARANUS usage is disabled. - name : a textual representation of the controller - varanus_home: home directory of varanus project """ if self.enable_varanus: if self.built: raise RuntimeError( 'build() method was already called; cannot add any more controllers' ) name = as_str( name ) storage = self.controllers check_duplicate( storage, name ) c = self._new_node( LocalSDNControllerConfig, name, \ varanus_home=varanus_home, sudo=sudo, \ **params ) storage[ name ] = c info( newline( '=== Added local VARANUS SDN controller', c ) ) return c else: return self.add_null_controller( name )
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 stop_custom( self, cmd ): output( newline( '<', 'Stopping shell command', "'" + self.cmd + "'", 'by executing', "'" + cmd + "'", '>' ) ) NodeUtils.run_cmd( self.node, cmd )
def terminate( self ): cmd_proc = self.cmd_proc if is_some( cmd_proc ): output( newline( '<', 'Terminating shell command', "'" + self.cmd + "'", '>' ) ) cmd_proc.terminate()
def _popen(self, cmd, **params): debug(newline('==== Popen in node', self.name, '====')) debug(newline(cmd)) debug(newline('PARAMS:', dict(**params))) debug(newline('================')) return super(NodeMixin, self)._popen(cmd, **params)
def write(self, data): debug(newline('==== Shell command in node', self.name, '====')) debug(newline(data)) debug(newline('================')) return super(NodeMixin, self).write(data)