Exemple #1
0
// Run will execute the given command in the ACI being built. a.CurrentACIPath
// is where the untarred ACI is stored, a.DepStoreTarPath is the directory to
// download dependencies into, a.DepStoreExpandedPath is where the dependencies
// are expanded into, a.OverlayWorkPath is the work directory used by
// overlayfs, and insecure signifies whether downloaded images should be
// fetched over http or https.
func (a *ACBuild) Run(cmd []string, insecure bool) (err error) {
	if err = a.lock(); err != nil {
		return err
	}
	defer func() {
		if err1 := a.unlock(); err == nil {
			err = err1
		}
	}()

	if os.Geteuid() != 0 {
		return fmt.Errorf("the run subcommand must be run as root")
	}

	err = util.RmAndMkdir(a.OverlayTargetPath)
	if err != nil {
		return err
	}
	defer os.RemoveAll(a.OverlayTargetPath)
	err = util.RmAndMkdir(a.OverlayWorkPath)
	if err != nil {
		return err
	}
	defer os.RemoveAll(a.OverlayWorkPath)
	err = os.MkdirAll(a.DepStoreExpandedPath, 0755)
	if err != nil {
		return err
	}
	err = os.MkdirAll(a.DepStoreTarPath, 0755)
	if err != nil {
		return err
	}

	man, err := util.GetManifest(a.CurrentACIPath)
	if err != nil {
		return err
	}

	if len(man.Dependencies) != 0 {
		if !supportsOverlay() {
			err := exec.Command("modprobe", "overlay").Run()
			if err != nil {
				return err
			}
			if !supportsOverlay() {
				return fmt.Errorf(
					"overlayfs support required for using run with dependencies")
			}
		}
	}

	deps, err := a.renderACI(insecure, a.Debug)
	if err != nil {
		return err
	}

	var nspawnpath string
	if deps == nil {
		nspawnpath = path.Join(a.CurrentACIPath, aci.RootfsDir)
	} else {
		for i, dep := range deps {
			deps[i] = path.Join(a.DepStoreExpandedPath, dep, aci.RootfsDir)
		}
		options := "lowerdir=" + strings.Join(deps, ":") +
			",upperdir=" + path.Join(a.CurrentACIPath, aci.RootfsDir) +
			",workdir=" + a.OverlayWorkPath
		err := syscall.Mount("overlay", a.OverlayTargetPath, "overlay", 0, options)
		if err != nil {
			return err
		}

		defer func() {
			err1 := syscall.Unmount(a.OverlayTargetPath, 0)
			if err == nil {
				err = err1
			}
		}()

		nspawnpath = a.OverlayTargetPath
	}
	nspawncmd := []string{"systemd-nspawn", "-q", "-D", nspawnpath}

	if man.App != nil {
		for _, evar := range man.App.Environment {
			nspawncmd = append(nspawncmd, "--setenv", evar.Name+"="+evar.Value)
		}
	}

	err = a.mirrorLocalZoneInfo()
	if err != nil {
		return err
	}

	if len(cmd) == 0 {
		return fmt.Errorf("command to run not set")
	}
	abscmd, err := findCmdInPath(pathlist, cmd[0], nspawnpath)
	if err != nil {
		return err
	}
	nspawncmd = append(nspawncmd, abscmd)
	nspawncmd = append(nspawncmd, cmd[1:]...)

	execCmd := exec.Command(nspawncmd[0], nspawncmd[1:]...)
	execCmd.Stdin = os.Stdin
	execCmd.Stdout = os.Stdout
	execCmd.Stderr = os.Stderr
	execCmd.Env = []string{"SYSTEMD_LOG_LEVEL=err"}

	err = execCmd.Run()
	if err != nil {
		if err == exec.ErrNotFound {
			return fmt.Errorf("systemd-nspawn is required but not found")
		}
		return err
	}

	return nil
}
Exemple #2
0
// Run will execute the given command in the ACI being built. acipath is where
// the untarred ACI is stored, depstore is the directory to download
// dependencies into, scratchpath is where the dependencies are expanded into,
// workpath is the work directory used by overlayfs, and insecure signifies
// whether downloaded images should be fetched over http or https.
func Run(acipath, depstore, targetpath, scratchpath, workpath string, cmd []string, insecure bool) error {
	err := util.RmAndMkdir(targetpath)
	if err != nil {
		return err
	}
	defer os.RemoveAll(targetpath)
	err = util.RmAndMkdir(workpath)
	if err != nil {
		return err
	}
	defer os.RemoveAll(workpath)
	err = os.MkdirAll(scratchpath, 0755)
	if err != nil {
		return err
	}
	err = os.MkdirAll(depstore, 0755)
	if err != nil {
		return err
	}

	man, err := util.GetManifest(acipath)
	if err != nil {
		return err
	}

	if len(man.Dependencies) != 0 {
		err := util.Exec("modprobe", "overlay")
		if err != nil {
			return err
		}
		if !supportsOverlay() {
			return fmt.Errorf(
				"overlayfs support required for using run with dependencies")
		}
	}

	deps, err := renderACI(acipath, scratchpath, depstore, insecure)
	if err != nil {
		return err
	}

	var nspawnpath string
	if deps == nil {
		nspawnpath = path.Join(acipath, aci.RootfsDir)
	} else {
		for i, dep := range deps {
			deps[i] = path.Join(scratchpath, dep, aci.RootfsDir)
		}
		options := "-olowerdir=" + strings.Join(deps, ":") +
			",upperdir=" + path.Join(acipath, aci.RootfsDir) + ",workdir=" + workpath
		err := util.Exec("mount", "-t", "overlay",
			"overlay", options, targetpath)
		if err != nil {
			return err
		}

		umount := exec.Command("umount", targetpath)
		umount.Stdout = os.Stdout
		umount.Stderr = os.Stderr
		defer umount.Run()

		nspawnpath = targetpath
	}
	nspawncmd := []string{"systemd-nspawn", "-q", "-D", nspawnpath}

	if man.App != nil {
		for _, evar := range man.App.Environment {
			nspawncmd = append(nspawncmd, "--setenv", evar.Name+"="+evar.Value)
		}
	}

	if len(cmd) == 0 {
		return fmt.Errorf("command to run not set")
	}
	abscmd, err := findCmdInPath(pathlist, cmd[0], nspawnpath)
	if err != nil {
		return err
	}
	nspawncmd = append(nspawncmd, abscmd)
	nspawncmd = append(nspawncmd, cmd[1:]...)
	//fmt.Printf("%v\n", nspawncmd)

	err = util.Exec(nspawncmd[0], nspawncmd[1:]...)
	if err != nil {
		return err
	}

	return nil
}