github.com/Cloud-Foundations/Dominator@v0.3.4/cmd/dominator/main.go (about) 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 _ "net/http/pprof" 7 "os" 8 "path" 9 "syscall" 10 "time" 11 12 "github.com/Cloud-Foundations/Dominator/dom/herd" 13 "github.com/Cloud-Foundations/Dominator/dom/rpcd" 14 "github.com/Cloud-Foundations/Dominator/lib/constants" 15 "github.com/Cloud-Foundations/Dominator/lib/flags/loadflags" 16 "github.com/Cloud-Foundations/Dominator/lib/log" 17 "github.com/Cloud-Foundations/Dominator/lib/log/serverlogger" 18 "github.com/Cloud-Foundations/Dominator/lib/mdb" 19 "github.com/Cloud-Foundations/Dominator/lib/mdb/mdbd" 20 objectserver "github.com/Cloud-Foundations/Dominator/lib/objectserver/filesystem" 21 "github.com/Cloud-Foundations/Dominator/lib/srpc" 22 "github.com/Cloud-Foundations/Dominator/lib/srpc/setupserver" 23 "github.com/Cloud-Foundations/Dominator/lib/wsyscall" 24 "github.com/Cloud-Foundations/tricorder/go/tricorder" 25 ) 26 27 const dirPerms = syscall.S_IRWXU 28 29 var ( 30 debug = flag.Bool("debug", false, 31 "If true, show debugging output") 32 fdLimit = flag.Uint64("fdLimit", getFdLimit(), 33 "Maximum number of open file descriptors (this limits concurrent connection attempts)") 34 imageServerHostname = flag.String("imageServerHostname", "localhost", 35 "Hostname of image server") 36 imageServerPortNum = flag.Uint("imageServerPortNum", 37 constants.ImageServerPortNumber, 38 "Port number of image server") 39 mdbFile = flag.String("mdbFile", constants.DefaultMdbFile, 40 "File to read MDB data from") 41 minInterval = flag.Uint("minInterval", 1, 42 "Minimum interval between loops (in seconds)") 43 objectsDir = flag.String("objectsDir", "objects", 44 "Directory containing computed objects, relative to stateDir") 45 permitInsecureMode = flag.Bool("permitInsecureMode", false, 46 "If true, run in insecure mode. This gives remote access to all") 47 portNum = flag.Uint("portNum", constants.DominatorPortNumber, 48 "Port number to allocate and listen on for HTTP/RPC") 49 stateDir = flag.String("stateDir", "/var/lib/Dominator", 50 "Name of dominator state directory.") 51 ) 52 53 func showMdb(mdb *mdb.Mdb) { 54 fmt.Println() 55 mdb.DebugWrite(os.Stdout) 56 fmt.Println() 57 } 58 59 func getFdLimit() uint64 { 60 _, maxFD, err := wsyscall.GetFileDescriptorLimit() 61 if err != nil { 62 panic(err) 63 } 64 return maxFD 65 } 66 67 func pathJoin(first, second string) string { 68 if path.IsAbs(second) { 69 return path.Clean(second) 70 } 71 return path.Join(first, second) 72 } 73 74 func newObjectServer(objectsDir string, logger log.DebugLogger) ( 75 *objectserver.ObjectServer, error) { 76 fi, err := os.Stat(objectsDir) 77 if err != nil { 78 if err := os.Mkdir(objectsDir, dirPerms); err != nil { 79 return nil, err 80 } 81 } else if !fi.IsDir() { 82 return nil, fmt.Errorf("%s is not a directory", objectsDir) 83 } 84 return objectserver.NewObjectServer(objectsDir, logger) 85 } 86 87 func main() { 88 if os.Geteuid() == 0 { 89 fmt.Fprintln(os.Stderr, "Do not run the Dominator as root") 90 os.Exit(1) 91 } 92 if err := loadflags.LoadForDaemon("dominator"); err != nil { 93 fmt.Fprintln(os.Stderr, err) 94 os.Exit(1) 95 } 96 flag.Parse() 97 tricorder.RegisterFlags() 98 logger := serverlogger.New("") 99 srpc.SetDefaultLogger(logger) 100 params := setupserver.Params{Logger: logger} 101 if err := setupserver.SetupTlsWithParams(params); err != nil { 102 if *permitInsecureMode { 103 logger.Println(err) 104 } else { 105 logger.Fatalln(err) 106 } 107 } 108 rlim := syscall.Rlimit{Cur: *fdLimit, Max: *fdLimit} 109 if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil { 110 fmt.Fprintf(os.Stderr, "Cannot set FD limit: %s\n", err) 111 os.Exit(1) 112 } 113 fi, err := os.Lstat(*stateDir) 114 if err != nil { 115 fmt.Fprintf(os.Stderr, "Cannot stat: %s: %s\n", *stateDir, err) 116 os.Exit(1) 117 } 118 if !fi.IsDir() { 119 fmt.Fprintf(os.Stderr, "%s is not a directory\n", *stateDir) 120 os.Exit(1) 121 } 122 interval := time.Duration(*minInterval) * time.Second 123 mdbChannel := mdbd.StartMdbDaemon(*mdbFile, logger) 124 objectServer, err := newObjectServer(path.Join(*stateDir, *objectsDir), 125 logger) 126 if err != nil { 127 fmt.Fprintf(os.Stderr, "Cannot load objectcache: %s\n", err) 128 os.Exit(1) 129 } 130 metricsDir, err := tricorder.RegisterDirectory("/dominator/herd") 131 if err != nil { 132 fmt.Fprintf(os.Stderr, "Cannot create metrics directory: %s\n", err) 133 os.Exit(1) 134 } 135 herd := herd.NewHerd(fmt.Sprintf("%s:%d", *imageServerHostname, 136 *imageServerPortNum), objectServer, metricsDir, logger) 137 herd.AddHtmlWriter(logger) 138 rpcd.Setup(herd, logger) 139 if err = herd.StartServer(*portNum, true); err != nil { 140 fmt.Fprintf(os.Stderr, "Unable to create http server: %s\n", err) 141 os.Exit(1) 142 } 143 scanTokenChannel := make(chan bool, 1) 144 scanTokenChannel <- true 145 nextCycleStopTime := time.Now().Add(interval) 146 for { 147 select { 148 case mdb := <-mdbChannel: 149 herd.MdbUpdate(mdb) 150 if *debug { 151 showMdb(mdb) 152 } 153 case <-scanTokenChannel: 154 // Scan one sub. 155 if herd.PollNextSub() { // We've reached the end of a scan cycle. 156 if *debug { 157 fmt.Print(".") 158 } 159 go func(sleepDuration time.Duration) { 160 time.Sleep(sleepDuration) 161 nextCycleStopTime = time.Now().Add(interval) 162 scanTokenChannel <- true 163 }(nextCycleStopTime.Sub(time.Now())) 164 } else { 165 scanTokenChannel <- true 166 } 167 } 168 } 169 }