#!/usr/bin/env python
import os
import sys

Debug = False

netname = 'H'

# Interface tupel ( first 3 octets of ip, uml_switch_id, broadcast )
       
net= [ {'name':'router1', 'role':'router','interface':[('172.17.16',1,'255.255.240.0'),('10.0.0',3,'255.0.0.0')]},
       {'name':'router2', 'role':'router', 'interface':[('172.17.40',1,'255.255.248.0'),('10.0.0',3,'255.0.0.0')]},
       {'name':'router3', 'role':'router', 'interface':[('172.17.52',1,'255.255.252.0'),('10.0.0',3,'255.0.0.0')]},
       {'name':'router4', 'role':'router', 'interface':[('172.17.64',1,'255.255.255.0'),('10.0.0',3,'255.0.0.0')]},
       {'name':'host1', 'role':'generic', 'interface':[('10.0.0',3,'255.255.255.0')]},
]

def create_switches(name, num):
    "Create 'num' switches in netork 'name')"
    for i in range(1,num+1):
        cmd = 'switch start %s_switch_%d  -hub' % (netname,i)
        execute(cmd)

def destroy_switches(name, num):
    "Destroy 'num' switches in network 'name'"
    for i in range(1,num+1):
        cmd = 'switch stop %s_switch_%d' % (netname,i)
        execute(cmd)

def create_hosts(network):
    """"
    Create hosts, based on list of dicts in network
    These dicts should at least contain:
    'name' : string                         Name for the host
    'role' : 'generic'|'bridge'|'router'    It's role
    'interface' : list of (x,y,z)
        where x = network segment (x.i)
              y = uml-switch to connect to
	      z = broadcast address
    """
    for machine in network:
        # Setup the base for the system
        cmd = 'MYDIR=${TMPDIR:-/tmp}/${USER}; mkdir -p ${MYDIR}; cd ${MYDIR};'
        cmd += ' screen -dmS %s linux umid=%s mem=10m \\\n' % (machine['name'], machine['name'])
        cmd += ' root=/dev/root rootflags=/snb/linux/i386/var/uml-root-fs rootfstype=hostfs \\\n'
        # Create network interfaces for the machine
        for interf in range(0,len(machine['interface'])):
            net, swi, broad  = machine['interface'][interf]
            cmd += ' eth%d=daemon,,unix,${HOME}/.uml/%s_switch_%d.sock \\\n' % (interf, netname, swi)
            cmd += ' ip_eth%d=%s.%d \\\n' % (interf, net, (network.index(machine)+1))
            cmd += ' mask_eth%d=%s \\\n' % ( interf, broad)
            cmd += ' bc_eth%d=%s.255 \\\n' % (interf, net)
        # If a gateway is declared, add it to cmd (there can be only one)
        if machine.has_key('gateway'):
            cmd += ' gateway=10.0.%d.%d \\\n' % (machine['interface'][0], machine['gateway'])
        # Last but not least, add a role keyword to the params
        cmd += ' role=%s' % machine['role']
        cmd += ' home_hostfs=${HOME}/uml-files'
        execute(cmd)

def destroy_hosts(network):
    "Destroy all the hosts in the network"
    for machine in network:
        cmd = 'uml_mconsole %s halt' % machine['name']
        execute(cmd)

def max_switches(network):
    "Find out how many switches there are in 'network'"
    num = 0
    for machine in network:
        for interf in machine['interface']:
            if interf[1] > num:
                num = interf[1]
    return num

def execute(cmd):
    if Debug:
        print cmd
    os.system(cmd)

if __name__ == "__main__":
    if len(sys.argv)==1:
        print "Please supply either 'start', 'stop' or 'test'"
    elif sys.argv[1]=='start':
        os.system('MYDIR=${TMPDIR:-/tmp}/${USER}; mkdir -p ${MYDIR}')
        create_switches(netname, max_switches(net))
        create_hosts(net)
    elif sys.argv[1]=='stop':
        destroy_switches(netname, max_switches(net))
        destroy_hosts(net)
        os.system('MYDIR=${TMPDIR:-/tmp}/${USER}; rm -fr ${MYDIR}')
    elif sys.argv[1]=='test':
        if len(sys.argv) < 2:
            print "Please supply either 'start' or 'stop' after 'test'"
        Debug = True
        if sys.argv[2]=='start':
            create_switches(netname, max_switches(net))
            print '\n'
            create_hosts(net)
        elif sys.argv[2]=='stop':
            destroy_switches(netname, max_switches(net))
            print '\n'
            destroy_hosts(net)
        else:
            print "Please supply either 'start' or 'stop' after 'test'"
    else:
        print "Please supply either 'start', 'stop' or 'test'"
