예제 #1
0
func (a *Agent) Start() {
	go func() {
		state.WaitGroup().Wait()
		if a.cmd != nil && a.cmd.Process != nil {
			a.cmd.Process.Signal(syscall.SIGTERM)
			a.cmd = nil
		}
		state.WaitGroup().Done()
	}()
	a.Lock()
	defer a.Unlock()
	if a.cmd == nil {
		a.start()
	}
}
예제 #2
0
func (link *Link) listen(l *label, address string) net.Listener {
	sock, err := net.Listen("unix", address)
	if err != nil {
		log.Fatalf("listen: %s", err)
	}
	go func() {
		state.WaitGroup().Wait()
		defer state.WaitGroup().Done()

		sock.Close()
	}()

	if err = os.Chmod(address, 0777); err != nil {
		log.Fatalf("chmod: %s", address)
	}

	return sock
}
예제 #3
0
func (a *Agent) start() {
	if a.cmd != nil {
		log.Fatal("Cannot call start(): program already running!")
	}
	if a.killcount > 0 {
		return
	}
	cmd := exec.Command(a.args[0], a.args[1:]...)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal("Unable to open pipe to stdout: %v", err)
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		log.Fatal("Unable to open pipe to stderr: %v", err)
	}
	if state.Local() {
		cmd.Dir = a.dir
	}
	go copyLines(a.Name, stdout)
	go copyLines(a.Name, stderr)
	log.Printf("Starting %v", a)
	err = cmd.Start()
	if err != nil {
		log.Fatalf("Could't spawn %v: %s", a, err)
	}
	go func() {
		err := cmd.Wait()
		a.Lock()
		defer a.Unlock()

		// Not the active command
		if a.cmd != cmd {
			return
		}

		var d string
		if err != nil {
			d = fmt.Sprintf("Command exited unexpectedly: %s (%s)", cmd, err)
		} else {
			d = fmt.Sprintf("Command exited unexpectedly (but cleanly!): %s", cmd)
		}
		state.RecordDisqualifier(d)

		state.WaitGroup().Exit()
	}()

	a.cmd = cmd
}
예제 #4
0
func (h *Harness) boot() bool {
	rng := state.NewRand("boot")
	bootQuery := h.generateInitialQuery()
	i := rng.Intn(len(h.agents))
	node := h.agents[i]

	for !h.issueQuery(0, node, bootQuery) {
		time.Sleep(100 * time.Millisecond)
		select {
		case <-state.WaitGroup().Quit:
			return false
		default:
		}
	}
	return true
}
예제 #5
0
func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, `
Usage: %s [options] [...args]

Octopus will run your sqlcluster and issue queries to it. It simulates
a lossy network, and to make things even more fun, will turn loose the
following chaotic monkeys:

  NET MONKEYS
  - latency: adjusts base latency between nodes
  - jitter: adjusts latency variance between nodes
  - lagsplit: spikes latency along a network partition
  - link: destroys individual links between nodes
  - netsplit: destroys links along a network partition

  NODE MONKEYS
  - freeze: stops nodes (by sending SIGTSTP)
  - murder: ruthlessly murders nodes (by sending SIGTERM)

Any positional arguments given to Octopus will be passed through to
SQLCluster. This should be mostly useful for passing a -v flag, like
so:

  ./octopus -- -v

OPTIONS:
`, os.Args[0])
		flag.PrintDefaults()
	}
	state.AddFlags()
	flag.Parse()
	state.AfterParse()

	// Handle SIGINT
	sigchan := make(chan os.Signal)
	signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM)

	d := director.NewDirector()
	if state.Dryrun() {
		d.Dryrun()
		return
	}

	// Create the working directory
	if err := os.MkdirAll(state.Root(), os.ModeDir|0755); err != nil {
		log.Fatal(err)
	}

	d.Start()

	go func() {
		select {
		case <-sigchan:
			log.Println("Terminating due to signal")
		case <-state.WaitGroup().Quit:
			// Someone else requested an exit
		case <-time.After(state.Duration()):
			// Time's up!
			log.Printf("The allotted %s have elapsed. Exiting!", state.Duration())
		}
		state.WaitGroup().Exit()
	}()

	h := harness.New(d.Agents())
	h.Start()

	d.StartMonkeys()

	<-state.WaitGroup().Quit

	if state.Write() != "" {
		results := state.JSONResults()
		if err := ioutil.WriteFile(state.Write(), results, 0755); err != nil {
			log.Fatalf("Could not write resuts: %s", err)
		}
	} else {
		results := state.PrettyPrintResults()
		log.Println(results)
	}

	state.WaitGroup().Exit()
}
예제 #6
0
func (h *Harness) losef(msg string, v ...interface{}) {
	disqualifier := fmt.Sprintf(msg, v...)
	state.RecordDisqualifier(disqualifier)
	state.WaitGroup().Exit()
}