Beispiel #1
0
func (b *Builder) commit(id string, autoCmd *runconfig.Command, comment string) error {
	if b.disableCommit {
		return nil
	}
	if b.image == "" && !b.noBaseImage {
		return fmt.Errorf("Please provide a source image with `from` prior to commit")
	}
	b.Config.Image = b.image
	if id == "" {
		cmd := b.Config.Cmd
		if runtime.GOOS != "windows" {
			b.Config.Cmd = runconfig.NewCommand("/bin/sh", "-c", "#(nop) "+comment)
		} else {
			b.Config.Cmd = runconfig.NewCommand("cmd", "/S /C", "REM (nop) "+comment)
		}
		defer func(cmd *runconfig.Command) { b.Config.Cmd = cmd }(cmd)

		hit, err := b.probeCache()
		if err != nil {
			return err
		}
		if hit {
			return nil
		}

		container, err := b.create()
		if err != nil {
			return err
		}
		id = container.ID
	}
	container, err := b.Daemon.Get(id)
	if err != nil {
		return err
	}

	// Note: Actually copy the struct
	autoConfig := *b.Config
	autoConfig.Cmd = autoCmd

	// Commit the container
	image, err := b.Daemon.Commit(container, "", "", "", b.maintainer, true, &autoConfig)
	if err != nil {
		return err
	}
	b.image = image.ID
	return nil
}
Beispiel #2
0
// CMD foo
//
// Set the default command to run in the container (which may be empty).
// Argument handling is the same as RUN.
//
func cmd(b *Builder, args []string, attributes map[string]bool, original string) error {
	if err := b.BuilderFlags.Parse(); err != nil {
		return err
	}

	cmdSlice := handleJsonArgs(args, attributes)

	if !attributes["json"] {
		if runtime.GOOS != "windows" {
			cmdSlice = append([]string{"/bin/sh", "-c"}, cmdSlice...)
		} else {
			cmdSlice = append([]string{"cmd", "/S /C"}, cmdSlice...)
		}
	}

	b.Config.Cmd = runconfig.NewCommand(cmdSlice...)

	if err := b.commit("", b.Config.Cmd, fmt.Sprintf("CMD %q", cmdSlice)); err != nil {
		return err
	}

	if len(args) != 0 {
		b.cmdSet = true
	}

	return nil
}
Beispiel #3
0
func (b *Builder) create() (*daemon.Container, error) {
	if b.image == "" && !b.noBaseImage {
		return nil, fmt.Errorf("Please provide a source image with `from` prior to run")
	}
	b.Config.Image = b.image
	config := *b.Config

	// Create the Pod

	podId := fmt.Sprintf("buildpod-%s", utils.RandStr(10, "alpha"))
	podString, err := MakeBasicPod(podId, b.image, b.Config.Cmd.Slice())
	if err != nil {
		return nil, err
	}
	err = b.Hyperdaemon.CreatePod(podId, podString, false)
	if err != nil {
		return nil, err
	}
	// Get the container
	var (
		containerId = ""
		c           *daemon.Container
	)
	ps, ok := b.Hyperdaemon.PodList.GetStatus(podId)
	if !ok {
		return nil, fmt.Errorf("Cannot find pod %s", podId)
	}
	for _, i := range ps.Containers {
		containerId = i.Id
	}
	c, err = b.Daemon.Get(containerId)
	if err != nil {
		glog.Error(err.Error())
		return nil, err
	}

	b.TmpContainers[c.ID] = struct{}{}
	b.TmpPods[podId] = struct{}{}
	fmt.Fprintf(b.OutStream, " ---> Running in %s\n", stringid.TruncateID(c.ID))

	if config.Cmd.Len() > 0 {
		// override the entry point that may have been picked up from the base image
		s := config.Cmd.Slice()
		c.Path = s[0]
		c.Args = s[1:]
	} else {
		config.Cmd = runconfig.NewCommand()
	}

	return c, nil
}
Beispiel #4
0
func (cli Docker) SendCmdCreate(name, image string, cmds []string, userConfig interface{}) ([]byte, int, error) {
	config := runconfig.Config{
		Image: image,
		Cmd:   runconfig.NewCommand(cmds...),
	}
	if userConfig != nil {
		config = userConfig.(runconfig.Config)
	}
	hostConfig := &runconfig.HostConfig{}
	containerId, _, err := cli.daemon.ContainerCreate(name, &config, hostConfig)
	if err != nil {
		return nil, 500, err
	}
	return []byte(containerId), 200, nil
}
Beispiel #5
0
func (b *Builder) runContextCommand(args []string, allowRemote bool, allowDecompression bool, cmdName string) error {
	if b.context == nil {
		return fmt.Errorf("No context given. Impossible to use %s", cmdName)
	}

	if len(args) < 2 {
		return fmt.Errorf("Invalid %s format - at least two arguments required", cmdName)
	}

	dest := args[len(args)-1] // last one is always the dest

	copyInfos := []*copyInfo{}

	b.Config.Image = b.image

	defer func() {
		for _, ci := range copyInfos {
			if ci.tmpDir != "" {
				os.RemoveAll(ci.tmpDir)
			}
		}
	}()

	// Loop through each src file and calculate the info we need to
	// do the copy (e.g. hash value if cached).  Don't actually do
	// the copy until we've looked at all src files
	for _, orig := range args[0 : len(args)-1] {
		if err := calcCopyInfo(
			b,
			cmdName,
			&copyInfos,
			orig,
			dest,
			allowRemote,
			allowDecompression,
			true,
		); err != nil {
			glog.Error(err.Error())
			return err
		}
	}

	if len(copyInfos) == 0 {
		return fmt.Errorf("No source files were specified")
	}

	if len(copyInfos) > 1 && !strings.HasSuffix(dest, "/") {
		return fmt.Errorf("When using %s with more than one source file, the destination must be a directory and end with a /", cmdName)
	}

	// For backwards compat, if there's just one CI then use it as the
	// cache look-up string, otherwise hash 'em all into one
	var srcHash string
	var origPaths string

	if len(copyInfos) == 1 {
		srcHash = copyInfos[0].hash
		origPaths = copyInfos[0].origPath
	} else {
		var hashs []string
		var origs []string
		for _, ci := range copyInfos {
			hashs = append(hashs, ci.hash)
			origs = append(origs, ci.origPath)
		}
		hasher := sha256.New()
		hasher.Write([]byte(strings.Join(hashs, ",")))
		srcHash = "multi:" + hex.EncodeToString(hasher.Sum(nil))
		origPaths = strings.Join(origs, " ")
	}

	cmd := b.Config.Cmd
	if runtime.GOOS != "windows" {
		b.Config.Cmd = runconfig.NewCommand("/bin/sh", "-c", fmt.Sprintf("#(nop) %s %s in %s", cmdName, srcHash, dest))
	} else {
		b.Config.Cmd = runconfig.NewCommand("cmd", "/S /C", fmt.Sprintf("REM (nop) %s %s in %s", cmdName, srcHash, dest))
	}
	defer func(cmd *runconfig.Command) { b.Config.Cmd = cmd }(cmd)

	hit, err := b.probeCache()
	if err != nil {
		return err
	}

	if hit {
		return nil
	}

	b.Config.Image = b.image
	//	config := *b.Config

	// Create the Pod
	podId := fmt.Sprintf("buildpod-%s", utils.RandStr(10, "alpha"))
	tempSrcDir := fmt.Sprintf("/var/run/hyper/temp/%s/", podId)
	if err := os.MkdirAll(tempSrcDir, 0755); err != nil {
		glog.Errorf(err.Error())
		return err
	}
	if _, err := os.Stat(tempSrcDir); err != nil {
		glog.Errorf(err.Error())
		return err
	}
	shellDir := fmt.Sprintf("/var/run/hyper/shell/%s/", podId)
	if err := os.MkdirAll(shellDir, 0755); err != nil {
		glog.Errorf(err.Error())
		return err
	}
	copyshell, err1 := os.Create(shellDir + "/exec-copy.sh")
	if err1 != nil {
		glog.Errorf(err1.Error())
		return err1
	}
	fmt.Fprintf(copyshell, "#!/bin/sh\n")

	podString, err := MakeCopyPod(podId, b.image, b.Config.WorkingDir, tempSrcDir, dest, shellDir)
	if err != nil {
		return err
	}
	err = b.Hyperdaemon.CreatePod(podId, podString, false)
	if err != nil {
		return err
	}
	// Get the container
	var (
		containerId = ""
		container   *daemon.Container
	)

	ps, ok := b.Hyperdaemon.PodList.GetStatus(podId)
	if !ok {
		return fmt.Errorf("Cannot find pod %s", podId)
	}
	for _, i := range ps.Containers {
		containerId = i.Id
	}
	container, err = b.Daemon.Get(containerId)
	if err != nil {
		glog.Error(err.Error())
		return err
	}

	b.TmpContainers[container.ID] = struct{}{}
	b.TmpPods[podId] = struct{}{}
	for _, ci := range copyInfos {
		glog.V(1).Infof("container %s, origPath %s, destPath %s", container.ID, ci.origPath, ci.destPath)
		// Copy the source files to tempSrcDir
		if err := b.addContext(container, ci.origPath, tempSrcDir, ci.decompress); err != nil {
			glog.Error(err.Error())
			return err
		}
		if strings.HasSuffix(dest, "/") == true {
			fmt.Fprintf(copyshell, fmt.Sprintf("cp /tmp/src/%s %s\n", ci.origPath, ci.destPath))
		} else {
			fmt.Fprintf(copyshell, fmt.Sprintf("cp /tmp/src/%s %s\n", ci.origPath, dest))
			break
		}
	}

	fmt.Fprintf(copyshell, "umount /tmp/src/\n")
	fmt.Fprintf(copyshell, "umount /tmp/shell/\n")
	fmt.Fprintf(copyshell, "rm -rf /tmp/shell/\n")
	fmt.Fprintf(copyshell, "rm -rf /tmp/src/\n")
	copyshell.Close()
	// start or replace pod
	vm, ok := b.Hyperdaemon.VmList[b.Name]
	if !ok {
		glog.Warningf("can not find VM(%s)", b.Name)

		bo := &hypervisor.BootConfig{
			CPU:    1,
			Memory: 512,
			Kernel: b.Hyperdaemon.Kernel,
			Initrd: b.Hyperdaemon.Initrd,
			Bios:   b.Hyperdaemon.Bios,
			Cbfs:   b.Hyperdaemon.Cbfs,
			Vbox:   b.Hyperdaemon.VboxImage,
		}

		vm = b.Hyperdaemon.NewVm(b.Name, 1, 512, false, types.VM_KEEP_AFTER_FINISH)

		err = vm.Launch(bo)
		if err != nil {
			return err
		}

		b.Hyperdaemon.AddVm(vm)
	}
	if vm.Status == types.S_VM_IDLE {
		code, cause, err := b.Hyperdaemon.StartPod(podId, "", b.Name, nil, false, false, types.VM_KEEP_AFTER_FINISH, []*hypervisor.TtyIO{})
		if err != nil {
			glog.Errorf("Code is %d, Cause is %s, %s", code, cause, err.Error())
			b.Hyperdaemon.KillVm(b.Name)
			return err
		}
		vm = b.Hyperdaemon.VmList[b.Name]
		// wait for cmd finish
		Status, err := vm.GetResponseChan()
		if err != nil {
			glog.Error(err.Error())
			return err
		}
		defer vm.ReleaseResponseChan(Status)

		var vmResponse *types.VmResponse
		for {
			vmResponse = <-Status
			if vmResponse.VmId == b.Name {
				if vmResponse.Code == types.E_POD_FINISHED {
					glog.Infof("Got E_POD_FINISHED code response")
					break
				}
			}
		}

		pod, ok := b.Hyperdaemon.PodList.Get(podId)
		if !ok {
			return fmt.Errorf("Cannot find pod %s", podId)
		}
		pod.SetVM(b.Name, vm)

		// release pod from VM
		glog.Warningf("start stop pod")
		code, cause, err = b.Hyperdaemon.StopPod(podId, "no")
		if err != nil {
			glog.Errorf("Code is %d, Cause is %s, %s", code, cause, err.Error())
			b.Hyperdaemon.KillVm(b.Name)
			return err
		}
		glog.Warningf("stop pod finish")
	} else {
		glog.Errorf("Vm is not IDLE")
		return fmt.Errorf("Vm is not IDLE")
	}

	glog.Warningf("begin commit")
	if err := b.commit(container.ID, cmd, fmt.Sprintf("%s %s in %s", cmdName, origPaths, dest)); err != nil {
		return err
	}

	return nil
}