Browse Source

Merge pull request #2498 from xiang90/agent-status

tools/functional-tester/etcd-agent: add status rpc
Xiang Li 10 years ago
parent
commit
a9ecf0caff

+ 53 - 7
tools/functional-tester/etcd-agent/agent.go

@@ -21,9 +21,20 @@ import (
 	"os/exec"
 	"path"
 	"time"
+
+	"github.com/coreos/etcd/tools/functional-tester/etcd-agent/client"
+)
+
+const (
+	stateUninitialized = "uninitialized"
+	stateStarted       = "started"
+	stateStopped       = "stopped"
+	stateTerminated    = "terminated"
 )
 
 type Agent struct {
+	state string // the state of etcd process
+
 	cmd     *exec.Cmd
 	logfile *os.File
 	l       net.Listener
@@ -43,7 +54,7 @@ func newAgent(etcd string) (*Agent, error) {
 		return nil, err
 	}
 
-	return &Agent{cmd: c, logfile: f}, nil
+	return &Agent{state: stateUninitialized, cmd: c, logfile: f}, nil
 }
 
 // start starts a new etcd process with the given args.
@@ -51,7 +62,13 @@ func (a *Agent) start(args ...string) error {
 	a.cmd = exec.Command(a.cmd.Path, args...)
 	a.cmd.Stdout = a.logfile
 	a.cmd.Stderr = a.logfile
-	return a.cmd.Start()
+	err := a.cmd.Start()
+	if err != nil {
+		return err
+	}
+
+	a.state = stateStarted
+	return nil
 }
 
 // stop stops the existing etcd process the agent started.
@@ -61,7 +78,13 @@ func (a *Agent) stop() error {
 		return err
 	}
 	_, err = a.cmd.Process.Wait()
-	return err
+	if err != nil {
+		return err
+
+	}
+
+	a.state = stateStopped
+	return nil
 }
 
 // restart restarts the stopped etcd process.
@@ -69,11 +92,22 @@ func (a *Agent) restart() error {
 	a.cmd = exec.Command(a.cmd.Path, a.cmd.Args[1:]...)
 	a.cmd.Stdout = a.logfile
 	a.cmd.Stderr = a.logfile
-	return a.cmd.Start()
+	err := a.cmd.Start()
+	if err != nil {
+		return err
+	}
+
+	a.state = stateStarted
+	return nil
 }
 
 func (a *Agent) cleanup() error {
-	a.stop()
+	err := a.stop()
+	if err != nil {
+		return err
+	}
+	a.state = stateUninitialized
+
 	a.logfile.Close()
 	if err := archiveLogAndDataDir("etcd.log", a.dataDir()); err != nil {
 		return err
@@ -86,8 +120,20 @@ func (a *Agent) cleanup() error {
 // terminate stops the exiting etcd process the agent started
 // and removes the data dir.
 func (a *Agent) terminate() error {
-	a.stop()
-	return os.RemoveAll(a.dataDir())
+	err := a.stop()
+	if err != nil {
+		return err
+	}
+	err = os.RemoveAll(a.dataDir())
+	if err != nil {
+		return err
+	}
+	a.state = stateTerminated
+	return nil
+}
+
+func (a *Agent) status() client.Status {
+	return client.Status{State: a.state}
 }
 
 func (a *Agent) dataDir() string {

+ 17 - 0
tools/functional-tester/etcd-agent/client/client.go

@@ -16,6 +16,12 @@ package client
 
 import "net/rpc"
 
+type Status struct {
+	// TODO: gather more informations
+	// TODO: memory usage, raft information, etc..
+	State string
+}
+
 type Agent interface {
 	ID() uint64
 	// Start starts a new etcd with the given args on the agent machine.
@@ -30,6 +36,8 @@ type Agent interface {
 	Terminate() error
 	// Isoloate isolates the network of etcd
 	Isolate() error
+	// Status returns the status of etcd on the agent
+	Status() (Status, error)
 }
 
 type agent struct {
@@ -79,6 +87,15 @@ func (a *agent) Isolate() error {
 	panic("not implemented")
 }
 
+func (a *agent) Status() (Status, error) {
+	var s Status
+	err := a.rpcClient.Call("Agent.RPCStatus", struct{}{}, &s)
+	if err != nil {
+		return s, err
+	}
+	return s, nil
+}
+
 func (a *agent) ID() uint64 {
 	panic("not implemented")
 }

+ 7 - 0
tools/functional-tester/etcd-agent/rpc.go

@@ -19,6 +19,8 @@ import (
 	"net"
 	"net/http"
 	"net/rpc"
+
+	"github.com/coreos/etcd/tools/functional-tester/etcd-agent/client"
 )
 
 func (a *Agent) serveRPC() {
@@ -69,3 +71,8 @@ func (a *Agent) RPCTerminate(args struct{}, reply *struct{}) error {
 func (a *Agent) RPCIsolate(args struct{}, reply *struct{}) error {
 	panic("not implemented")
 }
+
+func (a *Agent) RPCStatus(args struct{}, status *client.Status) error {
+	*status = a.status()
+	return nil
+}

+ 41 - 0
tools/functional-tester/etcd-agent/rpc_test.go

@@ -20,6 +20,8 @@ import (
 	"net/rpc"
 	"os"
 	"testing"
+
+	"github.com/coreos/etcd/tools/functional-tester/etcd-agent/client"
 )
 
 func init() {
@@ -123,3 +125,42 @@ func TestRPCTerminate(t *testing.T) {
 		t.Fatal(err)
 	}
 }
+
+func TestRPCStatus(t *testing.T) {
+	c, err := rpc.DialHTTP("tcp", ":9027")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var s client.Status
+	err = c.Call("Agent.RPCStatus", struct{}{}, &s)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if s.State != stateTerminated {
+		t.Errorf("state = %s, want %s", s.State, stateTerminated)
+	}
+
+	dir, err := ioutil.TempDir(os.TempDir(), "etcd-agent")
+	if err != nil {
+		t.Fatal(err)
+	}
+	var pid int
+	err = c.Call("Agent.RPCStart", []string{"-data-dir", dir}, &pid)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = c.Call("Agent.RPCStatus", struct{}{}, &s)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if s.State != stateStarted {
+		t.Errorf("state = %s, want %s", s.State, stateStarted)
+	}
+
+	err = c.Call("Agent.RPCTerminate", struct{}{}, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+}