コード例 #1
0
ファイル: net.py プロジェクト: ZhenyaKh/coco-beholder
 def run(self, test, *args, **kwargs):
     "Perform a complete start/test/stop cycle."
     self.start()
     info('*** Running test\n')
     result = test(*args, **kwargs)
     self.stop()
     return result
コード例 #2
0
ファイル: moduledeps.py プロジェクト: ZhenyaKh/coco-beholder
def moduleDeps(subtract=None, add=None):
    """Handle module dependencies.
       subtract: string or list of module names to remove, if already loaded
       add: string or list of module names to add, if not already loaded"""
    subtract = subtract if subtract is not None else []
    add = add if add is not None else []
    if isinstance(subtract, BaseString):
        subtract = [subtract]
    if isinstance(add, BaseString):
        add = [add]
    for mod in subtract:
        if mod in lsmod():
            info('*** Removing ' + mod + '\n')
            rmmodOutput = rmmod(mod)
            if rmmodOutput:
                error('Error removing ' + mod + ': "%s">\n' % rmmodOutput)
                exit(1)
            if mod in lsmod():
                error('Failed to remove ' + mod + '; still there!\n')
                exit(1)
    for mod in add:
        if mod not in lsmod():
            info('*** Loading ' + mod + '\n')
            modprobeOutput = modprobe(mod)
            if modprobeOutput:
                error('Error inserting ' + mod +
                      ' - is it installed and available via modprobe?\n' +
                      'Error was: "%s"\n' % modprobeOutput)
            if mod not in lsmod():
                error('Failed to insert ' + mod + ' - quitting.\n')
                exit(1)
        else:
            debug('*** ' + mod + ' already loaded\n')
コード例 #3
0
ファイル: net.py プロジェクト: ZhenyaKh/coco-beholder
 def startTerms(self):
     "Start a terminal for each node."
     if 'DISPLAY' not in os.environ:
         error("Error starting terms: Cannot connect to display\n")
         return
     info("*** Running terms on %s\n" % os.environ['DISPLAY'])
     cleanUpScreens()
     self.terms += makeTerms(self.controllers, 'controller')
     self.terms += makeTerms(self.switches, 'switch')
     self.terms += makeTerms(self.hosts, 'host')
コード例 #4
0
ファイル: net.py プロジェクト: ZhenyaKh/coco-beholder
 def build(self):
     "Build mininet."
     if self.topo:
         self.buildFromTopo(self.topo)
     if self.inNamespace:
         self.configureControlNetwork()
     info('*** Configuring hosts\n')
     self.configHosts()
     if self.xterms:
         self.startTerms()
     if self.autoStaticArp:
         self.staticArp()
     self.built = True
コード例 #5
0
ファイル: net.py プロジェクト: ZhenyaKh/coco-beholder
 def configHosts(self):
     "Configure a set of hosts."
     for host in self.hosts:
         info(host.name + ' ')
         intf = host.defaultIntf()
         if intf:
             host.configDefault()
         else:
             # Don't configure nonexistent intf
             host.configDefault(ip=None, mac=None)
         # You're low priority, dude!
         # BL: do we want to do this here or not?
         # May not make sense if we have CPU lmiting...
         # quietRun( 'renice +18 -p ' + repr( host.pid ) )
         # This may not be the right place to do this, but
         # it needs to be done somewhere.
     info('\n')
