From 1471cd57720be60a91b0aaad6c8ddab2123d2f34 Mon Sep 17 00:00:00 2001 From: zrinka Date: Mon, 6 Mar 2006 08:48:55 +0000 Subject: [PATCH] Remote execution with ssh, starting and stopping nodes. Bug found by: Submitted by: Requested by: Reviewed by: Approved by: Obtained from: --- editor.tcl | 58 +++- exec.tcl | 693 +++++++++++++++++++++++++++---------------- exec_server.tcl | 40 ++- host.tcl | 57 +++- hub.tcl | 49 +++ imunes.tcl | 3 +- lanswitch.tcl | 52 ++++ pc.tcl | 55 ++++ quagga.tcl | 57 +++- rj45.tcl | 52 ++++ static.tcl | 54 ++++ vimageShellServer.sh | 9 +- xorp.tcl | 56 ++++ 13 files changed, 943 insertions(+), 292 deletions(-) diff --git a/editor.tcl b/editor.tcl index a3319d4..71e88bd 100755 --- a/editor.tcl +++ b/editor.tcl @@ -1056,9 +1056,17 @@ proc button3node { c x y } { .button3menu.ethereal add command -label $label \ -command "startethereal $node $ifc" } + .button3menu add command -label Start \ + -command "[typemodel $node].start $eid $node" + .button3menu add command -label Stop \ + -command "[typemodel $node].shutdown $eid $node" } else { .button3menu add cascade -label "Ethereal" \ -menu .button3menu.ethereal -state disabled + .button3menu add command -label start \ + -command "[typemodel $node].start $eid $node" -state disabled + .button3menu add command -label stop \ + -command "[typemodel $node].stop $eid $node" -state disabled } # @@ -2742,7 +2750,7 @@ proc animate {} { proc configRemoteHosts {} { global exec_hosts global remote_exec old_remote_exec editor_only - global active_host + global active_host active_ssh set old_remote_exec $remote_exec @@ -2786,6 +2794,12 @@ proc configRemoteHosts {} { label $wi.hosts.monitors.label -text "Monitor port" -anchor w frame $wi.hosts.active -borderwidth 2 label $wi.hosts.active.label -text "Active" -anchor w +# frame $wi.hosts.weight -borderwidth 2 +# label $wi.hosts.weight.label -text "Load (%)" -anchor w + frame $wi.hosts.ssh -borderwidth 2 + label $wi.hosts.ssh.label -text "ssh" -anchor w + frame $wi.hosts.userName -borderwidth 2 + label $wi.hosts.userName.label -text "User name" -anchor w set i 0 foreach host_elem $exec_hosts { @@ -2807,10 +2821,28 @@ proc configRemoteHosts {} { eval checkbutton $wi.hosts.active.v$i \ -variable active_host($i) -onvalue true -offvalue false +# eval entry $wi.hosts.weight.v$i -bg white -width 5 \ +# -validate focus -invcmd "focusAndFlash" +# $wi.hosts.weight.v$i insert 0 [lindex $host_elem 4] + + eval checkbutton $wi.hosts.ssh.v$i \ + -variable active_ssh($i) -onvalue true -offvalue false + # -command { + # if { active_ssh(0) } { + # eval $wi.hosts.userName.v$i -configure state normal + # } else { + # eval $wi.hosts.userName.v$i -configure state disabled + # } + # } + + eval entry $wi.hosts.userName.v$i -bg white -width 5 \ + -validate focus -invcmd "focusAndFlash" + $wi.hosts.userName.v$i insert 0 [lindex $host_elem 5] + incr i } - foreach j [list labels address ports monitors active] { + foreach j [list labels address ports monitors active ssh userName] { eval pack $wi.hosts.$j.label -side top -padx 4 -pady 2 -fill x set n [llength $exec_hosts] for {set i 0} {$i < $n} {incr i} { @@ -2818,7 +2850,8 @@ proc configRemoteHosts {} { } } pack $wi.hosts.labels $wi.hosts.address $wi.hosts.ports \ - $wi.hosts.monitors $wi.hosts.active -side left -fill x + $wi.hosts.monitors $wi.hosts.active \ + $wi.hosts.ssh $wi.hosts.userName -side left -fill x pack $wi.select $wi.hosts -side top -fill x -padx 4 frame $wi.butt -borderwidth 4 @@ -2851,9 +2884,9 @@ proc configRemoteHosts {} { #**** proc configRemoteHostsApply { wi } { global exec_hosts - global active_host + global active_host active_ssh global remote_exec editor_only - global exec_sock monitor_sock exec_sockets_opened + global execSock monSock exec_sockets_opened set n [llength $exec_hosts] set exec_hosts [] @@ -2862,7 +2895,9 @@ proc configRemoteHostsApply { wi } { set ent [list [$wi.hosts.address.v$i get] \ [$wi.hosts.ports.v$i get] \ [$wi.hosts.monitors.v$i get]\ - $active_host($i) ] + $active_host($i) \ + $active_ssh($i)\ + [$wi.hosts.userName.v$i get]] lappend exec_hosts $ent if { $active_host($i) } { set at_least_one_up true } } @@ -2870,10 +2905,8 @@ proc configRemoteHostsApply { wi } { set editor_only true .menubar.experiment entryconfigure "Execute" -state disabled } - catch { close exec_sock } message - catch { close monitor_sock } message - catch { unset exec_sock monitor_sock } message - set exec_sockets_opened false +# catch { unset exec_sock monitor_sock } message +# set exec_sockets_opened false destroy $wi } @@ -2909,7 +2942,10 @@ proc enable_disable { wi } { eval $wi.hosts.address.v$i configure -state $state eval $wi.hosts.ports.v$i configure -state $state eval $wi.hosts.monitors.v$i configure -state $state - set i [expr $i + 1] + #eval $wi.hosts.weight.v$i configure -state $state + eval $wi.hosts.ssh.v$i configure -state $state + eval $wi.hosts.userName.v$i configure -state $state + incr i } } diff --git a/exec.tcl b/exec.tcl index 9f84ba5..29ff073 100755 --- a/exec.tcl +++ b/exec.tcl @@ -1,4 +1,4 @@ -# + # Copyright 2004, 2005 University of Zagreb, Croatia. All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -33,60 +33,8 @@ # and Technology through the research contract #IP-2003-143. # -#****h* imunes/exec.tcl -# NAME -# exec.tcl -- file used for all the actions regarding -# FUNCTION -# This module is used for all actions that are executed during the -# simulation, i.e.in the exec mode. -#**** -#****f* exec.tcl/nexec_local -# NAME -# nexec_local -- remove link from GUI -# SYNOPSIS -# set result [nexec_local $args] -# FUNCTION -# Locally executes the program passed by args. Returns the results -# of the program. -# INPUTS -# * args -- program name and arguments that are to be evaluated. -# RESULT -# * result -- the program standard output. -#**** -proc nexec_local { args } { - eval exec $args -} - - -#****f* exec.tcl/Read_exec_results -# NAME -# Read_exec_results -- read exec results -# SYNOPSIS -# Read_exec_results $sock -# FUNCTION -# Reads one line from socket. If the socket is closed the line is not read. -# When the string Kraj is read, the exec_result_ready variable is set to 1, -# otherwise the line is appended to the exec_results list. -# INPUTS -# * sock -- socket -#**** -proc Read_exec_results {sock} { - global exec_results exec_results_ready - if {[eof $sock] || [catch {gets $sock line}]} { - close $sock - } else { - if {$line=="Kraj"} { - set exec_results [string range $exec_results 0 [expr [string length $exec_results] - 2]] - set exec_results_ready 1 - } else { - append exec_results $line "\n" - } - } - return -} - #****f* exec.tcl/nexec # NAME # nexec -- execute program @@ -104,8 +52,13 @@ proc Read_exec_results {sock} { #**** proc nexec { args } { global remote_exec editor_only - global exec_sock exec_results exec_results_ready - global exec_sockets_opened + global execSock + + if { $remote_exec } { + if { ![info exists execSock] || $execSock == "" } { + remoteStart + } + } if { $editor_only } { tk_messageBox -title "Editor only" \ @@ -116,56 +69,13 @@ proc nexec { args } { } if { $remote_exec } { - if { ! $exec_sockets_opened } { - open_exec_sockets - if { ! [info exists exec_sock] } { - tk_messageBox -title "Editor only" \ - -message "Cannot open sockets.\nMode changed to \"editor only\"." \ - -type ok - set editor_only true - return "" - } - } - set exec_results "" - puts $exec_sock "$args" - vwait exec_results_ready - return $exec_results + rexec $execSock $args } else { eval exec $args } } -#****f* exec.tcl/Read_monitor_results -# NAME -# Read_monitor_results -- read monitor results -# SYNOPSIS -# Read_monitor_results $sock -# FUNCTION -# Reads one line from socket. If the socket is closed the line is not read. -# When the string Kraj is read, the monitor_result_ready variable is set -# to 1, otherwise the line is appended to the monitor_results list. -# INPUTS -# * sock -- socket -#**** -# And now the same for monitor -proc Read_monitor_results {sock} { - global monitor_results monitor_results_ready - if {[eof $sock] || [catch {gets $sock line}]} { - close $sock - } else { - if {$line=="Kraj"} { - set monitor_results \ - [string range $monitor_results 0 \ - [expr [string length $monitor_results] - 2]] - set monitor_results_ready 1 - } else { - append monitor_results $line "\n" - } - } -} - - #****f* exec.tcl/nexec_monitor # NAME # nexec_monitor -- execute monitor @@ -174,8 +84,8 @@ proc Read_monitor_results {sock} { # FUNCTION # Executes the sting given in args variable. The sting is not executed # if IMUNES is running in editor only mode. Execution of a string can -# be local or remote. Opens an execute socket if it is not yet opened. -# Sends the arguments to monitor_sock if the remote execution is +# be local or remote. Opens a monitor socket if it is not yet opened. +# Sends the arguments to monitor socket if the remote execution is # selected, otherwise executes arguments locally. # INPUTS # * args -- the string that should be executed locally or remotely. @@ -184,8 +94,13 @@ proc Read_monitor_results {sock} { #**** proc nexec_monitor { args } { global remote_exec editor_only - global monitor_sock monitor_results monitor_results_ready - global exec_sockets_opened + global monSock + + if { $remote_exec } { + if { ![info exists monSock] || $monSock == "" } { + remoteStart + } + } if { $editor_only } { tk_messageBox -title "Editor only" \ @@ -195,117 +110,13 @@ proc nexec_monitor { args } { } if { $remote_exec } { - if { ! $exec_sockets_opened } { open_exec_sockets } - set monitor_results "" - puts $monitor_sock "$args" - vwait monitor_results_ready - return $monitor_results + rexec $monSock $args } else { eval exec $args } } -#****f* exec.tcl/open_exec_sockets -# NAME -# open_exec_sockets -- open execute socket -# SYNOPSIS -# open_exec_sockets -# FUNCTION -# Opens a socket for remote execution. Opens an exec socket and -# a monitor socket. The ip address and port numbers for sockets -# are defined in exec_hosts variable. The exec_host variable is -# also set. -#**** -proc open_exec_sockets {} { - global exec_hosts remote_exec exec_sockets_opened - global exec_host exec_port monitor_port exec_sock monitor_sock - global editor_only - - if { ! $remote_exec } { return } - - set remote_exec false - set n [llength $exec_hosts] - for { set i 0 } { $i < $n } { incr i } { - if { [lindex [lindex $exec_hosts $i] 3] } { - set exec_host [lindex [lindex $exec_hosts $i] 0] - set exec_port [lindex [lindex $exec_hosts $i] 1] - set monitor_port [lindex [lindex $exec_hosts $i] 2] - set remote_exec true - break - } - } - - if { ! $remote_exec } { return } - - set fail true - while {$fail} { - - if { ! [info exists exec_sock] || ! [info exists monitor_sock] } { - catch {set exec_sock [socket -async $exec_host $exec_port]} - catch {set monitor_sock [socket -async $exec_host $monitor_port]} - } - - if { [info exists exec_sock] && [info exists monitor_sock] } { - for { set i 1 } { $i <= 4 } { incr i } { - if {([lindex [fconfigure $exec_sock -sockname] 0] != "0.0.0.0") && - ([lindex [fconfigure $monitor_sock -sockname] 0] != "0.0.0.0") - && ([catch {fconfigure $exec_sock -peername} a] == 0) - && ([catch {fconfigure $monitor_sock -peername} a] == 0) } { - set fail false - break - } else { - after 250 ;# Max 2 sec for socket creation - } - } - } - - if { $fail } { - set sel [tk_dialog .box "Socket problems" \ - "Cannot open sockets {$exec_host,$exec_port|$monitor_port}" \ - "" 0 "Retry" "Configure remote hosts" "Editor only mode" ] - switch $sel { - 0 { ;# retry - } - 1 { configRemoteHosts - ;# Never comes back!? - set at_least_one_up false - set n [llength $exec_hosts] - for { set i 0 } { $i < $n } { incr i } { - if { [lindex [lindex $exec_hosts $i] 3] } { - set exec_host [lindex [lindex $exec_hosts $i] 0] - set exec_port [lindex [lindex $exec_hosts $i] 1] - set monitor_port [lindex [lindex $exec_hosts $i] 2] - set at_least_one_up true - break - } - } - if { $remote_exec && ! $at_least_one_up } { - set editor_only true - .menubar.experiment entryconfigure \ - "Execute" -state disabled - } - } - - 2 { set editor_only true - .menubar.experiment entryconfigure "Execute" -state disabled - set fail false - return - } - default { } - } - } - } - - fconfigure $exec_sock -buffering line - fileevent $exec_sock readable [list Read_exec_results $exec_sock] - - fconfigure $monitor_sock -buffering line - fileevent $monitor_sock readable [list Read_monitor_results $monitor_sock] - - set exec_sockets_opened true -} - #****f* exec.tcl/setOperMode # NAME @@ -324,14 +135,14 @@ proc open_exec_sockets {} { # editor mode (editor_only variable is set). # When changing the mode to edit, all required buttons are enabled # (except for simulation/Terminate button that is disabled) and -# procedure vimageCleanup is called. +# procedure cleanupCfg is called. # INPUTS # * mode -- the new operating mode. Can be edit or exec. #**** proc setOperMode { mode } { global oper_mode activetool node_list global nmbufs nmbclusters - global editor_only + global editor_only remote_exec execSock if { $mode == "exec" } { ;# let's try something, sockets should be opened nexec id -u @@ -377,16 +188,27 @@ proc setOperMode { mode } { .menubar.tools entryconfigure "Rearrange selected" -state disabled .menubar.experiment entryconfigure "Execute" -state disabled .menubar.experiment entryconfigure "Terminate" -state normal + .menubar.experiment entryconfigure "Configure remote hosts" \ + -state disabled .menubar.edit entryconfigure "Undo" -state disabled .menubar.edit entryconfigure "Redo" -state disabled set oper_mode exec set nmbufs [lindex [split [nexec sysctl kern.ipc.nmbufs]] 1] set nmbclusters [lindex [split [nexec sysctl kern.ipc.nmbclusters]] 1] monitor_loop - deployCfg + if { $remote_exec } { + nexec create_conf_file config.imn + dumpCfg file $execSock + nexec close_conf_file + nexec imunes -b config.imn + nexec rm config.imn + } else { + deployCfg + } } else { if {$oper_mode != "edit"} { - vimageCleanup + #vimageCleanup + cleanupCfg .menubar.tools entryconfigure "Rearrange all" -state normal .menubar.tools entryconfigure "Rearrange selected" -state normal } @@ -396,9 +218,12 @@ proc setOperMode { mode } { .menubar.experiment entryconfigure "Execute" -state normal } .menubar.experiment entryconfigure "Terminate" -state disabled + .menubar.experiment entryconfigure "Configure remote hosts" \ + -state normal .menubar.edit entryconfigure "Undo" -state normal .menubar.edit entryconfigure "Redo" -state normal set oper_mode edit + remoteClose } .c config -cursor left_ptr } @@ -422,7 +247,6 @@ proc statline {line} { puts $line } else { .bottom.textbox config -text "$line" - animateCursor } } @@ -553,6 +377,109 @@ proc l3node.nghook { eid node ifc } { } } +#****f* exec.tcl/l3node.start +# NAME +# l3node.start -- layer 3 node start +# SYNOPSIS +# l3node.start $eid $node +# FUNCTION +# Starts a new layer 3 node (pc, host or router). The node can be +# started if it is instantiated. +# Simulates the booting proces of a node, starts all the services +# and assignes the ip addresses to the interfaces. +# INPUTS +# * eid -- experiment id +# * node -- node id +#**** +proc l3node.start { eid node } { + global remote_exec execSock + + set node_id "$eid\_$node" + + nexec rm -fr /tmp/$node_id + nexec mkdir /tmp/$node_id + nexec chmod 1777 /tmp/$node_id + foreach ifc [ifcList $node] { + set mtu [getIfcMTU $node $ifc] + nexec vimage $node_id ifconfig $ifc mtu $mtu + } + + if { [getCustomEnabled $node] == true } { + set bootcmd [getCustomCmd $node] + set bootcfg [getCustomConfig $node] + } else { + set bootcmd "" + set bootcfg "" + } + if { $bootcmd == "" || $bootcfg =="" } { + set bootcfg [[typemodel $node].cfggen $node] + set bootcmd [[typemodel $node].bootcmd $node] + } + if { ! $remote_exec } { + set fileId [open /tmp/$node_id/boot.conf w] + foreach line $bootcfg { + puts $fileId $line + } + close $fileId + } else { + nexec create_conf_file /tmp/$node_id/boot.conf + foreach line $bootcfg { + puts $execSock $line + } + nexec close_conf_file + } + catch "nexec vimage $node_id $bootcmd /tmp/$node_id/boot.conf &" +} + +#****f* exec.tcl/l3node.shutdown +# NAME +# l3node.shutdown -- layer 3 node shutdown +# SYNOPSIS +# l3node.shutdown $eid $node +# FUNCTION +# Shutdowns a layer 3 node (pc, host or router). +# Simulates the shutdown proces of a node, kills all the services +# and deletes ip addresses of all interfaces. +# INPUTS +# * eid -- experiment id +# * node -- node id +#**** +proc l3node.shutdown { eid node } { + set node_id "$eid\_$node" + catch "nexec vimage $node_id kill -9 -1 2> /dev/null" + foreach ifc [ifcList $node] { + foreach ipv4 [getIfcIPv4addr $node $ifc] { + catch "nexec vimage $node_id ifconfig $ifc $ipv4 -alias" + } + foreach ipv6 [getIfcIPv6addr $node $ifc] { + catch "nexec vimage $node_id ifconfig $ifc inet6 $ipv6 -alias" + } + } +} + + +#****f* exec.tcl/l3node.destroy +# NAME +# l3node.destroy -- layer 3 node destroy +# SYNOPSIS +# l3node.destroy $eid $node +# FUNCTION +# Destroys a layer 3 node (pc, host or router). +# Destroys all the interfaces of the node by sending a shutdown message +# to netgraph nodes and on the end destroys the vimage itself. +# INPUTS +# * eid -- experiment id +# * node -- node id +#**** +proc l3node.destroy {eid node } { + set node_id "$eid\_$node" + foreach ifc [ifcList $node] { + catch { nexec ngctl msg $ifc@$node_id: shutdown } + } + catch {nexec vimage -d $node_id} + nexec rm -fr /tmp/$node_id +} + #****f* exec.tcl/deployCfg # NAME @@ -569,14 +496,15 @@ proc deployCfg {} { global eid global node_list link_list supp_router_models global mac_byte4 mac_byte5 - global exec_host remote_exec + global remote_exec set mac_byte4 0 set mac_byte5 0 set t_start [clock seconds] - vimageCleanup + #vimageCleanup + cleanupCfg catch { nexec mv /etc/resolv.conf /etc/resolv.conf.bak } catch { nexec kldload ng_ether } @@ -676,43 +604,7 @@ proc deployCfg {} { continue } statline "Configuring node [getNodeName $node]" - set node_id "$eid\_$node" - set model [getNodeModel $node] - if { [lsearch -exact {router pc host} $type] >= 0 } { - nexec rm -fr /tmp/$node_id - nexec mkdir /tmp/$node_id - nexec chmod 1777 /tmp/$node_id - foreach ifc [ifcList $node] { - set mtu [getIfcMTU $node $ifc] - nexec vimage $node_id ifconfig $ifc mtu $mtu - } - - if { [getCustomEnabled $node] == true } { - set bootcmd [getCustomCmd $node] - set bootcfg [getCustomConfig $node] - } else { - set bootcmd "" - set bootcfg "" - } - if { $bootcmd == "" || $bootcfg =="" } { - set bootcfg [[typemodel $node].cfggen $node] - set bootcmd [[typemodel $node].bootcmd $node] - } - if { ! $remote_exec } { - set fileId [open /tmp/$node_id/boot.conf w] - foreach line $bootcfg { - puts $fileId $line - } - close $fileId - } else { - nexec create_conf_file /tmp/$node_id/boot.conf - foreach line $bootcfg { - nexec $line - } - nexec close_conf_file - } - catch "nexec vimage $node_id $bootcmd /tmp/$node_id/boot.conf &" - } + [typemodel $node].start $eid $node } statline "Network topology instantiated in [expr [clock seconds] - $t_start] seconds ([llength $node_list] nodes and [llength $link_list] links)." @@ -725,8 +617,8 @@ proc deployCfg {} { # SYNOPSIS # vimageCleanup # FUNCTION -# Called upon the termination of the simulation. If cleans all -# the imunes objects created by the simulation that is terminated. +# Called in special circumstances only. If cleans all +# the imunes objects from the kernel (vimages and netgraph nodes). #**** proc vimageCleanup {} { global .c @@ -737,7 +629,8 @@ proc vimageCleanup {} { set vimages [lreplace $vimages $defindex $defindex] # Detach / destroy / reassign interfaces pipe, eiface, iface, bridge - set ngnodes [split [nexec ngctl l | tail -n +3] " "] + set ngnodes [split [nexec ngctl l | tail -n +3] " +"] foreach ngline $ngnodes { set node [lindex [eval list $ngline] 1] statline "Shutting down netgraph node $node" @@ -935,3 +828,293 @@ proc execSetLinkParams { eid link } { downstream={ BER=$ber duplicate=$dup } }" } +#****f* exec.tcl/cleanupCfg +# NAME +# cleanupCfg -- cleanup configuration +# SYNOPSIS +# cleanupCfg +# FUNCTION +# Called upon the termination of the simulation. If cleans all +# the imunes objects created by the simulation that is terminated. +# Operates in three steps, first shutdowns all the nodes, than all +# the links and on the end destroys all the nodes. +#**** +proc cleanupCfg { } { + global .c link_list eid node_list + + set t_start [clock seconds] + +#shutting down nodes... + + foreach node $node_list { + set type [nodeType $node] + set name [getNodeName $node] + if { $type != "pseudo" } { + statline "Shutting down node $name" + [typemodel $node].shutdown $eid $node + } + } + +#shutting down links... + + for { set pending_links $link_list } { $pending_links != "" } {} { + set link [lindex $pending_links 0] + set i [lsearch -exact $pending_links $link] + set pending_links [lreplace $pending_links $i $i] + + set lnode1 [lindex [linkPeers $link] 0] + set lnode2 [lindex [linkPeers $link] 1] + set ifname1 [ifcByPeer $lnode1 $lnode2] + set ifname2 [ifcByPeer $lnode2 $lnode1] + + if { [getLinkMirror $link] != "" } { + set mirror_link [getLinkMirror $link] + set i [lsearch -exact $pending_links $mirror_link] + set pending_links [lreplace $pending_links $i $i] + + set p_lnode2 $lnode2 + set lnode2 [lindex [linkPeers $mirror_link] 0] + set ifnode2 [ifcByPeer $lnode2 [getNodeMirror $p_lnode2]] + } + set lname $eid\_$lnode1-$lnode2 + statline "Shutting down netgraph node $lname" + catch "nexec ngctl msg $lname: shutdown" + } + + +#destroying nodes... + + foreach node $node_list { + set type [nodeType $node] + set name [getNodeName $node] + if { $type != "pseudo" } { + statline "Destroying node $node" + [typemodel $node].destroy $eid $node + } + } + +#all the rest... + catch { nexec rm -f /usr/local/etc/quagga/Quagga.conf } + catch { nexec mv /etc/resolv.conf.bak /etc/resolv.conf } + statline "Cleanup completed in [expr [clock seconds] - $t_start] seconds." + +} + +#****f* exec.tcl/openFwrd +# NAME +# openFwrd -- open port forwarding +# SYNOPSIS +# set result [openFwrd lPort rPort rHost] +# FUNCTION +# Called upon starting remote execution with ssh port forwarding. +# Works only on unix hosts, opens a secure connection from local host +# to remote host. Uses a key authentication. Returns the proces id +# of port forwarding +# INPUTS +# lPort -- local port +# rPort -- remote port +# rHost -- remote host in the form: userName@hostName +# RESULT +# * result -- proces id of ssh port forwarding +#**** +proc openFwrd { lPort rPort rHost } { + global tcl_platform platform + if { $tcl_platform(platform) == "unix" } { + set pid [exec ssh -N -L $lPort:localhost:$rPort $rHost &] + return $pid + } +} + +#****f* exec.tcl/closeFwrd +# NAME +# closeFwrd -- close port forwarding +# SYNOPSIS +# set result [closeFwrd pid] +# FUNCTION +# Called upon ending remote execution with ssh port forwarding. +# Works only on unix hosts, closes a secure connection from a local host +# to the remote host. +# INPUTS +# pid -- proces id +#**** +proc closeFwrd { pid } { + global tcl_platform platform + if { $tcl_platform(platform) == "unix" } { + catch {eval exec kill $pid} + return "" + } +} + +#****f* exec.tcl/open_sock +# NAME +# open_sock -- open socket +# SYNOPSIS +# set sock [open_sock rHost rPort] +# FUNCTION +# Called upon starting remote execution. Opens a socket. +# If the ssh encryption is used a socket to the local port is opened, +# else a socket to the remote host is used. If the creation of +# socket fails, an empty string is returend. +# INPUTS +# rHost -- remote host in the form: hostName +# rPort -- remote port +# RESULT +# * sock -- socket +#**** +proc open_sock { rHost rPort } { + global ssh + + if { $ssh } { + catch { set sock [socket localhost [expr $rPort + 10]] } + } else { + catch { set sock [socket $rHost $rPort] } + } + if { [info exists sock] } { + return $sock + } else { + return "" + } +} + +#****f* exec.tcl/close_sock +# NAME +# close_sock -- close socket +# SYNOPSIS +# set sock [close_sock sock] +# FUNCTION +# Called upon ending remote execution. Closes a socket and returns an empty string. +# INPUTS +# sock -- socket that is being closed +# RESULT +# * sock -- an empty string +#**** +proc close_sock { sock } { + catch { close $sock } + return "" +} + +#****f* exec.tcl/rexec +# NAME +# rexec -- remote exec +# SYNOPSIS +# rexec io command +# FUNCTION +# Called upon remote execution of a command. Puts the command on the io, and reads the response +# until a string Kraj is read. Returns all the received lines before string Kraj. +# INPUTS +# io -- socket on which the command is passed +# command -- command that is remotly executed +# RESULT +# * response -- the command output +#**** +proc rexec { io command } { + set response "" + + puts $io $command + flush $io + + gets $io line + if { $line == "Kraj rada" } { + close $io + } + if {$line != "Kraj" } { + set response $line + gets $io line + } + while { $line != "Kraj" } { + append response "\n" $line + gets $io line + } + return $response +} + +#****f* exec.tcl/remoteStart +# NAME +# remoteStart -- remoteStart +# SYNOPSIS +# remoteStart +# FUNCTION +# Starts the remote execution. Reads the parameters from the gui, decides +# to open an encrypted chanel or e reguar socket for remote execution. +# If the sockets cannot be opened, a message box is displayed. +#**** +proc remoteStart {} { + global monSock execSock mpid epid lmPort lePort editor_only ssh + global remote_exec exec_hosts exec_host + + if { ! $remote_exec } { return } + + set remote_exec false + set n [llength $exec_hosts] + for { set i 0 } { $i < $n } { incr i } { + if { [lindex [lindex $exec_hosts $i] 3] } { + set rHost [lindex [lindex $exec_hosts $i] 0] + set rePort [lindex [lindex $exec_hosts $i] 1] + set rmPort [lindex [lindex $exec_hosts $i] 2] + set ssh [lindex [lindex $exec_hosts $i] 4] + set userName [lindex [lindex $exec_hosts $i] 5] + set remote_exec true + set exec_host $rHost + break + } + } + + if { ! $remote_exec } { return } + + + if { (![info exists mpid] || $mpid == "") && $ssh } { + set mpid [openFwrd [expr $rmPort + 10] $rmPort $userName@$rHost] + } + if { (![info exists epid] || $epid == "") && $ssh } { + set epid [openFwrd [expr $rePort + 10] $rePort $userName@$rHost] + } + after 500 { set t 1 } + vwait t + if { ![info exists monSock] || $monSock == "" } { + set monSock [open_sock $rHost $rmPort] + } + if { ![info exists execSock] || $execSock == "" } { + set execSock [open_sock $rHost $rePort] + } + if { $monSock == "" || $execSock == "" } { + set sel [tk_dialog .box "Socket problems" \ + "Cannot open sockets" \ + "" 0 "Retry" "Configure remote hosts" "Editor only mode" ] + switch $sel { + 0 { + remoteStart + } + 1 { + configRemoteHosts + } + 2 { + set editor_only true + } + + } + } +} + +#****f* exec.tcl/remoteClose +# NAME +# remoteClose +# SYNOPSIS +# remoteClose -- closes the remote execution +# FUNCTION +# Closes the remote execution of the experiment. Closes all the sockets. +#**** +proc remoteClose { } { + global execSock monSock remote_exec mpid epid + + if { $remote_exec } { + set execSock [close_sock $execSock] + set monSock [close_sock $monSock] + if { [info exists mpid] && ($mpid != "") } { + set mpid [closeFwrd $mpid] + } + if { [info exists epid] && ($epid != "") } { + set epid [closeFwrd $epid] + } + } + return +} diff --git a/exec_server.tcl b/exec_server.tcl index 4fdbd11..45dd531 100755 --- a/exec_server.tcl +++ b/exec_server.tcl @@ -72,38 +72,36 @@ proc Exec_command {sock} { exit 0 } - set command [lindex $line 0] - switch -exact $command { - - "create_conf_file" { - set conf_fajl [lindex $line 1] - if { $debug_output} { puts "Spremam conf fajl: $conf_fajl" } - set fileId [open "$conf_fajl" w] - ;# dodati provjeru!!! - set spremam_conf_fajl true - } - - "close_conf_file" { - if { $debug_output} { puts "Zatvaram conf fajl" } - close $fileId - set spremam_conf_fajl false - } - default { - if { $spremam_conf_fajl } { - catch {eval puts $fileId "$line"} odg + if {$spremam_conf_fajl} { + if { $line == "close_conf_file" } { + if { $debug_output} { puts "Zatvaram conf fajl" } + close $fileId + set spremam_conf_fajl false + puts $sock "Kraj" + } else { + catch {puts $fileId $line} odg if { $debug_output && ($odg != "") } { puts "$server_port/puts greska: $odg" } + } + } else { + if { [lindex $line 0] == "create_conf_file" } { + set conf_fajl [lindex $line 1] + if { $debug_output} { puts "Spremam conf fajl: $conf_fajl" } + set fileId [open "$conf_fajl" w] + ;# dodati provjeru!!! + set spremam_conf_fajl true + } else { if { [llength $line] == 0 } { return} catch {eval exec $line} odg if { $debug_output } { puts "$server_port/O: $odg" } puts $sock $odg } + + puts $sock "Kraj" } - } - puts $sock "Kraj" catch {flush $sock} rez if { $rez != "" } { puts "Socket closed on remote.\n$rez" diff --git a/host.tcl b/host.tcl index c0b7b0c..7ec829c 100755 --- a/host.tcl +++ b/host.tcl @@ -177,12 +177,67 @@ proc $MODULE.shellcmd { node } { # * eid - experiment id # * node_id - id of the node (type of the node is host) #**** - proc $MODULE.instantiate { eid node } { l3node.instantiate $eid $node return } + +#****f* host.tcl/host.start +# NAME +# host.start +# SYNOPSIS +# host.start $eid $node_id +# FUNCTION +# Starts a new host. The node can be started if it is instantiated. +# Simulates the booting proces of a host, by calling l3node.start +# procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is host) +#**** +proc $MODULE.start { eid node } { + l3node.start $eid $node + return +} + + +#****f* host.tcl/host.shutdown +# NAME +# host.shutdown +# SYNOPSIS +# host.shutdown $eid $node_id +# FUNCTION +# Shutdowns a host. Simulates the shutdown proces of a host, +# by calling the l3node.shutdown procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is host) +#**** +proc $MODULE.shutdown { eid node } { + l3node.shutdown $eid $node + return +} + + +#****f* host.tcl/host.destroy +# NAME +# host.destroy +# SYNOPSIS +# host.destroy $eid $node_id +# FUNCTION +# Destroys a host. Destroys all the interfaces of the host +# and the vimage itself by calling l3node.destroy procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is host) +#**** +proc $MODULE.destroy { eid node } { + l3node.destroy $eid $node + return +} + + #****f* host.tcl/host.nghook # NAME # host.nghook diff --git a/hub.tcl b/hub.tcl index 1eb1cdb..57f5f42 100755 --- a/hub.tcl +++ b/hub.tcl @@ -87,6 +87,55 @@ proc $MODULE.instantiate { eid node } { return } +#****f* hub.tcl/hub.start +# NAME +# hub.start +# SYNOPSIS +# hub.start $eid $node_id +# FUNCTION +# Starts a new hub. Since hub has no starting code, +# this procedure does nothing. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is hub) +#**** +proc $MODULE.start { eid node } { + return +} + +#****f* hub.tcl/hub.shutdown +# NAME +# hub.shutdown +# SYNOPSIS +# hub.shutdown $eid $node_id +# FUNCTION +# Shutdowns a hub. Since hub has no shutdown code, +# this procedure does nothing. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is hub) +#**** +proc $MODULE.shutdown { eid node } { + return +} + +#****f* hub.tcl/hub.destroy +# NAME +# hub.destroy +# SYNOPSIS +# hub.destroy $eid $node_id +# FUNCTION +# Destroys a hub. Destroys the netgraph node that represents +# the hub by sending a shutdown message. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is hub) +#**** +proc $MODULE.destroy { eid node } { + catch { nexec ngctl msg $eid\_$node: shutdown } + return +} + #****f* hub.tcl/hub.nghook # NAME # hub.nghook diff --git a/imunes.tcl b/imunes.tcl index fe80425..a65d081 100755 --- a/imunes.tcl +++ b/imunes.tcl @@ -90,6 +90,7 @@ source "$ROOTDIR/$LIBDIR/ipv4.tcl" source "$ROOTDIR/$LIBDIR/ipv6.tcl" source "$ROOTDIR/$LIBDIR/cfgparse.tcl" source "$ROOTDIR/$LIBDIR/exec.tcl" +#source "$ROOTDIR/$LIBDIR/partition.tcl" source "$ROOTDIR/$LIBDIR/canvas.tcl" source "$ROOTDIR/$LIBDIR/quagga.tcl" @@ -213,7 +214,7 @@ set exec_sockets_opened false # Used in spawnShell to start xterm or command.com with NetCat #***** -if { [catch {set s $env(COMSPEC)}] } { +if { $tcl_platform(platform) == "unix" } { set gui_unix true } else { set gui_unix false diff --git a/lanswitch.tcl b/lanswitch.tcl index 35fde54..e977296 100755 --- a/lanswitch.tcl +++ b/lanswitch.tcl @@ -87,6 +87,58 @@ proc $MODULE.instantiate { eid node } { return } + +#****f* lanswitch.tcl/lanswitch.start +# NAME +# lanswitch.start +# SYNOPSIS +# lanswitch.start $eid $node_id +# FUNCTION +# Starts a new lanswitch. Since lanswitch has no starting code, +# this procedure does nothing. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is lanswitch) +#**** +proc $MODULE.start { eid node } { + return +} + + +#****f* lanswitch.tcl/lanswitch.shutdown +# NAME +# lanswitch.shutdown +# SYNOPSIS +# lanswitch.shutdown $eid $node_id +# FUNCTION +# Shutdowns a lanswitch. Since lanswitch has no shutdown code, +# this procedure does nothing. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is lanswitch) +#**** +proc $MODULE.shutdown { eid node } { + return +} + +#****f* lanswitch.tcl/lanswitch.destroy +# NAME +# lanswitch.destroy +# SYNOPSIS +# lanswitch.destroy $eid $node_id +# FUNCTION +# Destroys a lanswitch. Destroys the netgraph node that represents +# the lanswitch by sending a shutdown message. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is lanswitch) +#**** +proc $MODULE.destroy { eid node } { + catch { nexec ngctl msg $eid\_$node: shutdown } + return +} + + #****f* lanswitch.tcl/lanswitch.nghook # NAME # lanswitch.nghook diff --git a/pc.tcl b/pc.tcl index d7e5c40..084d12f 100755 --- a/pc.tcl +++ b/pc.tcl @@ -177,6 +177,61 @@ proc $MODULE.instantiate { eid node } { return } + +#****f* pc.tcl/pc.start +# NAME +# pc.start +# SYNOPSIS +# pc.start $eid $node_id +# FUNCTION +# Starts a new pc. The node can be started if it is instantiated. +# Simulates the booting proces of a pc, by calling l3node.start +# procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is pc) +#**** +proc $MODULE.start { eid node } { + l3node.start $eid $node + return +} + +#****f* pc.tcl/pc.shutdown +# NAME +# pc.shutdown +# SYNOPSIS +# pc.shutdown $eid $node_id +# FUNCTION +# Shutdowns a pc. Simulates the shutdown proces of a pc, +# by calling the l3node.shutdown procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is pc) +#**** +proc $MODULE.shutdown { eid node } { + l3node.shutdown $eid $node + return +} + + +#****f* pc.tcl/pc.destroy +# NAME +# pc.destroy +# SYNOPSIS +# pc.destroy $eid $node_id +# FUNCTION +# Destroys a pc. Destroys all the interfaces of the pc +# and the vimage itself by calling l3node.destroy procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is pc) +#**** +proc $MODULE.destroy { eid node } { + l3node.destroy $eid $node + return +} + + #****f* pc.tcl/pc.nghook # NAME # pc.nghook diff --git a/quagga.tcl b/quagga.tcl index b7a0a3e..cf22535 100755 --- a/quagga.tcl +++ b/quagga.tcl @@ -187,7 +187,6 @@ proc $MODULE.shellcmd { node } { # * 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 @@ -196,6 +195,62 @@ proc $MODULE.instantiate { eid node } { return } + +#****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 + return +} + + +#****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 + return +} + + +#****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 + return +} + + #****f* quagga.tcl/router.quagga.nghook # NAME # router.quagga.nghook diff --git a/rj45.tcl b/rj45.tcl index 1e9e6eb..40afff2 100755 --- a/rj45.tcl +++ b/rj45.tcl @@ -81,6 +81,58 @@ proc $MODULE.instantiate { eid node } { return } + +#****f* rj45.tcl/rj45.start +# NAME +# rj45.start +# SYNOPSIS +# rj45.start $eid $node_id +# FUNCTION +# Starts a new rj45. Since rj45 has no starting code, +# this procedure does nothing. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is rj45) +#**** +proc $MODULE.start { eid node } { + return +} + + +#****f* rj45.tcl/rj45.shutdown +# NAME +# rj45.shutdown +# SYNOPSIS +# rj45.shutdown $eid $node_id +# FUNCTION +# Shutdowns a rj45. Since rj45 has no shutdown code, +# this procedure does nothing. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is rj45) +#**** +proc $MODULE.shutdown { eid node } { + return +} + + +#****f* rj45.tcl/rj45.destroy +# NAME +# rj45.destroy +# SYNOPSIS +# rj45.destroy $eid $node_id +# FUNCTION +# Destroys a rj45 emulation interface. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is rj45) +#**** +proc $MODULE.destroy { eid node } { + set ifname [getNodeName $node] + nexec ifconfig $ifname up -promisc + return +} + #****f* rj45.tcl/rj45.nghook # NAME # rj45.nghook diff --git a/static.tcl b/static.tcl index b120f0e..366aee9 100755 --- a/static.tcl +++ b/static.tcl @@ -190,6 +190,60 @@ proc $MODULE.instantiate { eid node } { return } +#****f* static.tcl/router.static.start +# NAME +# router.static.start +# SYNOPSIS +# router.static.start $eid $node_id +# FUNCTION +# Starts a new router.static. The node can be started if it is instantiated. +# Simulates the booting proces of a router.static, by calling l3node.start +# procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is router.static) +#**** +proc $MODULE.start { eid node } { + l3node.start $eid $node + return +} + +#****f* static.tcl/router.static.shutdown +# NAME +# router.static.shutdown +# SYNOPSIS +# router.static.shutdown $eid $node_id +# FUNCTION +# Shutdowns a router.static. Simulates the shutdown proces of a router.static, +# by calling the l3node.shutdown procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is router.static) +#**** +proc $MODULE.shutdown { eid node } { + l3node.shutdown $eid $node + return +} + + +#****f* static.tcl/router.static.destroy +# NAME +# router.static.destroy +# SYNOPSIS +# router.static.destroy $eid $node_id +# FUNCTION +# Destroys a router.static. Destroys all the interfaces of the router.static +# 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.static) +#**** +proc $MODULE.destroy { eid node } { + l3node.destroy $eid $node + return +} + + #****f* static.tcl/router.static.nghook # NAME # router.static.nghook diff --git a/vimageShellServer.sh b/vimageShellServer.sh index 67819e2..0891cce 100755 --- a/vimageShellServer.sh +++ b/vimageShellServer.sh @@ -7,8 +7,13 @@ scriptname=/tmp/vimage_shell.$$.sh echo "#! /bin/sh" > $scriptname -echo "vimage $1 $3 -i" >> $scriptname - +#echo "vimage $1 $3 -i" >> $scriptname +if [ "$3" = vtysh ] + then + echo "vimage $1 $3 " >> $scriptname + else + echo "vimage $1 $3 -i " >> $scriptname +fi chmod +x $scriptname nc -l -p $2 -e $scriptname rm $scriptname diff --git a/xorp.tcl b/xorp.tcl index a701115..b22b420 100755 --- a/xorp.tcl +++ b/xorp.tcl @@ -256,6 +256,62 @@ proc $MODULE.instantiate { eid node } { return } + +#****f* xorp.tcl/router.xorp.start +# NAME +# router.xorp.start +# SYNOPSIS +# router.xorp.start $eid $node_id +# FUNCTION +# Starts a new router.xorp. The node can be started if it is instantiated. +# Simulates the booting proces of a router.xorp, by calling l3node.start +# procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is router.xorp) +#**** +proc $MODULE.start { eid node } { + l3node.start $eid $node + return +} + + +#****f* xorp.tcl/router.xorp.shutdown +# NAME +# router.xorp.shutdown +# SYNOPSIS +# router.xorp.shutdown $eid $node_id +# FUNCTION +# Shutdowns a router.xorp. Simulates the shutdown proces of a router.xorp, +# by calling the l3node.shutdown procedure. +# INPUTS +# * eid - experiment id +# * node_id - id of the node (type of the node is router.xorp) +#**** +proc $MODULE.shutdown { eid node } { + l3node.shutdown $eid $node + return +} + + +#****f* xorp.tcl/router.xorp.destroy +# NAME +# router.xorp.destroy +# SYNOPSIS +# router.xorp.destroy $eid $node_id +# FUNCTION +# Destroys a router.xorp. Destroys all the interfaces of the router.xorp +# 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.xorp) +#**** +proc $MODULE.destroy { eid node } { + l3node.destroy $eid $node + return +} + + #****f* xorp.tcl/router.xorp.nghook # NAME # router.xorp.nghook -- 2.39.5