github.com/Cloud-Foundations/Dominator@v0.3.4/cmd/imaginator/main.go (about) 1 //go:build linux 2 3 package main 4 5 import ( 6 "flag" 7 "fmt" 8 "os" 9 "syscall" 10 "time" 11 12 "github.com/Cloud-Foundations/Dominator/imagebuilder/builder" 13 "github.com/Cloud-Foundations/Dominator/imagebuilder/httpd" 14 "github.com/Cloud-Foundations/Dominator/imagebuilder/logarchiver" 15 "github.com/Cloud-Foundations/Dominator/imagebuilder/rpcd" 16 "github.com/Cloud-Foundations/Dominator/lib/constants" 17 "github.com/Cloud-Foundations/Dominator/lib/flags/loadflags" 18 "github.com/Cloud-Foundations/Dominator/lib/flagutil" 19 "github.com/Cloud-Foundations/Dominator/lib/log/serverlogger" 20 "github.com/Cloud-Foundations/Dominator/lib/srpc" 21 "github.com/Cloud-Foundations/Dominator/lib/srpc/setupserver" 22 "github.com/Cloud-Foundations/tricorder/go/tricorder" 23 ) 24 25 const ( 26 dirPerms = syscall.S_IRWXU | syscall.S_IRGRP | syscall.S_IXGRP | 27 syscall.S_IROTH | syscall.S_IXOTH 28 ) 29 30 var ( 31 buildLogDir = flag.String("buildLogDir", "/var/log/imaginator/builds", 32 "Name of directory to write build logs to") 33 buildLogQuota = flagutil.Size(100 << 20) 34 configurationUrl = flag.String("configurationUrl", 35 "file:///etc/imaginator/conf.json", "URL containing configuration") 36 imageServerHostname = flag.String("imageServerHostname", "localhost", 37 "Hostname of image server") 38 imageServerPortNum = flag.Uint("imageServerPortNum", 39 constants.ImageServerPortNumber, 40 "Port number of image server") 41 imageRebuildInterval = flag.Duration("imageRebuildInterval", time.Hour, 42 "time between automatic rebuilds of images") 43 maximumExpirationDuration = flag.Duration("maximumExpirationDuration", 44 24*time.Hour, "Maximum expiration time for regular users") 45 maximumExpirationDurationPrivileged = flag.Duration( 46 "maximumExpirationDurationPrivileged", 730*time.Hour, 47 "Maximum expiration time for privileged users") 48 minimumExpirationDuration = flag.Duration("minimumExpirationDuration", 49 15*time.Minute, 50 "Minimum permitted expiration duration") 51 portNum = flag.Uint("portNum", constants.ImaginatorPortNumber, 52 "Port number to allocate and listen on for HTTP/RPC") 53 presentationImageServerHostname = flag.String( 54 "presentationImageServerHostname", "", 55 "Hostname of image server for links presentation") 56 slaveDriverConfigurationFile = flag.String("slaveDriverConfigurationFile", 57 "", "Name of configuration file for slave builders") 58 stateDir = flag.String("stateDir", "/var/lib/imaginator", 59 "Name of state directory") 60 variablesFile = flag.String("variablesFile", "", 61 "A JSON encoded file containing special variables (i.e. secrets)") 62 ) 63 64 func init() { 65 flag.Var(&buildLogQuota, "buildLogQuota", 66 "Build log quota. If exceeded, old logs are deleted") 67 } 68 69 func main() { 70 if err := loadflags.LoadForDaemon("imaginator"); err != nil { 71 fmt.Fprintln(os.Stderr, err) 72 os.Exit(1) 73 } 74 flag.Parse() 75 tricorder.RegisterFlags() 76 if os.Geteuid() != 0 { 77 fmt.Fprintln(os.Stderr, "Must run the Image Builder as root") 78 os.Exit(1) 79 } 80 logger := serverlogger.New("") 81 srpc.SetDefaultLogger(logger) 82 if umask := syscall.Umask(022); umask != 022 { 83 // Since we can't cleanly fix umask for all threads, fail instead. 84 logger.Fatalf("Umask must be 022, not 0%o\n", umask) 85 } 86 params := setupserver.Params{Logger: logger} 87 if err := setupserver.SetupTlsWithParams(params); err != nil { 88 logger.Fatalln(err) 89 } 90 if err := os.MkdirAll(*stateDir, dirPerms); err != nil { 91 logger.Fatalf("Cannot create state directory: %s\n", err) 92 } 93 slaveDriver, createSlaveTimeout, err := createSlaveDriver(logger) 94 if err != nil { 95 logger.Fatalf("Error starting slave driver: %s\n", err) 96 } 97 var buildLogArchiver logarchiver.BuildLogger 98 if *buildLogDir != "" && buildLogQuota > 1<<20 { 99 buildLogArchiver, err = logarchiver.New( 100 logarchiver.BuildLogArchiveOptions{ 101 Quota: uint64(buildLogQuota), 102 Topdir: *buildLogDir, 103 }, 104 logarchiver.BuildLogArchiveParams{ 105 Logger: logger, 106 }, 107 ) 108 if err != nil { 109 logger.Fatalf("Error starting build log archiver: %s\n", err) 110 } 111 } 112 builderObj, err := builder.LoadWithOptionsAndParams( 113 builder.BuilderOptions{ 114 ConfigurationURL: *configurationUrl, 115 CreateSlaveTimeout: createSlaveTimeout, 116 ImageRebuildInterval: *imageRebuildInterval, 117 ImageServerAddress: fmt.Sprintf("%s:%d", 118 *imageServerHostname, *imageServerPortNum), 119 MaximumExpirationDuration: *maximumExpirationDuration, 120 MaximumExpirationDurationPrivileged: *maximumExpirationDurationPrivileged, 121 MinimumExpirationDuration: *minimumExpirationDuration, 122 PresentationImageServerAddress: fmt.Sprintf("%s:%d", 123 *presentationImageServerHostname, *imageServerPortNum), 124 StateDirectory: *stateDir, 125 VariablesFile: *variablesFile, 126 }, 127 builder.BuilderParams{ 128 BuildLogArchiver: buildLogArchiver, 129 Logger: logger, 130 SlaveDriver: slaveDriver, 131 }) 132 if err != nil { 133 logger.Fatalf("Cannot start builder: %s\n", err) 134 } 135 rpcHtmlWriter, err := rpcd.Setup(builderObj, logger) 136 if err != nil { 137 logger.Fatalf("Cannot start builder: %s\n", err) 138 } 139 httpd.AddHtmlWriter(builderObj) 140 if slaveDriver != nil { 141 httpd.AddHtmlWriter(slaveDriver) 142 } 143 httpd.AddHtmlWriter(rpcHtmlWriter) 144 httpd.AddHtmlWriter(logger) 145 err = httpd.StartServerWithOptionsAndParams( 146 httpd.Options{ 147 PortNumber: *portNum, 148 }, 149 httpd.Params{ 150 Builder: builderObj, 151 BuildLogReporter: buildLogArchiver, 152 Logger: logger, 153 }, 154 ) 155 if err != nil { 156 logger.Fatalf("Unable to create http server: %s\n", err) 157 } 158 }