コード例 #6
0
ファイル: net.py プロジェクト: ZhenyaKh/coco-beholder
 def runCpuLimitTest(self, cpu, duration=5):
     """run CPU limit test with 'while true' processes.
     cpu: desired CPU fraction of each host
     duration: test duration in seconds (integer)
     returns a single list of measured CPU fractions as floats.
     """
     pct = cpu * 100
     info('*** Testing CPU %.0f%% bandwidth limit\n' % pct)
     hosts = self.hosts
     cores = int(quietRun('nproc'))
     # number of processes to run a while loop on per host
     num_procs = int(ceil(cores * cpu))
     pids = {}
     for h in hosts:
         pids[h] = []
         for _core in range(num_procs):
             h.cmd('while true; do a=1; done &')
             pids[h].append(h.cmd('echo $!').strip())
     outputs = {}
     time = {}
     # get the initial cpu time for each host
     for host in hosts:
         outputs[host] = []
         with open('/sys/fs/cgroup/cpuacct/%s/cpuacct.usage' % host,
                   'r') as f:
             time[host] = float(f.read())
     for _ in range(duration):
         sleep(1)
         for host in hosts:
             with open('/sys/fs/cgroup/cpuacct/%s/cpuacct.usage' % host,
                       'r') as f:
                 readTime = float(f.read())
             outputs[host].append(
                 ((readTime - time[host]) / 1000000000) / cores * 100)
             time[host] = readTime
     for h, pids in pids.items():
         for pid in pids:
             h.cmd('kill -9 %s' % pid)
     cpu_fractions = []
     for _host, outputs in outputs.items():
         for pct in outputs:
             cpu_fractions.append(pct)
     output('*** Results: %s\n' % cpu_fractions)
     return cpu_fractions
コード例 #7
0
    def config( self, **params ):
        """Configure the NAT and iptables"""
        super( NAT, self).config( **params )

        if not self.localIntf:
            self.localIntf = self.defaultIntf()

        if self.flush:
            self.cmd( 'sysctl net.ipv4.ip_forward=0' )
            self.cmd( 'iptables -F' )
            self.cmd( 'iptables -t nat -F' )
            # Create default entries for unmatched traffic
            self.cmd( 'iptables -P INPUT ACCEPT' )
            self.cmd( 'iptables -P OUTPUT ACCEPT' )
            self.cmd( 'iptables -P FORWARD DROP' )

        # Install NAT rules
        self.cmd( 'iptables -I FORWARD',
                  '-i', self.localIntf, '-d', self.subnet, '-j DROP' )
        self.cmd( 'iptables -A FORWARD',
                  '-i', self.localIntf, '-s', self.subnet, '-j ACCEPT' )
        self.cmd( 'iptables -A FORWARD',
                  '-o', self.localIntf, '-d', self.subnet, '-j ACCEPT' )
        self.cmd( 'iptables -t nat -A POSTROUTING',
                  '-s', self.subnet, "'!'", '-d', self.subnet,
                  '-j MASQUERADE' )

        # Instruct the kernel to perform forwarding
        self.cmd( 'sysctl net.ipv4.ip_forward=1' )

        # Prevent network-manager from messing with our interface
        # by specifying manual configuration in /etc/network/interfaces
        intf = self.localIntf
        cfile = '/etc/network/interfaces'
        line = '\niface %s inet manual\n' % intf
        config = open( cfile ).read()
        if ( line ) not in config:
            info( '*** Adding "' + line.strip() + '" to ' + cfile + '\n' )
            with open( cfile, 'a' ) as f:
                f.write( line )
        # Probably need to restart network-manager to be safe -
        # hopefully this won't disconnect you
        self.cmd( 'service network-manager restart' )
コード例 #8
0
 def run(self):
     "Run our cmdloop(), catching KeyboardInterrupt"
     while True:
         try:
             # Make sure no nodes are still waiting
             for node in self.mn.values():
                 while node.waiting:
                     info('stopping', node, '\n')
                     node.sendInt()
                     node.waitOutput()
             if self.isatty():
                 quietRun('stty echo sane intr ^C')
             self.cmdloop()
             break
         except KeyboardInterrupt:
             # Output a message - unless it's also interrupted
             # pylint: disable=broad-except
             try:
                 output('\nInterrupt\n')
             except Exception:
                 pass
コード例 #9
0
ファイル: net.py プロジェクト: ZhenyaKh/coco-beholder
 def waitConnected(self, timeout=None, delay=.5):
     """wait for each switch to connect to a controller,
        up to 5 seconds
        timeout: time to wait, or None to wait indefinitely
        delay: seconds to sleep per iteration
        returns: True if all switches are connected"""
     info('*** Waiting for switches to connect\n')
     time = 0
     remaining = list(self.switches)
     while True:
         for switch in tuple(remaining):
             if switch.connected():
                 info('%s ' % switch)
                 remaining.remove(switch)
         if not remaining:
             info('\n')
             return True
         if timeout is not None and time > timeout:
             break
         sleep(delay)
         time += delay
     warn('Timed out after %d seconds\n' % time)
     for switch in remaining:
         if not switch.connected():
             warn('Warning: %s is not connected to a controller\n' %
                  switch.name)
         else:
             remaining.remove(switch)
     return not remaining
