// 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 }
// 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 }