func setupBaseImage() { eng, err := engine.New(unitTestStoreBase) if err != nil { log.Fatalf("Can't initialize engine at %s: %s", unitTestStoreBase, err) } job := eng.Job("initserver") job.Setenv("Root", unitTestStoreBase) job.SetenvBool("Autorestart", false) job.Setenv("BridgeIface", unitTestNetworkBridge) if err := job.Run(); err != nil { log.Fatalf("Unable to create a runtime for tests: %s", err) } job = eng.Job("inspect", unitTestImageName, "image") img, _ := job.Stdout.AddEnv() // If the unit test is not found, try to download it. if err := job.Run(); err != nil || img.Get("id") != unitTestImageID { // Retrieve the Image job = eng.Job("pull", unitTestImageName) job.Stdout.Add(utils.NopWriteCloser(os.Stdout)) if err := job.Run(); err != nil { log.Fatalf("Unable to pull the test image: %s", err) } } }
// Job creates a new job which can later be executed. // This function mimics `Command` from the standard os/exec package. func (eng *Engine) Job(name string, args ...string) *Job { job := &Job{ Eng: eng, Name: name, Args: args, Stdin: NewInput(), Stdout: NewOutput(), Stderr: NewOutput(), env: &Env{}, } job.Stderr.Add(utils.NopWriteCloser(eng.Stderr)) handler, exists := eng.handlers[name] if exists { job.handler = handler } return job }
// Register makes a container object usable by the runtime as <container.ID> func (runtime *Runtime) Register(container *Container) error { if container.runtime != nil || runtime.Exists(container.ID) { return fmt.Errorf("Container is already loaded") } if err := validateID(container.ID); err != nil { return err } if err := runtime.ensureName(container); err != nil { return err } // Get the root filesystem from the driver basefs, err := runtime.driver.Get(container.ID) if err != nil { return fmt.Errorf("Error getting container filesystem %s from driver %s: %s", container.ID, runtime.driver, err) } defer runtime.driver.Put(container.ID) container.basefs = basefs container.runtime = runtime // Attach to stdout and stderr container.stderr = utils.NewWriteBroadcaster() container.stdout = utils.NewWriteBroadcaster() // Attach to stdin if container.Config.OpenStdin { container.stdin, container.stdinPipe = io.Pipe() } else { container.stdinPipe = utils.NopWriteCloser(ioutil.Discard) // Silently drop stdin } // done runtime.containers.PushBack(container) runtime.idIndex.Add(container.ID) // FIXME: if the container is supposed to be running but is not, auto restart it? // if so, then we need to restart monitor and init a new lock // If the container is supposed to be running, make sure of it if container.State.IsRunning() { info := runtime.execDriver.Info(container.ID) if !info.IsRunning() { utils.Debugf("Container %s was supposed to be running but is not.", container.ID) if runtime.config.AutoRestart { utils.Debugf("Restarting") container.State.SetGhost(false) container.State.SetStopped(0) if err := container.Start(); err != nil { return err } } else { utils.Debugf("Marking as stopped") container.State.SetStopped(-127) if err := container.ToDisk(); err != nil { return err } } } else { utils.Debugf("Reconnecting to container %v", container.ID) if err := container.allocateNetwork(); err != nil { return err } container.waitLock = make(chan struct{}) go container.monitor(nil) } } else { // When the container is not running, we still initialize the waitLock // chan and close it. Receiving on nil chan blocks whereas receiving on a // closed chan does not. In this case we do not want to block. container.waitLock = make(chan struct{}) close(container.waitLock) } return nil }