From 9265d3024034b9acd27254845be71bcf108b37d7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kosta=20Pribi=C4=87?= Date: Fri, 11 Sep 2009 15:11:19 +0200 Subject: [PATCH] Parcijalna implementacija routera (quagga) Elegantnije rijesena detekcija usera. Omogucen odabir routera u GUI-u, modificiran exec.tcl da propisno prosljedjuje konfiguraciju routeru. TODO izvrsavanje konfiguracije na routeru --- imunes.tcl | 4 +- linux/exec.tcl | 95 ++++++++++------ linux/quagga.tcl | 278 +++++++++++++++++++++++++++++++++++++++++++++++ test2.imn | 71 ++++++++++++ 4 files changed, 410 insertions(+), 38 deletions(-) create mode 100755 linux/quagga.tcl create mode 100644 test2.imn diff --git a/imunes.tcl b/imunes.tcl index 66fed15..308ae6a 100755 --- a/imunes.tcl +++ b/imunes.tcl @@ -146,7 +146,7 @@ if { $gui_unix && $gui_linux } { source "$ROOTDIR/$LIBDIR/eventsched.tcl" if { $gui_unix && $gui_linux } { -# source "$ROOTDIR/$LIBDIR/quagga.tcl" + source "$ROOTDIR/$LIBDIR/linux/quagga.tcl" # source "$ROOTDIR/$LIBDIR/xorp.tcl" # source "$ROOTDIR/$LIBDIR/static.tcl" source "$ROOTDIR/$LIBDIR/linux/pc.tcl" @@ -256,7 +256,7 @@ set exec_sockets_opened false #***** set remote_exec true -if { $gui_unix && [exec id -u] == 0 } { +if { $gui_unix && $::env(USERNAME) == "root" } { set remote_exec false } diff --git a/linux/exec.tcl b/linux/exec.tcl index 8c4126f..fd864da 100755 --- a/linux/exec.tcl +++ b/linux/exec.tcl @@ -103,11 +103,11 @@ proc setOperMode { mode } { puts "\nsetOperMode $mode" if { $mode == "exec" } { ;# let's try something, sockets should be opened - nexec id -u - if { $editor_only } { ;# if set in nexec or open_exec_sockets + puts $::env(USERNAME) + if { $editor_only } { ;# if set in nexec or open_exec_sockets .menubar.experiment entryconfigure "Execute" -state disabled return - } + } } # Verify that links to external interfaces are properly configured @@ -141,7 +141,7 @@ proc setOperMode { mode } { .bottom.oper_mode configure -text "$mode mode" set activetool select .left.select configure -state active - if { "$mode" == "exec" && [nexec id -u] == 0} { + if { "$mode" == "exec" && $::env(USERNAME) == "root" } { global autorearrange_enabled set autorearrange_enabled 0 .menubar.tools entryconfigure "Auto rearrange all" -state disabled @@ -289,6 +289,18 @@ proc l3node.instantiate { eid node } { nexec vzctl start $node +# s Linux/OpenVZ moramo pricekati da se izvrti init procedura, koja +# nam omoguci razne korisne stvari tipa proc filesystem itd + global openvz_node_dir + set openvz_node_dir "/var/lib/vz/private/$openvz_node_id" + set openvz_boot_done "$openvz_node_dir/tmp/imunes-boot-done" + puts " waiting for VE $openvz_node_id to actually start..." + while { ! [ file exists $openvz_boot_done ] } { + after 100 + } + puts " detected VE $openvz_node_id done" + file delete $openvz_boot_done + foreach ifc [ifcList $node] { switch -exact [string range $ifc 0 2] { eth { @@ -416,11 +428,11 @@ proc l3node.start { eid node } { # na FreeBSD-u vimagei imaju shared filesystem # na Linuxu VEovi to nemaju # set node_dir "/tmp/$eid/$node" - # puts " would recreate node_dir (/tmp/$eid/$node)" # nexec rm -fr $node_dir # nexec mkdir $node_dir # nexec chmod 1777 $node_dir + global openvz_node_dir # TODO: konfiguriranje MTU-a zasad ne podrzavamo (kao ni ostale L2 parametre) # foreach ifc [ifcList $node] { @@ -480,12 +492,14 @@ proc l3node.start { eid node } { puts " typemodel=[typemodel $node]" # puts "bootcfg=$bootcfg i bootcmd=$bootcmd" if { ! $remote_exec } { -# puts " would write node_dir/boot.conf" -# set fileId [open $node_dir/boot.conf w] -# foreach line $bootcfg { -# puts $fileId $line -# } -# close $fileId + if { $bootcmd != "/bin/sh" } { + puts " would write node_dir/boot.conf" + set fileId [open $node_dir/boot.conf w] + foreach line $bootcfg { + puts $fileId $line + } + close $fileId + } } else { nexec create_conf_file $node_dir/boot.conf foreach line $bootcfg { @@ -494,34 +508,43 @@ proc l3node.start { eid node } { nexec close_conf_file } -# puts " would execute bootcmd boot.conf in $node_id" -# catch nexec vimage $node_id $bootcmd $node_dir/boot.conf >& $node_dir/out.log &" - - foreach line $bootcfg { - puts " executing on $node: $line" - set command $line - if { "$command" != "" } { - catch { nexec vzctl exec $node $command } ret - # Ispravno izvedene naredbe u OpenVZ VE vracaju jedan prazan red - # pa ih se ignorira. Ako se preda prazan red kao naredba, takodjer je - # vracen jedan prazan red pa se i to ignorira. - if { $ret != "TCL_OK" && $ret != ""} { - - puts " =>Command \"$command\" executed on $node returned: \ - \"$ret\"" - - + if { $bootcmd == "/bin/sh" } { + foreach line $bootcfg { + puts " executing on $node: $line" + set command $line + if { "$command" != "" } { + catch { nexec vzctl exec $node $command } ret + # Ispravno izvedene naredbe u OpenVZ VE vracaju jedan prazan red + # pa ih se ignorira. Ako se preda prazan red kao naredba, takodjer je + # vracen jedan prazan red pa se i to ignorira. + if { $ret != "TCL_OK" && $ret != ""} { + puts " =>Command \"$command\" executed on $node returned: \ + \"$ret\"" + # TODO: batch mode handling + set str "Command \n\n \"$command\"\n\n executed on $node returned: \ + \n\n\"$ret\"\n\n" + tk_messageBox -message $str -type ok -icon info \ + -title "Configuration" + } + } + } + } else { +# quagga i drugi mogu imati svoje custom skripte za bootanje koja se prepoznaje po +# bootcmdu (interpreteru) koji nije obican shell + puts " would execute bootcmd $bootcmd boot.conf in $node_id" +# catch nexec vimage $node_id $bootcmd $node_dir/boot.conf >& $node_dir/out.log &" + set command "$bootcmd boot.conf" + catch { nexec vzctl exec $node $command } ret + if { $ret != "TCL_OK" && $ret != ""} { + puts " =>Command \"$command\" executed on $node returned: \ + \"$ret\"" # TODO: batch mode handling - # TODO: cemu sluzi TCL_OK uvjet? tko njega postavlja? kako znati da je - # odgovor error a ne samo neki info - set str "Command \n\n \"$command\"\n\n executed on $node returned: \ - \n\n\"$ret\"\n\n" - tk_messageBox -message $str -type ok -icon info \ - -title "Configuration" - } + set str "Command \n\n \"$command\"\n\n executed on $node returned: \ + \n\n\"$ret\"\n\n" + tk_messageBox -message $str -type ok -icon info \ + -title "Configuration" } } - } #****f* exec.tcl/l3node.shutdown diff --git a/linux/quagga.tcl b/linux/quagga.tcl new file mode 100755 index 0000000..f78b0a9 --- /dev/null +++ b/linux/quagga.tcl @@ -0,0 +1,278 @@ +# +# Copyright 2005-2008 University of Zagreb, Croatia. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# This work was supported in part by Croatian Ministry of Science +# and Technology through the research contract #IP-2003-143. +# + +# $Id: quagga.tcl,v 1.22 2008/01/02 12:08:46 marko Exp $ + + +#****h* imunes/quagga.tcl +# NAME +# router.quagga.tcl -- defines specific procedures for router +# using quagga routing model +# FUNCTION +# This module defines all the specific procedures for a router +# which uses quagga routing model. +# NOTES +# Procedures in this module start with the keyword router.quagga and +# end with function specific part that is the same for all the node +# types that work on the same layer. +#**** + + +set MODULE router.quagga + +#****f* quagga.tcl/router.quagga.layer +# NAME +# router.quagga.layer +# SYNOPSIS +# set layer [router.quagga.layer] +# FUNCTION +# Returns the layer on which the router using quagga model +# operates, i.e. returns NETWORK. +# RESULT +# * layer -- set to NETWORK +#**** + +proc $MODULE.layer {} { + return NETWORK +} + +#****f* quagga.tcl/router.quagga.cfggen +# NAME +# router.quagga.cfggen +# SYNOPSIS +# set config [router.quagga.cfggen $node_id] +# FUNCTION +# Generates configuration. This configuration represents +# the default configuration loaded on the booting time of the +# virtual nodes and it is closly related to the procedure +# router.quagga.bootcmd. +# Generated configuration comprises the ip addresses +# (both ipv4 and ipv6) and interface states (up or down) +# for each interface of a given node. Static routes are also +# included. +# INPUTS +# * node_id - id of the node (type of the node is router +# and routing model is quagga) +# RESULT +# * congif -- generated configuration +#**** + +proc $MODULE.cfggen { node } { + upvar 0 ::cf::[set ::curcfg]::$node $node + + set cfg {} + + foreach ifc [ifcList $node] { + lappend cfg "interface $ifc" + set addr [getIfcIPv4addr $node $ifc] + if { $addr != "" } { + lappend cfg " ip address $addr" + } + set addr [getIfcIPv6addr $node $ifc] + if { $addr != "" } { + lappend cfg " ipv6 address $addr" + } + if { [getIfcOperState $node $ifc] == "down" } { + lappend cfg " shutdown" + } + lappend cfg "!" + } + + foreach proto { rip ripng ospf ospf6 bgp } { + set protocfg [netconfFetchSection $node "router $proto"] + if { $protocfg != "" } { + lappend cfg "router $proto" + foreach line $protocfg { + lappend cfg "$line" + } + lappend cfg "!" + } + } + + foreach statrte [getStatIPv4routes $node] { + lappend cfg "ip route $statrte" + } + foreach statrte [getStatIPv6routes $node] { + lappend cfg "ipv6 route $statrte" + } + + return $cfg +} + +#****f* quagga.tcl/router.quagga.bootcmd +# NAME +# router.quagga.bootcmd +# SYNOPSIS +# set appl [router.quagga.bootcmd $node_id] +# FUNCTION +# Procedure bootcmd returns the defaut application that reads and +# employes the configuration generated in router.quagga.cfggen. +# In this case (procedure router.quagga.bootcmd) specific application +# is quaggaboot.sh +# INPUTS +# * node_id - id of the node (type of the node is router and +# routing model is quagga) +# RESULT +# * appl -- application that reads the configuration (quaggaboot.sh) +#**** + +proc $MODULE.bootcmd { node } { + + # TODO rijesiti konfiguraciju + puts " >>>>> $node <<<<< detekcija interpretera" + return "/bin/sh" + +# global ROOTDIR BINDIR + +# return "$ROOTDIR/$BINDIR/quaggaboot.sh" +} + +#****f* quagga.tcl/router.quagga.shellcmd +# NAME +# router.quagga.shellcmd +# SYNOPSIS +# set shell [router.quagga.shellcmd $node_id] +# FUNCTION +# Procedure shellcmd returns the shell that will be opened +# as a default shell for the virtual node. +# Procedure router.quagga.shellcmd returns vtysh. +# INPUTS +# * node_id - id of the node (type of the node is router +# and the routing model is quagga) +# RESULT +# * shell -- defalut shell for the router.quagga (vtysh) +#**** + +proc $MODULE.shellcmd { node } { + return "vtysh" +} + +#****f* quagga.tcl/router.quagga.instantiate +# NAME +# router.quagga.instantiate +# SYNOPSIS +# router.quagga.instantiate $eid $node_id +# FUNCTION +# Procedure instantiate creates a new virtaul node +# for a given node in imunes. +# Procedure router.quagga.instantiate cretaes a new virtual node +# with all the interfaces and CPU parameters as defined +# in imunes. It sets the net.inet.ip.forwarding and +# net.inet6.ip6.forwarding kernel variables to 1. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is router +# and routing model is quagga) +#**** +proc $MODULE.instantiate { eid node } { + set node_id "$eid\.$node" + l3node.instantiate $eid $node + + nexec vzctl exec $node sysctl -w net/ipv4/ip_forward=1 + nexec vzctl exec $node sysctl -w net/ipv6/conf/all/forwarding=1 + + puts " $eid $node ima aktivan IPv4 & IPv6 forwarding" + +} + + +#****f* quagga.tcl/router.quagga.start +# NAME +# router.quagga.start +# SYNOPSIS +# router.quagga.start $eid $node_id +# FUNCTION +# Starts a new router.quagga. The node can be started if it is instantiated. +# Simulates the booting proces of a router.quagga, by calling l3node.start +# procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is router.quagga) +#**** +proc $MODULE.start { eid node } { + l3node.start $eid $node +} + + +#****f* quagga.tcl/router.quagga.shutdown +# NAME +# router.quagga.shutdown +# SYNOPSIS +# router.quagga.shutdown $eid $node_id +# FUNCTION +# Shutdowns a router.quagga. Simulates the shutdown proces of a router.quagga, +# by calling the l3node.shutdown procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is router.quagga) +#**** +proc $MODULE.shutdown { eid node } { + l3node.shutdown $eid $node +} + + +#****f* quagga.tcl/router.quagga.destroy +# NAME +# router.quagga.destroy +# SYNOPSIS +# router.quagga.destroy $eid $node_id +# FUNCTION +# Destroys a router.quagga. Destroys all the interfaces of the router.quagga +# and the vimage itself by calling l3node.destroy procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is router.quagga) +#**** +proc $MODULE.destroy { eid node } { + l3node.destroy $eid $node +} + + +#****f* quagga.tcl/router.quagga.nghook +# NAME +# router.quagga.nghook +# SYNOPSIS +# router.quagga.nghook $eid $node_id $ifc +# FUNCTION +# Returns the id of the netgraph node and the name of the +# netgraph hook which is used for connecting two netgraph +# nodes. This procedure calls l3node.hook procedure and +# passes the result of that procedure. +# INPUTS +# * eid - experiment id +# * node_id - node id +# * ifc - interface name +# RESULT +# * nghook - the list containing netgraph node id and the +# netgraph hook (ngNode ngHook). +#**** + +proc $MODULE.nghook { eid node ifc } { + return [l3node.nghook $eid $node $ifc] +} + diff --git a/test2.imn b/test2.imn new file mode 100644 index 0000000..2d72238 --- /dev/null +++ b/test2.imn @@ -0,0 +1,71 @@ +node n0 { + type host + cpu {{min 0} {max 100} {weight 1}} + network-config { + hostname pero + ! + interface eth0 + ip address 10.0.0.10/24 + ipv6 address a:0::10/64 + ! + ip route 0.0.0.0/0 10.0.0.1 + ! + ipv6 route ::/0 a:0::1 + ! + } + canvas c0 + iconcoords {168.0 192.0} + labelcoords {168.0 224.0} + interface-peer {eth0 n1} +} + +node n1 { + type router + model quagga + network-config { + hostname n1 + ! + interface eth0 + ip address 10.0.0.1/24 + ipv6 address a:0::1/64 + ! + router rip + redistribute static + redistribute connected + redistribute ospf + network 0.0.0.0/0 + ! + router ripng + redistribute static + redistribute connected + redistribute ospf6 + network ::/0 + ! + } + canvas c0 + iconcoords {384.0 192.0} + labelcoords {384.0 216.0} + interface-peer {eth0 n0} +} + +link l0 { + nodes {n0 n1} + bandwidth 0 +} + +canvas c0 { + name {Canvas0} +} + +option show { + interface_names yes + ip_addresses yes + ipv6_addresses no + node_labels yes + link_labels yes + ipsec_configs yes + background_images no + annotations yes + grid yes +} + -- 2.39.5