go.dedis.ch/onet/v4@v4.0.0-pre1/simul/platform/deterlab_users/users.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"strings"
     6  	"sync"
     7  	"time"
     8  
     9  	"os"
    10  	"os/exec"
    11  	"regexp"
    12  	"runtime"
    13  	"strconv"
    14  
    15  	"go.dedis.ch/onet/v4"
    16  	"go.dedis.ch/onet/v4/log"
    17  	"go.dedis.ch/onet/v4/simul/monitor"
    18  	"go.dedis.ch/onet/v4/simul/platform"
    19  )
    20  
    21  var kill = false
    22  var suite string
    23  
    24  func init() {
    25  	flag.BoolVar(&kill, "kill", false, "kill everything (and don't start anything)")
    26  	flag.StringVar(&suite, "suite", "ed25519", "suite used for simulation")
    27  }
    28  
    29  // DeterlabUsers is called on the users.deterlab.net-server and will:
    30  // - copy the simulation-files to the server
    31  // - start the simulation
    32  func main() {
    33  	// init with deter.toml
    34  	deter := deterFromConfig()
    35  	flag.Parse()
    36  
    37  	// kill old processes
    38  	var wg sync.WaitGroup
    39  	re := regexp.MustCompile(" +")
    40  	hosts, err := exec.Command("/usr/testbed/bin/node_list", "-e", deter.Project+","+deter.Experiment).Output()
    41  	if err != nil {
    42  		log.Fatal("Deterlab experiment", deter.Project+"/"+deter.Experiment, "seems not to be swapped in. Aborting.")
    43  		os.Exit(-1)
    44  	}
    45  	hostsTrimmed := strings.TrimSpace(re.ReplaceAllString(string(hosts), " "))
    46  	hostlist := strings.Split(hostsTrimmed, " ")
    47  	doneHosts := make([]bool, len(hostlist))
    48  	log.Lvl2("Found the following hosts:", hostlist)
    49  	if kill {
    50  		log.Lvl1("Cleaning up", len(hostlist), "hosts.")
    51  	}
    52  	for i, h := range hostlist {
    53  		wg.Add(1)
    54  		go func(i int, h string) {
    55  			defer wg.Done()
    56  			if kill {
    57  				log.Lvl3("Cleaning up host", h, ".")
    58  				runSSH(h, "sudo killall -9 simul scp 2>/dev/null >/dev/null")
    59  				time.Sleep(1 * time.Second)
    60  				runSSH(h, "sudo killall -9 simul 2>/dev/null >/dev/null")
    61  				time.Sleep(1 * time.Second)
    62  				// Also kill all other process that start with "./" and are probably
    63  				// locally started processes
    64  				runSSH(h, "sudo pkill -9 -f '\\./'")
    65  				time.Sleep(1 * time.Second)
    66  				if log.DebugVisible() > 3 {
    67  					log.Lvl4("Cleaning report:")
    68  					_ = platform.SSHRunStdout("", h, "ps aux")
    69  				}
    70  			} else {
    71  				log.Lvl3("Setting the file-limit higher on", h)
    72  
    73  				// Copy configuration file to make higher file-limits
    74  				err := platform.SSHRunStdout("", h, "sudo cp remote/simul.conf /etc/security/limits.d")
    75  				if err != nil {
    76  					log.Fatal("Couldn't copy limit-file:", err)
    77  				}
    78  			}
    79  			doneHosts[i] = true
    80  			log.Lvl3("Host", h, "cleaned up")
    81  		}(i, h)
    82  	}
    83  
    84  	cleanupChannel := make(chan string)
    85  	go func() {
    86  		wg.Wait()
    87  		log.Lvl3("Done waiting")
    88  		cleanupChannel <- "done"
    89  	}()
    90  	select {
    91  	case msg := <-cleanupChannel:
    92  		log.Lvl3("Received msg from cleanupChannel", msg)
    93  	case <-time.After(time.Second * 20):
    94  		for i, m := range doneHosts {
    95  			if !m {
    96  				log.Lvl1("Missing host:", hostlist[i], "- You should run")
    97  				log.Lvl1("/usr/testbed/bin/node_reboot", hostlist[i])
    98  			}
    99  		}
   100  		log.Fatal("Didn't receive all replies while cleaning up - aborting.")
   101  	}
   102  
   103  	if kill {
   104  		log.Lvl2("Only cleaning up - returning")
   105  		return
   106  	}
   107  
   108  	// ADDITIONS : the monitoring part
   109  	// Proxy will listen on Sink:SinkPort and redirect every packet to
   110  	// RedirectionAddress:SinkPort-1. With remote tunnel forwarding it will
   111  	// be forwarded to the real sink
   112  	addr, port := deter.ProxyAddress, uint16(deter.MonitorPort+1)
   113  	log.Lvl2("Launching proxy redirecting to", addr, ":", port)
   114  	prox, err := monitor.NewProxy(uint16(deter.MonitorPort), addr, port)
   115  	if err != nil {
   116  		log.Fatal("Couldn't start proxy:", err)
   117  	}
   118  	go prox.Run()
   119  
   120  	log.Lvl1("starting", deter.Servers, "cothorities for a total of", deter.Hosts, "processes.")
   121  	killing := false
   122  	for i, phys := range deter.Phys {
   123  		log.Lvl2("Launching simul on", phys)
   124  		wg.Add(1)
   125  		go func(phys, internal string) {
   126  			//log.Lvl4("running on", phys, cmd)
   127  			defer wg.Done()
   128  			monitorAddr := deter.MonitorAddress + ":" + strconv.Itoa(deter.MonitorPort)
   129  			log.Lvl4("Starting servers on physical machine ", internal, "with monitor = ",
   130  				monitorAddr)
   131  
   132  			// If PreScript is defined, run the appropriate script _before_ the simulation.
   133  			if deter.PreScript != "" {
   134  				err := platform.SSHRunStdout("", phys, "cd remote; sudo ./"+deter.PreScript+" deterlab")
   135  				if err != nil {
   136  					log.Fatal("error deploying PreScript: ", err)
   137  				}
   138  			}
   139  			args := " -address=" + internal +
   140  				" -simul=" + deter.Simulation +
   141  				" -monitor=" + monitorAddr +
   142  				" -debug=" + strconv.Itoa(log.DebugVisible()) +
   143  				" -suite=" + suite
   144  			log.Lvl3("Args is", args)
   145  			err := platform.SSHRunStdout("", phys, "cd remote; sudo ./simul "+
   146  				args)
   147  			if err != nil && !killing {
   148  				log.Lvl1("Error starting simul - will kill all others:", err, internal)
   149  				killing = true
   150  				err := exec.Command("killall", "ssh").Run()
   151  				if err != nil {
   152  					log.Fatal("Couldn't killall ssh:", err)
   153  				}
   154  			}
   155  			log.Lvl4("Finished with simul on", internal)
   156  		}(phys, deter.Virt[i])
   157  	}
   158  
   159  	// wait for the servers to finish before stopping
   160  	wg.Wait()
   161  	prox.Stop()
   162  }
   163  
   164  // Reads in the deterlab-config and drops out if there is an error
   165  func deterFromConfig(name ...string) *platform.Deterlab {
   166  	d := &platform.Deterlab{}
   167  	configName := "deter.toml"
   168  	if len(name) > 0 {
   169  		configName = name[0]
   170  	}
   171  	err := onet.ReadTomlConfig(d, configName)
   172  	_, caller, line, _ := runtime.Caller(1)
   173  	who := caller + ":" + strconv.Itoa(line)
   174  	if err != nil {
   175  		log.Fatal("Couldn't read config in", who, ":", err)
   176  	}
   177  	log.SetDebugVisible(d.Debug)
   178  	return d
   179  }
   180  
   181  // Runs a command on the remote host and outputs an eventual error if debug level >= 3
   182  func runSSH(host, cmd string) {
   183  	if _, err := platform.SSHRun("", host, cmd); err != nil {
   184  		log.Lvlf3("Host %s got error %s while running [%s]", host, err.Error(), cmd)
   185  	}
   186  }