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) }
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 }
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()) } }
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 }
// 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) } }
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) } }
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) } }
func NewRPC() *RPC { return &RPC{ rpcs: rpc.NewServer(), auto: 1, // Start seq numbers from 1, so that 0 is always an invalid seq number } }
func (me *Mirror) serveRpc() { server := rpc.NewServer() server.Register(me) server.ServeConn(me.rpcConn) me.Shutdown() }
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) } }