Пример #1
0
func (me *Master) createMirror(addr string, jobs int) (*mirrorConnection, os.Error) {
	conn, err := DialTypedConnection(addr, RPC_CHANNEL, me.secret)
	if err != nil {
		return nil, err
	}
	defer conn.Close()

	rpcId := ConnectionId()
	rpcConn, err := DialTypedConnection(addr, rpcId, me.secret)
	if err != nil {
		return nil, err
	}

	revId := ConnectionId()
	revConn, err := DialTypedConnection(addr, revId, me.secret)
	if err != nil {
		rpcConn.Close()
		return nil, err
	}

	req := CreateMirrorRequest{
		RpcId:        rpcId,
		RevRpcId:     revId,
		WritableRoot: me.writableRoot,
		MaxJobCount:  jobs,
	}
	rep := CreateMirrorResponse{}
	cl := rpc.NewClient(conn)
	err = cl.Call("WorkerDaemon.CreateMirror", &req, &rep)

	if err != nil {
		revConn.Close()
		rpcConn.Close()
		return nil, err
	}

	go me.fileServerRpc.ServeConn(revConn)

	mc := &mirrorConnection{
		rpcClient:     rpc.NewClient(rpcConn),
		connection:    rpcConn,
		maxJobs:       rep.GrantedJobCount,
		availableJobs: rep.GrantedJobCount,
	}

	mc.queueFiles(me.fileServer.copyCache())

	return mc, nil
}
Пример #2
0
func TestEndToEndShutdown(t *testing.T) {
	if os.Geteuid() == 0 {
		log.Println("This test should not run as root")
		return
	}

	tc := NewTestCase(t)
	defer tc.Clean()

	// In the test, shutdown doesn't really exit the worker, since
	// we can't stop the already running accept(); retry would
	// cause the test to hang.
	tc.master.retryCount = 0

	req := WorkRequest{
		Binary: tc.FindBin("touch"),
		Argv:   []string{"touch", "file.txt"},
		Env:    testEnv(),
		Dir:    tc.tmp + "/wd",
	}
	rep := tc.Run(req)

	hostname, err := os.Hostname()
	if err != nil {
		t.Fatalf("hostname error %v", err)
	}
	conn, err := DialTypedConnection(
		fmt.Sprintf("%s:%d", hostname, tc.workerPort), RPC_CHANNEL, tc.secret)
	if conn == nil {
		t.Fatal("DialTypedConnection to shutdown worker: ", err)
	}

	stopReq := 1
	stopRep := 1
	err = rpc.NewClient(conn).Call("WorkerDaemon.Shutdown", &stopReq, &stopRep)
	if err != nil {
		t.Errorf("Shutdown insuccessful: %v", err)
	}

	rpcConn := OpenSocketConnection(tc.socket, RPC_CHANNEL)
	err = rpc.NewClient(rpcConn).Call("LocalMaster.Run", &req, &rep)
	if err == nil {
		t.Error("LocalMaster.Run should fail after shutdown")
	}

	// TODO - check that DialTypedConnection to worker stops working?
}
Пример #3
0
func (me *testCase) Run(req WorkRequest) (rep WorkReply) {
	rpcConn := OpenSocketConnection(me.socket, RPC_CHANNEL)
	client := rpc.NewClient(rpcConn)

	err := client.Call("LocalMaster.Run", &req, &rep)
	if err != nil {
		me.tester.Fatal("LocalMaster.Run: ", err)
	}
	return rep
}
Пример #4
0
func Refresh() {
	socket := termite.FindSocket()
	conn := termite.OpenSocketConnection(socket, termite.RPC_CHANNEL)

	client := rpc.NewClient(conn)

	req := 1
	rep := 1
	err := client.Call("LocalMaster.RefreshAttributeCache", &req, &rep)
	if err != nil {
		log.Fatal("LocalMaster.RefreshAttributeCache: ", err)
	}
	conn.Close()
}
Пример #5
0
func (me *Master) setupWorkers(addresses []string) {
	var out []*rpc.Client
	for _, addr := range addresses {
		conn, err := SetupClient(addr, me.secret)
		if err != nil {
			log.Println("Failed setting up connection with: ", addr, err)
			continue
		}
		out = append(out, rpc.NewClient(conn))
	}
	if len(out) == 0 {
		log.Fatal("No workers available.")
	}
	me.workServers = out
}
Пример #6
0
func NewMirror(daemon *WorkerDaemon, rpcConn, revConn net.Conn) *Mirror {
	log.Println("Mirror for", rpcConn, revConn)

	mirror := &Mirror{
		fileServerConn:     revConn,
		rpcConn:            rpcConn,
		fileServer:         rpc.NewClient(revConn),
		daemon:             daemon,
		workingFileSystems: make(map[*WorkerFuseFs]string),
	}
	mirror.rpcFs = NewRpcFs(mirror.fileServer, daemon.contentCache)
	mirror.rpcFs.localRoots = []string{"/lib", "/usr"}
	mirror.cond = sync.NewCond(&mirror.fuseFileSystemsMutex)

	go mirror.serveRpc()
	return mirror
}
Пример #7
0
func test_rpc() {
	fmt.Println("Testing rpc with TimeService...")
	cli, srv := net.Pipe()
	go rpc.ServeConn(srv)

	client := rpc.NewClient(cli)
	defer client.Close()

	// Synchronous calls
	args := &Args{"GMT"}
	reply := new(Reply)
	for i := 0; i < 10; i++ {
		err := client.Call("TimeService.GetTime", args, reply)
		if err != nil {
			fmt.Errorf("TimeService.GetTime: expected no error but got string %q", err.String())
		}

		fmt.Printf("time:%s\n rpc.counter:%d\n", reply.Time, reply.Counter)
	}
}
Пример #8
0
func (me *Coordinator) workerHandler(w http.ResponseWriter, req *http.Request) {
	w.Header().Set("Content-Type", "text/html")
	q := req.URL.Query()
	vs, ok := q["host"]
	if !ok || len(vs) == 0 {
		fmt.Fprintf(w, "<html><body>404 query param 'host' missing</body></html>")
		return
	}
	addr := string(vs[0])
	fmt.Fprintf(w, "<html><head><title>Termite worker status</title></head>")
	fmt.Fprintf(w, "<body><h1>Status %s</h1>", addr)
	defer fmt.Fprintf(w, "</body></html>")

	if !me.haveWorker(addr) {
		fmt.Fprintf(w, "<p><tt>worker %q unknown<tt>", addr)
		return
	}

	conn, err := DialTypedConnection(addr, RPC_CHANNEL, me.secret)
	if err != nil {
		fmt.Fprintf(w, "<p><tt>error dialing: %v<tt>", err)
		return
	}

	statusReq := WorkerStatusRequest{}
	status := WorkerStatusResponse{}

	client := rpc.NewClient(conn)
	err = client.Call("WorkerDaemon.Status", &statusReq, &status)
	if err != nil {
		fmt.Fprintf(w, "<p><tt>RPC error: %v<tt>\n", err)
		return
	}

	fmt.Fprintf(w, "<p>Worker %s<p>Version %s<p>Jobs %d\n", addr, status.Version, status.MaxJobCount)
	for _, mirrorStatus := range status.MirrorStatus {
		me.mirrorStatusHtml(w, mirrorStatus)
	}
	fmt.Fprintf(w, "<p><a href=\"/workerkill?host=%s\">Kill worker %s</a>\n", addr, addr)
	conn.Close()
}
Пример #9
0
func main() {
	cachedir := flag.String("cachedir", "/tmp/termite-cache", "content cache")
	server := flag.String("server", "localhost:1234", "file server")
	secretFile := flag.String("secret", "/tmp/secret.txt", "file containing password.")

	flag.Parse()
	if flag.NArg() < 1 {
		fmt.Fprintf(os.Stderr, "usage: %s MOUNTPOINT\n", os.Args[0])
		os.Exit(2)
	}
	secret, err := ioutil.ReadFile(*secretFile)
	if err != nil {
		log.Fatal("ReadFile", err)
	}

	rpcConn, err := termite.SetupClient(*server, secret)
	if err != nil {
		log.Fatal("dialing:", err)
	}

	var fs fuse.FileSystem
	cache := termite.NewDiskFileCache(*cachedir)
	fs = termite.NewRpcFs(rpc.NewClient(rpcConn), cache)
	conn := fuse.NewFileSystemConnector(fs, nil)
	state := fuse.NewMountState(conn)
	opts := fuse.MountOptions{}
	if os.Geteuid() == 0 {
		opts.AllowOther = true
	}

	state.Mount(flag.Arg(0), &opts)
	if err != nil {
		fmt.Printf("Mount fail: %v\n", err)
		os.Exit(1)
	}

	state.Debug = true
	state.Loop(false)
}
Пример #10
0
func (me *Coordinator) killHandler(w http.ResponseWriter, req *http.Request) {
	w.Header().Set("Content-Type", "text/html")
	q := req.URL.Query()
	vs, ok := q["host"]
	if !ok || len(vs) == 0 {
		fmt.Fprintf(w, "<html><body>404 query param 'host' missing</body></html>")
		return
	}
	addr := string(vs[0])

	fmt.Fprintf(w, "<html><head><title>Termite worker status</title></head>")
	fmt.Fprintf(w, "<body><h1>Status %s</h1>", addr)
	defer fmt.Fprintf(w, "</body></html>")

	if !me.haveWorker(addr) {
		fmt.Fprintf(w, "<p><tt>worker %q unknown<tt>", addr)
		return
	}

	conn, err := DialTypedConnection(addr, RPC_CHANNEL, me.secret)
	if err != nil {
		fmt.Fprintf(w, "<p><tt>error dialing: %v<tt>", err)
		return
	}

	killReq := 1
	rep := 1
	err = rpc.NewClient(conn).Call("WorkerDaemon.Shutdown", &killReq, &rep)
	if err != nil {
		fmt.Fprintf(w, "<p><tt>RPC error: %v<tt>", err)
		return
	}

	fmt.Fprintf(w, "<p>Shutdown of %s in progress", addr)
	conn.Close()
}
Пример #11
0
func main() {
	command := flag.String("c", "", "command to run.")
	refresh := flag.Bool("refresh", false, "refresh master file cache.")
	debug := flag.Bool("dbg", false, "set on debugging in request.")
	flag.Parse()

	if *refresh {
		Refresh()
	}

	if *command == "" {
		return
	}
	os.Args[0] = _SHELL
	TryRunDirect(*command)

	socket := termite.FindSocket()
	if socket == "" {
		log.Fatal("Could not find .termite-socket")
	}
	topDir, _ := filepath.Split(socket)

	localWaitMsg, localRule := TryRunLocally(*command, topDir)
	if localWaitMsg != nil && !localRule.SkipRefresh {
		Refresh()
	}

	wd, err := os.Getwd()
	if err != nil {
		log.Fatal("Getwd", err)
	}

	conn := termite.OpenSocketConnection(socket, termite.RPC_CHANNEL)

	// TODO - could skip the shell if we can deduce it is a
	// no-frills command invocation.
	req := termite.WorkRequest{
		Binary:     _SHELL,
		Argv:       []string{"/bin/sh", "-c", *command},
		Env:        cleanEnv(os.Environ()),
		Dir:        wd,
		Debug:      os.Getenv("TERMITE_DEBUG") != "" || *debug,
		RanLocally: localWaitMsg != nil,
	}
	client := rpc.NewClient(conn)

	rep := termite.WorkReply{}
	err = client.Call("LocalMaster.Run", &req, &rep)
	if err != nil {
		log.Fatal("LocalMaster.Run: ", err)
	}

	os.Stdout.Write([]byte(rep.Stdout))
	os.Stderr.Write([]byte(rep.Stderr))

	// TODO -something with signals.
	if localWaitMsg == nil {
		localWaitMsg = &rep.Exit
	}
	conn.Close()
	os.Exit(localWaitMsg.ExitStatus())
}
Пример #12
0
func TestRpcFS(t *testing.T) {
	tmp, _ := ioutil.TempDir("", "")
	defer os.RemoveAll(tmp)

	mnt := tmp + "/mnt"
	orig := tmp + "/orig"
	srvCache := tmp + "/server-cache"
	clientCache := tmp + "/client-cache"

	os.Mkdir(mnt, 0700)
	os.Mkdir(orig, 0700)
	os.Mkdir(orig+"/subdir", 0700)
	content := "hello"
	err := ioutil.WriteFile(orig+"/file.txt", []byte(content), 0644)
	if err != nil {
		t.Fatal(err)
	}

	cache := NewContentCache(srvCache)
	server := NewFsServer(orig, cache, []string{})

	l, r, err := fuse.Socketpair("unix")
	if err != nil {
		t.Fatal(err)
	}
	defer l.Close()
	defer r.Close()

	rpcServer := rpc.NewServer()
	rpcServer.Register(server)
	go rpcServer.ServeConn(l)

	rpcClient := rpc.NewClient(r)
	fs := NewRpcFs(rpcClient, NewContentCache(clientCache))

	state, _, err := fuse.MountPathFileSystem(mnt, fs, nil)
	state.Debug = true
	if err != nil {
		t.Fatal("Mount", err)
	}
	defer func() {
		log.Println("unmounting")
		err := state.Unmount()
		if err == nil {
			os.RemoveAll(tmp)
		}
	}()

	go state.Loop(false)

	fi, err := os.Lstat(mnt + "/subdir")
	if fi == nil || !fi.IsDirectory() {
		t.Fatal("subdir stat", fi, err)
	}

	c, err := ioutil.ReadFile(mnt + "/file.txt")
	if err != nil || string(c) != "hello" {
		t.Error("Readfile", c)
	}

	entries, err := ioutil.ReadDir(mnt)
	if err != nil || len(entries) != 2 {
		t.Error("Readdir", err, entries)
	}

	// This test implementation detail - should be separate?
	storedHash := server.hashCache["/file.txt"]
	if storedHash == "" || string(storedHash) != string(md5str(content)) {
		t.Errorf("cache error %x (%v)", storedHash, storedHash)
	}

	newData := []FileAttr{
		FileAttr{
			Path: "/file.txt",
			Hash: md5str("somethingelse"),
		},
	}
	server.updateFiles(newData)
	storedHash = server.hashCache["/file.txt"]
	if storedHash == "" || storedHash != newData[0].Hash {
		t.Errorf("cache error %x (%v)", storedHash, storedHash)
	}
}