コード例 #10
0
    def __init__(self, mininet, stdin=sys.stdin, script=None):
        """Start and run interactive or batch mode CLI
           mininet: Mininet network object
           stdin: standard input for CLI
           script: script to run in batch mode"""
        self.mn = mininet
        # Local variable bindings for py command
        self.locals = {'net': mininet}
        # Attempt to handle input
        self.stdin = stdin
        self.inPoller = poll()
        self.inPoller.register(stdin)
        self.inputFile = script
        Cmd.__init__(self)
        info('*** Starting CLI:\n')

        if self.inputFile:
            self.do_source(self.inputFile)
            return

        self.initReadline()
        self.run()
コード例 #11
0
ファイル: net.py プロジェクト: ZhenyaKh/coco-beholder
 def configureRoutedControlNetwork(self, ip='192.168.123.1', prefixLen=16):
     """Configure a routed control network on controller and switches.
        For use with the user datapath only right now."""
     controller = self.controllers[0]
     info(controller.name + ' <->')
     cip = ip
     snum = ipParse(ip)
     for switch in self.switches:
         info(' ' + switch.name)
         link = self.link(switch, controller, port1=0)
         sintf, cintf = link.intf1, link.intf2
         switch.controlIntf = sintf
         snum += 1
         while snum & 0xff in [0, 255]:
             snum += 1
         sip = ipStr(snum)
         cintf.setIP(cip, prefixLen)
         sintf.setIP(sip, prefixLen)
         controller.setHostRoute(sip, cintf)
         switch.setHostRoute(cip, sintf)
     info('\n')
     info('*** Testing control network\n')
     while not cintf.isUp():
         info('*** Waiting for', cintf, 'to come up\n')
         sleep(1)
     for switch in self.switches:
         while not sintf.isUp():
             info('*** Waiting for', sintf, 'to come up\n')
             sleep(1)
         if self.ping(hosts=[switch, controller]) != 0:
             error('*** Error: control network test failed\n')
             exit(1)
     info('\n')
コード例 #12
0
    def config( self, bw=None, delay=None, jitter=None, loss=None,
                gro=False, txo=True, rxo=True,
                speedup=0, use_hfsc=False, use_tbf=False,
                latency_ms=None, enable_ecn=False, enable_red=False,
                max_queue_size=None, **params ):
        """Configure the port and set its properties.
           bw: bandwidth in b/s (e.g. '10m')
           delay: transmit delay (e.g. '1ms' )
           jitter: jitter (e.g. '1ms')
           loss: loss (e.g. '1%' )
           gro: enable GRO (False)
           txo: enable transmit checksum offload (True)
           rxo: enable receive checksum offload (True)
           speedup: experimental switch-side bw option
           use_hfsc: use HFSC scheduling
           use_tbf: use TBF scheduling
           latency_ms: TBF latency parameter
           enable_ecn: enable ECN (False)
           enable_red: enable RED (False)
           max_queue_size: queue limit parameter for netem"""

        # Support old names for parameters
        gro = not params.pop( 'disable_gro', not gro )

        result = Intf.config( self, **params)

        def on( isOn ):
            "Helper method: bool -> 'on'/'off'"
            return 'on' if isOn else 'off'

        # Set offload parameters with ethool
        self.cmd( 'ethtool -K', self,
                  'gro', on( gro ),
                  'tx', on( txo ),
                  'rx', on( rxo ) )

        # Optimization: return if nothing else to configure
        # Question: what happens if we want to reset things?
        if ( bw is None and not delay and not loss
             and max_queue_size is None ):
            return

        # Clear existing configuration
        tcoutput = self.tc( '%s qdisc show dev %s' )
        if "priomap" not in tcoutput and "noqueue" not in tcoutput:
            cmds = [ '%s qdisc del dev %s root' ]
        else:
            cmds = []

        # Bandwidth limits via various methods
        bwcmds, parent = self.bwCmds( bw=bw, speedup=speedup,
                                      use_hfsc=use_hfsc, use_tbf=use_tbf,
                                      latency_ms=latency_ms,
                                      enable_ecn=enable_ecn,
                                      enable_red=enable_red )
        cmds += bwcmds

        # Delay/jitter/loss/max_queue_size using netem
        delaycmds, parent = self.delayCmds( delay=delay, jitter=jitter,
                                            loss=loss,
                                            max_queue_size=max_queue_size,
                                            parent=parent )
        cmds += delaycmds

        # Ugly but functional: display configuration info
        stuff = ( ( [ '%.2fMbit' % bw ] if bw is not None else [] ) +
                  ( [ '%s delay' % delay ] if delay is not None else [] ) +
                  ( [ '%s jitter' % jitter ] if jitter is not None else [] ) +
                  ( ['%.5f%% loss' % loss ] if loss is not None else [] ) +
                  ( [ 'ECN' ] if enable_ecn else [ 'RED' ]
                    if enable_red else [] ) )
        info( '(' + ' '.join( stuff ) + ') ' )

        # Execute all the commands in our node
        debug("at map stage w/cmds: %s\n" % cmds)
        tcoutputs = [ self.tc(cmd) for cmd in cmds ]
        for output in tcoutputs:
            if output != '':
                error( "*** Error: %s" % output )
        debug( "cmds:", cmds, '\n' )
        debug( "outputs:", tcoutputs, '\n' )
        result[ 'tcoutputs'] = tcoutputs
        result[ 'parent' ] = parent

        return result
