Example #1
0
File: main.go Project: lht/termite
func main() {
	cachedir := flag.String("cachedir", "/tmp/fsserver-cache", "content cache")
	port := flag.Int("port", 1234, "file server")
	secretFile := flag.String("secret", "/tmp/secret.txt", "file containing password.")

	flag.Parse()
	if flag.NArg() < 1 {
		log.Fatalf("usage: %s EXPORTED-ROOT\n", os.Args[0])
	}
	secret, err := ioutil.ReadFile(*secretFile)
	if err != nil {
		log.Fatal("ReadFile", err)
	}
	cache := termite.NewContentCache(*cachedir)
	fileServer := termite.NewFsServer(flag.Arg(0), cache, []string{"/proc"})

	out := make(chan net.Conn)
	go termite.SetupServer(*port, secret, out)

	conn := <-out
	rpcServer := rpc.NewServer()
	err = rpcServer.Register(fileServer)
	if err != nil {
		log.Fatal("could not register file server", err)
	}
	log.Println("Server started...")
	rpcServer.ServeConn(conn)
}
Example #2
0
func NewWorkerDaemon(options *WorkerOptions) *WorkerDaemon {
	if options.FileContentCount == 0 {
		options.FileContentCount = 1024
	}

	cache := NewContentCache(options.CacheDir)
	cache.SetMemoryCacheSize(options.FileContentCount)
	me := &WorkerDaemon{
		secret:        options.Secret,
		contentCache:  cache,
		mirrorMap:     make(map[string]*Mirror),
		contentServer: &ContentServer{Cache: cache},
		pending:       NewPendingConnections(),
		maxJobCount:   options.Jobs,
		tmpDir:        options.TempDir,
		rpcServer:     rpc.NewServer(),
	}
	if os.Geteuid() == 0 && options.User != nil {
		nobody, err := user.Lookup(*options.User)
		if err != nil {
			log.Fatalf("can't lookup %q: %v", options.User, err)
		}
		me.Nobody = nobody
	}
	me.cond = sync.NewCond(&me.mirrorMapMutex)
	me.stopListener = make(chan int, 1)
	me.rpcServer.Register(me)
	return me
}
Example #3
0
func (me *Coordinator) ServeHTTP(port int) {
	me.Mux.HandleFunc("/",
		func(w http.ResponseWriter, req *http.Request) {
			me.rootHandler(w, req)
		})
	me.Mux.HandleFunc("/worker",
		func(w http.ResponseWriter, req *http.Request) {
			me.workerHandler(w, req)
		})
	me.Mux.HandleFunc("/workerkill",
		func(w http.ResponseWriter, req *http.Request) {
			me.killHandler(w, req)
		})

	rpcServer := rpc.NewServer()
	if err := rpcServer.Register(me); err != nil {
		log.Fatal(err)
	}
	me.Mux.HandleFunc(rpc.DefaultRPCPath,
		func(w http.ResponseWriter, req *http.Request) {
			rpcServer.ServeHTTP(w, req)
		})

	addr := fmt.Sprintf(":%d", port)
	log.Println("Coordinator listening on", addr)

	httpServer := http.Server{
		Addr:    addr,
		Handler: me.Mux,
	}
	err := httpServer.ListenAndServe()
	if err != nil {
		log.Fatal("ListenAndServe: ", err.String())
	}
}
Example #4
0
func NewMaster(cache *ContentCache, coordinator string, workers []string, secret []byte, excluded []string, maxJobs int) *Master {
	me := &Master{
		cache:      cache,
		fileServer: NewFsServer("/", cache, excluded),
		secret:     secret,
		retryCount: 3,
		stats:      newMasterStats(),
	}
	me.fileServer.multiplyPaths = func(n string) []string { return me.multiplyPaths(n) }
	me.mirrors = newMirrorConnections(me, workers, coordinator, maxJobs)
	me.localServer = &LocalMaster{me}
	me.secret = secret
	me.pending = NewPendingConnections()
	me.fileServerRpc = rpc.NewServer()
	me.fileServerRpc.Register(me.fileServer)
	me.localRpcServer = rpc.NewServer()
	me.localRpcServer.Register(me.localServer)

	return me
}
Example #5
0
// StartServer starts the connection listener.  Should be invoked in a coroutine.
func (me *Master) startServer(server interface{}, port int) {
	out := make(chan net.Conn)
	me.fileServerAddress = MyAddress(port)
	go SetupServer(port, me.secret, out)
	for {
		conn := <-out
		rpcServer := rpc.NewServer()
		err := rpcServer.Register(server)
		if err != nil {
			log.Fatal("could not register server", err)
		}
		log.Println("Server started...")
		go rpcServer.ServeConn(conn)
	}
}
Example #6
0
func (me *Master) startLocalServer(sock string) {
	listener, err := net.Listen("unix", sock)
	if err != nil {
		log.Fatal("startLocalServer", err)
	}
	err = os.Chmod(sock, 0700)
	if err != nil {
		log.Fatal("sock chmod", err)
	}

	for {
		conn, err := listener.Accept()
		if err != nil {
			panic(err)
		}
		rpcServer := rpc.NewServer()
		err = rpcServer.Register(me.masterRun)
		if err != nil {
			log.Fatal("could not register server", err)
		}
		go rpcServer.ServeConn(conn)
	}
}
Example #7
0
func main() {
	cachedir := flag.String("cachedir", "/tmp/worker-cache", "content cache")
	secretFile := flag.String("secret", "/tmp/secret.txt", "file containing password.")
	port := flag.Int("port", 1235, "Where to listen for work requests.")
	chrootBinary := flag.String("chroot", "", "binary to use for chroot'ing.")
	flag.Parse()
	secret, err := ioutil.ReadFile(*secretFile)
	if err != nil {
		log.Fatal("ReadFile", err)
	}

	daemon := termite.NewWorkerDaemon(secret, *cachedir)
	daemon.ChrootBinary = *chrootBinary

	out := make(chan net.Conn)
	go termite.SetupServer(*port, secret, out)
	for {
		conn := <-out
		log.Println("Opening RPC channel from", conn.RemoteAddr())
		rpcServer := rpc.NewServer()
		rpcServer.Register(daemon)
		go rpcServer.ServeConn(conn)
	}
}
Example #8
0
func NewRPC() *RPC {
	return &RPC{
		rpcs: rpc.NewServer(),
		auto: 1, // Start seq numbers from 1, so that 0 is always an invalid seq number
	}
}
Example #9
0
func (me *Mirror) serveRpc() {
	server := rpc.NewServer()
	server.Register(me)
	server.ServeConn(me.rpcConn)
	me.Shutdown()
}
Example #10
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)
	}
}