Журнал лабораторных работ

Содержание

Журнал

Четверг (02/21/08)

22:08:05
$l3cd /users/demo-user/xentaur

22:08:15
$l3pwd
/users/demo-user/xentaur
22:08:16
$pkill -1 l3-agent

22:08:20
$ls
freebsd  images-library  procurve    scripts  xentaur         xentaur_old
images   lost+found      production  xen9     xentaur-images
22:10:47
$cd images

22:10:51
$ls
freebsd-62-hvm.img  snrs                   xenomips-config0.img   xenomips-config3.img  xenomips-config8.img
ldap.img            windows-vista-hvm.img  xenomips-config10.img  xenomips-config4.img  xenomips-config9.img
openvpn-experiment  windowsxp-hvm.img      xenomips-config11.img  xenomips-config5.img  xenomips-configXXX.img
procurve            xenomips1              xenomips-config1.img   xenomips-config6.img  xenomips-ios1.img
samba.img           xenomips1.img          xenomips-config2.img   xenomips-config7.img
22:10:51
$cd openvpn-experiment/

22:10:54
$ls
debian1.img  debian3.img  debian5.img  ids2007dec.cmapx  ids2007dec.jpg  ids2007dec.svg
debian2.img  debian4.img  debian6.img  ids2007dec.dot    ids2007dec.png
22:10:55
$vi /xen/xentaur/xentaur.py
22:11:55
$vi /xen/xentaur/xentaur.py
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ /xen/xentaur/xentaur.py	2008-02-21 22:12:26.000000000 +0200
@@ -0,0 +1,773 @@
+#!/usr/bin/python
+# vim: set fileencoding=utf-8 :
+
+import sys,os,time
+
+xentaur_path=os.environ['HOME']+"/xentaur"
+
+sys.path.append('/etc/xen')
+sys.path.append(xentaur_path)
+
+#network='snrs_ipsec_rsa_1'
+node_object={}
+link_object={}
+bridge_object={}
+
+network='openvpn-bridge'
+domain='debian1'
+
+#network='snrs'
+#domain='dyn1'
+from xendomain import *
+
+bridges_turned_down=[]
+
+from IPython.Shell import IPShellEmbed
+
+
+screenrc=os.environ['HOME']+"/.screenrc_xentaur"
+path_shapes='/xen/xentaur/shapes'
+
+def run(program, *args):
+    pid = os.fork()
+    if not pid:
+        os.execvp(program, (program,) +  args)
+    return os.wait()[0]
+
+def run_command(line):
+    #cmds=line.split()
+    #run(cmds[0],*cmds[1:])
+    run("/bin/sh", "-c", line)
+
+def run_command_return_stdout(line):
+    p = os.popen(line)
+    output = p.read()
+    p.close()
+    return output
+
+################################################################################
+#Xentaur command-line commands
+
+## Start
+
+def start_bridges():
+    unbound_bridges=set(bridges)-set(real_bridges)
+    script=""
+    script="\n".join(map(lambda x: "sudo brctl show | awk '{print $1}' | grep -qx "+x+" || sudo brctl addbr "+x, unbound_bridges))
+    script+="\n"+"\n".join(map(lambda x: "sudo brctl stp "+x+" off", unbound_bridges))
+    script+="\n"+"\n".join(map(lambda x: "sudo ip link set "+x+" up", unbound_bridges))
+
+    print """#!/bin/sh
+# create unbound bridges
+%s
+""" % (script)
+
+def start_domain(domain):
+    print "sudo xm create "+xentaur_path+"/xendomain.py "+" domain="+domain+" network="+network+" && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep "+domain+" | awk '{print $2}') -c 10 && sleep 1"
+
+def start_domains(doms=domains):
+    for domain in doms:
+        if not domain in real_nodes:
+            start_domain(domain)
+
+def start_all():
+    graph()
+    screen()
+    start_bridges()
+    start_domains()
+
+## Stop
+
+def stop_domain(domain,wait=0):
+    if wait:
+        print "sudo xm shutdown -w "+domain
+    else:
+        print "sudo xm shutdown "+domain
+
+def stop_domains(doms=domains, wait=0):
+    for domain in doms:
+        if not domain in real_nodes:
+            stop_domain(domain,wait)
+
+def stop_bridges():
+    ###FIXME###
+    return 0
+
+def stop_all(wait=0):
+    stop_domains(domains, wait)
+    stop_bridges()
+
+def restart_all():
+    stop_all(1)
+    start_all()
+
+####################################################
+
+def create_objects():
+    create_node_objects()
+    create_bridge_objects()
+    create_link_objects()
+
+def create_node_objects():
+    for dom in domains:
+        node_object[dom]=Node(dom)
+
+def create_bridge_objects():
+    for bridge in bridges:
+        bridge_object[bridge]=Bridge(bridge)
+
+def create_link_objects():
+
+    for node, bridges_raw in vbridges_table.iteritems():
+        interface=0
+        j=0
+        for this_bridge in bridges_raw:
+            int_label=""
+            if this_bridge.find(':') != -1:
+                res = this_bridge.split(':')
+                this_bridge= res[0]
+                bridges_raw[j] = this_bridge
+                int_label  = res[1]
+            if not [ node, bridges_raw.index(this_bridge), this_bridge ] in temporary_links:
+                name="%s %s %s" % (node,interface,this_bridge)
+                link_object[name]=Link(name,node,interface,this_bridge,int_label)
+                interface+=1
+        vbridges_table[node]=bridges_raw
+
+    for node, bridges_raw in bridge_bridge_table.iteritems():
+        interface=0
+        j=0
+        for this_bridge in bridges_raw:
+            int_label=""
+            if this_bridge.find(':') != -1:
+                res = this_bridge.split(':')
+                this_bridge= res[2]
+                bridges_raw[j] = this_bridge
+                int_label  = res[1]
+            if not [ node, bridges_raw.index(this_bridge), this_bridge ] in temporary_links:
+                name="%s %s %s" % (node,interface,this_bridge)
+                link_object[name]=Link(name,node,interface,this_bridge,int_label)
+                interface+=1
+        bridge_bridge_table[node]=bridges_raw
+
+    for node,interface,bridge in temporary_links:
+        name="%s %s %s" % (node,interface,bridge)
+        link_object[name]=Link(name,node,interface,this_bridge)
+
+    for node,interface,bridge in broken_links:
+        name="%s %s %s" % (node,interface,bridge)
+        link_object[name]=Link(name,node,interface,this_bridge)
+
+
+####################################################
+
+def screen():
+    wait_seconds=1
+    screens=[]
+    for domain in domains:
+        screens.append("screen -t %s %s sh -c 'while true; do %s ; echo Retrying in %s secods...; sleep %s ; clear; done'" %
+                                 (domain,domains.index(domain)+1,node_object[domain].console_string(),wait_seconds,wait_seconds))
+    screenlist="\n".join(screens)
+
+    hardstatus='hardstatus string "%{rk}Xentaur%{bk}@%H %{gk}%c %{yk}%d.%m %{wk}%?%-Lw%?%{bw}%n*%f%t%?(%u)%?%{wk}%?%+Lw%?"'
+   
+    f=open(screenrc, "w");
+    f.write("""
+hardstatus on
+hardstatus alwayslastline
+%s
+
+screen -t console 0 sh -c 'while true; do cd %s; ./xentaur.py shell ; echo Retrying in %s secods...; sleep %s ; clear; done'
+#screen -t xentaur - sh -c 'while true; do bash ; echo Retrying in %s secods...; sleep %s ; clear; done'
+%s
+""" % (hardstatus,xentaur_path,wait_seconds,wait_seconds,wait_seconds,wait_seconds,screenlist))
+    f.close()
+    print "# GNU Screen config file is written to: %s" % screenrc
+
+def graph():
+    nodelist=""
+    bridgelist=""
+    linklist=""
+    physicallist=""
+    networklist=""
+
+    nodelist=";\n    ".join(map(lambda node: node_object[node].graphviz_string(),nodes))
+    if nodelist: nodelist += ";"
+    bridgelist=";\n    ".join(map(lambda bridge: bridge_object[bridge].graphviz_string(),bridges))
+    if bridgelist: bridgelist += ";"
+    linklist=";\n    ".join(map(lambda link: link_object[link].graphviz_string(),link_object.keys()))
+    if linklist: linklist += ";"
+
+    f = open(network+".dot", "w");
+    f.write ("""
+graph G {
+    edge [len=1.25];
+    splines=true;
+// nodes
+    %s
+
+// bridges
+    %s
+
+// physical
+    node [shape=rectangle,color=blue];
+    %s
+
+// networks (not bridges, not physical)
+    node [shape=rectangle,color=green];
+    %s
+
+// links (between nodes and bridges)
+    %s
+
+};
+""" % (nodelist, bridgelist, physicallist, networklist, linklist))
+    f.close()
+    run_command("neato -Tpng -o %s.png %s.dot "%(network,network))
+    run_command("neato -Tjpg -o %s.jpg %s.dot "%(network,network))
+    run_command("neato -Tsvg -o %s.svg %s.dot "%(network,network))
+    run_command("neato -Tcmapx -o %s.cmapx -NURL=http://google.com %s.dot "%(network,network))
+    print "# Network map is written to files: %s.{png,svg,jpg,dot}" % network
+
+def autoredraw():
+    graph()
+
+def shell():
+    autoredraw()
+    ipshell = IPShellEmbed()
+    ipshell()
+
+def version():
+    print """
+Xentaur 0.1-PRE
+
+             ,--,
+       _ ___/ /\\|
+   ,;`( )__, )  ~
+  // .//   '--;
+  ' / \     |
+
+    """
+#    print "Xentaur 0.1-PRE"
+#    print "(Godzilla-mutant)  _"
+#    print "                 / * \\"
+#    print "                /   .-"
+#    print "               /   |"
+#    print "              | \\ \\\\ \\"
+#    print "     _ -------|  \\ \\\\ \\"
+#    print " / /              \\_\\ -"
+#    print "/ |\\           |   |"
+#    print "| |  \\ .-----. | \\ |"
+#    print "  |  /        \\ \\ \\ \\"
+#    print "  \\/|.\\        \\ \\ \\ \\"
+#    print "   \\| - .       \\_\\ \\_\\"
+#    print "-----------------------------------------------"
+
+
+def info():
+    version()
+
+    print "Network name: ", network
+    print "-----------------------------------------------"
+    print
+    print "Nodes: ", len(domains)
+    print "  * virtual nodes: ", len(domains)-len(real_nodes)
+    print "  * real nodes:", len(real_nodes)
+    print 
+    print "Bridges:", len(bridges)
+    print "  * virtual bridges:", len(bridges)-len(real_bridges)-len(cross_bridges)
+    print "  * real switches:", len(real_bridges)
+    print "  * direct links:", len(cross_bridges)
+
+def show_usage():
+    print """Usage:
+    xentaur <command> [<argument>]
+
+Commands:
+    start-all       --  start bridges and domains
+    start-domains   --  start domains only
+    start-bridges   --  start bridges only
+    stop-all        --  stop bridges and domains
+    stop-domains    --  stop domains only
+    stop-bridges    --  stop bridges only (domains have to be stopped already)
+    restart-all     --  restart bridges and domains
+
+    start <domain>  --  start the <domain>
+    stop <domain>   --  stop the <domain>
+
+    graph           --  generate network scheme (result is in <network>.{png,jpg,svg})
+    screen          --  generate GNU Screen config file (~/.screenrc_xentaur)
+    shell           --  run Xentaur shell
+
+"""
+
+def save():
+    print "network =",          xen_config_name
+    print "domains =",          domains
+    print "domain_types =",     domain_types
+    print "bridges =",          bridges
+    print "vbridges_table =",   vbridges_table
+    print "hidden_bridges =",   hidden_bridges
+    print "broken_links =",     broken_links
+    print "temporary_links =",  temporary_links
+    print "bridges_turned_down =", bridges_turned_down
+
+#-----------------------------------------------------------------------
+# CLASSES
+
+class Bridge:
+    def __init__ (self,name):
+        self.name=name
+    def up(self):
+        bridge_up(self.name)
+    def down(self):
+        bridge_down(self.name)
+    def show(self):
+        show_bridge(self.name)
+    def dump_start(self,filter=""):
+        dump_start(self.name,filter)
+
+    def is_hidden(self):
+        return self.name in hidden_bridges
+    def is_real(self):
+        return self.name in real_bridges
+    def is_turned_down(self):
+        return self.name in bridges_turned_down
+    def is_cross(self):
+        return self.name in cross_bridges
+
+    def graphviz_string(self):
+        if self.is_hidden():
+            return ""
+        elif self.is_cross():
+            return "%s [shape=circle,height=0.03,color=black,fillcolor=black,style=filled,label=\"\"]" % (self.name)
+        elif self.is_real():
+            return "%s [color=white,shape=none,shapefile=\"%s/all/real_switch.png\"]" % (self.name, path_shapes)
+        elif self.is_turned_down():
+            return "%s [color=white,shape=none,shapefile=\"%s/all/switch_turned_down.png\"]" % (self.name, path_shapes)
+        else:
+            return "%s [color=white,shape=none,shapefile=\"%s/all/switch.png\"]" % (self.name, path_shapes)
+
+
+class Node:
+    def __init__ (self,name):
+        self.name=name
+        self.type=domain_types[domains.index(name)]
+    def start(self):
+        return ""
+    def stop(self):
+        return ""
+    def start_commandline(self):
+        return ""
+    def get_domain_id(self):
+        return get_domain_id(self.name)
+    def graphviz_string(self):
+        return self.name+" [color=white,shape=plaintext,label=\"  "+self.name+"\",shapefile=\""+path_shapes+"/all/"+\
+        domain_types[domains.index(self.name)]+".png\",fontcolor=black,fontsize=16,target=\"http://google.com\"]"
+    def console_string(self):
+        if self.type in [ 'quagga', 'xenomips', 'freebsd', 'linux' ]:
+            return "sudo xm console "+self.name
+        elif self.name in real_bridges or self.name in real_nodes:
+            return "echo Press enter to connect; read line; "+connection_table[self.name]
+
+
+class Link:
+    def __init__ (self,name,node,interface,bridge,label=""):
+        self.name=name
+        self.node=node
+        self.interface=interface
+        self.bridge=bridge
+        self.label=label
+
+    def is_temporary(self):
+        return [self.node,self.interface,self.bridge] in temporary_links
+
+    def is_broken(self):
+        return ([self.node,self.interface,self.bridge] in broken_links)
+
+    def graphviz_string(self):
+        if self.is_temporary():
+            return self.node+" -- "+self.bridge+" [taillabel=\"fa"+str(self.interface)+"/0\",color=blue,len=10,w=5,weight=5]"
+        if self.is_broken():
+            return self.node+" -- "+self.bridge+" [taillabel=\"fa"+str(self.interface)+"/0\",style=dashed]"
+
+        ip="\\n.%s.%s" % (bridges.index(self.bridge)+1, domains.index(self.node)+1) 
+        if domain_types[domains.index(self.node)] == 'xenomips':
+            int_name="fa"+str(self.interface)+"/0"
+        else:
+            int_name="eth"+str(self.interface)
+        if self.label != "":
+            int_name = self.label
+        return self.node+" -- "+self.bridge+" [taillabel=\""+int_name+ip+"\",fontsize=14,fontname=fixed]"
+
+
+#-----------------------------------------------------------------------
+# DOMAINS
+
+def get_domain_id(domain):
+    return run_command_return_stdout("sudo xm list | awk '{if ($1 == \"'%s'\") print $2}'" % domain).rstrip("\n")
+
+
+#-----------------------------------------------------------------------
+# BRIDGES and IFACES
+
+def bridge_down(bridge):
+    """
+    Turn the bridge <bridge> down
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    if bridge in bridges_turned_down:
+        print "Bridge %s is turned down already" % (bridge)
+    else:
+        bridges_turned_down.append(bridge)
+        run_command("sudo ip link set %s down" % bridge)
+        autoredraw()
+
+def bridge_up(bridge):
+    """
+    Turn the bridge <bridge> up
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    if not (bridge in bridges_turned_down):
+        print "Bridge %s is turned up already" % (bridge)
+    else:
+        bridges_turned_down.remove(bridge)
+        run_command("sudo ip link set %s up" % bridge)
+        autoredraw()
+
+def show_bridge(bridge):
+    """
+    Show the state of the bridge <bridge>
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    run_command("sudo ip link show %s" % bridge)
+
+
+def int_disconnect(domain, int_number):
+    """
+    Disconnect the interface with the number <int_number>
+    of the domain <domain> from the bridge to which
+    it is connected
+    """
+    dom_id=get_domain_id(domain)
+    bridge=vbridges_table[domain][int_number]
+    if not bridge:
+        print "Interface %s of the %s domain is not connected" % (int_number, domain)
+        return 1
+    run_command("sudo brctl delif %s vif%s.%s" % (bridge, dom_id, int_number))
+    vbridges_table[domain][int_number]=''
+    if [ domain, int_number, bridge ] in temporary_links:
+        temporary_links.remove([ domain, int_number, bridge ])
+    else:
+        broken_links.append([ domain, int_number, bridge ])
+    autoredraw()
+
+def int_connect(domain, int_number, bridge):
+    """
+    Connect the interface with the number <int_number>
+    of the domain <domain> to the bridge <bridge>
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+
+    dom_id=get_domain_id(domain)
+    if vbridges_table[domain][int_number]:
+        print "Interface %s of the %s domain is connected already to the %s bridge" % (int_number, domain, vbridges_table[domain][int_number])
+        return 1
+    run_command("sudo brctl addif %s vif%s.%s" % (bridge, dom_id, int_number))
+    vbridges_table[domain][int_number]=bridge
+    if [ domain, int_number, bridge ] in broken_links:
+        broken_links.remove([ domain, int_number, bridge ])
+    else:
+        temporary_links.append([ domain, int_number, bridge ])
+    autoredraw()
+
+def int_reconnect(domain, int_number, bridge):
+    """
+    Reconnect the interface with the number <int_number>
+    of the domain <domain> from the bridge to which
+    it is connected to the bridge <bridge>
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    
+    int_disconnect(domain, int_number)
+    int_connect(domain, int_number, bridge)
+
+def show_int(domain, int_number):
+    """
+    Show information about the interface <int_nuber>
+    of the domain <domain>
+    """
+    return vbridges_table[domain][int_number]
+
+
+def dump_start(bridge, filter=""):
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    try:
+        print "Writing dump... (press Ctrl-C to stop)"
+        run_command("sudo tcpdump -w xentaur.dump -i %s %s > /dev/null 2>&1 " % (bridge,filter))
+    except:
+        print "Done.\n Dump is written to xentaur.dump"
+    return 0
+
+def dump_stop():
+    return 0
+
+
+#-----------------------------------------------------------------------
+# CONFIGURATION TEMPLATES
+
+
+def configure_ip_addresses(doms=domains):
+
+    cisco_set_ip_on_int="""
+\n\n\n
+int fa%s/0
+no ip address
+ip address %s 255.255.255.0
+no shutdown
+exit
+"""
+
+    quagga_set_ip_on_int="""
+int eth%s
+no ip address
+ip address %s/24
+no shutdown
+exit
+"""
+
+    for dom in doms:
+        i=domains.index(dom)+1
+        if domain_types[domains.index(dom)] == 'quagga':
+            command = quagga_set_ip_on_int
+            write_to(i,"\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+        else:
+            command = cisco_set_ip_on_int
+            write_to(i,"\nena\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+    return 0
+
+def configure_no_ip_addresses(doms=domains):
+
+    cisco_set_ip_on_int="""
+\n\n\n
+int fa%s/0
+no ip address %s 255.255.255.0
+exit
+"""
+
+    quagga_set_ip_on_int="""
+int eth%s
+no ip address %s/24
+exit
+"""
+
+    for dom in doms:
+        i=domains.index(dom)+1
+        if domain_types[domains.index(dom)] == 'quagga':
+            command = quagga_set_ip_on_int
+            write_to(i,"\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+        else:
+            command = cisco_set_ip_on_int
+            write_to(i,"\nena\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+    return 0
+
+def configure_ospf(doms=domains):
+    for dom in doms:
+        if domain_types[domains.index(dom)] == 'quagga':
+            write_to(dom,"\n\nconf t\nrouter ospf\nnetwork 192.168.0.0/16 area 0\nend\n")
+        else:
+            write_to(dom,"\n\nena\nconf t\nrouter ospf 1\nnetwork 192.168.0.0 0.0.255.255 area 0\nend\n")
+    return 0
+
+def configure_hostname(doms=domains):
+    for dom in doms:
+        if domain_types[domains.index(dom)] == 'quagga':
+            write_to(dom,"\n\nconf t\nhostname %s\nend\n" % dom)
+        else:
+            write_to(dom,"\n\nena\nconf t\nhostname %s\nend\n" % dom)
+    return 0
+
+def configure_logging_synchronous(doms=domains):
+    for dom in domains:
+        if domain_types[domains.index(dom)] == 'quagga':
+            0
+        else:
+            write_to(dom,"\n\nena\nconf t\nline console 0\nlogging synchronous\nend\n")
+    return 0
+
+def configure_exec_timeout_0(doms=domains):
+    for dom in domains:
+        if domain_types[domains.index(dom)] == 'quagga':
+            0
+        else:
+            write_to(dom,"\n\nena\nconf t\nline console 0\nexec-timeout 0\nend\n")
+    return 0
+
+def configure_no_cdp_log_mismatch_duplex(doms=domains):
+    for dom in filter_by_type(domains,'xenomips'):
+        write_to(dom,"\n\nena\nconf t\nno cdp log mismatch duplex\nend\n")
+
+def configure_save(doms=domains):
+    write_to(doms,"\nwr\n")
+
+def configure_root(doms=domains):
+    write_to(doms,"root\n")
+
+#-----------------------------------------------------------------------
+
+
+def add_domain(name,type):
+    domains.append(name)
+    domain_types.append(type)
+
+def brake_link(domain,bridge):
+    broken_links.append([domain,bridge])
+
+wt_timeout=0.5
+def write_to(screen,string,return_to_screen=""):
+    """
+    write_to(screen,string):
+
+        Type *string* to the specified screen(s).
+        Screen may be specified with the number *screen*,
+        with array of numbers, 
+        with array of names.
+
+    """
+    screen_numbers=[]           # number of the screens to write to
+    if type(screen) == list:
+        screen_numbers=map(lambda x: domains.index(x)+1, screen)
+    elif type(screen) == int:
+        screen_numbers=[screen]
+    else:
+        screen_numbers=[domains.index(screen)+1]
+    
+    for screen_number in screen_numbers:
+        run_command("screen -X select "+str(screen_number))
+        time.sleep(wt_timeout)
+        for line in string.splitlines():
+            f=open('/tmp/xentaurbuf', 'w')
+            f.write(line+"\n")
+            f.close()
+            run_command("screen -X readreg p /tmp/xentaurbuf")
+            time.sleep(wt_timeout)
+            run_command("nohup screen -X paste p >& /dev/null")
+            time.sleep(wt_timeout)
+    
+        if return_to_screen != "":
+            run_command("screen -X select %s" % (return_to_screen))
+            time.sleep(wt_timeout)
+
+def filter_by_type(doms,type):
+    """
+    filter_by_type(doms,type)
+
+        Return only domains of *doms* that have specified *type*
+    """
+    return filter(lambda x: domain_types[domains.index(x)]==type,domains)
+
+#-----------------------------------------------------------------------
+
+cisco_fa01_up="""
+ena
+conf t
+int fa0/0
+duplex half
+no shutdown
+exit
+int fa1/0
+duplex half
+no shutdown
+exit
+exit
+exit
+"""
+
+cisco_set_ip_on_int="""
+interface fa%s/0
+no ip address
+ip address %s 255.255.255.0
+exit
+"""
+
+nodes=domains
+
+create_objects()
+
+
+if len(sys.argv) == 2:
+    if sys.argv[1] == 'start-all':
+        start_all()
+    elif sys.argv[1] == 'start-domains':
+        start_domains()
+    elif sys.argv[1] == 'start-bridges':
+        start_bridges()
+    elif sys.argv[1] == 'stop-all':
+        stop_all()
+    elif sys.argv[1] == 'stop-domains':
+        stop_domains()
+    elif sys.argv[1] == 'stop-bridges':
+        stop_bridges()
+    elif sys.argv[1] == 'restart-all':
+        restart_all()
+    elif sys.argv[1] == 'screen':
+        screen()
+    elif sys.argv[1] == 'graph':
+        graph()
+    elif sys.argv[1] == 'shell':
+        shell()
+    elif sys.argv[1] == 'info':
+        info()
+    else:
+        show_usage()
+        sys.exit(1)
+elif len(sys.argv) == 3:
+    if sys.argv[1] == 'start':
+        start_domain(sys.argv[2])
+    elif sys.argv[1] == 'stop':
+        stop_domain(sys.argv[2])
+    elif sys.argv[1] == 'restart':
+        stop_domain(sys.argv[2])
+        start_domain(sys.argv[2])
+    else:
+        show_usage()
+        sys.exit(1)
+else:
+    show_usage()
+    sys.exit(1)
+
+sys.exit(0)
+
+
22:12:26
$cp /xen/xentaur/ids2007dec.py
ids2007dec.py   ids2007dec.pyc
22:12:26
$cp /xen/xentaur/ids2007dec.py openvpn-bridge.py

22:12:42
$vi openvpn-bridge.py
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ openvpn-bridge.py	2008-02-21 22:15:01.000000000 +0200
@@ -0,0 +1,40 @@
+import os
+domain=os.environ['xendomain']
+
+network='ids2007dec'
+
+domains =       [  
+                   'debian1', 
+                   'debian2', 
+                   'debian3', 
+                   'debian4', 
+                   'debian5', 
+                ]
+domain_types =  [  
+                    'linux', 'linux', 'linux', 
+                    'linux', 'linux',
+                ]
+bridges =       [  
+                    'br1', 
+                    'br2', 
+                    'br3',
+                    'br4', 
+                ]
+
+vbridges_table ={
+        'debian1'      : [ 'br1' ],
+        'debian2'      : [ 'br1', 'br2' ],
+        'debian3'      : [ 'br2', 'br3' ],
+        'debian4'      : [ 'br3', 'br4' ],
+        'debian5'      : [ 'br4' ],
+}
+
+
+#xenomips_dir='/xen/images/snrs/xentaur/'
+#platform="7200"                 # 7200|3600|2691|3725|3745
+#npe_type='npe-400'              # (7200 only) "npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300" and "npe-400"
+#ios_name='C7200-AD.BIN'
+
+#if domain=='dyn1':
+#    ios_name='pix635-125.bin'
+
22:15:01
$cat openvpn-bridge.py
import os
domain=os.environ['xendomain']
network='ids2007dec'
domains =       [
                   'debian1',
                   'debian2',
                   'debian3',
                   'debian4',
                   'debian5',
                ]
...
        'debian3'      : [ 'br2', 'br3' ],
        'debian4'      : [ 'br3', 'br4' ],
        'debian5'      : [ 'br4' ],
}
#xenomips_dir='/xen/images/snrs/xentaur/'
#platform="7200"                 # 7200|3600|2691|3725|3745
#npe_type='npe-400'              # (7200 only) "npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300" and "npe-400"
#ios_name='C7200-AD.BIN'
#if domain=='dyn1':
#    ios_name='pix635-125.bin'
22:15:03
$/xen/xentaur/xentaur.py
Traceback (most recent call last):
  File "/xen/xentaur/xentaur.py", line 21, in ?
    from xendomain import *
  File "/xen/xentaur/xendomain.py", line 47, in ?
    exec 'from %s import *' % (network)
  File "<string>", line 1
    from openvpn-bridge import *
                ^
SyntaxError: invalid syntax
22:15:18
$vi /xen/xentaur/xentaur.py
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ /xen/xentaur/xentaur.py	2008-02-21 22:15:31.000000000 +0200
@@ -0,0 +1,774 @@
+#!/usr/bin/python
+# vim: set fileencoding=utf-8 :
+
+import sys,os,time
+
+xentaur_path=os.environ['HOME']+"/xentaur"
+
+sys.path.append('/etc/xen')
+sys.path.append(xentaur_path)
+sys.path.append('.')
+
+#network='snrs_ipsec_rsa_1'
+node_object={}
+link_object={}
+bridge_object={}
+
+network='openvpn-bridge'
+domain='debian1'
+
+#network='snrs'
+#domain='dyn1'
+from xendomain import *
+
+bridges_turned_down=[]
+
+from IPython.Shell import IPShellEmbed
+
+
+screenrc=os.environ['HOME']+"/.screenrc_xentaur"
+path_shapes='/xen/xentaur/shapes'
+
+def run(program, *args):
+    pid = os.fork()
+    if not pid:
+        os.execvp(program, (program,) +  args)
+    return os.wait()[0]
+
+def run_command(line):
+    #cmds=line.split()
+    #run(cmds[0],*cmds[1:])
+    run("/bin/sh", "-c", line)
+
+def run_command_return_stdout(line):
+    p = os.popen(line)
+    output = p.read()
+    p.close()
+    return output
+
+################################################################################
+#Xentaur command-line commands
+
+## Start
+
+def start_bridges():
+    unbound_bridges=set(bridges)-set(real_bridges)
+    script=""
+    script="\n".join(map(lambda x: "sudo brctl show | awk '{print $1}' | grep -qx "+x+" || sudo brctl addbr "+x, unbound_bridges))
+    script+="\n"+"\n".join(map(lambda x: "sudo brctl stp "+x+" off", unbound_bridges))
+    script+="\n"+"\n".join(map(lambda x: "sudo ip link set "+x+" up", unbound_bridges))
+
+    print """#!/bin/sh
+# create unbound bridges
+%s
+""" % (script)
+
+def start_domain(domain):
+    print "sudo xm create "+xentaur_path+"/xendomain.py "+" domain="+domain+" network="+network+" && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep "+domain+" | awk '{print $2}') -c 10 && sleep 1"
+
+def start_domains(doms=domains):
+    for domain in doms:
+        if not domain in real_nodes:
+            start_domain(domain)
+
+def start_all():
+    graph()
+    screen()
+    start_bridges()
+    start_domains()
+
+## Stop
+
+def stop_domain(domain,wait=0):
+    if wait:
+        print "sudo xm shutdown -w "+domain
+    else:
+        print "sudo xm shutdown "+domain
+
+def stop_domains(doms=domains, wait=0):
+    for domain in doms:
+        if not domain in real_nodes:
+            stop_domain(domain,wait)
+
+def stop_bridges():
+    ###FIXME###
+    return 0
+
+def stop_all(wait=0):
+    stop_domains(domains, wait)
+    stop_bridges()
+
+def restart_all():
+    stop_all(1)
+    start_all()
+
+####################################################
+
+def create_objects():
+    create_node_objects()
+    create_bridge_objects()
+    create_link_objects()
+
+def create_node_objects():
+    for dom in domains:
+        node_object[dom]=Node(dom)
+
+def create_bridge_objects():
+    for bridge in bridges:
+        bridge_object[bridge]=Bridge(bridge)
+
+def create_link_objects():
+
+    for node, bridges_raw in vbridges_table.iteritems():
+        interface=0
+        j=0
+        for this_bridge in bridges_raw:
+            int_label=""
+            if this_bridge.find(':') != -1:
+                res = this_bridge.split(':')
+                this_bridge= res[0]
+                bridges_raw[j] = this_bridge
+                int_label  = res[1]
+            if not [ node, bridges_raw.index(this_bridge), this_bridge ] in temporary_links:
+                name="%s %s %s" % (node,interface,this_bridge)
+                link_object[name]=Link(name,node,interface,this_bridge,int_label)
+                interface+=1
+        vbridges_table[node]=bridges_raw
+
+    for node, bridges_raw in bridge_bridge_table.iteritems():
+        interface=0
+        j=0
+        for this_bridge in bridges_raw:
+            int_label=""
+            if this_bridge.find(':') != -1:
+                res = this_bridge.split(':')
+                this_bridge= res[2]
+                bridges_raw[j] = this_bridge
+                int_label  = res[1]
+            if not [ node, bridges_raw.index(this_bridge), this_bridge ] in temporary_links:
+                name="%s %s %s" % (node,interface,this_bridge)
+                link_object[name]=Link(name,node,interface,this_bridge,int_label)
+                interface+=1
+        bridge_bridge_table[node]=bridges_raw
+
+    for node,interface,bridge in temporary_links:
+        name="%s %s %s" % (node,interface,bridge)
+        link_object[name]=Link(name,node,interface,this_bridge)
+
+    for node,interface,bridge in broken_links:
+        name="%s %s %s" % (node,interface,bridge)
+        link_object[name]=Link(name,node,interface,this_bridge)
+
+
+####################################################
+
+def screen():
+    wait_seconds=1
+    screens=[]
+    for domain in domains:
+        screens.append("screen -t %s %s sh -c 'while true; do %s ; echo Retrying in %s secods...; sleep %s ; clear; done'" %
+                                 (domain,domains.index(domain)+1,node_object[domain].console_string(),wait_seconds,wait_seconds))
+    screenlist="\n".join(screens)
+
+    hardstatus='hardstatus string "%{rk}Xentaur%{bk}@%H %{gk}%c %{yk}%d.%m %{wk}%?%-Lw%?%{bw}%n*%f%t%?(%u)%?%{wk}%?%+Lw%?"'
+   
+    f=open(screenrc, "w");
+    f.write("""
+hardstatus on
+hardstatus alwayslastline
+%s
+
+screen -t console 0 sh -c 'while true; do cd %s; ./xentaur.py shell ; echo Retrying in %s secods...; sleep %s ; clear; done'
+#screen -t xentaur - sh -c 'while true; do bash ; echo Retrying in %s secods...; sleep %s ; clear; done'
+%s
+""" % (hardstatus,xentaur_path,wait_seconds,wait_seconds,wait_seconds,wait_seconds,screenlist))
+    f.close()
+    print "# GNU Screen config file is written to: %s" % screenrc
+
+def graph():
+    nodelist=""
+    bridgelist=""
+    linklist=""
+    physicallist=""
+    networklist=""
+
+    nodelist=";\n    ".join(map(lambda node: node_object[node].graphviz_string(),nodes))
+    if nodelist: nodelist += ";"
+    bridgelist=";\n    ".join(map(lambda bridge: bridge_object[bridge].graphviz_string(),bridges))
+    if bridgelist: bridgelist += ";"
+    linklist=";\n    ".join(map(lambda link: link_object[link].graphviz_string(),link_object.keys()))
+    if linklist: linklist += ";"
+
+    f = open(network+".dot", "w");
+    f.write ("""
+graph G {
+    edge [len=1.25];
+    splines=true;
+// nodes
+    %s
+
+// bridges
+    %s
+
+// physical
+    node [shape=rectangle,color=blue];
+    %s
+
+// networks (not bridges, not physical)
+    node [shape=rectangle,color=green];
+    %s
+
+// links (between nodes and bridges)
+    %s
+
+};
+""" % (nodelist, bridgelist, physicallist, networklist, linklist))
+    f.close()
+    run_command("neato -Tpng -o %s.png %s.dot "%(network,network))
+    run_command("neato -Tjpg -o %s.jpg %s.dot "%(network,network))
+    run_command("neato -Tsvg -o %s.svg %s.dot "%(network,network))
+    run_command("neato -Tcmapx -o %s.cmapx -NURL=http://google.com %s.dot "%(network,network))
+    print "# Network map is written to files: %s.{png,svg,jpg,dot}" % network
+
+def autoredraw():
+    graph()
+
+def shell():
+    autoredraw()
+    ipshell = IPShellEmbed()
+    ipshell()
+
+def version():
+    print """
+Xentaur 0.1-PRE
+
+             ,--,
+       _ ___/ /\\|
+   ,;`( )__, )  ~
+  // .//   '--;
+  ' / \     |
+
+    """
+#    print "Xentaur 0.1-PRE"
+#    print "(Godzilla-mutant)  _"
+#    print "                 / * \\"
+#    print "                /   .-"
+#    print "               /   |"
+#    print "              | \\ \\\\ \\"
+#    print "     _ -------|  \\ \\\\ \\"
+#    print " / /              \\_\\ -"
+#    print "/ |\\           |   |"
+#    print "| |  \\ .-----. | \\ |"
+#    print "  |  /        \\ \\ \\ \\"
+#    print "  \\/|.\\        \\ \\ \\ \\"
+#    print "   \\| - .       \\_\\ \\_\\"
+#    print "-----------------------------------------------"
+
+
+def info():
+    version()
+
+    print "Network name: ", network
+    print "-----------------------------------------------"
+    print
+    print "Nodes: ", len(domains)
+    print "  * virtual nodes: ", len(domains)-len(real_nodes)
+    print "  * real nodes:", len(real_nodes)
+    print 
+    print "Bridges:", len(bridges)
+    print "  * virtual bridges:", len(bridges)-len(real_bridges)-len(cross_bridges)
+    print "  * real switches:", len(real_bridges)
+    print "  * direct links:", len(cross_bridges)
+
+def show_usage():
+    print """Usage:
+    xentaur <command> [<argument>]
+
+Commands:
+    start-all       --  start bridges and domains
+    start-domains   --  start domains only
+    start-bridges   --  start bridges only
+    stop-all        --  stop bridges and domains
+    stop-domains    --  stop domains only
+    stop-bridges    --  stop bridges only (domains have to be stopped already)
+    restart-all     --  restart bridges and domains
+
+    start <domain>  --  start the <domain>
+    stop <domain>   --  stop the <domain>
+
+    graph           --  generate network scheme (result is in <network>.{png,jpg,svg})
+    screen          --  generate GNU Screen config file (~/.screenrc_xentaur)
+    shell           --  run Xentaur shell
+
+"""
+
+def save():
+    print "network =",          xen_config_name
+    print "domains =",          domains
+    print "domain_types =",     domain_types
+    print "bridges =",          bridges
+    print "vbridges_table =",   vbridges_table
+    print "hidden_bridges =",   hidden_bridges
+    print "broken_links =",     broken_links
+    print "temporary_links =",  temporary_links
+    print "bridges_turned_down =", bridges_turned_down
+
+#-----------------------------------------------------------------------
+# CLASSES
+
+class Bridge:
+    def __init__ (self,name):
+        self.name=name
+    def up(self):
+        bridge_up(self.name)
+    def down(self):
+        bridge_down(self.name)
+    def show(self):
+        show_bridge(self.name)
+    def dump_start(self,filter=""):
+        dump_start(self.name,filter)
+
+    def is_hidden(self):
+        return self.name in hidden_bridges
+    def is_real(self):
+        return self.name in real_bridges
+    def is_turned_down(self):
+        return self.name in bridges_turned_down
+    def is_cross(self):
+        return self.name in cross_bridges
+
+    def graphviz_string(self):
+        if self.is_hidden():
+            return ""
+        elif self.is_cross():
+            return "%s [shape=circle,height=0.03,color=black,fillcolor=black,style=filled,label=\"\"]" % (self.name)
+        elif self.is_real():
+            return "%s [color=white,shape=none,shapefile=\"%s/all/real_switch.png\"]" % (self.name, path_shapes)
+        elif self.is_turned_down():
+            return "%s [color=white,shape=none,shapefile=\"%s/all/switch_turned_down.png\"]" % (self.name, path_shapes)
+        else:
+            return "%s [color=white,shape=none,shapefile=\"%s/all/switch.png\"]" % (self.name, path_shapes)
+
+
+class Node:
+    def __init__ (self,name):
+        self.name=name
+        self.type=domain_types[domains.index(name)]
+    def start(self):
+        return ""
+    def stop(self):
+        return ""
+    def start_commandline(self):
+        return ""
+    def get_domain_id(self):
+        return get_domain_id(self.name)
+    def graphviz_string(self):
+        return self.name+" [color=white,shape=plaintext,label=\"  "+self.name+"\",shapefile=\""+path_shapes+"/all/"+\
+        domain_types[domains.index(self.name)]+".png\",fontcolor=black,fontsize=16,target=\"http://google.com\"]"
+    def console_string(self):
+        if self.type in [ 'quagga', 'xenomips', 'freebsd', 'linux' ]:
+            return "sudo xm console "+self.name
+        elif self.name in real_bridges or self.name in real_nodes:
+            return "echo Press enter to connect; read line; "+connection_table[self.name]
+
+
+class Link:
+    def __init__ (self,name,node,interface,bridge,label=""):
+        self.name=name
+        self.node=node
+        self.interface=interface
+        self.bridge=bridge
+        self.label=label
+
+    def is_temporary(self):
+        return [self.node,self.interface,self.bridge] in temporary_links
+
+    def is_broken(self):
+        return ([self.node,self.interface,self.bridge] in broken_links)
+
+    def graphviz_string(self):
+        if self.is_temporary():
+            return self.node+" -- "+self.bridge+" [taillabel=\"fa"+str(self.interface)+"/0\",color=blue,len=10,w=5,weight=5]"
+        if self.is_broken():
+            return self.node+" -- "+self.bridge+" [taillabel=\"fa"+str(self.interface)+"/0\",style=dashed]"
+
+        ip="\\n.%s.%s" % (bridges.index(self.bridge)+1, domains.index(self.node)+1) 
+        if domain_types[domains.index(self.node)] == 'xenomips':
+            int_name="fa"+str(self.interface)+"/0"
+        else:
+            int_name="eth"+str(self.interface)
+        if self.label != "":
+            int_name = self.label
+        return self.node+" -- "+self.bridge+" [taillabel=\""+int_name+ip+"\",fontsize=14,fontname=fixed]"
+
+
+#-----------------------------------------------------------------------
+# DOMAINS
+
+def get_domain_id(domain):
+    return run_command_return_stdout("sudo xm list | awk '{if ($1 == \"'%s'\") print $2}'" % domain).rstrip("\n")
+
+
+#-----------------------------------------------------------------------
+# BRIDGES and IFACES
+
+def bridge_down(bridge):
+    """
+    Turn the bridge <bridge> down
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    if bridge in bridges_turned_down:
+        print "Bridge %s is turned down already" % (bridge)
+    else:
+        bridges_turned_down.append(bridge)
+        run_command("sudo ip link set %s down" % bridge)
+        autoredraw()
+
+def bridge_up(bridge):
+    """
+    Turn the bridge <bridge> up
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    if not (bridge in bridges_turned_down):
+        print "Bridge %s is turned up already" % (bridge)
+    else:
+        bridges_turned_down.remove(bridge)
+        run_command("sudo ip link set %s up" % bridge)
+        autoredraw()
+
+def show_bridge(bridge):
+    """
+    Show the state of the bridge <bridge>
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    run_command("sudo ip link show %s" % bridge)
+
+
+def int_disconnect(domain, int_number):
+    """
+    Disconnect the interface with the number <int_number>
+    of the domain <domain> from the bridge to which
+    it is connected
+    """
+    dom_id=get_domain_id(domain)
+    bridge=vbridges_table[domain][int_number]
+    if not bridge:
+        print "Interface %s of the %s domain is not connected" % (int_number, domain)
+        return 1
+    run_command("sudo brctl delif %s vif%s.%s" % (bridge, dom_id, int_number))
+    vbridges_table[domain][int_number]=''
+    if [ domain, int_number, bridge ] in temporary_links:
+        temporary_links.remove([ domain, int_number, bridge ])
+    else:
+        broken_links.append([ domain, int_number, bridge ])
+    autoredraw()
+
+def int_connect(domain, int_number, bridge):
+    """
+    Connect the interface with the number <int_number>
+    of the domain <domain> to the bridge <bridge>
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+
+    dom_id=get_domain_id(domain)
+    if vbridges_table[domain][int_number]:
+        print "Interface %s of the %s domain is connected already to the %s bridge" % (int_number, domain, vbridges_table[domain][int_number])
+        return 1
+    run_command("sudo brctl addif %s vif%s.%s" % (bridge, dom_id, int_number))
+    vbridges_table[domain][int_number]=bridge
+    if [ domain, int_number, bridge ] in broken_links:
+        broken_links.remove([ domain, int_number, bridge ])
+    else:
+        temporary_links.append([ domain, int_number, bridge ])
+    autoredraw()
+
+def int_reconnect(domain, int_number, bridge):
+    """
+    Reconnect the interface with the number <int_number>
+    of the domain <domain> from the bridge to which
+    it is connected to the bridge <bridge>
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    
+    int_disconnect(domain, int_number)
+    int_connect(domain, int_number, bridge)
+
+def show_int(domain, int_number):
+    """
+    Show information about the interface <int_nuber>
+    of the domain <domain>
+    """
+    return vbridges_table[domain][int_number]
+
+
+def dump_start(bridge, filter=""):
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    try:
+        print "Writing dump... (press Ctrl-C to stop)"
+        run_command("sudo tcpdump -w xentaur.dump -i %s %s > /dev/null 2>&1 " % (bridge,filter))
+    except:
+        print "Done.\n Dump is written to xentaur.dump"
+    return 0
+
+def dump_stop():
+    return 0
+
+
+#-----------------------------------------------------------------------
+# CONFIGURATION TEMPLATES
+
+
+def configure_ip_addresses(doms=domains):
+
+    cisco_set_ip_on_int="""
+\n\n\n
+int fa%s/0
+no ip address
+ip address %s 255.255.255.0
+no shutdown
+exit
+"""
+
+    quagga_set_ip_on_int="""
+int eth%s
+no ip address
+ip address %s/24
+no shutdown
+exit
+"""
+
+    for dom in doms:
+        i=domains.index(dom)+1
+        if domain_types[domains.index(dom)] == 'quagga':
+            command = quagga_set_ip_on_int
+            write_to(i,"\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+        else:
+            command = cisco_set_ip_on_int
+            write_to(i,"\nena\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+    return 0
+
+def configure_no_ip_addresses(doms=domains):
+
+    cisco_set_ip_on_int="""
+\n\n\n
+int fa%s/0
+no ip address %s 255.255.255.0
+exit
+"""
+
+    quagga_set_ip_on_int="""
+int eth%s
+no ip address %s/24
+exit
+"""
+
+    for dom in doms:
+        i=domains.index(dom)+1
+        if domain_types[domains.index(dom)] == 'quagga':
+            command = quagga_set_ip_on_int
+            write_to(i,"\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+        else:
+            command = cisco_set_ip_on_int
+            write_to(i,"\nena\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+    return 0
+
+def configure_ospf(doms=domains):
+    for dom in doms:
+        if domain_types[domains.index(dom)] == 'quagga':
+            write_to(dom,"\n\nconf t\nrouter ospf\nnetwork 192.168.0.0/16 area 0\nend\n")
+        else:
+            write_to(dom,"\n\nena\nconf t\nrouter ospf 1\nnetwork 192.168.0.0 0.0.255.255 area 0\nend\n")
+    return 0
+
+def configure_hostname(doms=domains):
+    for dom in doms:
+        if domain_types[domains.index(dom)] == 'quagga':
+            write_to(dom,"\n\nconf t\nhostname %s\nend\n" % dom)
+        else:
+            write_to(dom,"\n\nena\nconf t\nhostname %s\nend\n" % dom)
+    return 0
+
+def configure_logging_synchronous(doms=domains):
+    for dom in domains:
+        if domain_types[domains.index(dom)] == 'quagga':
+            0
+        else:
+            write_to(dom,"\n\nena\nconf t\nline console 0\nlogging synchronous\nend\n")
+    return 0
+
+def configure_exec_timeout_0(doms=domains):
+    for dom in domains:
+        if domain_types[domains.index(dom)] == 'quagga':
+            0
+        else:
+            write_to(dom,"\n\nena\nconf t\nline console 0\nexec-timeout 0\nend\n")
+    return 0
+
+def configure_no_cdp_log_mismatch_duplex(doms=domains):
+    for dom in filter_by_type(domains,'xenomips'):
+        write_to(dom,"\n\nena\nconf t\nno cdp log mismatch duplex\nend\n")
+
+def configure_save(doms=domains):
+    write_to(doms,"\nwr\n")
+
+def configure_root(doms=domains):
+    write_to(doms,"root\n")
+
+#-----------------------------------------------------------------------
+
+
+def add_domain(name,type):
+    domains.append(name)
+    domain_types.append(type)
+
+def brake_link(domain,bridge):
+    broken_links.append([domain,bridge])
+
+wt_timeout=0.5
+def write_to(screen,string,return_to_screen=""):
+    """
+    write_to(screen,string):
+
+        Type *string* to the specified screen(s).
+        Screen may be specified with the number *screen*,
+        with array of numbers, 
+        with array of names.
+
+    """
+    screen_numbers=[]           # number of the screens to write to
+    if type(screen) == list:
+        screen_numbers=map(lambda x: domains.index(x)+1, screen)
+    elif type(screen) == int:
+        screen_numbers=[screen]
+    else:
+        screen_numbers=[domains.index(screen)+1]
+    
+    for screen_number in screen_numbers:
+        run_command("screen -X select "+str(screen_number))
+        time.sleep(wt_timeout)
+        for line in string.splitlines():
+            f=open('/tmp/xentaurbuf', 'w')
+            f.write(line+"\n")
+            f.close()
+            run_command("screen -X readreg p /tmp/xentaurbuf")
+            time.sleep(wt_timeout)
+            run_command("nohup screen -X paste p >& /dev/null")
+            time.sleep(wt_timeout)
+    
+        if return_to_screen != "":
+            run_command("screen -X select %s" % (return_to_screen))
+            time.sleep(wt_timeout)
+
+def filter_by_type(doms,type):
+    """
+    filter_by_type(doms,type)
+
+        Return only domains of *doms* that have specified *type*
+    """
+    return filter(lambda x: domain_types[domains.index(x)]==type,domains)
+
+#-----------------------------------------------------------------------
+
+cisco_fa01_up="""
+ena
+conf t
+int fa0/0
+duplex half
+no shutdown
+exit
+int fa1/0
+duplex half
+no shutdown
+exit
+exit
+exit
+"""
+
+cisco_set_ip_on_int="""
+interface fa%s/0
+no ip address
+ip address %s 255.255.255.0
+exit
+"""
+
+nodes=domains
+
+create_objects()
+
+
+if len(sys.argv) == 2:
+    if sys.argv[1] == 'start-all':
+        start_all()
+    elif sys.argv[1] == 'start-domains':
+        start_domains()
+    elif sys.argv[1] == 'start-bridges':
+        start_bridges()
+    elif sys.argv[1] == 'stop-all':
+        stop_all()
+    elif sys.argv[1] == 'stop-domains':
+        stop_domains()
+    elif sys.argv[1] == 'stop-bridges':
+        stop_bridges()
+    elif sys.argv[1] == 'restart-all':
+        restart_all()
+    elif sys.argv[1] == 'screen':
+        screen()
+    elif sys.argv[1] == 'graph':
+        graph()
+    elif sys.argv[1] == 'shell':
+        shell()
+    elif sys.argv[1] == 'info':
+        info()
+    else:
+        show_usage()
+        sys.exit(1)
+elif len(sys.argv) == 3:
+    if sys.argv[1] == 'start':
+        start_domain(sys.argv[2])
+    elif sys.argv[1] == 'stop':
+        stop_domain(sys.argv[2])
+    elif sys.argv[1] == 'restart':
+        stop_domain(sys.argv[2])
+        start_domain(sys.argv[2])
+    else:
+        show_usage()
+        sys.exit(1)
+else:
+    show_usage()
+    sys.exit(1)
+
+sys.exit(0)
+
+
22:15:31
$/xen/xentaur/xentaur.py
Traceback (most recent call last):
  File "/xen/xentaur/xentaur.py", line 22, in ?
    from xendomain import *
  File "/xen/xentaur/xendomain.py", line 47, in ?
    exec 'from %s import *' % (network)
  File "<string>", line 1
    from openvpn-bridge import *
                ^
SyntaxError: invalid syntax
22:15:32
$vi /xen/xentaur/xentaur.py
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ /xen/xentaur/xentaur.py	2008-02-21 22:15:39.000000000 +0200
@@ -0,0 +1,774 @@
+#!/usr/bin/python
+# vim: set fileencoding=utf-8 :
+
+import sys,os,time
+
+xentaur_path=os.environ['HOME']+"/xentaur"
+
+sys.path.append('/etc/xen')
+sys.path.append(xentaur_path)
+sys.path.append('.')
+
+#network='snrs_ipsec_rsa_1'
+node_object={}
+link_object={}
+bridge_object={}
+
+network='openvpnbridge'
+domain='debian1'
+
+#network='snrs'
+#domain='dyn1'
+from xendomain import *
+
+bridges_turned_down=[]
+
+from IPython.Shell import IPShellEmbed
+
+
+screenrc=os.environ['HOME']+"/.screenrc_xentaur"
+path_shapes='/xen/xentaur/shapes'
+
+def run(program, *args):
+    pid = os.fork()
+    if not pid:
+        os.execvp(program, (program,) +  args)
+    return os.wait()[0]
+
+def run_command(line):
+    #cmds=line.split()
+    #run(cmds[0],*cmds[1:])
+    run("/bin/sh", "-c", line)
+
+def run_command_return_stdout(line):
+    p = os.popen(line)
+    output = p.read()
+    p.close()
+    return output
+
+################################################################################
+#Xentaur command-line commands
+
+## Start
+
+def start_bridges():
+    unbound_bridges=set(bridges)-set(real_bridges)
+    script=""
+    script="\n".join(map(lambda x: "sudo brctl show | awk '{print $1}' | grep -qx "+x+" || sudo brctl addbr "+x, unbound_bridges))
+    script+="\n"+"\n".join(map(lambda x: "sudo brctl stp "+x+" off", unbound_bridges))
+    script+="\n"+"\n".join(map(lambda x: "sudo ip link set "+x+" up", unbound_bridges))
+
+    print """#!/bin/sh
+# create unbound bridges
+%s
+""" % (script)
+
+def start_domain(domain):
+    print "sudo xm create "+xentaur_path+"/xendomain.py "+" domain="+domain+" network="+network+" && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep "+domain+" | awk '{print $2}') -c 10 && sleep 1"
+
+def start_domains(doms=domains):
+    for domain in doms:
+        if not domain in real_nodes:
+            start_domain(domain)
+
+def start_all():
+    graph()
+    screen()
+    start_bridges()
+    start_domains()
+
+## Stop
+
+def stop_domain(domain,wait=0):
+    if wait:
+        print "sudo xm shutdown -w "+domain
+    else:
+        print "sudo xm shutdown "+domain
+
+def stop_domains(doms=domains, wait=0):
+    for domain in doms:
+        if not domain in real_nodes:
+            stop_domain(domain,wait)
+
+def stop_bridges():
+    ###FIXME###
+    return 0
+
+def stop_all(wait=0):
+    stop_domains(domains, wait)
+    stop_bridges()
+
+def restart_all():
+    stop_all(1)
+    start_all()
+
+####################################################
+
+def create_objects():
+    create_node_objects()
+    create_bridge_objects()
+    create_link_objects()
+
+def create_node_objects():
+    for dom in domains:
+        node_object[dom]=Node(dom)
+
+def create_bridge_objects():
+    for bridge in bridges:
+        bridge_object[bridge]=Bridge(bridge)
+
+def create_link_objects():
+
+    for node, bridges_raw in vbridges_table.iteritems():
+        interface=0
+        j=0
+        for this_bridge in bridges_raw:
+            int_label=""
+            if this_bridge.find(':') != -1:
+                res = this_bridge.split(':')
+                this_bridge= res[0]
+                bridges_raw[j] = this_bridge
+                int_label  = res[1]
+            if not [ node, bridges_raw.index(this_bridge), this_bridge ] in temporary_links:
+                name="%s %s %s" % (node,interface,this_bridge)
+                link_object[name]=Link(name,node,interface,this_bridge,int_label)
+                interface+=1
+        vbridges_table[node]=bridges_raw
+
+    for node, bridges_raw in bridge_bridge_table.iteritems():
+        interface=0
+        j=0
+        for this_bridge in bridges_raw:
+            int_label=""
+            if this_bridge.find(':') != -1:
+                res = this_bridge.split(':')
+                this_bridge= res[2]
+                bridges_raw[j] = this_bridge
+                int_label  = res[1]
+            if not [ node, bridges_raw.index(this_bridge), this_bridge ] in temporary_links:
+                name="%s %s %s" % (node,interface,this_bridge)
+                link_object[name]=Link(name,node,interface,this_bridge,int_label)
+                interface+=1
+        bridge_bridge_table[node]=bridges_raw
+
+    for node,interface,bridge in temporary_links:
+        name="%s %s %s" % (node,interface,bridge)
+        link_object[name]=Link(name,node,interface,this_bridge)
+
+    for node,interface,bridge in broken_links:
+        name="%s %s %s" % (node,interface,bridge)
+        link_object[name]=Link(name,node,interface,this_bridge)
+
+
+####################################################
+
+def screen():
+    wait_seconds=1
+    screens=[]
+    for domain in domains:
+        screens.append("screen -t %s %s sh -c 'while true; do %s ; echo Retrying in %s secods...; sleep %s ; clear; done'" %
+                                 (domain,domains.index(domain)+1,node_object[domain].console_string(),wait_seconds,wait_seconds))
+    screenlist="\n".join(screens)
+
+    hardstatus='hardstatus string "%{rk}Xentaur%{bk}@%H %{gk}%c %{yk}%d.%m %{wk}%?%-Lw%?%{bw}%n*%f%t%?(%u)%?%{wk}%?%+Lw%?"'
+   
+    f=open(screenrc, "w");
+    f.write("""
+hardstatus on
+hardstatus alwayslastline
+%s
+
+screen -t console 0 sh -c 'while true; do cd %s; ./xentaur.py shell ; echo Retrying in %s secods...; sleep %s ; clear; done'
+#screen -t xentaur - sh -c 'while true; do bash ; echo Retrying in %s secods...; sleep %s ; clear; done'
+%s
+""" % (hardstatus,xentaur_path,wait_seconds,wait_seconds,wait_seconds,wait_seconds,screenlist))
+    f.close()
+    print "# GNU Screen config file is written to: %s" % screenrc
+
+def graph():
+    nodelist=""
+    bridgelist=""
+    linklist=""
+    physicallist=""
+    networklist=""
+
+    nodelist=";\n    ".join(map(lambda node: node_object[node].graphviz_string(),nodes))
+    if nodelist: nodelist += ";"
+    bridgelist=";\n    ".join(map(lambda bridge: bridge_object[bridge].graphviz_string(),bridges))
+    if bridgelist: bridgelist += ";"
+    linklist=";\n    ".join(map(lambda link: link_object[link].graphviz_string(),link_object.keys()))
+    if linklist: linklist += ";"
+
+    f = open(network+".dot", "w");
+    f.write ("""
+graph G {
+    edge [len=1.25];
+    splines=true;
+// nodes
+    %s
+
+// bridges
+    %s
+
+// physical
+    node [shape=rectangle,color=blue];
+    %s
+
+// networks (not bridges, not physical)
+    node [shape=rectangle,color=green];
+    %s
+
+// links (between nodes and bridges)
+    %s
+
+};
+""" % (nodelist, bridgelist, physicallist, networklist, linklist))
+    f.close()
+    run_command("neato -Tpng -o %s.png %s.dot "%(network,network))
+    run_command("neato -Tjpg -o %s.jpg %s.dot "%(network,network))
+    run_command("neato -Tsvg -o %s.svg %s.dot "%(network,network))
+    run_command("neato -Tcmapx -o %s.cmapx -NURL=http://google.com %s.dot "%(network,network))
+    print "# Network map is written to files: %s.{png,svg,jpg,dot}" % network
+
+def autoredraw():
+    graph()
+
+def shell():
+    autoredraw()
+    ipshell = IPShellEmbed()
+    ipshell()
+
+def version():
+    print """
+Xentaur 0.1-PRE
+
+             ,--,
+       _ ___/ /\\|
+   ,;`( )__, )  ~
+  // .//   '--;
+  ' / \     |
+
+    """
+#    print "Xentaur 0.1-PRE"
+#    print "(Godzilla-mutant)  _"
+#    print "                 / * \\"
+#    print "                /   .-"
+#    print "               /   |"
+#    print "              | \\ \\\\ \\"
+#    print "     _ -------|  \\ \\\\ \\"
+#    print " / /              \\_\\ -"
+#    print "/ |\\           |   |"
+#    print "| |  \\ .-----. | \\ |"
+#    print "  |  /        \\ \\ \\ \\"
+#    print "  \\/|.\\        \\ \\ \\ \\"
+#    print "   \\| - .       \\_\\ \\_\\"
+#    print "-----------------------------------------------"
+
+
+def info():
+    version()
+
+    print "Network name: ", network
+    print "-----------------------------------------------"
+    print
+    print "Nodes: ", len(domains)
+    print "  * virtual nodes: ", len(domains)-len(real_nodes)
+    print "  * real nodes:", len(real_nodes)
+    print 
+    print "Bridges:", len(bridges)
+    print "  * virtual bridges:", len(bridges)-len(real_bridges)-len(cross_bridges)
+    print "  * real switches:", len(real_bridges)
+    print "  * direct links:", len(cross_bridges)
+
+def show_usage():
+    print """Usage:
+    xentaur <command> [<argument>]
+
+Commands:
+    start-all       --  start bridges and domains
+    start-domains   --  start domains only
+    start-bridges   --  start bridges only
+    stop-all        --  stop bridges and domains
+    stop-domains    --  stop domains only
+    stop-bridges    --  stop bridges only (domains have to be stopped already)
+    restart-all     --  restart bridges and domains
+
+    start <domain>  --  start the <domain>
+    stop <domain>   --  stop the <domain>
+
+    graph           --  generate network scheme (result is in <network>.{png,jpg,svg})
+    screen          --  generate GNU Screen config file (~/.screenrc_xentaur)
+    shell           --  run Xentaur shell
+
+"""
+
+def save():
+    print "network =",          xen_config_name
+    print "domains =",          domains
+    print "domain_types =",     domain_types
+    print "bridges =",          bridges
+    print "vbridges_table =",   vbridges_table
+    print "hidden_bridges =",   hidden_bridges
+    print "broken_links =",     broken_links
+    print "temporary_links =",  temporary_links
+    print "bridges_turned_down =", bridges_turned_down
+
+#-----------------------------------------------------------------------
+# CLASSES
+
+class Bridge:
+    def __init__ (self,name):
+        self.name=name
+    def up(self):
+        bridge_up(self.name)
+    def down(self):
+        bridge_down(self.name)
+    def show(self):
+        show_bridge(self.name)
+    def dump_start(self,filter=""):
+        dump_start(self.name,filter)
+
+    def is_hidden(self):
+        return self.name in hidden_bridges
+    def is_real(self):
+        return self.name in real_bridges
+    def is_turned_down(self):
+        return self.name in bridges_turned_down
+    def is_cross(self):
+        return self.name in cross_bridges
+
+    def graphviz_string(self):
+        if self.is_hidden():
+            return ""
+        elif self.is_cross():
+            return "%s [shape=circle,height=0.03,color=black,fillcolor=black,style=filled,label=\"\"]" % (self.name)
+        elif self.is_real():
+            return "%s [color=white,shape=none,shapefile=\"%s/all/real_switch.png\"]" % (self.name, path_shapes)
+        elif self.is_turned_down():
+            return "%s [color=white,shape=none,shapefile=\"%s/all/switch_turned_down.png\"]" % (self.name, path_shapes)
+        else:
+            return "%s [color=white,shape=none,shapefile=\"%s/all/switch.png\"]" % (self.name, path_shapes)
+
+
+class Node:
+    def __init__ (self,name):
+        self.name=name
+        self.type=domain_types[domains.index(name)]
+    def start(self):
+        return ""
+    def stop(self):
+        return ""
+    def start_commandline(self):
+        return ""
+    def get_domain_id(self):
+        return get_domain_id(self.name)
+    def graphviz_string(self):
+        return self.name+" [color=white,shape=plaintext,label=\"  "+self.name+"\",shapefile=\""+path_shapes+"/all/"+\
+        domain_types[domains.index(self.name)]+".png\",fontcolor=black,fontsize=16,target=\"http://google.com\"]"
+    def console_string(self):
+        if self.type in [ 'quagga', 'xenomips', 'freebsd', 'linux' ]:
+            return "sudo xm console "+self.name
+        elif self.name in real_bridges or self.name in real_nodes:
+            return "echo Press enter to connect; read line; "+connection_table[self.name]
+
+
+class Link:
+    def __init__ (self,name,node,interface,bridge,label=""):
+        self.name=name
+        self.node=node
+        self.interface=interface
+        self.bridge=bridge
+        self.label=label
+
+    def is_temporary(self):
+        return [self.node,self.interface,self.bridge] in temporary_links
+
+    def is_broken(self):
+        return ([self.node,self.interface,self.bridge] in broken_links)
+
+    def graphviz_string(self):
+        if self.is_temporary():
+            return self.node+" -- "+self.bridge+" [taillabel=\"fa"+str(self.interface)+"/0\",color=blue,len=10,w=5,weight=5]"
+        if self.is_broken():
+            return self.node+" -- "+self.bridge+" [taillabel=\"fa"+str(self.interface)+"/0\",style=dashed]"
+
+        ip="\\n.%s.%s" % (bridges.index(self.bridge)+1, domains.index(self.node)+1) 
+        if domain_types[domains.index(self.node)] == 'xenomips':
+            int_name="fa"+str(self.interface)+"/0"
+        else:
+            int_name="eth"+str(self.interface)
+        if self.label != "":
+            int_name = self.label
+        return self.node+" -- "+self.bridge+" [taillabel=\""+int_name+ip+"\",fontsize=14,fontname=fixed]"
+
+
+#-----------------------------------------------------------------------
+# DOMAINS
+
+def get_domain_id(domain):
+    return run_command_return_stdout("sudo xm list | awk '{if ($1 == \"'%s'\") print $2}'" % domain).rstrip("\n")
+
+
+#-----------------------------------------------------------------------
+# BRIDGES and IFACES
+
+def bridge_down(bridge):
+    """
+    Turn the bridge <bridge> down
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    if bridge in bridges_turned_down:
+        print "Bridge %s is turned down already" % (bridge)
+    else:
+        bridges_turned_down.append(bridge)
+        run_command("sudo ip link set %s down" % bridge)
+        autoredraw()
+
+def bridge_up(bridge):
+    """
+    Turn the bridge <bridge> up
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    if not (bridge in bridges_turned_down):
+        print "Bridge %s is turned up already" % (bridge)
+    else:
+        bridges_turned_down.remove(bridge)
+        run_command("sudo ip link set %s up" % bridge)
+        autoredraw()
+
+def show_bridge(bridge):
+    """
+    Show the state of the bridge <bridge>
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    run_command("sudo ip link show %s" % bridge)
+
+
+def int_disconnect(domain, int_number):
+    """
+    Disconnect the interface with the number <int_number>
+    of the domain <domain> from the bridge to which
+    it is connected
+    """
+    dom_id=get_domain_id(domain)
+    bridge=vbridges_table[domain][int_number]
+    if not bridge:
+        print "Interface %s of the %s domain is not connected" % (int_number, domain)
+        return 1
+    run_command("sudo brctl delif %s vif%s.%s" % (bridge, dom_id, int_number))
+    vbridges_table[domain][int_number]=''
+    if [ domain, int_number, bridge ] in temporary_links:
+        temporary_links.remove([ domain, int_number, bridge ])
+    else:
+        broken_links.append([ domain, int_number, bridge ])
+    autoredraw()
+
+def int_connect(domain, int_number, bridge):
+    """
+    Connect the interface with the number <int_number>
+    of the domain <domain> to the bridge <bridge>
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+
+    dom_id=get_domain_id(domain)
+    if vbridges_table[domain][int_number]:
+        print "Interface %s of the %s domain is connected already to the %s bridge" % (int_number, domain, vbridges_table[domain][int_number])
+        return 1
+    run_command("sudo brctl addif %s vif%s.%s" % (bridge, dom_id, int_number))
+    vbridges_table[domain][int_number]=bridge
+    if [ domain, int_number, bridge ] in broken_links:
+        broken_links.remove([ domain, int_number, bridge ])
+    else:
+        temporary_links.append([ domain, int_number, bridge ])
+    autoredraw()
+
+def int_reconnect(domain, int_number, bridge):
+    """
+    Reconnect the interface with the number <int_number>
+    of the domain <domain> from the bridge to which
+    it is connected to the bridge <bridge>
+    """
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    
+    int_disconnect(domain, int_number)
+    int_connect(domain, int_number, bridge)
+
+def show_int(domain, int_number):
+    """
+    Show information about the interface <int_nuber>
+    of the domain <domain>
+    """
+    return vbridges_table[domain][int_number]
+
+
+def dump_start(bridge, filter=""):
+    if bridge in real_bridges:
+        print "Bridge %s is a real bridge" % (bridge)
+        return -1
+    try:
+        print "Writing dump... (press Ctrl-C to stop)"
+        run_command("sudo tcpdump -w xentaur.dump -i %s %s > /dev/null 2>&1 " % (bridge,filter))
+    except:
+        print "Done.\n Dump is written to xentaur.dump"
+    return 0
+
+def dump_stop():
+    return 0
+
+
+#-----------------------------------------------------------------------
+# CONFIGURATION TEMPLATES
+
+
+def configure_ip_addresses(doms=domains):
+
+    cisco_set_ip_on_int="""
+\n\n\n
+int fa%s/0
+no ip address
+ip address %s 255.255.255.0
+no shutdown
+exit
+"""
+
+    quagga_set_ip_on_int="""
+int eth%s
+no ip address
+ip address %s/24
+no shutdown
+exit
+"""
+
+    for dom in doms:
+        i=domains.index(dom)+1
+        if domain_types[domains.index(dom)] == 'quagga':
+            command = quagga_set_ip_on_int
+            write_to(i,"\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+        else:
+            command = cisco_set_ip_on_int
+            write_to(i,"\nena\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+    return 0
+
+def configure_no_ip_addresses(doms=domains):
+
+    cisco_set_ip_on_int="""
+\n\n\n
+int fa%s/0
+no ip address %s 255.255.255.0
+exit
+"""
+
+    quagga_set_ip_on_int="""
+int eth%s
+no ip address %s/24
+exit
+"""
+
+    for dom in doms:
+        i=domains.index(dom)+1
+        if domain_types[domains.index(dom)] == 'quagga':
+            command = quagga_set_ip_on_int
+            write_to(i,"\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+        else:
+            command = cisco_set_ip_on_int
+            write_to(i,"\nena\nconf t\n")
+            j=0
+            for br in  vbridges_table[dom]:
+                write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
+                j+=1
+            write_to(i,"\nend\n")
+    return 0
+
+def configure_ospf(doms=domains):
+    for dom in doms:
+        if domain_types[domains.index(dom)] == 'quagga':
+            write_to(dom,"\n\nconf t\nrouter ospf\nnetwork 192.168.0.0/16 area 0\nend\n")
+        else:
+            write_to(dom,"\n\nena\nconf t\nrouter ospf 1\nnetwork 192.168.0.0 0.0.255.255 area 0\nend\n")
+    return 0
+
+def configure_hostname(doms=domains):
+    for dom in doms:
+        if domain_types[domains.index(dom)] == 'quagga':
+            write_to(dom,"\n\nconf t\nhostname %s\nend\n" % dom)
+        else:
+            write_to(dom,"\n\nena\nconf t\nhostname %s\nend\n" % dom)
+    return 0
+
+def configure_logging_synchronous(doms=domains):
+    for dom in domains:
+        if domain_types[domains.index(dom)] == 'quagga':
+            0
+        else:
+            write_to(dom,"\n\nena\nconf t\nline console 0\nlogging synchronous\nend\n")
+    return 0
+
+def configure_exec_timeout_0(doms=domains):
+    for dom in domains:
+        if domain_types[domains.index(dom)] == 'quagga':
+            0
+        else:
+            write_to(dom,"\n\nena\nconf t\nline console 0\nexec-timeout 0\nend\n")
+    return 0
+
+def configure_no_cdp_log_mismatch_duplex(doms=domains):
+    for dom in filter_by_type(domains,'xenomips'):
+        write_to(dom,"\n\nena\nconf t\nno cdp log mismatch duplex\nend\n")
+
+def configure_save(doms=domains):
+    write_to(doms,"\nwr\n")
+
+def configure_root(doms=domains):
+    write_to(doms,"root\n")
+
+#-----------------------------------------------------------------------
+
+
+def add_domain(name,type):
+    domains.append(name)
+    domain_types.append(type)
+
+def brake_link(domain,bridge):
+    broken_links.append([domain,bridge])
+
+wt_timeout=0.5
+def write_to(screen,string,return_to_screen=""):
+    """
+    write_to(screen,string):
+
+        Type *string* to the specified screen(s).
+        Screen may be specified with the number *screen*,
+        with array of numbers, 
+        with array of names.
+
+    """
+    screen_numbers=[]           # number of the screens to write to
+    if type(screen) == list:
+        screen_numbers=map(lambda x: domains.index(x)+1, screen)
+    elif type(screen) == int:
+        screen_numbers=[screen]
+    else:
+        screen_numbers=[domains.index(screen)+1]
+    
+    for screen_number in screen_numbers:
+        run_command("screen -X select "+str(screen_number))
+        time.sleep(wt_timeout)
+        for line in string.splitlines():
+            f=open('/tmp/xentaurbuf', 'w')
+            f.write(line+"\n")
+            f.close()
+            run_command("screen -X readreg p /tmp/xentaurbuf")
+            time.sleep(wt_timeout)
+            run_command("nohup screen -X paste p >& /dev/null")
+            time.sleep(wt_timeout)
+    
+        if return_to_screen != "":
+            run_command("screen -X select %s" % (return_to_screen))
+            time.sleep(wt_timeout)
+
+def filter_by_type(doms,type):
+    """
+    filter_by_type(doms,type)
+
+        Return only domains of *doms* that have specified *type*
+    """
+    return filter(lambda x: domain_types[domains.index(x)]==type,domains)
+
+#-----------------------------------------------------------------------
+
+cisco_fa01_up="""
+ena
+conf t
+int fa0/0
+duplex half
+no shutdown
+exit
+int fa1/0
+duplex half
+no shutdown
+exit
+exit
+exit
+"""
+
+cisco_set_ip_on_int="""
+interface fa%s/0
+no ip address
+ip address %s 255.255.255.0
+exit
+"""
+
+nodes=domains
+
+create_objects()
+
+
+if len(sys.argv) == 2:
+    if sys.argv[1] == 'start-all':
+        start_all()
+    elif sys.argv[1] == 'start-domains':
+        start_domains()
+    elif sys.argv[1] == 'start-bridges':
+        start_bridges()
+    elif sys.argv[1] == 'stop-all':
+        stop_all()
+    elif sys.argv[1] == 'stop-domains':
+        stop_domains()
+    elif sys.argv[1] == 'stop-bridges':
+        stop_bridges()
+    elif sys.argv[1] == 'restart-all':
+        restart_all()
+    elif sys.argv[1] == 'screen':
+        screen()
+    elif sys.argv[1] == 'graph':
+        graph()
+    elif sys.argv[1] == 'shell':
+        shell()
+    elif sys.argv[1] == 'info':
+        info()
+    else:
+        show_usage()
+        sys.exit(1)
+elif len(sys.argv) == 3:
+    if sys.argv[1] == 'start':
+        start_domain(sys.argv[2])
+    elif sys.argv[1] == 'stop':
+        stop_domain(sys.argv[2])
+    elif sys.argv[1] == 'restart':
+        stop_domain(sys.argv[2])
+        start_domain(sys.argv[2])
+    else:
+        show_usage()
+        sys.exit(1)
+else:
+    show_usage()
+    sys.exit(1)
+
+sys.exit(0)
+
+
22:15:39
$ls -l
итого 12595396
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:18 debian1.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:19 debian2.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:20 debian3.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:21 debian4.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:23 debian5.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:24 debian6.img
-rw-r--r-- 1 igor igor       2017 Фев 21 21:57 ids2007dec.cmapx
-rw-r--r-- 1 igor igor       3831 Фев 21 21:57 ids2007dec.dot
-rw-r--r-- 1 igor igor      39959 Фев 21 21:57 ids2007dec.jpg
-rw-r--r-- 1 igor igor      98402 Фев 21 21:57 ids2007dec.png
-rw-r--r-- 1 igor igor      15520 Фев 21 21:57 ids2007dec.svg
-rw-r--r-- 1 igor igor       1060 Фев 21 22:15 openvpn-bridge.py
22:15:40
$mv openvpn-bridge.py openvpnbridge.py

22:15:46
$cat openvpnbridge.py
import os
domain=os.environ['xendomain']
network='ids2007dec'
domains =       [
                   'debian1',
                   'debian2',
                   'debian3',
                   'debian4',
                   'debian5',
                ]
...
        'debian3'      : [ 'br2', 'br3' ],
        'debian4'      : [ 'br3', 'br4' ],
        'debian5'      : [ 'br4' ],
}
#xenomips_dir='/xen/images/snrs/xentaur/'
#platform="7200"                 # 7200|3600|2691|3725|3745
#npe_type='npe-400'              # (7200 only) "npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300" and "npe-400"
#ios_name='C7200-AD.BIN'
#if domain=='dyn1':
#    ios_name='pix635-125.bin'
22:15:47
$/xen/xentaur/xentaur.py
Usage:
    xentaur <command> [<argument>]
Commands:
    start-all       --  start bridges and domains
    start-domains   --  start domains only
    start-bridges   --  start bridges only
    stop-all        --  stop bridges and domains
    stop-domains    --  stop domains only
    stop-bridges    --  stop bridges only (domains have to be stopped already)
    restart-all     --  restart bridges and domains
    start <domain>  --  start the <domain>
    stop <domain>   --  stop the <domain>
    graph           --  generate network scheme (result is in <network>.{png,jpg,svg})
    screen          --  generate GNU Screen config file (~/.screenrc_xentaur)
    shell           --  run Xentaur shell
22:15:50
$/xen/xentaur/xentaur.py graph
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
# Network map is written to files: ids2007dec.{png,svg,jpg,dot}
22:15:54
$rm ids*

22:16:02
$ls -l
итого 12595232
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:18 debian1.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:19 debian2.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:20 debian3.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:21 debian4.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:23 debian5.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:24 debian6.img
-rw-r--r-- 1 igor igor       1060 Фев 21 22:15 openvpnbridge.py
-rw-r--r-- 1 igor igor        541 Фев 21 22:15 openvpnbridge.pyc
22:16:04
$vi openvpnbridge.py
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ openvpnbridge.py	2008-02-21 22:16:19.000000000 +0200
@@ -0,0 +1,40 @@
+import os
+domain=os.environ['xendomain']
+
+network='openvpnbridge'
+
+domains =       [  
+                   'debian1', 
+                   'debian2', 
+                   'debian3', 
+                   'debian4', 
+                   'debian5', 
+                ]
+domain_types =  [  
+                    'linux', 'linux', 'linux', 
+                    'linux', 'linux',
+                ]
+bridges =       [  
+                    'br1', 
+                    'br2', 
+                    'br3',
+                    'br4', 
+                ]
+
+vbridges_table ={
+        'debian1'      : [ 'br1' ],
+        'debian2'      : [ 'br1', 'br2' ],
+        'debian3'      : [ 'br2', 'br3' ],
+        'debian4'      : [ 'br3', 'br4' ],
+        'debian5'      : [ 'br4' ],
+}
+
+
+#xenomips_dir='/xen/images/snrs/xentaur/'
+#platform="7200"                 # 7200|3600|2691|3725|3745
+#npe_type='npe-400'              # (7200 only) "npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300" and "npe-400"
+#ios_name='C7200-AD.BIN'
+
+#if domain=='dyn1':
+#    ios_name='pix635-125.bin'
+
22:16:19
$/xen/xentaur/xentaur.py graph
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
# Network map is written to files: openvpnbridge.{png,svg,jpg,dot}
22:16:21
$gqview openvpnbridge.png

22:16:54
$l3upload openvpnbridge.png
Uploaded file name is 112991902427971280-1203624331_1203625044_openvpnbridge.png
Upload complete
screenshot id 112991902427971280-1203624331_1203625044_openvpnbridge.png
22:18:11
$ls -l
итого 12595296
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:18 debian1.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:19 debian2.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:20 debian3.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:21 debian4.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:23 debian5.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:24 debian6.img
-rw-r--r-- 1 igor igor        996 Фев 21 22:16 openvpnbridge.cmapx
-rw-r--r-- 1 igor igor       1966 Фев 21 22:16 openvpnbridge.dot
-rw-r--r-- 1 igor igor      16489 Фев 21 22:16 openvpnbridge.jpg
-rw-r--r-- 1 igor igor      27473 Фев 21 22:16 openvpnbridge.png
-rw-r--r-- 1 igor igor       1063 Фев 21 22:16 openvpnbridge.py
-rw-r--r-- 1 igor igor        544 Фев 21 22:16 openvpnbridge.pyc
-rw-r--r-- 1 igor igor       7484 Фев 21 22:16 openvpnbridge.svg
22:18:42
$vi openvpnbridge.py
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ openvpnbridge.py	2008-02-21 22:19:27.000000000 +0200
@@ -0,0 +1,42 @@
+import os
+domain=os.environ['xendomain']
+
+network='openvpnbridge'
+
+domains =       [  
+                   'debian1', 
+                   'debian2', 
+                   'debian3', 
+                   'debian4', 
+                   'debian5', 
+                   'freebsd6', 
+                ]
+domain_types =  [  
+                    'linux', 'linux', 'linux', 
+                    'linux', 'linux',
+                ]
+bridges =       [  
+                    'br1', 
+                    'br2', 
+                    'br3',
+                    'br4', 
+                ]
+
+vbridges_table ={
+        'debian1'      : [ 'br1' ],
+        'debian2'      : [ 'br1', 'br2' ],
+        'debian3'      : [ 'br2', 'br3' ],
+        'debian4'      : [ 'br3', 'br4' ],
+        'debian5'      : [ 'br4' ],
+        'freebsd6'     : [ 'br1', 'br4' ],
+}
+
+
+#xenomips_dir='/xen/images/snrs/xentaur/'
+#platform="7200"                 # 7200|3600|2691|3725|3745
+#npe_type='npe-400'              # (7200 only) "npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300" and "npe-400"
+#ios_name='C7200-AD.BIN'
+
+#if domain=='dyn1':
+#    ios_name='pix635-125.bin'
+
22:19:27
$/xen/xentaur/xentaur.py graph
Traceback (most recent call last):
  File "/xen/xentaur/xentaur.py", line 728, in ?
    create_objects()
  File "/xen/xentaur/xentaur.py", line 108, in create_objects
    create_node_objects()
  File "/xen/xentaur/xentaur.py", line 114, in create_node_objects
    node_object[dom]=Node(dom)
  File "/xen/xentaur/xentaur.py", line 356, in __init__
    self.type=domain_types[domains.index(name)]
IndexError: list index out of range
22:19:30
$vi openvpnbridge.py
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ openvpnbridge.py	2008-02-21 22:19:40.000000000 +0200
@@ -0,0 +1,43 @@
+import os
+domain=os.environ['xendomain']
+
+network='openvpnbridge'
+
+domains =       [  
+                   'debian1', 
+                   'debian2', 
+                   'debian3', 
+                   'debian4', 
+                   'debian5', 
+                   'freebsd6', 
+                ]
+domain_types =  [  
+                    'linux', 'linux', 'linux', 
+                    'linux', 'linux',
+                    'freebsd'
+                ]
+bridges =       [  
+                    'br1', 
+                    'br2', 
+                    'br3',
+                    'br4', 
+                ]
+
+vbridges_table ={
+        'debian1'      : [ 'br1' ],
+        'debian2'      : [ 'br1', 'br2' ],
+        'debian3'      : [ 'br2', 'br3' ],
+        'debian4'      : [ 'br3', 'br4' ],
+        'debian5'      : [ 'br4' ],
+        'freebsd6'     : [ 'br1', 'br4' ],
+}
+
+
+#xenomips_dir='/xen/images/snrs/xentaur/'
+#platform="7200"                 # 7200|3600|2691|3725|3745
+#npe_type='npe-400'              # (7200 only) "npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300" and "npe-400"
+#ios_name='C7200-AD.BIN'
+
+#if domain=='dyn1':
+#    ios_name='pix635-125.bin'
+
22:19:40
$/xen/xentaur/xentaur.py graph
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
# Network map is written to files: openvpnbridge.{png,svg,jpg,dot}
22:19:41
$l3upload openvpnbridge.png
Uploaded file name is 112991902427971280-1203624331_1203625186_openvpnbridge.png
Upload complete
22:19:46
$set | less
screenshot id 112991902427971280-1203624331_1203625186_openvpnbridge.png
22:23:51
$vi r
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ r	2008-02-21 22:23:57.000000000 +0200
@@ -0,0 +1,2 @@
+hello
+
22:23:57
$vi r
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ r	2008-02-21 22:24:02.000000000 +0200
@@ -0,0 +1,3 @@
+hello
+hello line 2
+
22:24:02
$[ -e r ] && echo exists
exists
22:24:31
$set | less
22:25:54
$ls /tmp/
acroread_1000_1000  cacti  gconfd-igor  index.pdf  kde-igor  orbit-igor  plugtmp  plugtmp-1  v625055
22:25:56
$vi r
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ r	2008-02-21 22:28:12.000000000 +0200
@@ -0,0 +1,4 @@
+hello
+hello line 2
+hello line 3
+
/dev/pts/4
22:26:03
$ls /tmp/
acroread_1000_1000  index.pdf                  orbit-igor  v625055
cacti               kde-igor                   plugtmp     v628711
gconfd-igor         l3-saved-2606.17003.30353  plugtmp-1
22:26:05
$cat /tmp/l3-saved-2606.17003.30353
hello
hello line 2
22:26:09
$set | less
22:27:29
$vi /home/igor/.lilalo/l3bashrc
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ /home/igor/.lilalo/l3bashrc	2008-02-21 22:28:51.000000000 +0200
@@ -0,0 +1,286 @@
+#!/bin/sh
+
+# (c) Igor Chubin, igor@chub.in, 2004-2006
+
+# Environment variables set by the script:
+#
+#       L3_SESSION_ID   - uniq id of the LiLaLo-session
+#       L3_PARENT_TTY   - name of tty on which script is running
+#       PS1             - intercative shell prompt in which LiLaLo hides
+#                         various information about the command
+#       L3_TAMPERED_EDITORS - list of editors which are tampered with functions
+
+
+# Functions with the names starting _l3_ are internal.
+# Such functions are unset before this rc script exits
+
+_l3_editors_to_tamper='/bin/vi /usr/bin/vi /usr/bin/vim /bin/ee /usr/bin/ee /usr/bin/pico /usr/bin/nano /usr/local/bin/vim'
+
+_l3_start()
+{
+    echo $- | grep -q i || return 0
+    if _l3_is_running_here
+    then
+        _l3_env
+        _l3_init_prompt
+         l3_fix_prompt
+        _l3_tamper_editors
+        _l3_tamper_commands
+        _l3_unset_internal
+    else
+        _l3_start_session
+        _l3_run_script
+    fi
+}
+
+# ===================== STAGE 1 ============================
+
+_l3_is_running_here()
+{
+	ps waux | awk '{print $2" "$11 }' | grep -q ^$PPID" "script 
+	return $?
+
+# Check if ^^^^ run on Linux
+# and del  vvvv this if it does
+
+    export L3_TTY=`/usr/bin/tty` 
+    uname -a | grep -qi bsd && bsd=yes
+    proc_on_the_term=`w | grep "${L3_TTY##/dev/}" | awk '{print $8;}'`
+    # freeBSD: 
+    [ -n "$bsd" ] && \
+    proc_on_the_term=`w | grep "${L3_TTY##/dev/tty}" | awk '{print $6;}'`
+
+    [ -n "$proc_on_the_term" ] && echo $proc_on_the_term | grep -q script
+}
+
+_l3_start_session()
+{
+    export L3_SESSION_ID=${RANDOM}${RANDOM}${RANDOM}${RANDOM}-`date +%s`
+    export L3_HOME=~/.lilalo/
+    mkdir -p $L3_HOME
+
+    tty=`/usr/bin/tty`
+    uname -a | grep -qi bsd && bsd=yes
+    parent=`cat /proc/$PPID/cmdline 2> /dev/null`
+    [ -z "$parent" ] && parent="`ps waux | awk '{if ($2 == '$PPID') print $11; }'`"
+    system=`uname -rs`
+    login_from=`who | grep "${tty##/dev/}" | awk '{print $6;}' | tr -d '()'`
+    #[ -n "$bsd" ] && login_from="" #FIXME!
+    start_time=`date +%s`
+    hostname=`hostname -f 2> /dev/null`
+    [ -n "$bsd" ] && hostname=`hostname`
+
+    cat <<INFO > $L3_HOME/$L3_SESSION_ID.info
+<session>
+    <local_session_id>$L3_SESSION_ID</local_session_id>
+    <hostname>$hostname</hostname>
+    <user>$USER</user>
+    <uid>$UID</uid>
+    <login_from>$login_from</login_from>
+    <tty>$tty</tty>
+    <system>$system</system>
+    <parent>$parent</parent>
+    <ppid>$PPID</ppid>
+    <pid>$$</pid>
+    <start_time>$start_time</start_time>
+    <lang>$LANG</lang>
+</session>
+INFO
+
+    unset parent system login_from start_time hostname tty
+}
+
+_l3_run_script()
+{
+    uname -a | grep -qi bsd && bsd=yes
+    flush="-f"                          #linux
+    [ -n "$bsd" ] && flush="-t 0"       #freebsd
+    export L3_PARENT_TTY=`/usr/bin/tty`
+    exec script $flush -q $L3_HOME/${L3_SESSION_ID}.script
+}
+
+# ===================== STAGE 2 ============================
+
+_l3_env()
+{
+    trap l3_close_session 2
+    trap l3_close_session EXIT
+    true
+}
+
+l3_close_session()
+{
+    ( 
+        echo '<history>'
+        history | sed 's/&/\&amp;/; s/</\&lt;/g; s/>/\&gt;/g'
+        echo '</history>'
+    ) >> $L3_HOME/$L3_SESSION_ID.info
+}
+
+_l3_init_prompt()
+{
+    PS1='[\u@\h:\W]\$ '
+    [ $UID = 0 ] \
+        && PS1='\[\033[0;31m\]'$PS1'\[\033[0m\]' \
+        || PS1='\[\033[0;32m\]'$PS1'\[\033[0m\]' \
+    export PS1
+}
+
+l3_fix_prompt()
+{
+    export PS1='\[v2#\!#$?#$UID#$$#$(/bin/date +%s)$(l3_save_last_line)#$PWD#\033[1024D\033[K\]'$PS1
+}
+
+_l3_tamper_editors()
+{
+    for editor_file in $_l3_editors_to_tamper
+    do
+        [ -x $editor_file ] || continue
+        editor_name=${editor_file##*/}
+        eval "
+        $editor_name() { 
+            set -x
+            if [ -d \"\$1\" ] 
+            then
+                $editor_file \"\$1\"
+                return \$?
+            else
+                TIME=\"\`date +%s\`\"
+                DIR=\"\"
+                [ \"\${1#/}\" = \"\$1\" ] && DIR=\"\$PWD/\"
+                DIFFNAME=\"\${L3_SESSION_ID}_\${TIME}\`echo \$DIR\$1| sed s@_@__@ | sed 's@/@_@g'\`.diff\"
+                old_file=\"/tmp/l3-saved-\$\$.\$RANDOM.\$RANDOM\"
+                /bin/cp -- \"\$1\" \"\$old_file\" 2> /dev/null
+                $editor_file \"\$@\" || ERR=\$?
+                [ -e \"\$old_file\" ] \
+                 && diff -u \"\$old_file\" \"\$1\" > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null \
+                 || diff -u /dev/null \"\$1\"  > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null
+                /bin/rm \"\$old_file\" 2> /dev/null
+                return \$ERR
+            fi
+            set +x
+        }
+        "
+        L3_TAMPERED_EDITORS="$L3_TAMPERED_EDITORS $editor_name"
+    done
+    [ -n "$L3_TAMPERED_EDITORS" ] && export L3_TAMPERED_EDITORS
+}
+
+_l3_tamper_commands()
+{
+    tty()
+    {
+        [ -n "$L3_PARENT_TTY" ] && echo $L3_PARENT_TTY || /usr/bin/tty
+    }
+}
+
+_l3_unset_internal()
+{
+    unset `set | grep '^_l3_.*()' | sed 's/()//'`
+    unset `set | grep '^_l3_.*=' | sed 's/=.*//'`
+}
+
+
+l3shot()
+{
+    if [ -x "`which xwd`" ]
+    then
+        _l3_home=${L3_HOME:-~/.lilalo}
+        shot_name="${L3_SESSION_ID}_`date +%s`".xwd
+        echo -n Choose window to be shoot ... >&2
+        [ -d ${_l3_home} ] || mkdir -p ${_l3_home}
+        xwd -out "$_l3_home/$shot_name" \
+        && echo Screenshot is written to ${_l3_home}/${shot_name} \
+        && curl -s -F photo=@$_l3_home/$shot_name http://xgu.ru/l3-upload
+    else
+        {
+            echo
+            echo "Can't make screenshot :("
+            echo 
+            echo I must use program xwd to make screenshot, 
+            echo but it seems not to be installed
+            echo Try to find the program in the \"xbase-clients\" package
+            echo
+        }   >&2 
+    fi
+}
+
+l3upload()
+{
+    if [ $# -lt 1 ]
+    then
+        echo Usage:
+        echo 
+        echo    l3upload "<filename>"
+        echo
+        echo "<filename>" - name of the file to upload
+        return 1
+    else
+        source=$1 
+        target="${L3_SESSION_ID}_`date +%s`"_"$(echo $source|sed s@.*/@@)"
+        if echo $source | grep -q http://
+        then
+            curl -s "$source" > /tmp/$target 
+        else 
+            [ -r "$source" ] || { echo "l3upload: Can't open $source for reading" > /dev/stderr; return 1; }
+            cp $source /tmp/$target
+        fi
+        echo Uploaded file name is ${target}
+        curl -s -F photo=@/tmp/$target http://xgu.ru/l3-upload && rm -f /tmp/$target
+    fi
+}
+
+# Append lines from "$@" files to the end of the shell history
+hist_append ()
+{
+    eval $(cat "$@" | sed 's/"/\\\\"/g' | while read line; do echo history -s \"$line\"\;; done);
+}
+
+l3_save_last_line ()
+{
+    (
+    echo '<cline>'
+    history 1 | sed 's/&/&amp;/; s/</\&lt;/g; s/>/\&gt;/g'
+    echo '</cline>'
+    ) >> $L3_HOME/$L3_SESSION_ID.info
+}
+
+l3 ()
+{
+    case "$1" in
+        on)
+            echo switching on
+        ;;
+        off)
+            echo switcing off
+        ;;
+        cd)
+            echo l3cd="$2" > ~/.l3rc
+        ;;
+        pwd)
+            grep ^l3cd= ~/.l3rc | sed s/[^=]*=//
+        ;;
+        *) 
+            cat <<EOF
+l3 [command]:
+
+    cd new_context   - change current lilalo context
+    pwd              - show current lilalo context
+    on               - switch writing on (NOT IMPLEMENTED YET)
+    off              - switch writing off (NOT IMPLEMENTED YET)
+
+EOF
+        ;;
+    esac
+}
+
+l3cd()
+{
+    l3 cd "$@"
+}
+
+l3pwd()
+{
+    l3 pwd
+}
+
/dev/pts/4
22:29:27
$vi /tmp/r
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ /tmp/r	2008-02-21 22:29:33.000000000 +0200
@@ -0,0 +1,2 @@
+line 1
+
22:29:33
$vi /tmp/r
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ /tmp/r	2008-02-21 22:29:55.000000000 +0200
@@ -0,0 +1,3 @@
+line 1
+line 2
+
22:29:55
$vi /home/igor/.lilalo/l3bashrc
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ /home/igor/.lilalo/l3bashrc	2008-02-21 22:33:27.000000000 +0200
@@ -0,0 +1,289 @@
+#!/bin/sh
+
+# (c) Igor Chubin, igor@chub.in, 2004-2006
+
+# Environment variables set by the script:
+#
+#       L3_SESSION_ID   - uniq id of the LiLaLo-session
+#       L3_PARENT_TTY   - name of tty on which script is running
+#       PS1             - intercative shell prompt in which LiLaLo hides
+#                         various information about the command
+#       L3_TAMPERED_EDITORS - list of editors which are tampered with functions
+
+
+# Functions with the names starting _l3_ are internal.
+# Such functions are unset before this rc script exits
+
+_l3_editors_to_tamper='/bin/vi /usr/bin/vi /usr/bin/vim /bin/ee /usr/bin/ee /usr/bin/pico /usr/bin/nano /usr/local/bin/vim'
+
+_l3_start()
+{
+    echo $- | grep -q i || return 0
+    if _l3_is_running_here
+    then
+        _l3_env
+        _l3_init_prompt
+         l3_fix_prompt
+        _l3_tamper_editors
+        _l3_tamper_commands
+        _l3_unset_internal
+    else
+        _l3_start_session
+        _l3_run_script
+    fi
+}
+
+# ===================== STAGE 1 ============================
+
+_l3_is_running_here()
+{
+	ps waux | awk '{print $2" "$11 }' | grep -q ^$PPID" "script 
+	return $?
+
+# Check if ^^^^ run on Linux
+# and del  vvvv this if it does
+
+    export L3_TTY=`/usr/bin/tty` 
+    uname -a | grep -qi bsd && bsd=yes
+    proc_on_the_term=`w | grep "${L3_TTY##/dev/}" | awk '{print $8;}'`
+    # freeBSD: 
+    [ -n "$bsd" ] && \
+    proc_on_the_term=`w | grep "${L3_TTY##/dev/tty}" | awk '{print $6;}'`
+
+    [ -n "$proc_on_the_term" ] && echo $proc_on_the_term | grep -q script
+}
+
+_l3_start_session()
+{
+    export L3_SESSION_ID=${RANDOM}${RANDOM}${RANDOM}${RANDOM}-`date +%s`
+    export L3_HOME=~/.lilalo/
+    mkdir -p $L3_HOME
+
+    tty=`/usr/bin/tty`
+    uname -a | grep -qi bsd && bsd=yes
+    parent=`cat /proc/$PPID/cmdline 2> /dev/null`
+    [ -z "$parent" ] && parent="`ps waux | awk '{if ($2 == '$PPID') print $11; }'`"
+    system=`uname -rs`
+    login_from=`who | grep "${tty##/dev/}" | awk '{print $6;}' | tr -d '()'`
+    #[ -n "$bsd" ] && login_from="" #FIXME!
+    start_time=`date +%s`
+    hostname=`hostname -f 2> /dev/null`
+    [ -n "$bsd" ] && hostname=`hostname`
+
+    cat <<INFO > $L3_HOME/$L3_SESSION_ID.info
+<session>
+    <local_session_id>$L3_SESSION_ID</local_session_id>
+    <hostname>$hostname</hostname>
+    <user>$USER</user>
+    <uid>$UID</uid>
+    <login_from>$login_from</login_from>
+    <tty>$tty</tty>
+    <system>$system</system>
+    <parent>$parent</parent>
+    <ppid>$PPID</ppid>
+    <pid>$$</pid>
+    <start_time>$start_time</start_time>
+    <lang>$LANG</lang>
+</session>
+INFO
+
+    unset parent system login_from start_time hostname tty
+}
+
+_l3_run_script()
+{
+    uname -a | grep -qi bsd && bsd=yes
+    flush="-f"                          #linux
+    [ -n "$bsd" ] && flush="-t 0"       #freebsd
+    export L3_PARENT_TTY=`/usr/bin/tty`
+    exec script $flush -q $L3_HOME/${L3_SESSION_ID}.script
+}
+
+# ===================== STAGE 2 ============================
+
+_l3_env()
+{
+    trap l3_close_session 2
+    trap l3_close_session EXIT
+    true
+}
+
+l3_close_session()
+{
+    ( 
+        echo '<history>'
+        history | sed 's/&/\&amp;/; s/</\&lt;/g; s/>/\&gt;/g'
+        echo '</history>'
+    ) >> $L3_HOME/$L3_SESSION_ID.info
+}
+
+_l3_init_prompt()
+{
+    PS1='[\u@\h:\W]\$ '
+    [ $UID = 0 ] \
+        && PS1='\[\033[0;31m\]'$PS1'\[\033[0m\]' \
+        || PS1='\[\033[0;32m\]'$PS1'\[\033[0m\]' \
+    export PS1
+}
+
+l3_fix_prompt()
+{
+    export PS1='\[v2#\!#$?#$UID#$$#$(/bin/date +%s)$(l3_save_last_line)#$PWD#\033[1024D\033[K\]'$PS1
+}
+
+_l3_tamper_editors()
+{
+    for editor_file in $_l3_editors_to_tamper
+    do
+        [ -x $editor_file ] || continue
+        editor_name=${editor_file##*/}
+        eval "
+        $editor_name() { 
+            set -x
+            if [ -d \"\$1\" ] 
+            then
+                $editor_file \"\$1\"
+                return \$?
+            else
+                TIME=\"\`date +%s\`\"
+                DIR=\"\"
+                [ \"\${1#/}\" = \"\$1\" ] && DIR=\"\$PWD/\"
+                DIFFNAME=\"\${L3_SESSION_ID}_\${TIME}\`echo \$DIR\$1| sed s@_@__@ | sed 's@/@_@g'\`.diff\"
+                old_file=\"/tmp/l3-saved-\$\$.\$RANDOM.\$RANDOM\"
+                /bin/cp -- \"\$1\" \"\$old_file\" 2> /dev/null
+                $editor_file \"\$@\" || ERR=\$?
+                if [ -e \"\$old_file\" ]
+                then
+                diff -u \"\$old_file\" \"\$1\" > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null \
+                else
+                diff -u /dev/null \"\$1\"  > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null
+                fi
+                /bin/rm \"\$old_file\" 2> /dev/null
+                return \$ERR
+            fi
+            set +x
+        }
+        "
+        L3_TAMPERED_EDITORS="$L3_TAMPERED_EDITORS $editor_name"
+    done
+    [ -n "$L3_TAMPERED_EDITORS" ] && export L3_TAMPERED_EDITORS
+}
+
+_l3_tamper_commands()
+{
+    tty()
+    {
+        [ -n "$L3_PARENT_TTY" ] && echo $L3_PARENT_TTY || /usr/bin/tty
+    }
+}
+
+_l3_unset_internal()
+{
+    unset `set | grep '^_l3_.*()' | sed 's/()//'`
+    unset `set | grep '^_l3_.*=' | sed 's/=.*//'`
+}
+
+
+l3shot()
+{
+    if [ -x "`which xwd`" ]
+    then
+        _l3_home=${L3_HOME:-~/.lilalo}
+        shot_name="${L3_SESSION_ID}_`date +%s`".xwd
+        echo -n Choose window to be shoot ... >&2
+        [ -d ${_l3_home} ] || mkdir -p ${_l3_home}
+        xwd -out "$_l3_home/$shot_name" \
+        && echo Screenshot is written to ${_l3_home}/${shot_name} \
+        && curl -s -F photo=@$_l3_home/$shot_name http://xgu.ru/l3-upload
+    else
+        {
+            echo
+            echo "Can't make screenshot :("
+            echo 
+            echo I must use program xwd to make screenshot, 
+            echo but it seems not to be installed
+            echo Try to find the program in the \"xbase-clients\" package
+            echo
+        }   >&2 
+    fi
+}
+
+l3upload()
+{
+    if [ $# -lt 1 ]
+    then
+        echo Usage:
+        echo 
+        echo    l3upload "<filename>"
+        echo
+        echo "<filename>" - name of the file to upload
+        return 1
+    else
+        source=$1 
+        target="${L3_SESSION_ID}_`date +%s`"_"$(echo $source|sed s@.*/@@)"
+        if echo $source | grep -q http://
+        then
+            curl -s "$source" > /tmp/$target 
+        else 
+            [ -r "$source" ] || { echo "l3upload: Can't open $source for reading" > /dev/stderr; return 1; }
+            cp $source /tmp/$target
+        fi
+        echo Uploaded file name is ${target}
+        curl -s -F photo=@/tmp/$target http://xgu.ru/l3-upload && rm -f /tmp/$target
+    fi
+}
+
+# Append lines from "$@" files to the end of the shell history
+hist_append ()
+{
+    eval $(cat "$@" | sed 's/"/\\\\"/g' | while read line; do echo history -s \"$line\"\;; done);
+}
+
+l3_save_last_line ()
+{
+    (
+    echo '<cline>'
+    history 1 | sed 's/&/&amp;/; s/</\&lt;/g; s/>/\&gt;/g'
+    echo '</cline>'
+    ) >> $L3_HOME/$L3_SESSION_ID.info
+}
+
+l3 ()
+{
+    case "$1" in
+        on)
+            echo switching on
+        ;;
+        off)
+            echo switcing off
+        ;;
+        cd)
+            echo l3cd="$2" > ~/.l3rc
+        ;;
+        pwd)
+            grep ^l3cd= ~/.l3rc | sed s/[^=]*=//
+        ;;
+        *) 
+            cat <<EOF
+l3 [command]:
+
+    cd new_context   - change current lilalo context
+    pwd              - show current lilalo context
+    on               - switch writing on (NOT IMPLEMENTED YET)
+    off              - switch writing off (NOT IMPLEMENTED YET)
+
+EOF
+        ;;
+    esac
+}
+
+l3cd()
+{
+    l3 cd "$@"
+}
+
+l3pwd()
+{
+    l3 pwd
+}
+
22:33:27
$vi /home/igor/.lilalo/l3bashrc
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ /home/igor/.lilalo/l3bashrc	2008-02-21 22:33:36.000000000 +0200
@@ -0,0 +1,287 @@
+#!/bin/sh
+
+# (c) Igor Chubin, igor@chub.in, 2004-2006
+
+# Environment variables set by the script:
+#
+#       L3_SESSION_ID   - uniq id of the LiLaLo-session
+#       L3_PARENT_TTY   - name of tty on which script is running
+#       PS1             - intercative shell prompt in which LiLaLo hides
+#                         various information about the command
+#       L3_TAMPERED_EDITORS - list of editors which are tampered with functions
+
+
+# Functions with the names starting _l3_ are internal.
+# Such functions are unset before this rc script exits
+
+_l3_editors_to_tamper='/bin/vi /usr/bin/vi /usr/bin/vim /bin/ee /usr/bin/ee /usr/bin/pico /usr/bin/nano /usr/local/bin/vim'
+
+_l3_start()
+{
+    echo $- | grep -q i || return 0
+    if _l3_is_running_here
+    then
+        _l3_env
+        _l3_init_prompt
+         l3_fix_prompt
+        _l3_tamper_editors
+        _l3_tamper_commands
+        _l3_unset_internal
+    else
+        _l3_start_session
+        _l3_run_script
+    fi
+}
+
+# ===================== STAGE 1 ============================
+
+_l3_is_running_here()
+{
+	ps waux | awk '{print $2" "$11 }' | grep -q ^$PPID" "script 
+	return $?
+
+# Check if ^^^^ run on Linux
+# and del  vvvv this if it does
+
+    export L3_TTY=`/usr/bin/tty` 
+    uname -a | grep -qi bsd && bsd=yes
+    proc_on_the_term=`w | grep "${L3_TTY##/dev/}" | awk '{print $8;}'`
+    # freeBSD: 
+    [ -n "$bsd" ] && \
+    proc_on_the_term=`w | grep "${L3_TTY##/dev/tty}" | awk '{print $6;}'`
+
+    [ -n "$proc_on_the_term" ] && echo $proc_on_the_term | grep -q script
+}
+
+_l3_start_session()
+{
+    export L3_SESSION_ID=${RANDOM}${RANDOM}${RANDOM}${RANDOM}-`date +%s`
+    export L3_HOME=~/.lilalo/
+    mkdir -p $L3_HOME
+
+    tty=`/usr/bin/tty`
+    uname -a | grep -qi bsd && bsd=yes
+    parent=`cat /proc/$PPID/cmdline 2> /dev/null`
+    [ -z "$parent" ] && parent="`ps waux | awk '{if ($2 == '$PPID') print $11; }'`"
+    system=`uname -rs`
+    login_from=`who | grep "${tty##/dev/}" | awk '{print $6;}' | tr -d '()'`
+    #[ -n "$bsd" ] && login_from="" #FIXME!
+    start_time=`date +%s`
+    hostname=`hostname -f 2> /dev/null`
+    [ -n "$bsd" ] && hostname=`hostname`
+
+    cat <<INFO > $L3_HOME/$L3_SESSION_ID.info
+<session>
+    <local_session_id>$L3_SESSION_ID</local_session_id>
+    <hostname>$hostname</hostname>
+    <user>$USER</user>
+    <uid>$UID</uid>
+    <login_from>$login_from</login_from>
+    <tty>$tty</tty>
+    <system>$system</system>
+    <parent>$parent</parent>
+    <ppid>$PPID</ppid>
+    <pid>$$</pid>
+    <start_time>$start_time</start_time>
+    <lang>$LANG</lang>
+</session>
+INFO
+
+    unset parent system login_from start_time hostname tty
+}
+
+_l3_run_script()
+{
+    uname -a | grep -qi bsd && bsd=yes
+    flush="-f"                          #linux
+    [ -n "$bsd" ] && flush="-t 0"       #freebsd
+    export L3_PARENT_TTY=`/usr/bin/tty`
+    exec script $flush -q $L3_HOME/${L3_SESSION_ID}.script
+}
+
+# ===================== STAGE 2 ============================
+
+_l3_env()
+{
+    trap l3_close_session 2
+    trap l3_close_session EXIT
+    true
+}
+
+l3_close_session()
+{
+    ( 
+        echo '<history>'
+        history | sed 's/&/\&amp;/; s/</\&lt;/g; s/>/\&gt;/g'
+        echo '</history>'
+    ) >> $L3_HOME/$L3_SESSION_ID.info
+}
+
+_l3_init_prompt()
+{
+    PS1='[\u@\h:\W]\$ '
+    [ $UID = 0 ] \
+        && PS1='\[\033[0;31m\]'$PS1'\[\033[0m\]' \
+        || PS1='\[\033[0;32m\]'$PS1'\[\033[0m\]' \
+    export PS1
+}
+
+l3_fix_prompt()
+{
+    export PS1='\[v2#\!#$?#$UID#$$#$(/bin/date +%s)$(l3_save_last_line)#$PWD#\033[1024D\033[K\]'$PS1
+}
+
+_l3_tamper_editors()
+{
+    for editor_file in $_l3_editors_to_tamper
+    do
+        [ -x $editor_file ] || continue
+        editor_name=${editor_file##*/}
+        eval "
+        $editor_name() { 
+            if [ -d \"\$1\" ] 
+            then
+                $editor_file \"\$1\"
+                return \$?
+            else
+                TIME=\"\`date +%s\`\"
+                DIR=\"\"
+                [ \"\${1#/}\" = \"\$1\" ] && DIR=\"\$PWD/\"
+                DIFFNAME=\"\${L3_SESSION_ID}_\${TIME}\`echo \$DIR\$1| sed s@_@__@ | sed 's@/@_@g'\`.diff\"
+                old_file=\"/tmp/l3-saved-\$\$.\$RANDOM.\$RANDOM\"
+                /bin/cp -- \"\$1\" \"\$old_file\" 2> /dev/null
+                $editor_file \"\$@\" || ERR=\$?
+                if [ -e \"\$old_file\" ]
+                then
+                diff -u \"\$old_file\" \"\$1\" > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null \
+                else
+                diff -u /dev/null \"\$1\"  > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null
+                fi
+                /bin/rm \"\$old_file\" 2> /dev/null
+                return \$ERR
+            fi
+        }
+        "
+        L3_TAMPERED_EDITORS="$L3_TAMPERED_EDITORS $editor_name"
+    done
+    [ -n "$L3_TAMPERED_EDITORS" ] && export L3_TAMPERED_EDITORS
+}
+
+_l3_tamper_commands()
+{
+    tty()
+    {
+        [ -n "$L3_PARENT_TTY" ] && echo $L3_PARENT_TTY || /usr/bin/tty
+    }
+}
+
+_l3_unset_internal()
+{
+    unset `set | grep '^_l3_.*()' | sed 's/()//'`
+    unset `set | grep '^_l3_.*=' | sed 's/=.*//'`
+}
+
+
+l3shot()
+{
+    if [ -x "`which xwd`" ]
+    then
+        _l3_home=${L3_HOME:-~/.lilalo}
+        shot_name="${L3_SESSION_ID}_`date +%s`".xwd
+        echo -n Choose window to be shoot ... >&2
+        [ -d ${_l3_home} ] || mkdir -p ${_l3_home}
+        xwd -out "$_l3_home/$shot_name" \
+        && echo Screenshot is written to ${_l3_home}/${shot_name} \
+        && curl -s -F photo=@$_l3_home/$shot_name http://xgu.ru/l3-upload
+    else
+        {
+            echo
+            echo "Can't make screenshot :("
+            echo 
+            echo I must use program xwd to make screenshot, 
+            echo but it seems not to be installed
+            echo Try to find the program in the \"xbase-clients\" package
+            echo
+        }   >&2 
+    fi
+}
+
+l3upload()
+{
+    if [ $# -lt 1 ]
+    then
+        echo Usage:
+        echo 
+        echo    l3upload "<filename>"
+        echo
+        echo "<filename>" - name of the file to upload
+        return 1
+    else
+        source=$1 
+        target="${L3_SESSION_ID}_`date +%s`"_"$(echo $source|sed s@.*/@@)"
+        if echo $source | grep -q http://
+        then
+            curl -s "$source" > /tmp/$target 
+        else 
+            [ -r "$source" ] || { echo "l3upload: Can't open $source for reading" > /dev/stderr; return 1; }
+            cp $source /tmp/$target
+        fi
+        echo Uploaded file name is ${target}
+        curl -s -F photo=@/tmp/$target http://xgu.ru/l3-upload && rm -f /tmp/$target
+    fi
+}
+
+# Append lines from "$@" files to the end of the shell history
+hist_append ()
+{
+    eval $(cat "$@" | sed 's/"/\\\\"/g' | while read line; do echo history -s \"$line\"\;; done);
+}
+
+l3_save_last_line ()
+{
+    (
+    echo '<cline>'
+    history 1 | sed 's/&/&amp;/; s/</\&lt;/g; s/>/\&gt;/g'
+    echo '</cline>'
+    ) >> $L3_HOME/$L3_SESSION_ID.info
+}
+
+l3 ()
+{
+    case "$1" in
+        on)
+            echo switching on
+        ;;
+        off)
+            echo switcing off
+        ;;
+        cd)
+            echo l3cd="$2" > ~/.l3rc
+        ;;
+        pwd)
+            grep ^l3cd= ~/.l3rc | sed s/[^=]*=//
+        ;;
+        *) 
+            cat <<EOF
+l3 [command]:
+
+    cd new_context   - change current lilalo context
+    pwd              - show current lilalo context
+    on               - switch writing on (NOT IMPLEMENTED YET)
+    off              - switch writing off (NOT IMPLEMENTED YET)
+
+EOF
+        ;;
+    esac
+}
+
+l3cd()
+{
+    l3 cd "$@"
+}
+
+l3pwd()
+{
+    l3 pwd
+}
+
/dev/pts/4
22:39:31
$vi /tmp/r
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ /tmp/r	2008-02-21 22:39:38.000000000 +0200
@@ -0,0 +1,4 @@
+line 1
+line 2
+line 3
+
22:39:38
$cat /tmp/r
line 1
line 2
line 3
22:40:56
$vi /tmp/r
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ /tmp/r	2008-02-21 22:41:02.000000000 +0200
@@ -0,0 +1,5 @@
+line 1
+line 2
+line 3
+line 4
+
22:41:02
$set | less
22:41:22
$vi /home/igor/.lilalo/l3bashrc
--- /dev/null	2008-02-21 10:31:37.004062750 +0200
+++ /home/igor/.lilalo/l3bashrc	2008-02-21 22:41:46.000000000 +0200
@@ -0,0 +1,287 @@
+#!/bin/sh
+
+# (c) Igor Chubin, igor@chub.in, 2004-2006
+
+# Environment variables set by the script:
+#
+#       L3_SESSION_ID   - uniq id of the LiLaLo-session
+#       L3_PARENT_TTY   - name of tty on which script is running
+#       PS1             - intercative shell prompt in which LiLaLo hides
+#                         various information about the command
+#       L3_TAMPERED_EDITORS - list of editors which are tampered with functions
+
+
+# Functions with the names starting _l3_ are internal.
+# Such functions are unset before this rc script exits
+
+_l3_editors_to_tamper='/bin/vi /usr/bin/vi /usr/bin/vim /bin/ee /usr/bin/ee /usr/bin/pico /usr/bin/nano /usr/local/bin/vim'
+
+_l3_start()
+{
+    echo $- | grep -q i || return 0
+    if _l3_is_running_here
+    then
+        _l3_env
+        _l3_init_prompt
+         l3_fix_prompt
+        _l3_tamper_editors
+        _l3_tamper_commands
+        _l3_unset_internal
+    else
+        _l3_start_session
+        _l3_run_script
+    fi
+}
+
+# ===================== STAGE 1 ============================
+
+_l3_is_running_here()
+{
+	ps waux | awk '{print $2" "$11 }' | grep -q ^$PPID" "script 
+	return $?
+
+# Check if ^^^^ run on Linux
+# and del  vvvv this if it does
+
+    export L3_TTY=`/usr/bin/tty` 
+    uname -a | grep -qi bsd && bsd=yes
+    proc_on_the_term=`w | grep "${L3_TTY##/dev/}" | awk '{print $8;}'`
+    # freeBSD: 
+    [ -n "$bsd" ] && \
+    proc_on_the_term=`w | grep "${L3_TTY##/dev/tty}" | awk '{print $6;}'`
+
+    [ -n "$proc_on_the_term" ] && echo $proc_on_the_term | grep -q script
+}
+
+_l3_start_session()
+{
+    export L3_SESSION_ID=${RANDOM}${RANDOM}${RANDOM}${RANDOM}-`date +%s`
+    export L3_HOME=~/.lilalo/
+    mkdir -p $L3_HOME
+
+    tty=`/usr/bin/tty`
+    uname -a | grep -qi bsd && bsd=yes
+    parent=`cat /proc/$PPID/cmdline 2> /dev/null`
+    [ -z "$parent" ] && parent="`ps waux | awk '{if ($2 == '$PPID') print $11; }'`"
+    system=`uname -rs`
+    login_from=`who | grep "${tty##/dev/}" | awk '{print $6;}' | tr -d '()'`
+    #[ -n "$bsd" ] && login_from="" #FIXME!
+    start_time=`date +%s`
+    hostname=`hostname -f 2> /dev/null`
+    [ -n "$bsd" ] && hostname=`hostname`
+
+    cat <<INFO > $L3_HOME/$L3_SESSION_ID.info
+<session>
+    <local_session_id>$L3_SESSION_ID</local_session_id>
+    <hostname>$hostname</hostname>
+    <user>$USER</user>
+    <uid>$UID</uid>
+    <login_from>$login_from</login_from>
+    <tty>$tty</tty>
+    <system>$system</system>
+    <parent>$parent</parent>
+    <ppid>$PPID</ppid>
+    <pid>$$</pid>
+    <start_time>$start_time</start_time>
+    <lang>$LANG</lang>
+</session>
+INFO
+
+    unset parent system login_from start_time hostname tty
+}
+
+_l3_run_script()
+{
+    uname -a | grep -qi bsd && bsd=yes
+    flush="-f"                          #linux
+    [ -n "$bsd" ] && flush="-t 0"       #freebsd
+    export L3_PARENT_TTY=`/usr/bin/tty`
+    exec script $flush -q $L3_HOME/${L3_SESSION_ID}.script
+}
+
+# ===================== STAGE 2 ============================
+
+_l3_env()
+{
+    trap l3_close_session 2
+    trap l3_close_session EXIT
+    true
+}
+
+l3_close_session()
+{
+    ( 
+        echo '<history>'
+        history | sed 's/&/\&amp;/; s/</\&lt;/g; s/>/\&gt;/g'
+        echo '</history>'
+    ) >> $L3_HOME/$L3_SESSION_ID.info
+}
+
+_l3_init_prompt()
+{
+    PS1='[\u@\h:\W]\$ '
+    [ $UID = 0 ] \
+        && PS1='\[\033[0;31m\]'$PS1'\[\033[0m\]' \
+        || PS1='\[\033[0;32m\]'$PS1'\[\033[0m\]' \
+    export PS1
+}
+
+l3_fix_prompt()
+{
+    export PS1='\[v2#\!#$?#$UID#$$#$(/bin/date +%s)$(l3_save_last_line)#$PWD#\033[1024D\033[K\]'$PS1
+}
+
+_l3_tamper_editors()
+{
+    for editor_file in $_l3_editors_to_tamper
+    do
+        [ -x $editor_file ] || continue
+        editor_name=${editor_file##*/}
+        eval "
+        $editor_name() { 
+            if [ -d \"\$1\" ] 
+            then
+                $editor_file \"\$1\"
+                return \$?
+            else
+                TIME=\"\`date +%s\`\"
+                DIR=\"\"
+                [ \"\${1#/}\" = \"\$1\" ] && DIR=\"\$PWD/\"
+                DIFFNAME=\"\${L3_SESSION_ID}_\${TIME}\`echo \$DIR\$1| sed s@_@__@ | sed 's@/@_@g'\`.diff\"
+                old_file=\"/tmp/l3-saved-\$\$.\$RANDOM.\$RANDOM\"
+                /bin/cp -- \"\$1\" \"\$old_file\" 2> /dev/null
+                $editor_file \"\$@\" || ERR=\$?
+                if [ -e \"\$old_file\" ]
+                then
+                diff -u \"\$old_file\" \"\$1\" > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null
+                else
+                diff -u /dev/null \"\$1\"  > \"\$L3_HOME/\$DIFFNAME\" 2> /dev/null
+                fi
+                /bin/rm \"\$old_file\" 2> /dev/null
+                return \$ERR
+            fi
+        }
+        "
+        L3_TAMPERED_EDITORS="$L3_TAMPERED_EDITORS $editor_name"
+    done
+    [ -n "$L3_TAMPERED_EDITORS" ] && export L3_TAMPERED_EDITORS
+}
+
+_l3_tamper_commands()
+{
+    tty()
+    {
+        [ -n "$L3_PARENT_TTY" ] && echo $L3_PARENT_TTY || /usr/bin/tty
+    }
+}
+
+_l3_unset_internal()
+{
+    unset `set | grep '^_l3_.*()' | sed 's/()//'`
+    unset `set | grep '^_l3_.*=' | sed 's/=.*//'`
+}
+
+
+l3shot()
+{
+    if [ -x "`which xwd`" ]
+    then
+        _l3_home=${L3_HOME:-~/.lilalo}
+        shot_name="${L3_SESSION_ID}_`date +%s`".xwd
+        echo -n Choose window to be shoot ... >&2
+        [ -d ${_l3_home} ] || mkdir -p ${_l3_home}
+        xwd -out "$_l3_home/$shot_name" \
+        && echo Screenshot is written to ${_l3_home}/${shot_name} \
+        && curl -s -F photo=@$_l3_home/$shot_name http://xgu.ru/l3-upload
+    else
+        {
+            echo
+            echo "Can't make screenshot :("
+            echo 
+            echo I must use program xwd to make screenshot, 
+            echo but it seems not to be installed
+            echo Try to find the program in the \"xbase-clients\" package
+            echo
+        }   >&2 
+    fi
+}
+
+l3upload()
+{
+    if [ $# -lt 1 ]
+    then
+        echo Usage:
+        echo 
+        echo    l3upload "<filename>"
+        echo
+        echo "<filename>" - name of the file to upload
+        return 1
+    else
+        source=$1 
+        target="${L3_SESSION_ID}_`date +%s`"_"$(echo $source|sed s@.*/@@)"
+        if echo $source | grep -q http://
+        then
+            curl -s "$source" > /tmp/$target 
+        else 
+            [ -r "$source" ] || { echo "l3upload: Can't open $source for reading" > /dev/stderr; return 1; }
+            cp $source /tmp/$target
+        fi
+        echo Uploaded file name is ${target}
+        curl -s -F photo=@/tmp/$target http://xgu.ru/l3-upload && rm -f /tmp/$target
+    fi
+}
+
+# Append lines from "$@" files to the end of the shell history
+hist_append ()
+{
+    eval $(cat "$@" | sed 's/"/\\\\"/g' | while read line; do echo history -s \"$line\"\;; done);
+}
+
+l3_save_last_line ()
+{
+    (
+    echo '<cline>'
+    history 1 | sed 's/&/&amp;/; s/</\&lt;/g; s/>/\&gt;/g'
+    echo '</cline>'
+    ) >> $L3_HOME/$L3_SESSION_ID.info
+}
+
+l3 ()
+{
+    case "$1" in
+        on)
+            echo switching on
+        ;;
+        off)
+            echo switcing off
+        ;;
+        cd)
+            echo l3cd="$2" > ~/.l3rc
+        ;;
+        pwd)
+            grep ^l3cd= ~/.l3rc | sed s/[^=]*=//
+        ;;
+        *) 
+            cat <<EOF
+l3 [command]:
+
+    cd new_context   - change current lilalo context
+    pwd              - show current lilalo context
+    on               - switch writing on (NOT IMPLEMENTED YET)
+    off              - switch writing off (NOT IMPLEMENTED YET)
+
+EOF
+        ;;
+    esac
+}
+
+l3cd()
+{
+    l3 cd "$@"
+}
+
+l3pwd()
+{
+    l3 pwd
+}
+
/dev/pts/4
22:41:52
$vi /tmp/r
--- /tmp/l3-saved-3726.24989.16604	2008-02-21 22:41:53.000000000 +0200
+++ /tmp/r	2008-02-21 22:41:59.000000000 +0200
@@ -2,4 +2,5 @@
 line 2
 line 3
 line 4
+line 5
 
22:41:59
$scp /home/igor/.lilalo/l3bashrc igor@chub.in:~/cvs/lilalo/
l3bashrc                                      100% 7453     7.3KB/s   00:00
прошло 10 минут
22:52:51
$св
bash: св: command not found
22:52:52
$cd

22:52:53
$cd /xen/images/openvpn-experiment/

22:53:07
$ls
debian1.img  debian3.img  debian5.img  openvpnbridge.cmapx  openvpnbridge.jpg  openvpnbridge.py   openvpnbridge.svg
debian2.img  debian4.img  debian6.img  openvpnbridge.dot    openvpnbridge.png  openvpnbridge.pyc  r
22:53:07
$rm r

22:53:10
$cat openvpnbridge.dot
graph G {
    edge [len=1.25];
    splines=true;
// nodes
    debian1 [color=white,shape=plaintext,label="  debian1",shapefile="/xen/xentaur/shapes/all/linux.png",fontcolor=black,fontsize=16,target="http://google.com"];
    debian2 [color=white,shape=plaintext,label="  debian2",shapefile="/xen/xentaur/shapes/all/linux.png",fontcolor=black,fontsize=16,target="http://google.com"];
    debian3 [color=white,shape=plaintext,label="  debian3",shapefile="/xen/xentaur/shapes/all/linux.png",fontcolor=black,fontsize=16,target="http://google.com"];
    debian4 [color=white,shape=plaintext,label="  debian4",shapefile="/xen/xentaur/shapes/all/linux.png",fontcolor=black,fontsize=16,target="http://google.com"];
    debian5 [color=white,shape=plaintext,label="  debian5",shapefile="/xen/xentaur/shapes/all/linux.png",fontcolor=black,fontsize=16,target="http://google.com"];
    freebsd6 [color=white,shape=plaintext,label="  freebsd6",shapefile="/xen/xentaur/shapes/all/freebsd.png",fontcolor=black,fontsize=16,target="http://google.com"];
...
    freebsd6 -- br4 [taillabel="eth1\n.4.6",fontsize=14,fontname=fixed];
    debian5 -- br4 [taillabel="eth0\n.4.5",fontsize=14,fontname=fixed];
    freebsd6 -- br1 [taillabel="eth0\n.1.6",fontsize=14,fontname=fixed];
    debian4 -- br3 [taillabel="eth0\n.3.4",fontsize=14,fontname=fixed];
    debian2 -- br1 [taillabel="eth0\n.1.2",fontsize=14,fontname=fixed];
    debian1 -- br1 [taillabel="eth0\n.1.1",fontsize=14,fontname=fixed];
    debian2 -- br2 [taillabel="eth1\n.2.2",fontsize=14,fontname=fixed];
    debian3 -- br3 [taillabel="eth1\n.3.3",fontsize=14,fontname=fixed];
    debian3 -- br2 [taillabel="eth0\n.2.3",fontsize=14,fontname=fixed];
};
22:53:14
$ls -l
итого 12595320
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:18 debian1.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:19 debian2.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:20 debian3.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:21 debian4.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:23 debian5.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:24 debian6.img
-rw-r--r-- 1 igor igor       1123 Фев 21 22:19 openvpnbridge.cmapx
-rw-r--r-- 1 igor igor       2278 Фев 21 22:19 openvpnbridge.dot
-rw-r--r-- 1 igor igor      23219 Фев 21 22:19 openvpnbridge.jpg
-rw-r--r-- 1 igor igor      44043 Фев 21 22:19 openvpnbridge.png
-rw-r--r-- 1 igor igor       1168 Фев 21 22:19 openvpnbridge.py
-rw-r--r-- 1 igor igor        590 Фев 21 22:19 openvpnbridge.pyc
-rw-r--r-- 1 igor igor       8785 Фев 21 22:19 openvpnbridge.svg
22:53:21
$cat openvpnbridge.py
import os
domain=os.environ['xendomain']
network='openvpnbridge'
domains =       [
                   'debian1',
                   'debian2',
                   'debian3',
                   'debian4',
                   'debian5',
                   'freebsd6',
...
        'debian4'      : [ 'br3', 'br4' ],
        'debian5'      : [ 'br4' ],
        'freebsd6'     : [ 'br1', 'br4' ],
}
#xenomips_dir='/xen/images/snrs/xentaur/'
#platform="7200"                 # 7200|3600|2691|3725|3745
#npe_type='npe-400'              # (7200 only) "npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300" and "npe-400"
#ios_name='C7200-AD.BIN'
#if domain=='dyn1':
#    ios_name='pix635-125.bin'
22:53:27
$vi openvpnbridge.py
--- /tmp/l3-saved-3726.22955.28173	2008-02-21 22:53:31.000000000 +0200
+++ openvpnbridge.py	2008-02-21 22:53:43.000000000 +0200
@@ -9,12 +9,10 @@
                    'debian3', 
                    'debian4', 
                    'debian5', 
-                   'freebsd6', 
                 ]
 domain_types =  [  
                     'linux', 'linux', 'linux', 
                     'linux', 'linux',
-                    'freebsd'
                 ]
 bridges =       [  
                     'br1', 
@@ -29,15 +27,7 @@
         'debian3'      : [ 'br2', 'br3' ],
         'debian4'      : [ 'br3', 'br4' ],
         'debian5'      : [ 'br4' ],
-        'freebsd6'     : [ 'br1', 'br4' ],
 }
 
 
-#xenomips_dir='/xen/images/snrs/xentaur/'
-#platform="7200"                 # 7200|3600|2691|3725|3745
-#npe_type='npe-400'              # (7200 only) "npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300" and "npe-400"
-#ios_name='C7200-AD.BIN'
-
-#if domain=='dyn1':
-#    ios_name='pix635-125.bin'
 
22:53:43
$/xen/xentaur/xentaur.py graph
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
# Network map is written to files: openvpnbridge.{png,svg,jpg,dot}
22:53:53
$gqview openvpnbridge.png

22:54:06
$/xen/xentaur/xentaur.py
Usage:
    xentaur <command> [<argument>]
Commands:
    start-all       --  start bridges and domains
    start-domains   --  start domains only
    start-bridges   --  start bridges only
    stop-all        --  stop bridges and domains
    stop-domains    --  stop domains only
    stop-bridges    --  stop bridges only (domains have to be stopped already)
    restart-all     --  restart bridges and domains
    start <domain>  --  start the <domain>
    stop <domain>   --  stop the <domain>
    graph           --  generate network scheme (result is in <network>.{png,jpg,svg})
    screen          --  generate GNU Screen config file (~/.screenrc_xentaur)
    shell           --  run Xentaur shell
22:54:09
$/xen/xentaur/xentaur.py start-bridges
#!/bin/sh
# create unbound bridges
sudo brctl show | awk '{print $1}' | grep -qx br4 || sudo brctl addbr br4
sudo brctl show | awk '{print $1}' | grep -qx br3 || sudo brctl addbr br3
sudo brctl show | awk '{print $1}' | grep -qx br2 || sudo brctl addbr br2
sudo brctl show | awk '{print $1}' | grep -qx br1 || sudo brctl addbr br1
sudo brctl stp br4 off
sudo brctl stp br3 off
sudo brctl stp br2 off
sudo brctl stp br1 off
sudo ip link set br4 up
sudo ip link set br3 up
sudo ip link set br2 up
sudo ip link set br1 up
22:54:13
$/xen/xentaur/xentaur.py start-bridges | sh -s
[sudo] password for igor:
Sorry, try again.
[sudo] password for igor:
22:54:26
$ls -l
итого 12595296
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:18 debian1.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:19 debian2.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:20 debian3.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:21 debian4.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:23 debian5.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:24 debian6.img
-rw-r--r-- 1 igor igor        996 Фев 21 22:53 openvpnbridge.cmapx
-rw-r--r-- 1 igor igor       1966 Фев 21 22:53 openvpnbridge.dot
-rw-r--r-- 1 igor igor      16489 Фев 21 22:53 openvpnbridge.jpg
-rw-r--r-- 1 igor igor      27473 Фев 21 22:53 openvpnbridge.png
-rw-r--r-- 1 igor igor        758 Фев 21 22:53 openvpnbridge.py
-rw-r--r-- 1 igor igor        544 Фев 21 22:53 openvpnbridge.pyc
-rw-r--r-- 1 igor igor       7484 Фев 21 22:53 openvpnbridge.svg
22:54:35
$/xen/xentaur/xentaur.py
Usage:
    xentaur <command> [<argument>]
Commands:
    start-all       --  start bridges and domains
    start-domains   --  start domains only
    start-bridges   --  start bridges only
    stop-all        --  stop bridges and domains
    stop-domains    --  stop domains only
    stop-bridges    --  stop bridges only (domains have to be stopped already)
    restart-all     --  restart bridges and domains
    start <domain>  --  start the <domain>
    stop <domain>   --  stop the <domain>
    graph           --  generate network scheme (result is in <network>.{png,jpg,svg})
    screen          --  generate GNU Screen config file (~/.screenrc_xentaur)
    shell           --  run Xentaur shell
22:54:50
$/xen/xentaur/xentaur.py start-domains
sudo xm create /home/igor/xentaur/xendomain.py  domain=debian1 network=openvpnbridge && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep debian1 | awk '{print $2}') -c 10 && sleep 1
sudo xm create /home/igor/xentaur/xendomain.py  domain=debian2 network=openvpnbridge && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep debian2 | awk '{print $2}') -c 10 && sleep 1
sudo xm create /home/igor/xentaur/xendomain.py  domain=debian3 network=openvpnbridge && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep debian3 | awk '{print $2}') -c 10 && sleep 1
sudo xm create /home/igor/xentaur/xendomain.py  domain=debian4 network=openvpnbridge && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep debian4 | awk '{print $2}') -c 10 && sleep 1
sudo xm create /home/igor/xentaur/xendomain.py  domain=debian5 network=openvpnbridge && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep debian5 | awk '{print $2}') -c 10 && sleep 1
22:54:57
$ls /home/igor/xentaur
build-xenomips-image  ids-2007dec.jpg  ios-packed      mini.svg                    snrs_ipsec_rsa_1.dot  snrs.pyc
CVS                   ids2007dec.jpg   logo.txt        netw.py                     snrs_ipsec_rsa_1.jpg  snrs.svg
dynamips              ids-2007dec.png  make-xen-vlans  netw.pyc                    snrs_ipsec_rsa_1.png  xendomain.py
examples              ids2007dec.png   mini.cmapx      shapes                      snrs_ipsec_rsa_1.py   xendomain.pyc
files                 ids2007dec.py    mini.dot        snrs-1.svg                  snrs_ipsec_rsa_1.pyc  xenomips.dot
ids-2007dec.cmapx     ids2007dec.pyc   mini.jpg        snrs.cmapx                  snrs_ipsec_rsa_1.svg  xentaur.dump
ids2007dec.cmapx      ids-2007dec.svg  mini.png        snrs.dot                    snrs.jpg              xentaur.py
ids-2007dec.dot       ids2007dec.svg   mini.py         snrs_ipsec_preshared_1.py   snrs.png
ids2007dec.dot        ios              mini.pyc        snrs_ipsec_preshared_1.pyc  snrs.py
22:55:11
$vi /home/igor/xentaur/xendomain.py
22:56:10
$ls /xen/xentaur-images/
ids2007dec  lost+found  masters  snrs  snrs-win2003-0.img
22:56:25
$ls -l
итого 12595296
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:18 debian1.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:19 debian2.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:20 debian3.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:21 debian4.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:23 debian5.img
-rw-r--r-- 1 igor igor 2147483648 Фев 21 21:24 debian6.img
-rw-r--r-- 1 igor igor        996 Фев 21 22:53 openvpnbridge.cmapx
-rw-r--r-- 1 igor igor       1966 Фев 21 22:53 openvpnbridge.dot
-rw-r--r-- 1 igor igor      16489 Фев 21 22:53 openvpnbridge.jpg
-rw-r--r-- 1 igor igor      27473 Фев 21 22:53 openvpnbridge.png
-rw-r--r-- 1 igor igor        758 Фев 21 22:53 openvpnbridge.py
-rw-r--r-- 1 igor igor        544 Фев 21 22:53 openvpnbridge.pyc
-rw-r--r-- 1 igor igor       7484 Фев 21 22:53 openvpnbridge.svg
22:56:34
$pwd
/xen/images/openvpn-experiment
22:56:38
$cd ..

22:57:05
$ln -s /xen/images/openvpn-experiment /xen/xentaur-images/openvpnbridge

22:57:27
$cd /xen/xentaur-images/openvpnbridge

22:57:33
$ls
debian1.img  debian3.img  debian5.img  openvpnbridge.cmapx  openvpnbridge.jpg  openvpnbridge.py   openvpnbridge.svg
debian2.img  debian4.img  debian6.img  openvpnbridge.dot    openvpnbridge.png  openvpnbridge.pyc
22:57:34
$/xen/xentaur/xentaur.py
Usage:
    xentaur <command> [<argument>]
Commands:
    start-all       --  start bridges and domains
    start-domains   --  start domains only
    start-bridges   --  start bridges only
    stop-all        --  stop bridges and domains
    stop-domains    --  stop domains only
    stop-bridges    --  stop bridges only (domains have to be stopped already)
    restart-all     --  restart bridges and domains
    start <domain>  --  start the <domain>
    stop <domain>   --  stop the <domain>
    graph           --  generate network scheme (result is in <network>.{png,jpg,svg})
    screen          --  generate GNU Screen config file (~/.screenrc_xentaur)
    shell           --  run Xentaur shell
22:57:58
$/xen/xentaur/xentaur.py start-domains
sudo xm create /home/igor/xentaur/xendomain.py  domain=debian1 network=openvpnbridge && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep debian1 | awk '{print $2}') -c 10 && sleep 1
sudo xm create /home/igor/xentaur/xendomain.py  domain=debian2 network=openvpnbridge && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep debian2 | awk '{print $2}') -c 10 && sleep 1
sudo xm create /home/igor/xentaur/xendomain.py  domain=debian3 network=openvpnbridge && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep debian3 | awk '{print $2}') -c 10 && sleep 1
sudo xm create /home/igor/xentaur/xendomain.py  domain=debian4 network=openvpnbridge && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep debian4 | awk '{print $2}') -c 10 && sleep 1
sudo xm create /home/igor/xentaur/xendomain.py  domain=debian5 network=openvpnbridge && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep debian5 | awk '{print $2}') -c 10 && sleep 1
22:58:04
$/xen/xentaur/xentaur.py start-domains | sh 0s
sh: 0s: Нет такого файла или каталога
close failed: [Errno 11] Resource temporarily unavailable
22:58:06
$/xen/xentaur/xentaur.py start-domains | sh -s
Using config file "/home/igor/xentaur/xendomain.py".
Error: No module named openvpnbridge
Using config file "/home/igor/xentaur/xendomain.py".
Error: No module named openvpnbridge
Using config file "/home/igor/xentaur/xendomain.py".
Error: No module named openvpnbridge
Using config file "/home/igor/xentaur/xendomain.py".
Error: No module named openvpnbridge
Using config file "/home/igor/xentaur/xendomain.py".
Error: No module named openvpnbridge
22:58:10
$vi /home/igor/xentaur/xendomain.py
--- /tmp/l3-saved-3726.6630.11195	2008-02-21 22:58:32.000000000 +0200
+++ /home/igor/xentaur/xendomain.py	2008-02-21 22:58:48.000000000 +0200
@@ -14,6 +14,7 @@
 import os
 
 sys.path.append(os.environ['HOME']+"/xentaur")
+sys.path.append('.')
 os.environ['xendomain']=domain
 
         
22:58:48
$/xen/xentaur/xentaur.py start-domains | sh -s
Using config file "/home/igor/xentaur/xendomain.py".
Started domain debian1
Using config file "/home/igor/xentaur/xendomain.py".
Error: Not enough free memory and dom0_min_mem is 0, so I cannot release any more.  I need 563200 KiB but only have 177176.
Using config file "/home/igor/xentaur/xendomain.py".
Interrupted.
xend [ERROR] Reading config file /etc/xen/xend-config.sxp:
Traceback (most recent call last):
  File "/usr/lib/xen-3.2-1/bin/xm", line 5, in ?
    from xen.xm import main
  File "/usr/lib/xen-3.2-1/lib/python/xen/xm/main.py", line 54, in ?
    from xen.util.acmpolicy import ACM_LABEL_UNLABELED_DISPLAY
  File "/usr/lib/xen-3.2-1/lib/python/xen/util/acmpolicy.py", line 30, in ?
    import xen.util.xsm.acm.acm as security
  File "/usr/lib/xen-3.2-1/lib/python/xen/util/xsm/acm/acm.py", line 39, in ?
    security_dir_prefix = XendOptions.instance().get_xend_security_path()
  File "/usr/lib/xen-3.2-1/lib/python/xen/xend/XendOptions.py", line 439, in instance
    inst = XendOptionsFile()
22:59:27
$sudo xm list
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0  1171     1     r-----   7943.1
debian1                                      2   550     1     -b----      3.5
dhcp                                         1   128     1     -b----      2.7
22:59:42
$sudo xm destroy debian1

22:59:53
$vi /home/igor/xentaur/xendomain.py
--- /tmp/l3-saved-3726.8555.10245	2008-02-21 22:59:56.000000000 +0200
+++ /home/igor/xentaur/xendomain.py	2008-02-21 23:00:37.000000000 +0200
@@ -146,7 +146,7 @@
 if domain_types[N] == 'quagga':
     memory = 64
 elif domain_types[N] == 'linux':
-    memory = 550
+    memory = 128
 else:
     memory = 300
 
23:00:37
$sudo xm list
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0  1171     1     r-----   7957.4
dhcp                                         1   128     1     -b----      2.8
23:00:42
$/xen/xentaur/xentaur.py start-domains | sh -s
Using config file "/home/igor/xentaur/xendomain.py".
Started domain debian1
Using config file "/home/igor/xentaur/xendomain.py".
Started domain debian2
Using config file "/home/igor/xentaur/xendomain.py".
Started domain debian3
Using config file "/home/igor/xentaur/xendomain.py".
Started domain debian4
Using config file "/home/igor/xentaur/xendomain.py".
Started domain debian5
23:01:14
$sudo xm list
Name                                        ID   Mem VCPUs      State   Time(s)
Domain-0                                     0  1171     1     r-----   8033.3
debian1                                      5   128     1     -b----      3.2
debian2                                      6   128     1     -b----      3.2
debian3                                      7   128     1     -b----      3.2
debian4                                      8   128     1     -b----      3.2
debian5                                      9   128     1     -b----      3.2
dhcp                                         1   128     1     -b----      2.8
23:06:04
$/xen/xentaur/xentaur.py screen
# GNU Screen config file is written to: /home/igor/.screenrc_xentaur
23:06:18
$screen -c /home/igor/.screenrc_xentaur
/dev/pts/11
23:06:49
$/xen/xentaur/xentaur.py shell
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
Warning: No loadimage plugin for "png:map"
# Network map is written to files: openvpnbridge.{png,svg,jpg,dot}
...
sudo xm shutdown debian4
sudo xm shutdown debian5
In [8]: stop_domains(domains)
sudo xm shutdown debian1
sudo xm shutdown debian2
sudo xm shutdown debian3
sudo xm shutdown debian4
sudo xm shutdown debian5
In [9]:
Do you really want to exit ([y]/n)?
23:08:47
$/xen/xentaur/xentaur.py
Usage:
    xentaur <command> [<argument>]
Commands:
    start-all       --  start bridges and domains
    start-domains   --  start domains only
    start-bridges   --  start bridges only
    stop-all        --  stop bridges and domains
    stop-domains    --  stop domains only
    stop-bridges    --  stop bridges only (domains have to be stopped already)
    restart-all     --  restart bridges and domains
    start <domain>  --  start the <domain>
    stop <domain>   --  stop the <domain>
    graph           --  generate network scheme (result is in <network>.{png,jpg,svg})
    screen          --  generate GNU Screen config file (~/.screenrc_xentaur)
    shell           --  run Xentaur shell
23:08:55
$/xen/xentaur/xentaur.py stop-domains | sh -s

Файлы

  • /tmp/l3-saved-2606.17003.30353
  • /tmp/r
  • openvpn-bridge.py
  • openvpnbridge.dot
  • openvpnbridge.py
  • /tmp/l3-saved-2606.17003.30353
    >
    hello
    hello line 2
    
    /tmp/r
    >
    line 1
    line 2
    line 3
    
    openvpn-bridge.py
    >
    import os
    domain=os.environ['xendomain']
    network='ids2007dec'
    domains =       [
                       'debian1',
                       'debian2',
                       'debian3',
                       'debian4',
                       'debian5',
                    ]
    domain_types =  [
                        'linux', 'linux', 'linux',
                        'linux', 'linux',
                    ]
    bridges =       [
                        'br1',
                        'br2',
                        'br3',
                        'br4',
                    ]
    vbridges_table ={
            'debian1'      : [ 'br1' ],
            'debian2'      : [ 'br1', 'br2' ],
            'debian3'      : [ 'br2', 'br3' ],
            'debian4'      : [ 'br3', 'br4' ],
            'debian5'      : [ 'br4' ],
    }
    #xenomips_dir='/xen/images/snrs/xentaur/'
    #platform="7200"                 # 7200|3600|2691|3725|3745
    #npe_type='npe-400'              # (7200 only) "npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300" and "npe-400"
    #ios_name='C7200-AD.BIN'
    #if domain=='dyn1':
    #    ios_name='pix635-125.bin'
    
    openvpnbridge.dot
    >
    graph G {
        edge [len=1.25];
        splines=true;
    // nodes
        debian1 [color=white,shape=plaintext,label="  debian1",shapefile="/xen/xentaur/shapes/all/linux.png",fontcolor=black,fontsize=16,target="http://google.com"];
        debian2 [color=white,shape=plaintext,label="  debian2",shapefile="/xen/xentaur/shapes/all/linux.png",fontcolor=black,fontsize=16,target="http://google.com"];
        debian3 [color=white,shape=plaintext,label="  debian3",shapefile="/xen/xentaur/shapes/all/linux.png",fontcolor=black,fontsize=16,target="http://google.com"];
        debian4 [color=white,shape=plaintext,label="  debian4",shapefile="/xen/xentaur/shapes/all/linux.png",fontcolor=black,fontsize=16,target="http://google.com"];
        debian5 [color=white,shape=plaintext,label="  debian5",shapefile="/xen/xentaur/shapes/all/linux.png",fontcolor=black,fontsize=16,target="http://google.com"];
        freebsd6 [color=white,shape=plaintext,label="  freebsd6",shapefile="/xen/xentaur/shapes/all/freebsd.png",fontcolor=black,fontsize=16,target="http://google.com"];
    // bridges
        br1 [color=white,shape=none,shapefile="/xen/xentaur/shapes/all/switch.png"];
        br2 [color=white,shape=none,shapefile="/xen/xentaur/shapes/all/switch.png"];
        br3 [color=white,shape=none,shapefile="/xen/xentaur/shapes/all/switch.png"];
        br4 [color=white,shape=none,shapefile="/xen/xentaur/shapes/all/switch.png"];
    // physical
        node [shape=rectangle,color=blue];
    // networks (not bridges, not physical)
        node [shape=rectangle,color=green];
    // links (between nodes and bridges)
        debian4 -- br4 [taillabel="eth1\n.4.4",fontsize=14,fontname=fixed];
        freebsd6 -- br4 [taillabel="eth1\n.4.6",fontsize=14,fontname=fixed];
        debian5 -- br4 [taillabel="eth0\n.4.5",fontsize=14,fontname=fixed];
        freebsd6 -- br1 [taillabel="eth0\n.1.6",fontsize=14,fontname=fixed];
        debian4 -- br3 [taillabel="eth0\n.3.4",fontsize=14,fontname=fixed];
        debian2 -- br1 [taillabel="eth0\n.1.2",fontsize=14,fontname=fixed];
        debian1 -- br1 [taillabel="eth0\n.1.1",fontsize=14,fontname=fixed];
        debian2 -- br2 [taillabel="eth1\n.2.2",fontsize=14,fontname=fixed];
        debian3 -- br3 [taillabel="eth1\n.3.3",fontsize=14,fontname=fixed];
        debian3 -- br2 [taillabel="eth0\n.2.3",fontsize=14,fontname=fixed];
    };
    
    openvpnbridge.py
    >
    import os
    domain=os.environ['xendomain']
    network='openvpnbridge'
    domains =       [
                       'debian1',
                       'debian2',
                       'debian3',
                       'debian4',
                       'debian5',
                       'freebsd6',
                    ]
    domain_types =  [
                        'linux', 'linux', 'linux',
                        'linux', 'linux',
                        'freebsd'
                    ]
    bridges =       [
                        'br1',
                        'br2',
                        'br3',
                        'br4',
                    ]
    vbridges_table ={
            'debian1'      : [ 'br1' ],
            'debian2'      : [ 'br1', 'br2' ],
            'debian3'      : [ 'br2', 'br3' ],
            'debian4'      : [ 'br3', 'br4' ],
            'debian5'      : [ 'br4' ],
            'freebsd6'     : [ 'br1', 'br4' ],
    }
    #xenomips_dir='/xen/images/snrs/xentaur/'
    #platform="7200"                 # 7200|3600|2691|3725|3745
    #npe_type='npe-400'              # (7200 only) "npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300" and "npe-400"
    #ios_name='C7200-AD.BIN'
    #if domain=='dyn1':
    #    ios_name='pix635-125.bin'
    

    Статистика

    Время первой команды журнала22:08:05 2008- 2-21
    Время последней команды журнала23:08:55 2008- 2-21
    Количество командных строк в журнале100
    Процент команд с ненулевым кодом завершения, %11.00
    Процент синтаксически неверно набранных команд, % 2.00
    Суммарное время работы с терминалом *, час 1.01
    Количество командных строк в единицу времени, команда/мин 1.64
    Частота использования команд
    vi24|====================| 20.69%
    xentaur.py23|===================| 19.83%
    ls15|============| 12.93%
    cd6|=====| 5.17%
    sh6|=====| 5.17%
    cat6|=====| 5.17%
    sudo4|===| 3.45%
    xm4|===| 3.45%
    set4|===| 3.45%
    less4|===| 3.45%
    cp2|=| 1.72%
    rm2|=| 1.72%
    gqview2|=| 1.72%
    l3upload2|=| 1.72%
    screen1|| 0.86%
    &1|| 0.86%
    pwd1|| 0.86%
    св1|| 0.86%
    pkill1|| 0.86%
    scp1|| 0.86%
    echo1|| 0.86%
    [1|| 0.86%
    l3cd1|| 0.86%
    ln1|| 0.86%
    l3pwd1|| 0.86%
    mv1|| 0.86%
    ____
    *) Интервалы неактивности длительностью 30 минут и более не учитываются

    Справка

    Для того чтобы использовать LiLaLo, не нужно знать ничего особенного: всё происходит само собой. Однако, чтобы ведение и последующее использование журналов было как можно более эффективным, желательно иметь в виду следующее:
    1. В журнал автоматически попадают все команды, данные в любом терминале системы.

    2. Для того чтобы убедиться, что журнал на текущем терминале ведётся, и команды записываются, дайте команду w. В поле WHAT, соответствующем текущему терминалу, должна быть указана программа script.

    3. Команды, при наборе которых были допущены синтаксические ошибки, выводятся перечёркнутым текстом:
      $ l s-l
      bash: l: command not found
      

    4. Если код завершения команды равен нулю, команда была выполнена без ошибок. Команды, код завершения которых отличен от нуля, выделяются цветом.
      $ test 5 -lt 4
      Обратите внимание на то, что код завершения команды может быть отличен от нуля не только в тех случаях, когда команда была выполнена с ошибкой. Многие команды используют код завершения, например, для того чтобы показать результаты проверки

    5. Команды, ход выполнения которых был прерван пользователем, выделяются цветом.
      $ find / -name abc
      find: /home/devi-orig/.gnome2: Keine Berechtigung
      find: /home/devi-orig/.gnome2_private: Keine Berechtigung
      find: /home/devi-orig/.nautilus/metafiles: Keine Berechtigung
      find: /home/devi-orig/.metacity: Keine Berechtigung
      find: /home/devi-orig/.inkscape: Keine Berechtigung
      ^C
      

    6. Команды, выполненные с привилегиями суперпользователя, выделяются слева красной чертой.
      # id
      uid=0(root) gid=0(root) Gruppen=0(root)
      

    7. Изменения, внесённые в текстовый файл с помощью редактора, запоминаются и показываются в журнале в формате ed. Строки, начинающиеся символом "<", удалены, а строки, начинающиеся символом ">" -- добавлены.
      $ vi ~/.bashrc
      2a3,5
      >    if [ -f /usr/local/etc/bash_completion ]; then
      >         . /usr/local/etc/bash_completion
      >        fi
      

    8. Для того чтобы изменить файл в соответствии с показанными в диффшоте изменениями, можно воспользоваться командой patch. Нужно скопировать изменения, запустить программу patch, указав в качестве её аргумента файл, к которому применяются изменения, и всавить скопированный текст:
      $ patch ~/.bashrc
      В данном случае изменения применяются к файлу ~/.bashrc

    9. Для того чтобы получить краткую справочную информацию о команде, нужно подвести к ней мышь. Во всплывающей подсказке появится краткое описание команды.

      Если справочная информация о команде есть, команда выделяется голубым фоном, например: vi. Если справочная информация отсутствует, команда выделяется розовым фоном, например: notepad.exe. Справочная информация может отсутствовать в том случае, если (1) команда введена неверно; (2) если распознавание команды LiLaLo выполнено неверно; (3) если информация о команде неизвестна LiLaLo. Последнее возможно для редких команд.

    10. Большие, в особенности многострочные, всплывающие подсказки лучше всего показываются браузерами KDE Konqueror, Apple Safari и Microsoft Internet Explorer. В браузерах Mozilla и Firefox они отображаются не полностью, а вместо перевода строки выводится специальный символ.

    11. Время ввода команды, показанное в журнале, соответствует времени начала ввода командной строки, которое равно тому моменту, когда на терминале появилось приглашение интерпретатора

    12. Имя терминала, на котором была введена команда, показано в специальном блоке. Этот блок показывается только в том случае, если терминал текущей команды отличается от терминала предыдущей.

    13. Вывод не интересующих вас в настоящий момент элементов журнала, таких как время, имя терминала и других, можно отключить. Для этого нужно воспользоваться формой управления журналом вверху страницы.

    14. Небольшие комментарии к командам можно вставлять прямо из командной строки. Комментарий вводится прямо в командную строку, после символов #^ или #v. Символы ^ и v показывают направление выбора команды, к которой относится комментарий: ^ - к предыдущей, v - к следующей. Например, если в командной строке было введено:

      $ whoami
      
      user
      
      $ #^ Интересно, кто я?
      
      в журнале это будет выглядеть так:
      $ whoami
      
      user
      
      Интересно, кто я?

    15. Если комментарий содержит несколько строк, его можно вставить в журнал следующим образом:

      $ whoami
      
      user
      
      $ cat > /dev/null #^ Интересно, кто я?
      
      Программа whoami выводит имя пользователя, под которым 
      мы зарегистрировались в системе.
      -
      Она не может ответить на вопрос о нашем назначении 
      в этом мире.
      
      В журнале это будет выглядеть так:
      $ whoami
      user
      
      Интересно, кто я?
      Программа whoami выводит имя пользователя, под которым
      мы зарегистрировались в системе.

      Она не может ответить на вопрос о нашем назначении
      в этом мире.
      Для разделения нескольких абзацев между собой используйте символ "-", один в строке.

    16. Комментарии, не относящиеся непосредственно ни к какой из команд, добавляются точно таким же способом, только вместо симолов #^ или #v нужно использовать символы #=

    17. Содержимое файла может быть показано в журнале. Для этого его нужно вывести с помощью программы cat. Если вывод команды отметить симоволами #!, содержимое файла будет показано в журнале в специально отведённой для этого секции.
    18. Для того чтобы вставить скриншот интересующего вас окна в журнал, нужно воспользоваться командой l3shot. После того как команда вызвана, нужно с помощью мыши выбрать окно, которое должно быть в журнале.
    19. Команды в журнале расположены в хронологическом порядке. Если две команды давались одна за другой, но на разных терминалах, в журнале они будут рядом, даже если они не имеют друг к другу никакого отношения.
      1
          2
      3   
          4
      
      Группы команд, выполненных на разных терминалах, разделяются специальной линией. Под этой линией в правом углу показано имя терминала, на котором выполнялись команды. Для того чтобы посмотреть команды только одного сенса, нужно щёкнуть по этому названию.

    О программе

    LiLaLo (L3) расшифровывается как Live Lab Log.
    Программа разработана для повышения эффективности обучения Unix/Linux-системам.
    (c) Игорь Чубин, 2004-2008

    $Id$