# HG changeset patch # User Igor Chubin # Date 1263061208 -7200 # Node ID aaf034af3a357e133b6c0f554cc59c8772e9fa49 # Parent cf823d27b0295c425837e1851eb236a69b25fb85 Merge of Xgurulla into Xentaur code. Not completed yet!!! Now Xentaur can work with Amazon EC2, but only with. Local domains management is switched off temporarily. diff -r cf823d27b029 -r aaf034af3a35 files/ec2-instances --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/files/ec2-instances Sat Jan 09 20:20:08 2010 +0200 @@ -0,0 +1,183 @@ +#!/bin/sh + +DOMAIN=ec2.xgu.ru +NETWORK=net1 +INSTANCES_NUMBER=2 +INSTANCE_AMI=ami-b21ff8db +INSTANCE_AMI=ami-7cfd1a15 +SSH_SECRET_KEY=~/.ec2/id_rsa-pstam-keypair +SSH_KEYPAIR=pstam-keypair +VOLUME_NAME=vol-28d13141 +EC2_ZONE=us-east-1a +DOMAIN=ec2.xgu.ru +SCRIPTS_PATH=~/hg/xentaur/files + +XGURULLA_DIR=~/.xgurulla/ +WORK_DIR=${XGURULLA_DIR}/${NETWORK} +mkdir -p ${WORK_DIR} + +set -e -x +source ./start-instances-$NETWORK +# start_emulators is here + +message() +{ + printf "\033[1;33m[`date +"%T.%N"|cut -c1-12`] $*\033[0;39m\n" +} + +start_instances() +{ + message "* Starting instances" + > $NETWORK-instances + for i in `seq 0 $((INSTANCES_NUMBER-1))` + do + > /tmp/$NETWORK-ec2-run-instances + ec2-run-instances $INSTANCE_AMI -z $EC2_ZONE -k $SSH_KEYPAIR > /tmp/$NETWORK-ec2-run-instances + cat /tmp/$NETWORK-ec2-run-instances | grep INSTANCE | awk '{print $2}' >> $NETWORK-instances + message Instance `tail -1 $NETWORK-instances` started + done + message "* All $INSTANCES_NUMBER instances started" + cat $NETWORK-instances +} + +wait_for_loading() +{ + message "* Waiting for the instances finish loading" + > $NETWORK-instances-ready + exit=no + while [ "$exit" != yes ] + do + ec2-describe-instances | grep INSTANCE | egrep "`cat $NETWORK-instances|tr '\n' '|'`"NNNN | grep -q pending || exit=yes + ec2-describe-instances | grep INSTANCE | egrep "`cat $NETWORK-instances|tr '\n' '|'`"NNNN | grep -v pending \ + | egrep -v "`cat $NETWORK-instances-ready|tr '\n' '|'`"XXXX | awk '{print $2}'> /tmp/$NETWORK-instances-new + if [ -s "/tmp/$NETWORK-instances-new" ] + then + cat /tmp/$NETWORK-instances-new >> $NETWORK-instances-ready + echo -n " "`cat /tmp/$NETWORK-instances-new` + rm /tmp/$NETWORK-instances-new + else + echo -n . + fi + sleep 5 + done + echo + message "* Loading finished" +} + +update_dns() +{ + message "* Updating DNS records" + i=0 + cat $NETWORK-instances | while read instance + do + echo $NETWORK-node$i A $(host $(ec2-describe-instances $instance | grep INS | awk '{print $4}') | awk '{print $3}') + i=$((i+1)) + done > /tmp/zone-$NETWORK + message "New records:" + cat /tmp/zone-$NETWORK + cat /tmp/zone-$NETWORK | awk '{print $1}' > $NETWORK-hostnames + +#FIXME: The file should be not overwritten, but merged! + sudo mv /tmp/zone-$NETWORK /etc/bind/ec2-include + sudo rndc reload + message "* Updating DNS records finished" +} + +clear_old_ssh_keys() +{ +#FIXME! +# rm ~/.ssh/known_hosts + for i in `seq 0 $((INSTANCES_NUMBER-1))` + do + ssh-keygen -R $NETWORK-node$i.$DOMAIN + ssh-keygen -R $NETWORK-node$i + done +} + +ssh_keys() +{ + message "* Doing SSH keyscan" + for i in `seq 0 $((INSTANCES_NUMBER-1))` + do + ssh-keyscan $NETWORK-node$i.$DOMAIN + ssh-keyscan $NETWORK-node$i + done > ssh-keys-$NETWORK + clear_old_ssh_keys + cat ssh-keys-$NETWORK >> ~/.ssh/known_hosts + grep ^# ssh-keys-$NETWORK || true + message "* SSH keyscan finished" +} + +attach_block_device() +{ + ec2-attach-volume -d /dev/sdb -i `head -1 $NETWORK-instances` $VOLUME_NAME +} + +configure_instances() +{ +#FIXME: Only for managed hosts! Not for all! + cat < ~/.ssh/config +Host *.$DOMAIN + User root + IdentityFile $SSH_SECRET_KEY +EOF + > $NETWORK-preparation.log + message "* Preparing network. Detailed log messages are in $NETWORK-preparation.log" + for i in `seq 0 $((INSTANCES_NUMBER-1))` + do + host=$NETWORK-node$i.$DOMAIN + message "* Preparing $host" + message "** Copying configuration files" + ssh $host 'mkdir /etc/xgurulla' >> $NETWORK-preparation.log 2>&1 + scp ssh-keys-$NETWORK $host:~/.ssh/known_hosts >> $NETWORK-preparation.log 2>&1 + scp $SSH_SECRET_KEY $host:~/.ssh/id_dsa >> $NETWORK-preparation.log 2>&1 + cat < /etc/xgurulla/config' +NETWORK=$NETWORK +N=$i +SERVER=$NETWORK-node0.$DOMAIN +HOSTNAME=$host +EOF + scp $SCRIPTS_PATH/prepare-ec2-instance $host:/etc/xgurulla/ >> $NETWORK-preparation.log 2>&1 + message "** Installing software" + ssh $host sh /etc/xgurulla/prepare-ec2-instance >> $NETWORK-preparation.log 2>&1 + done +} + +start_all() { +start_instances +wait_for_loading +update_dns +ssh_keys +attach_block_device +configure_instances +message "* Starting emulators" +start_emulators +message "* Networking building completed" +} + +stop_instances() +{ +[ -s "$NETWORK-instances" ] && ec2-terminate-instances `cat $NETWORK-instances` +ec2-describe-instances +} + + +stop_all() +{ + stop_instances +} + +if [ "$1" = start ] +then + start_all +elif [ "$1" = stop ] +then + stop_all +else + cat << | | | | | | | + | | / / \ | | | | | | | + \_____ \____ _______ O / \ \____| \____| O | \____| + | + | + ----' + +EOF +} + +show_status() +{ +cat < /etc/hostname + echo 127.0.0.1 $HOSTNAME ${HOSTNAME%%.*} > /etc/hosts + hostname $HOSTNAME + touch /root/.hushlogin + export DEBIAN_FRONTEND=noninteractive + pkill apt-get ; pkill dpkg ; sleep 5; pkill apt-get; pkill dpkg ; sleep 5 + dpkg --configure -a + apt-get -q -y update + apt-get -q -y install dynamips openvpn bridge-utils rsync vlan unzip screen & + while ps waux | grep -q apt-get + do + sleep 5 + if ps aux | grep -v grep | grep -q dpkg.*defunct + then + pkill apt-get ; pkill dpkg ; sleep 5; pkill apt-get; pkill dpkg ; sleep 5 + dpkg --configure -a + apt-get -q -y install dynamips openvpn bridge-utils rsync vlan unzip screen & + fi + done +} + +server_bridges_setup() +{ + brctl addbr br0 + ip link set br0 up + ifconfig br0 promisc + for i in `seq 0 $MAX_INSTANCES` + do + brctl addif br0 tap$i + ip link set tap$i up + done +} + +vlans_setup() +{ + interface=$1 + ip link set $interface up + vconfig set_name_type VLAN_PLUS_VID_NO_PAD + for i in `seq $FIRST_VLAN $LAST_VLAN` + do + vconfig add $interface $i + ip link set vlan$i up + brctl addbr br$i + ip link set br$i up + ifconfig br$i promisc + brctl addif br$i vlan$i + done +} + +server_setup() +{ + cd /etc/openvpn + openvpn --genkey --secret static.key + for i in `seq 0 $MAX_INSTANCES` + do + cat < server$i.conf +port $((22000+i)) +secret static.key +dev tap$i +EOF + done + /etc/init.d/openvpn restart +} + +client_setup() +{ + cd /etc/openvpn + scp $SERVER:/etc/openvpn/static.key . + cat < client.conf +port $((22000+N)) +secret static.key +remote $SERVER +dev tap0 +EOF + /etc/init.d/openvpn restart +} + +copy_files_to_server() +{ + mkdir /mnt2 + mount /dev/sdb1 /mnt2 + rsync -a /mnt2/ /mnt/ + umount /mnt2 + rmdir /mnt2 + + #mkdir /mnt/ios + #cd /mnt/ios + #wget http://igor.chub.in/tmp/ios + #unzip ios +} + +copy_files_from_server() +{ + rsync -a $SERVER:/mnt/ /mnt/ +} + +if [ "$1" = vlans_setup ] +then + [ "$N" = 0 ] && vlans_setup br0 || vlan_setup tap0 + exit 0 +fi + +if [ "$1" = server_bridges_setup ] +then + [ "$N" = 0 ] && server_bridges_setup + exit 0 +fi + + +if [ "$N" = 0 ] +then + common_setup + server_setup + server_bridges_setup + vlans_setup br0 + copy_files_to_server +else + common_setup + client_setup + vlans_setup tap0 + copy_files_from_server +fi + diff -r cf823d27b029 -r aaf034af3a35 xendomain.py --- a/xendomain.py Mon Oct 12 00:12:11 2009 +0300 +++ b/xendomain.py Sat Jan 09 20:20:08 2010 +0200 @@ -45,7 +45,8 @@ real_nodes=[] connection_table={} -exec 'from %s import *' % (network) +#exec 'from %s import *' % (network) +from network import * # overriden by network config ############################ diff -r cf823d27b029 -r aaf034af3a35 xentaur.py --- a/xentaur.py Mon Oct 12 00:12:11 2009 +0300 +++ b/xentaur.py Sat Jan 09 20:20:08 2010 +0200 @@ -2,32 +2,34 @@ # vim: set fileencoding=utf-8 : import sys,os,time +from IPython.Shell import IPShellEmbed -xentaur_path="/xentaur/xentaur" +path_xentaur="%s/hg/xentaur" % os.environ['HOME'] +path_shapes=path_xentaur+'/shapes' +path_scripts=path_xentaur+'/files' + +network='net1' + +path_network=os.environ['HOME']+"/.xentaur/"+network +if not os.path.exists(path_network): + os.makedirs(path_network) +screenrc=path_network+"/.screenrc_xentaur" sys.path.append('/etc/xen') -sys.path.append(xentaur_path) +sys.path.append(path_xentaur) +sys.path.append(path_network) sys.path.append('.') node_object={} link_object={} bridge_object={} +ec2_node={} -network='multicast' domain='dyn1' - -#network='snrs' -#domain='dyn1' from xendomain import * bridges_turned_down=[] -from IPython.Shell import IPShellEmbed - - -screenrc=".screenrc_xentaur_"+network -path_shapes='/xentaur/xentaur/shapes' - def run(program, *args): pid = os.fork() if not pid: @@ -63,7 +65,7 @@ """ % (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" + print "sudo xm create "+path_xentaur+"/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: @@ -73,9 +75,56 @@ def start_all(): graph() screen() + html() start_bridges() start_domains() +def ec2_assign_nodes_to_instances(): + domain_number=0 + for dom in domains: + node_name=network+"-node%s"%(domain_number/2) + ec2_node[dom]=node_name + domain_number+=1 + +def make_start_emulators(): + s="" + #s+="cat screenrc_template > screenrc_$NETWORK\n" + #s+="echo \"screen -t console 0 sh -c 'cd ~/xentaur; ./xentaur.py shell'\" >> screenrc_$NETWORK\n" + ios="/mnt/ios/C7200-AD.BIN" + ec2_assign_nodes_to_instances() + for dom in domains: + node_name=ec2_node[dom] + i=0 + line='dynamips '+ios + line2='' + for iface in vbridges_table[dom]: + bridge=vbridges_table[dom][i] + if i>0: + line += " -p %s:PA-FE-TX "%i + line += " -s %s:0:tap:%s_%s "% (i,dom,iface) + line2 += "sleep 2; brctl addif %s %s; "%(bridge, dom+"_"+iface) + line2 +='ifconfig %s up; ifconfig %s promisc ;' %(bridge, bridge) + line2 += "ifconfig %s_%s up; "%(dom, iface) + i+=1 + s += "ssh %s \"mkdir -p /mnt/%s; cd /mnt/%s; screen -S %s- -d -m %s\"\n"%(node_name,dom,dom,dom,line) + s += "ssh %s \"%s\"\n" % (node_name, line2) + #s += "echo \"screen %s ssh -t %s 'screen -r %s-'\" >> screenrc_%s\n" % (domain_number, node_name, dom, network) + #s += "echo \"screen -t %s %s connect-ec2-session INSTANCE EC2_NODE %s %s %s\" >> screenrc_$NETWORK\n" % (dom, domain_number+1, node_name, network, dom) + return s + +def make_start_instances_config(net=network): + f = open(path_network+"/start-instances-"+network, "w"); + f.write("INSTANCES_NUMBER=%s\n"%((len(domains)+1)/2)) + f.write("start_emulators()\n{\n%s\n}\n"%make_start_emulators()) + f.close() + +def start_network(net=network): + make_start_instances_config() + #run_command("cd %s; env NETWORK=%s sh %s instances start" % (path_network, network, path_scrips+"/ec2-instances")) + +def stop_network(net=network): + run_command("cd %s; env NETWORK=%s sh instances stop" % (path_network, network)) + ## Stop def stop_domain(domain,wait=0): @@ -165,8 +214,12 @@ 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)) + screens.append("screen -t %(domain)s %(domain_number)s %(console_string)s" % { + 'domain' : domain, + 'domain_number' : domains.index(domain)+1, + 'console_string': node_object[domain].console_string(), + 'wait_interval' : 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%?"' @@ -179,7 +232,7 @@ screen -t console 0 sh -c 'while true; do %s/xentaur.py shell ; echo Retrying in %s secods...; sleep %s ; clear; done' %s -""" % (hardstatus,xentaur_path,wait_seconds,wait_seconds,screenlist)) +""" % (hardstatus,path_xentaur,wait_seconds,wait_seconds,screenlist)) f.close() print "# GNU Screen config file is written to: %s" % screenrc @@ -197,7 +250,7 @@ linklist=";\n ".join(map(lambda link: link_object[link].graphviz_string(),link_object.keys())) if linklist: linklist += ";" - f = open(network+".dot", "w"); + f = open(path_network+"/"+network+".dot", "w"); f.write (""" graph G { edge [len=1.25]; @@ -222,18 +275,40 @@ }; """ % (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 + run_command("neato -Tpng -o %s.png %s.dot "%(path_network+"/"+network,path_network+"/"+network)) + run_command("neato -Tjpg -o %s.jpg %s.dot "%(path_network+"/"+network,path_network+"/"+network)) + run_command("neato -Tsvg -o %s.svg %s.dot "%(path_network+"/"+network,path_network+"/"+network)) + #run_command("neato -Tcmapx -o %s.cmapx -NURL=http://google.com %s.dot "%(path_network+"/"+network,path_network+"/"+network)) + print "# Network map is written to files: %s.{png,svg,jpg,dot}" % (path_network+"/"+network) + +def html(): + f = open(path_network+"/index.html", "w"); + f.write (""" + + +Network %s map</network> +<body> +<img src="%s.png" /><br/> +<pre> +nodes=%s +bridges=%s +vbridges_table=%s +</pre> +</body> +</head> +</html> +""" % (network, network, domains, bridges, vbridges_table)) + f.close() + #run_command("cp %s.html /var/www/ec2/network/%s/index.html"%(network,network)) def autoredraw(): graph() + html() + screen() def shell(): autoredraw() - ipshell = IPShellEmbed() + ipshell = IPShellEmbed(['-noconfirm_exit']) ipshell() def version(): @@ -247,21 +322,6 @@ ' / \ | """ -# print "Xentaur 0.1-PRE" -# print "(Godzilla-mutant) _" -# print " / * \\" -# print " / .-" -# print " / |" -# print " | \\ \\\\ \\" -# print " _ -------| \\ \\\\ \\" -# print " / / \\_\\ -" -# print "/ |\\ | |" -# print "| | \\ .-----. | \\ |" -# print " | / \\ \\ \\ \\" -# print " \\/|.\\ \\ \\ \\ \\" -# print " \\| - . \\_\\ \\_\\" -# print "-----------------------------------------------" - def info(): version() @@ -364,6 +424,11 @@ 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): + ec2=True # FIXME + ec2_assign_nodes_to_instances() + if ec2: + return path_scripts+"/node-terminal-session INSTANCE EC2_NODE %s %s %s"%(ec2_node[self.name], network, self.name) + if self.type in [ 'quagga', 'dynamips', 'freebsd', 'linux' ]: return "sudo xm console "+self.name elif self.name in real_bridges or self.name in real_nodes: @@ -396,7 +461,7 @@ 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': + if domain_types[domains.index(self.node)] == 'dynamips': int_name="fa"+str(self.interface)+"/0" else: int_name="eth"+str(self.interface) @@ -538,6 +603,7 @@ cisco_set_ip_on_int=""" \n\n\n int fa%s/0 +duplex full no ip address ip address %s 255.255.255.0 no shutdown @@ -651,7 +717,7 @@ return 0 def configure_no_cdp_log_mismatch_duplex(doms=domains): - for dom in filter_by_type(domains,'xenomips'): + for dom in filter_by_type(domains,'dynamips'): write_to(dom,"\n\nena\nconf t\nno cdp log mismatch duplex\nend\n") def configure_save(doms=domains):