Permalink
Browse files

a skeleton being setup

  • Loading branch information...
0 parents commit 3726dc400d209b46077575c0718a4bb5ae7b1986 jvimal committed Jul 17, 2010
Showing with 510 additions and 0 deletions.
  1. 0 __init__.py
  2. +178 −0 log.py
  3. +80 −0 net.py
  4. +57 −0 node.py
  5. +195 −0 util.py
No changes.
178 log.py
@@ -0,0 +1,178 @@
+"Logging functions for Mininet."
+
+import logging
+from logging import Logger
+import types
+
+# Create a new loglevel, 'CLI info', which enables a Mininet user to see only
+# the output of the commands they execute, plus any errors or warnings. This
+# level is in between info and warning. CLI info-level commands should not be
+# printed during regression tests.
+OUTPUT = 25
+
+LEVELS = { 'debug': logging.DEBUG,
+ 'info': logging.INFO,
+ 'output': OUTPUT,
+ 'warning': logging.WARNING,
+ 'error': logging.ERROR,
+ 'critical': logging.CRITICAL }
+
+# change this to logging.INFO to get printouts when running unit tests
+LOGLEVELDEFAULT = logging.WARNING
+
+#default: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
+LOGMSGFORMAT = '%(message)s'
+
+
+# Modified from python2.5/__init__.py
+class StreamHandlerNoNewline( logging.StreamHandler ):
+ """StreamHandler that doesn't print newlines by default.
+ Since StreamHandler automatically adds newlines, define a mod to more
+ easily support interactive mode when we want it, or errors-only logging
+ for running unit tests."""
+
+ def emit( self, record ):
+ """Emit a record.
+ If a formatter is specified, it is used to format the record.
+ The record is then written to the stream with a trailing newline
+ [ N.B. this may be removed depending on feedback ]. If exception
+ information is present, it is formatted using
+ traceback.printException and appended to the stream."""
+ try:
+ msg = self.format( record )
+ fs = '%s' # was '%s\n'
+ if not hasattr( types, 'UnicodeType' ): # if no unicode support...
+ self.stream.write( fs % msg )
+ else:
+ try:
+ self.stream.write( fs % msg )
+ except UnicodeError:
+ self.stream.write( fs % msg.encode( 'UTF-8' ) )
+ self.flush()
+ except ( KeyboardInterrupt, SystemExit ):
+ raise
+ except:
+ self.handleError( record )
+
+
+class Singleton( type ):
+ """Singleton pattern from Wikipedia
+ See http://en.wikipedia.org/wiki/SingletonPattern#Python
+
+ Intended to be used as a __metaclass_ param, as shown for the class
+ below.
+
+ Changed cls first args to mcs to satisfy pylint."""
+
+ def __init__( mcs, name, bases, dict_ ):
+ super( Singleton, mcs ).__init__( name, bases, dict_ )
+ mcs.instance = None
+
+ def __call__( mcs, *args, **kw ):
+ if mcs.instance is None:
+ mcs.instance = super( Singleton, mcs ).__call__( *args, **kw )
+ return mcs.instance
+
+
+class MininetLogger( Logger, object ):
+ """Mininet-specific logger
+ Enable each mininet .py file to with one import:
+
+ from mininet.log import [lg, info, error]
+
+ ...get a default logger that doesn't require one newline per logging
+ call.
+
+ Inherit from object to ensure that we have at least one new-style base
+ class, and can then use the __metaclass__ directive, to prevent this
+ error:
+
+ TypeError: Error when calling the metaclass bases
+ a new-style class can't have only classic bases
+
+ If Python2.5/logging/__init__.py defined Filterer as a new-style class,
+ via Filterer( object ): rather than Filterer, we wouldn't need this.
+
+ Use singleton pattern to ensure only one logger is ever created."""
+
+ __metaclass__ = Singleton
+
+ def __init__( self ):
+
+ Logger.__init__( self, "mininet" )
+
+ # create console handler
+ ch = StreamHandlerNoNewline()
+ # create formatter
+ formatter = logging.Formatter( LOGMSGFORMAT )
+ # add formatter to ch
+ ch.setFormatter( formatter )
+ # add ch to lg
+ self.addHandler( ch )
+
+ self.setLogLevel()
+
+ def setLogLevel( self, levelname=None ):
+ """Setup loglevel.
+ Convenience function to support lowercase names.
+ levelName: level name from LEVELS"""
+ level = LOGLEVELDEFAULT
+ if levelname != None:
+ if levelname not in LEVELS:
+ raise Exception( 'unknown levelname seen in setLogLevel' )
+ else:
+ level = LEVELS.get( levelname, level )
+
+ self.setLevel( level )
+ self.handlers[ 0 ].setLevel( level )
+
+ # pylint: disable-msg=E0202
+ # "An attribute inherited from mininet.log hide this method"
+ # Not sure why this is occurring - this function definitely gets called.
+
+ # See /usr/lib/python2.5/logging/__init__.py; modified from warning()
+ def output( self, msg, *args, **kwargs ):
+ """Log 'msg % args' with severity 'OUTPUT'.
+
+ To pass exception information, use the keyword argument exc_info
+ with a true value, e.g.
+
+ logger.warning("Houston, we have a %s", "cli output", exc_info=1)
+ """
+ if self.manager.disable >= OUTPUT:
+ return
+ if self.isEnabledFor( OUTPUT ):
+ self._log( OUTPUT, msg, args, kwargs )
+
+ # pylint: enable-msg=E0202
+
+lg = MininetLogger()
+
+# Make things a bit more convenient by adding aliases
+# (info, warn, error, debug) and allowing info( 'this', 'is', 'OK' )
+# In the future we may wish to make things more efficient by only
+# doing the join (and calling the function) unless the logging level
+# is high enough.
+
+def makeListCompatible( fn ):
+ """Return a new function allowing fn( 'a 1 b' ) to be called as
+ newfn( 'a', 1, 'b' )"""
+
+ def newfn( *args ):
+ "Generated function. Closure-ish."
+ if len( args ) == 1:
+ return fn( *args )
+ args = ' '.join( [ str( arg ) for arg in args ] )
+ return fn( args )
+
+ # Fix newfn's name and docstring
+ setattr( newfn, '__name__', fn.__name__ )
+ setattr( newfn, '__doc__', fn.__doc__ )
+ return newfn
+
+info, output, warn, error, debug = (
+ lg.info, lg.output, lg.warn, lg.error, lg.debug ) = [
+ makeListCompatible( f ) for f in
+ lg.info, lg.output, lg.warn, lg.error, lg.debug ]
+
+setLogLevel = lg.setLogLevel
80 net.py
@@ -0,0 +1,80 @@
+
+"""
+Networking is setup as follows:
+* All guests are created with a veth device;
+ the host end is called veth<id>.0
+ the guest end is called eth0
+ IP address is 10.0.0.0+<id>
+* A 'switch' with some hosts connected to it
+ can be seen as a "bridge" between those devices
+* switch <-> switch connection is also possible
+ this makes it possible to create interesting
+ topologies
+"""
+
+class Mininet:
+
+ def __init__(self, HostClass, SwitchClass):
+ self.host = HostClass
+ self.switch = SwitchClass
+
+ self.hosts = []
+ self.switches = []
+ self.controllers = []
+ self.name_to_node = {}
+
+
+ def add_host(self, name, _mac=None, _ip=None):
+ """ Adds a host to the network with given properties """
+ host = self.host(name, mac=_mac, ip=_ip)
+ self.hosts.append(host)
+ self.name_to_node[name] = host
+ return host
+
+ def add_switch(self, name, _mac=None, _ip=None):
+ """
+ It can be a kernel switch, a user switch, or just
+ a simple Linux bridge. Let's go with bridge for
+ now
+ """
+ sw = self.switch(name, mac=_mac, ip=_ip)
+ self.switches.append(sw)
+ self.name_to_node[name] = sw
+ return sw
+
+ def add_controller(self, controller):
+ """ Add an OF controller, ONLY IF we use an OF switch """
+ pass
+
+ def configure_hosts(self):
+ for host in self.hosts:
+ # Add IP address; for now, each host has only one eth0 interface
+ # Add default route
+ host.configure()
+
+ def configure_switches(self):
+ # nothing to be done as of now
+ pass
+
+ def build_topology(self, topo):
+ pass
+
+ def start(self):
+ """ Boot up all the hosts """
+ for h in self.hosts:
+ h.start()
+
+ def stop(self):
+ """ Shutdown all the hosts """
+ for h in self.hosts:
+ h.stop()
+
+ def destroy(self):
+ """ Clean up mininet instances """
+ for h in self.hosts:
+ h.destroy()
+
+ for s in self.switches:
+ s.destroy()
+
+ self.destroy_links()
57 node.py
@@ -0,0 +1,57 @@
+
+"""
+In contrast to mininet, there are no Switches
+or Controller nodes. Just an end host.
+"""
+
+from util import run
+
+def cmd(s):
+ print '# %s' % s
+ #run(s)
+
+class Host:
+ def __init__(self,id):
+ self.id = id
+ # Create scratch area if not there already
+ self.create()
+ self.ifaces = []
+
+ def create(self):
+ cmd("vzctl create %d" % self.id)
+
+ def start(self):
+ cmd("vzctl start %d" % self.id)
+
+ def stop(self):
+ cmd("vzctl stop %d" % self.id)
+
+ def cmd(self, cmd):
+ cmd("vzctl exec %d %s" % (id, cmd))
+
+ def add_iface(self):
+ next_iface_id = len(self.ifaces)
+ self.ifaces.append('eth%d' % next_iface_id)
+ cmd("vzctl set %d --netif_add eth%d" % (self.id, next_iface_id))
+
+ def del_iface(self):
+ pass
+
+ def destroy(self):
+ cmd("vzctl destroy %d" % self.id)
+
+
+class Switch:
+ def __init__(self,id):
+ self.name = 'sw%d' % id
+ self.id = id
+ # This will be a bridge sw<id>
+ self.create()
+ self.ifaces = []
+
+ def create(self):
+ cmd("brctl addbr %s" % self.name)
+
+ def destroy(self):
+ cmd("brctl delbr %s" % self.name)
+
Oops, something went wrong.

0 comments on commit 3726dc4

Please sign in to comment.