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  }