コード例 #13
0
ファイル: net.py プロジェクト: ZhenyaKh/coco-beholder
 def start(self):
     "Start controller and switches."
     if not self.built:
         self.build()
     info('*** Starting controller\n')
     for controller in self.controllers:
         info(controller.name + ' ')
         controller.start()
     info('\n')
     info('*** Starting %s switches\n' % len(self.switches))
     for switch in self.switches:
         info(switch.name + ' ')
         switch.start(self.controllers)
     started = {}
     for swclass, switches in groupby(
             sorted(self.switches, key=lambda s: str(type(s))), type):
         switches = tuple(switches)
         if hasattr(swclass, 'batchStartup'):
             success = swclass.batchStartup(switches)
             started.update({s: s for s in success})
     info('\n')
     if self.waitConn:
         self.waitConnected()
コード例 #14
0
ファイル: net.py プロジェクト: ZhenyaKh/coco-beholder
    def buildFromTopo(self, topo=None):
        """Build mininet from a topology object
           At the end of this function, everything should be connected
           and up."""

        # Possibly we should clean up here and/or validate
        # the topo
        if self.cleanup:
            pass

        info('*** Creating network\n')

        if not self.controllers and self.controller:
            # Add a default controller
            info('*** Adding controller\n')
            classes = self.controller
            if not isinstance(classes, list):
                classes = [classes]
            for i, cls in enumerate(classes):
                # Allow Controller objects because nobody understands partial()
                if isinstance(cls, Controller):
                    self.addController(cls)
                else:
                    self.addController('c%d' % i, cls)

        info('*** Adding hosts:\n')
        for hostName in topo.hosts():
            self.addHost(hostName, **topo.nodeInfo(hostName))
            info(hostName + ' ')

        info('\n*** Adding switches:\n')
        for switchName in topo.switches():
            # A bit ugly: add batch parameter if appropriate
            params = topo.nodeInfo(switchName)
            cls = params.get('cls', self.switch)
            if hasattr(cls, 'batchStartup'):
                params.setdefault('batch', True)
            self.addSwitch(switchName, **params)
            info(switchName + ' ')

        info('\n*** Adding links:\n')
        for srcName, dstName, params in topo.links(sort=True, withInfo=True):
            self.addLink(**params)
            info('(%s, %s) ' % (srcName, dstName))

        info('\n')
コード例 #15
0
def sh( cmd ):
    "Print a command and send it to the shell"
    info( cmd + '\n' )
    result = Popen( [ '/bin/sh', '-c', cmd ], stdout=PIPE ).communicate()[ 0 ]
    return decode( result )
