// StartDaemon starts a daemon using the provided binary returning // a client to the binary, a close function, and error. func StartDaemon(binary string, lc LogCapturer) (*dockerclient.Client, func() error, error) { // Get Docker version of process previousVersion, err := versionutil.BinaryVersion(binary) if err != nil { return nil, nil, fmt.Errorf("could not get binary version: %s", err) } logrus.Debugf("Starting daemon with %s", binary) binaryArgs := []string{} if previousVersion.LessThan(versionutil.StaticVersion(1, 8, 0)) { binaryArgs = append(binaryArgs, "--daemon") } else { binaryArgs = append(binaryArgs, "daemon") } binaryArgs = append(binaryArgs, "--log-level=debug") binaryArgs = append(binaryArgs, "--storage-driver="+getGraphDriver()) cmd := exec.Command(binary, binaryArgs...) cmd.Stdout = lc.Stdout() cmd.Stderr = lc.Stderr() if err := cmd.Start(); err != nil { return nil, nil, fmt.Errorf("could not start daemon: %s", err) } logrus.Debugf("Waiting for daemon to start") time.Sleep(2 * time.Second) client, err := dockerclient.NewClientFromEnv() if err != nil { return nil, nil, fmt.Errorf("could not initialize client: %s", err) } // Wait for it to start for i := 0; ; i++ { v, err := client.Version() if err == nil { logrus.Debugf("Established connection to daemon with version %s", v.Get("Version")) break } if i >= 10 { logrus.Fatalf("Failed to establish connection to daemon, check logs, quitting") } time.Sleep(time.Second) } kill := func() error { if err := cmd.Process.Kill(); err != nil { return err } time.Sleep(500 * time.Millisecond) return os.RemoveAll("/var/run/docker.pid") } return client, kill, nil }
func cleanDockerGraph(graphDir string, v versionutil.Version) error { logrus.Debugf("Cleaning for version %s", v) // Handle migration files migratedVersion := versionutil.StaticVersion(1, 10, 0) migratedVersion.Tag = "dev" if v.LessThan(migratedVersion) { if err := removeIfExists(filepath.Join(graphDir, ".migration-v1-images.json")); err != nil { return err } if err := removeIfExists(filepath.Join(graphDir, ".migration-v1-tags")); err != nil { return err } root := filepath.Join(graphDir, "graph") migrationPurger := func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { if strings.HasPrefix(filepath.Base(path), ".migrat") { logrus.Debugf("Removing migration file %s", path) if err := os.Remove(path); err != nil { return err } } } return nil } if err := filepath.Walk(root, migrationPurger); err != nil { return err } // Remove all containers infos, err := ioutil.ReadDir(filepath.Join(graphDir, "containers")) if err != nil { if os.IsNotExist(err) { return nil } return err } drivers, err := getAllGraphDrivers(graphDir) if err != nil { return err } for _, info := range infos { container := info.Name() for _, graphDriver := range drivers { if err := removeLayerGraphContent(container, "mount-id", graphDriver, graphDir); err != nil && !os.IsNotExist(err) { return err } if err := removeLayerGraphContent(container, "init-id", graphDriver, graphDir); err != nil && !os.IsNotExist(err) { return err } } if err := os.RemoveAll(filepath.Join(graphDir, "containers", container)); err != nil { return err } } if err := os.RemoveAll(filepath.Join(graphDir, "image")); err != nil { return err } if err := removeIfExists(filepath.Join(graphDir, "linkgraph.db")); err != nil { return err } // TODO: Remove everything in graph driver directory which is not in graph } return nil }
func main() { name := filepath.Base(os.Args[0]) if name == "golem_runner" { runnerMain() return } if name == "golem_tapper" { tapperMain() return } var ( cacheDir string startDaemon bool debug bool ) cm := runner.NewConfigurationManager(name) cm.FlagSet.StringVar(&cacheDir, "cache", "", "Cache directory") cm.FlagSet.BoolVar(&startDaemon, "rundaemon", false, "Start daemon") cm.FlagSet.BoolVar(&debug, "debug", false, "Whether to output debug logs") if err := cm.ParseFlags(os.Args[1:]); err != nil { logrus.Fatalf("Invalid options: %v", err) } if debug { logrus.SetLevel(logrus.DebugLevel) } runConfig, err := cm.RunnerConfiguration() if err != nil { logrus.Fatalf("Error creating run configuration: %v", err) } if cacheDir == "" { td, err := ioutil.TempDir("", "golem-cache-") if err != nil { logrus.Fatalf("Error creating tempdir: %v", err) } cacheDir = td defer os.RemoveAll(td) } cacheConfig := runner.CacheConfiguration{ ImageCache: runner.NewImageCache(filepath.Join(cacheDir, "images")), } var client runner.DockerClient if startDaemon { logger := runner.NewConsoleLogCapturer() c, shutdown, err := runner.StartDaemon(context.Background(), "docker", logger) if err != nil { logrus.Fatalf("Error starting deamon: %v", err) } defer shutdown() client = c } else { c, err := cm.DockerClient() if err != nil { logrus.Fatalf("Failed to create client: %v", err) } client = c } // require running on docker 1.10 to ensure content addressable // image identifiers are used if err := client.CheckServerVersion(versionutil.StaticVersion(1, 10, 0)); err != nil { logrus.Fatal(err) } r := runner.NewRunner(runConfig, cacheConfig, debug) if err := r.Build(client); err != nil { logrus.Fatalf("Error building test images: %v", err) } if err := r.Run(client); err != nil { logrus.Fatalf("Error running tests: %v", err) } }