コード例 #16
0
    def cleanup( cls):
        """Clean up junk which might be left over from old runs;
           do fast stuff before slow dp and link removal!"""

        info( "*** Removing excess controllers/ofprotocols/ofdatapaths/"
              "pings/noxes\n" )
        zombies = ( 'controller ofprotocol ofdatapath ping nox_core'
                    'lt-nox_core ovs-openflowd ovs-controller'
                    'ovs-testcontroller udpbwtest vdlocalmnexec ivs ryu-manager' )
        # Note: real zombie processes can't actually be killed, since they
        # are already (un)dead. Then again,
        # you can't connect to them either, so they're mostly harmless.
        # Send SIGTERM first to give processes a chance to shutdown cleanly.
        sh( 'killall ' + zombies + ' 2> /dev/null' )
        time.sleep( 1 )
        sh( 'killall -9 ' + zombies + ' 2> /dev/null' )

        # And kill off sudo vdlocalmnexec
        sh( 'pkill -9 -f "sudo vdlocalmnexec"')

        info( "*** Removing junk from /tmp\n" )
        sh( 'rm -f /tmp/vconn* /tmp/vlogs* /tmp/*.out /tmp/*.log' )

        info( "*** Removing old X11 tunnels\n" )
        cleanUpScreens()

        info( "*** Removing excess kernel datapaths\n" )
        dps = sh( "ps ax | egrep -o 'dp[0-9]+' | sed 's/dp/nl:/'"
                  ).splitlines()
        for dp in dps:
            if dp:
                sh( 'dpctl deldp ' + dp )
        info( "***  Removing OVS datapaths\n" )
        dps = sh("ovs-vsctl --timeout=1 list-br").strip().splitlines()
        if dps:
            sh( "ovs-vsctl " + " -- ".join( "--if-exists del-br " + dp
                                            for dp in dps if dp ) )
        # And in case the above didn't work...
        dps = sh( "ovs-vsctl --timeout=1 list-br" ).strip().splitlines()
        for dp in dps:
            sh( 'ovs-vsctl del-br ' + dp )

        info( "*** Removing all links of the pattern foo-ethX\n" )
        links = sh( "ip link show | "
                    "egrep -o '([-_.[:alnum:]]+-eth[[:digit:]]+)'"
                    ).splitlines()
        # Delete blocks of links
        n = 1000  # chunk size
        for i in range( 0, len( links ), n ):
            cmd = ';'.join( 'ip link del %s' % link
                             for link in links[ i : i + n ] )
            sh( '( %s ) 2> /dev/null' % cmd )

        if 'tap9' in sh( 'ip link show' ):
            info( "*** Removing tap9 - assuming it's from cluster edition\n" )
            sh( 'ip link del tap9' )

        info( "*** Killing stale mininet node processes\n" )
        killprocs( 'mininet:' )

        info( "*** Shutting down stale tunnels\n" )
        killprocs( 'Tunnel=Ethernet' )
        killprocs( '.ssh/mn')
        sh( 'rm -f ~/.ssh/mn/*' )

        # Call any additional cleanup code if necessary
        for callback in cls.callbacks:
            callback()

        info( "*** Cleanup complete.\n" )
コード例 #17
0
ファイル: net.py プロジェクト: ZhenyaKh/coco-beholder
 def stop(self):
     "Stop the controller(s), switches and hosts"
     info('*** Stopping %i controllers\n' % len(self.controllers))
     for controller in self.controllers:
         info(controller.name + ' ')
         controller.stop()
     info('\n')
     if self.terms:
         info('*** Stopping %i terms\n' % len(self.terms))
         self.stopXterms()
     info('*** Stopping %i links\n' % len(self.links))
     for link in self.links:
         info('.')
         link.stop()
     info('\n')
     info('*** Stopping %i switches\n' % len(self.switches))
     stopped = {}
     for swclass, switches in groupby(
             sorted(self.switches, key=lambda s: str(type(s))), type):
         switches = tuple(switches)
         if hasattr(swclass, 'batchShutdown'):
             success = swclass.batchShutdown(switches)
             stopped.update({s: s for s in success})
     for switch in self.switches:
         info(switch.name + ' ')
         if switch not in stopped:
             switch.stop()
         switch.terminate()
     info('\n')
     info('*** Stopping %i hosts\n' % len(self.hosts))
     for host in self.hosts:
         info(host.name + ' ')
         host.terminate()
     info('\n*** Done\n')