func LoadConfig(filepath string) { if _, err := os.Stat(filepath); os.IsNotExist(err) { gologit.Fatalf("%s not present or not readable", filepath) } buffer := &bytes.Buffer{} buffer.WriteString("[main]\n") f, err := os.Open(filepath) if err != nil { gologit.Printf("Error reading config file %s", filepath) gologit.Fatal(err) } defer f.Close() _, err = buffer.ReadFrom(f) if err != nil { gologit.Printf("Error reading config file %s", filepath) gologit.Fatal(err) } err = gcfg.ReadInto(&Config, buffer) if err != nil { gologit.Printf("Error parsing config file %s", filepath) gologit.Fatal(err) } }
func setCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to set properties\n") } if len(args) < 2 { gologit.Fatalln("Improper usage") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } props, err := ParseProps(args[1:]...) if err != nil { gologit.Fatalln(err) } for _, prop := range props { prefix := "" if _, ok := CustomProperties[prop[0]]; ok { prefix = "org.freebsd.iocage:" } zfsArgs := []string{ "set", fmt.Sprintf("%s%s=%s", prefix, prop[0], prop[1]), jail.Path, } core.ZFSMust(fmt.Errorf("Error setting property"), zfsArgs...) } }
func releaseDestroyCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to destroy\n") } release, err := core.FindRelease(args[0]) if err != nil { gologit.Fatalf("Release '%s' not found!\n", args[0]) } fmt.Printf("Ready to remove release: %s\n", release.Name) if !force { fmt.Print("Are you sure [yN]? ") var response string _, err = fmt.Scanln(&response) if err != nil { if err.Error() == "unexpected newline" { os.Exit(0) } gologit.Fatalf("%s", err) } response = strings.ToLower(strings.TrimSpace(response)) if len(response) != 1 || response[0] != 'y' { return } } fmt.Printf("Destroying: %s\n", release.Name) core.ZFSMust( fmt.Errorf("Error destroying release"), "destroy", "-fr", release.Path) os.RemoveAll(release.Mountpoint) }
func snapshotCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to snapshot\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } var snapname string if len(args) > 1 { snapname = strings.TrimLeft(args[1], "@") } else { snapname = fmt.Sprintf( "ioc-%s", time.Now().Format("2006-01-02_15:04:05")) } zfsCmd := []string{"snapshot"} if recusiveSnapshot { zfsCmd = append(zfsCmd, "-r") } zfsCmd = append(zfsCmd, fmt.Sprintf("%s/root@%s", jail.Path, snapname)) core.ZFSMust(fmt.Errorf("Error removing snapshot"), zfsCmd...) }
func stopCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to stop\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } if !jail.IsRunning() { gologit.Fatalf("Jail is not running!\n") } // create file f, err := os.OpenFile(jail.GetLogPath(), os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) if err != nil { gologit.Fatal(err) } defer f.Close() fmt.Printf("* Stopping %s (%s)\n", jail.HostUUID, jail.Tag) fmt.Printf(" + Removing jail process\n") file, err := ioutil.TempFile(os.TempDir(), "rollcage.") defer os.Remove(file.Name()) jailConfig := jail.JailConfig() gologit.Debugln(jailConfig) file.WriteString(jailConfig) file.Close() excmd := exec.Command( "/usr/sbin/jail", "-f", file.Name(), "-r", fmt.Sprintf("ioc-%s", jail.HostUUID)) excmd.Stdout = f excmd.Stderr = f err = excmd.Run() if err != nil { gologit.Fatal(err) } // mostly for safety... fmt.Printf(" + Tearing down mounts\n") umountCmd("-afvF", path.Join(jail.Mountpoint, "fstab")) umountCmd(path.Join(jail.Mountpoint, "root/dev/fd")) umountCmd(path.Join(jail.Mountpoint, "root/dev")) umountCmd(path.Join(jail.Mountpoint, "root/proc")) // TODO: basejail here? // TODO: rctl stuff here... }
func snapremoveCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to snapremove\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } matchers := args[1:] gologit.Debugf("matchers: %#v\n", matchers) zfsArgs := []string{"list", "-Hrt", "snapshot", "-o", "name", "-d2", jail.Path} lines := core.SplitOutput(core.ZFSMust( fmt.Errorf("Error listing snapshots"), zfsArgs...)) rmlist := []string{} for _, line := range lines { if len(line) == 0 || len(line[0]) == 0 { continue } snapname := strings.SplitN(line[0], "@", 2)[1] gologit.Debugf("source snapname: %#v\n", snapname) for _, m := range matchers { if snapremoveRegex { matched, err := regexp.MatchString(m, snapname) if err != nil { gologit.Fatalf("Regex error: %s", err) } if matched { rmlist = append(rmlist, line[0]) continue } } else { if m == snapname { rmlist = append(rmlist, line[0]) continue } } } } gologit.Debugf("match list: %#v\n", rmlist) for _, snap := range rmlist { fmt.Printf("Removing snapshot: %s\n", strings.SplitN(snap, "@", 2)[1]) core.ZFSMust( fmt.Errorf("Error removing snapshot"), "destroy", "-r", snap) } }
func restartCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to stop\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } if !jail.IsRunning() { gologit.Fatalf("Jail is not running!\n") } // create file f, err := os.OpenFile(jail.GetLogPath(), os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) if err != nil { gologit.Fatal(err) } defer f.Close() props := jail.GetProperties() jexec := []string{fmt.Sprintf("ioc-%s", jail.HostUUID)} jexec_stop := append(jexec, core.SplitFieldsQuoteSafe(props.GetIOC("exec_stop"))...) excmd := exec.Command("/usr/sbin/jexec", jexec_stop...) excmd.Stdout = f excmd.Stderr = f err = excmd.Run() if err != nil { gologit.Printf("%s\n", err) } jexec_start := append(jexec, core.SplitFieldsQuoteSafe(props.GetIOC("exec_start"))...) excmd = exec.Command("/usr/sbin/jexec", jexec_start...) excmd.Stdout = f excmd.Stderr = f err = excmd.Run() if err != nil { gologit.Printf("%s\n", err) } // set last_started property t := time.Now() core.ZFSMust( fmt.Errorf("Error setting property"), "set", fmt.Sprintf( "org.freebsd.iocage:last_started=%s", t.Format("2006-01-02_15:04:05")), jail.Path) }
func execCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to use exec\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } if !jail.IsRunning() { gologit.Fatalf("Jail is not running!\n") } // get exec fib property lines := core.SplitOutput(core.ZFSMust( fmt.Errorf("Error listing jails"), "list", "-H", "-o", "org.freebsd.iocage:login_flags,org.freebsd.iocage:exec_fib", jail.Path)) execFib := lines[0][1] jexec := []string{} if execFib != "0" { jexec = append(jexec, "/usr/sbin/setfib", execFib) } jexec = append(jexec, "/usr/sbin/jexec") if hostUser != "" { jexec = append(jexec, "-u", hostUser) } if jailUser != "" { jexec = append(jexec, "-U", jailUser) } jexec = append(jexec, fmt.Sprintf("ioc-%s", jail.HostUUID)) jexec = append(jexec, args[1:]...) // set a default path environ := []string{ "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin", } // set a term from caller environ = append(environ, fmt.Sprintf("TERM=%s", os.Getenv("TERM"))) gologit.Debugf("%#s\n", jexec) execErr := syscall.Exec(jexec[0], jexec, environ) if execErr != nil { gologit.Fatal(execErr) } }
func rollbackCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to rollback\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } snapname := strings.TrimLeft(args[1], "@") // get FS's lines := core.SplitOutput(core.ZFSMust( fmt.Errorf("Error listing jails"), "list", "-Hr", "-o", "name", path.Join(jail.Path, "root"))) if len(lines) < 1 { gologit.Fatalf("No datasets at jailpath!\n") } snapshots := []string{} for _, line := range lines { out := core.ZFSMust( fmt.Errorf("Error listing snapshots"), "list", "-Ht", "snapshot", "-o", "name", "-d1", fmt.Sprintf("%s@%s", line[0], snapname)) if len(out) != 0 { snapshots = append(snapshots, out) } } if len(snapshots) == 0 { gologit.Fatalln("Snapshot '%s' not found!", snapname) } for _, snapshot := range snapshots { i := strings.LastIndex(snapshot, "@") elemName := snapshot[:i] j := strings.LastIndex(snapshot, "/") elemName = elemName[j:] fmt.Printf("* Rolling back jail dataset '%s' to '@%s'\n", elemName, snapname) core.ZFSMust( fmt.Errorf("Error rolling back jail"), "rollback", "-r", snapshot) } }
func runtimeCmdRun(cmd *cobra.Command, args []string) { jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } out, err := core.Jls("-n", "-j", fmt.Sprintf("ioc-%s", jail.HostUUID)) if err != nil { gologit.Fatalf("Jail is not running!\n") } lines := strings.Split(out, " ") for _, line := range lines { fmt.Fprintf(os.Stdout, "%s\n", line) } }
func CmdMust(errmsg error, name string, arg ...string) string { out, err := Cmd(name, arg...) if err != nil { gologit.Fatalf("Error: %s\n", errmsg) } return out }
func dfCmdRun(cmd *cobra.Command, args []string) { propertyList := "org.freebsd.iocage:host_hostuuid," + "org.freebsd.iocage:tag,compressratio,reservation," + "quota,used,available" outputHeaders := []string{"uuid", "tag", "crt", "res", "qta", "use", "ava"} zfsArgs := []string{"list", "-H", "-o", propertyList} if ParsableValues { zfsArgs = append(zfsArgs, "-p") } if len(args) == 0 { zfsArgs = append(zfsArgs, "-d", "1", core.GetJailsPath()) } else { jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } zfsArgs = append(zfsArgs, jail.Path) } out := core.ZFSMust(fmt.Errorf("Error listing jails"), zfsArgs...) lines := strings.Split(out, "\n") wf := core.NewOutputWriter(outputHeaders, MachineOutput) for _, line := range lines { if strings.HasPrefix(line, "-") { continue } fmt.Fprintf(wf, "%s\n", line) } wf.Flush() }
func snaplistCmdRun(cmd *cobra.Command, args []string) { jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } zfsArgs := []string{"list", "-Hrt", "snapshot", "-o", "name,creation,used,referenced", "-d2"} if ParsableValues { zfsArgs = append(zfsArgs, "-p") } zfsArgs = append(zfsArgs, jail.Path) lines := core.SplitOutput(core.ZFSMust( fmt.Errorf("Error listing snapshots"), zfsArgs...)) gologit.Debugf("%#v", lines) if len(lines) == 0 || len(lines[0]) == 0 || len(lines[0][0]) == 0 { return } var rxmatch *regexp.Regexp if snaplistRegex != "" { rxmatch, err = regexp.Compile(snaplistRegex) if err != nil { gologit.Fatalf("Bad regex: %s", err) } } outputHeaders := []string{"name", "created", "rsize", "used"} wf := core.NewOutputWriter(outputHeaders, MachineOutput) for _, line := range lines { if len(line) < 4 { continue } snapname := strings.SplitN(line[0], "@", 2)[1] if rxmatch != nil && !rxmatch.MatchString(snapname) { continue } fmt.Fprintf(wf, "%s\t%s\t%s\t%s\n", snapname, line[1], line[2], line[3]) } wf.Flush() }
func rebootCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to stop\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } if !jail.IsRunning() { gologit.Fatalf("Jail is not running!\n") } stopCmdRun(cmd, args) startCmdRun(cmd, args) }
func chrootCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to chroot\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } propertyOut := core.ZFSMust( fmt.Errorf("Error getting properties"), "get", "-H", "-o", "value", "mountpoint", jail.Path) chrootArgs := []string{ "/usr/sbin/chroot", path.Join(propertyOut, "root"), } if len(args) > 1 { chrootArgs = append(chrootArgs, args[1:]...) } else { shell := os.Getenv("SHELL") if shell == "" { shell = "/bin/sh" } chrootArgs = append(chrootArgs, shell) } // set a default path environ := []string{ "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin", } // set a term from caller environ = append(environ, fmt.Sprintf("TERM=%s", os.Getenv("TERM"))) execErr := syscall.Exec(chrootArgs[0], chrootArgs, environ) if execErr != nil { gologit.Fatal(execErr) } }
func destroyCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to destroy\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("Jail '%s' not found!\n", args[0]) } if jail.IsRunning() { gologit.Fatalf("Jail is running. Shutdown first.\n") } propertyList := []string{ "mountpoint", "org.freebsd.iocage:type", } lines := core.SplitOutput(core.ZFSMust( fmt.Errorf("Error listing jails"), "list", "-H", "-o", strings.Join(propertyList, ","), jail.Path)) if len(lines) < 1 { gologit.Fatalf("No output from property fetch\n") } prop_mountpoint := removeDash(lines[0][0]) prop_type := removeDash(lines[0][1]) if prop_type != "thickjail" { gologit.Fatalf("Type is not thickjail.\nI don't know how to handle this yet.\nGiving up!") } fmt.Printf("Ready to remove jail: %s (%s)\n", jail.HostUUID, jail.Tag) fmt.Print("Are you sure [yN]? ") var response string _, err = fmt.Scanln(&response) if err != nil { if err.Error() == "unexpected newline" { os.Exit(0) } gologit.Fatalf("%s", err) } if !force { response = strings.ToLower(strings.TrimSpace(response)) if len(response) != 1 || response[0] != 'y' { return } } fmt.Printf("Destroying: %s (%s)\n", jail.HostUUID, jail.Tag) core.ZFSMust( fmt.Errorf("Error destroying jail"), "destroy", "-fr", jail.Path) os.RemoveAll(prop_mountpoint) }
func (jail *JailMeta) GetProperties() ZFSProperties { if jail.props != nil { return jail.props } props := make(ZFSProperties, 0) lines := SplitOutput(ZFSMust( fmt.Errorf("Error listing properties"), "get", "-H", "-o", "property,value", "all", jail.Path)) if len(lines) < 1 { gologit.Fatalf("No output from property fetch\n") } for _, line := range lines { props[strings.TrimSpace(line[0])] = strings.TrimSpace(line[1]) } jail.props = props return props }
func startCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to stop\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } if jail.IsRunning() { gologit.Fatalf("Jail is already running!\n") } props := jail.GetProperties() // set a default path environ := []string{ "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin", } fmt.Printf("* Starting %s (%s)\n", jail.HostUUID, jail.Tag) // mount procfs if props.GetIOC("mount_procfs") == "1" { fmt.Printf(" + mounting procfs\n") procpath := path.Join(jail.Mountpoint, "root/proc") excmd := exec.Command("/sbin/mount", "-t", "procfs", "proc", procpath) excmd.Env = environ err := excmd.Run() if err != nil { gologit.Printf("%s\n", err) } } // prepare jail zfs dataset if enabled if props.GetIOC("jail_zfs") == "on" { fmt.Printf(" + jailing zfs dataset\n") setprops := core.ZFSProperties{ "org.freebsd.iocage:allow_mount": "1", "org.freebsd.iocage:allow_mount_zfs": "1", "org.freebsd.iocage:enforce_statfs": "1", } jail.SetProperties(setprops) core.ZFSMust( fmt.Errorf("Error setting property"), "set", "jailed=on", path.Join(core.GetZFSRootPath(), props.GetIOC("jail_zfs_dataset"))) } // copy resolv conf err = core.CopyFile( "/etc/resolv.conf", path.Join(jail.Mountpoint, "root/etc/resolv.conf")) if err != nil { gologit.Printf("%s\n", err) } // create log file logfile, err := os.OpenFile(jail.GetLogPath(), os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) if err != nil { gologit.Fatal(err) } defer logfile.Close() file, err := ioutil.TempFile(os.TempDir(), "rollcage.") defer os.Remove(file.Name()) jailConfig := jail.JailConfig() gologit.Debugln(jailConfig) file.WriteString(jailConfig) file.Close() excmd := exec.Command( "/usr/sbin/jail", "-f", file.Name(), "-c", fmt.Sprintf("ioc-%s", jail.HostUUID)) excmd.Stdout = logfile excmd.Stderr = logfile err = excmd.Run() if err != nil { gologit.Fatal(err) } // rctl_limits? // cpuset? // jail zfs if props.GetIOC("jail_zfs") == "on" { core.ZFSMust( fmt.Errorf("Error setting property"), "jail", fmt.Sprintf("ioc-%s", jail.HostUUID), path.Join(core.GetZFSRootPath(), props.GetIOC("jail_zfs_dataset"))) out, err := exec.Command( "/usr/sbin/jexec", fmt.Sprintf("ioc-%s", jail.HostUUID), "zfs", "mount", "-a").CombinedOutput() gologit.Debugln(string(out)) if err != nil { gologit.Printf("%s\n", err) } } // set last_started property t := time.Now() core.ZFSMust( fmt.Errorf("Error setting property"), "set", fmt.Sprintf( "org.freebsd.iocage:last_started=%s", t.Format("2006-01-02_15:04:05")), jail.Path) }
func releaseUpdateCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to update\n") } release, err := core.FindRelease(args[0]) if err != nil { gologit.Fatalf("Release '%s' not found!\n", args[0]) } mountpoint := release.Mountpoint resolvconf := path.Join(mountpoint, "root/etc/resolv.conf") if _, err := os.Stat(resolvconf); os.IsNotExist(err) { data, err := ioutil.ReadFile("/etc/resolv.conf") if err != nil { gologit.Fatalln("/etc/resolv.conf not present or not readable") } err = ioutil.WriteFile(resolvconf, data, 0755) if err != nil { gologit.Fatalf("Could not copy contents to '%s'\n", resolvconf) } } devroot := path.Join(mountpoint, "root/dev") ecmd := exec.Command("/sbin/mount", "-t", "devfs", "devfs", devroot) gologit.Debugln(ecmd.Args) eout, err := ecmd.CombinedOutput() if err != nil { gologit.Fatalf("Error mounting devfs: %s\n", err) } gologit.Debugln(string(eout)) defer func() { ecmd := exec.Command("/sbin/umount", devroot) gologit.Debugln(ecmd.Args) err := ecmd.Run() if err != nil { gologit.Fatalf("Error unmounting devfs: %s\n", err) } }() fmt.Println("* Updating release...") root := path.Join(mountpoint, "root") exargs := []string{root, "/usr/sbin/freebsd-update"} if release.Name != "9.3-RELEASE" && release.Name != "10.1-RELEASE" { exargs = append(exargs, "--not-running-from-cron") } exargs = append(exargs, "fetch", "install") ecmd = exec.Command("/usr/sbin/chroot", exargs...) unamer := release.Name if release.Patchlevel != "" { unamer = release.Patchlevel } ecmd.Env = []string{ "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin", fmt.Sprintf("UNAME_r=%s", unamer), "PAGER=/bin/cat", } gologit.Debugln(ecmd.Args) ecmd.Stdout = os.Stdout ecmd.Stderr = os.Stderr ecmd.Stdin = os.Stdin ecmd.Run() fmt.Println("* update finished") }
func releaseFetchCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to fetch\n") } // find/verify release name releaseName := strings.ToUpper(args[0]) found := false for _, release := range core.SupportedReleases { if releaseName == release { found = true break } } if !found { gologit.Fatalf("Release '%s' is not currently supported\n", releaseName) } // get some meta release, err := core.CreateRelease(releaseName) if err != nil { gologit.Fatalf("Couldn't create release '%s'\n", releaseName) } // fetch if !strings.HasPrefix(mirrorHost, "http://") { mirrorHost = "http://" + mirrorHost } u, err := url.Parse(mirrorHost) if err != nil { gologit.Fatalf("error parsing internal sets fetch url\n") } u.Path = mirrorDir fmt.Printf("Fetching sets:\n") tarset := []string{} for _, setname := range strings.Split(fetchSets, " ") { ux := *u ux.Path = path.Join(ux.Path, release.Name, setname) destPth := path.Join(release.Mountpoint, "sets", setname) tarset = append(tarset, destPth) if _, err := os.Stat(destPth); !os.IsNotExist(err) { fmt.Printf("'%s' already present -- skipping download\n", setname) continue } err := core.FetchHTTPFile(ux.String(), destPth, true) if err != nil { gologit.Fatalf("Failed to fetch: %s\n", ux.String()) } } fmt.Printf("Extracting sets:\n") for _, pth := range tarset { basepth := path.Base(pth) fmt.Printf("* %s\n", basepth) excmd := exec.Command( "tar", "-C", path.Join(release.Mountpoint, "root"), "-xf", pth) excmd.Stdout = os.Stdout excmd.Stderr = os.Stdout err := excmd.Run() if err != nil { gologit.Debugf("Error: %s\n", err) gologit.Fatalf("Failed to extract: %s\n", basepth) } } err = os.MkdirAll(path.Join(release.Mountpoint, "root", "usr/home"), 0755) if err != nil { gologit.Fatalf("Failed to make: %s\n", "/usr/home") } err = os.MkdirAll(path.Join(release.Mountpoint, "root", "usr/ports"), 0755) if err != nil { gologit.Fatalf("Failed to make: %s\n", "/usr/ports") } }
func updateCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to snapremove\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } zfsArgs := []string{ "get", "-Ho", "value", "org.freebsd.iocage:release,mountpoint", jail.Path} out := strings.Split( core.ZFSMust(fmt.Errorf("Error getting properties"), zfsArgs...), "\n") release := out[0] mountpoint := out[1] resolvconf := path.Join(mountpoint, "root/etc/resolv.conf") if _, err := os.Stat(resolvconf); os.IsNotExist(err) { data, err := ioutil.ReadFile("/etc/resolv.conf") if err != nil { gologit.Fatalln("/etc/resolv.conf not present or not readable") } err = ioutil.WriteFile(resolvconf, data, 0755) if err != nil { gologit.Fatalf("Could not copy contents to '%s'\n", resolvconf) } } fmt.Println("* Creating back out snapshot") snappath := fmt.Sprintf( "%s/root@%s", jail.Path, fmt.Sprintf( "ioc-update-%s", time.Now().Format("2006-01-02_15:04:05"))) core.ZFSMust( fmt.Errorf("Error taking snapshot"), "snapshot", snappath) devroot := path.Join(mountpoint, "root/dev") ecmd := exec.Command("/sbin/mount", "-t", "devfs", "devfs", devroot) gologit.Debugln(ecmd.Args) eout, err := ecmd.CombinedOutput() if err != nil { gologit.Fatalf("Error mounting devfs: %s\n", err) } gologit.Debugln(string(eout)) defer func() { ecmd := exec.Command("/sbin/umount", devroot) gologit.Debugln(ecmd.Args) err := ecmd.Run() if err != nil { gologit.Fatalf("Error unmounting devfs: %s\n", err) } }() fmt.Println("* Updating jail...") root := path.Join(mountpoint, "root") ecmd = exec.Command("/usr/sbin/chroot", root, "/usr/sbin/freebsd-update", "--not-running-from-cron", "fetch", "install") ecmd.Env = []string{ "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin", fmt.Sprintf("UNAME_r=%s", release), "PAGER=/bin/cat", } gologit.Debugln(ecmd.Args) ecmd.Stdout = os.Stdout ecmd.Stderr = os.Stderr ecmd.Run() fmt.Println("* update finished") fmt.Println(" Once verified, don't forget to remove the snapshot!") }
func stopCmdRun(cmd *cobra.Command, args []string) { // requires root if !core.IsRoot() { gologit.Fatalf("Must be root to stop\n") } jail, err := core.FindJail(args[0]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[0]) } if !jail.IsRunning() { gologit.Fatalf("Jail is not running!\n") } propertyList := []string{ "mountpoint", "org.freebsd.iocage:type", "org.freebsd.iocage:tag", "org.freebsd.iocage:prestop", "org.freebsd.iocage:exec_stop", "org.freebsd.iocage:poststop", "org.freebsd.iocage:vnet", "org.freebsd.iocage:ip4", } lines := core.SplitOutput(core.ZFSMust( fmt.Errorf("Error listing properties"), "list", "-H", "-o", strings.Join(propertyList, ","), jail.Path)) if len(lines) < 1 { gologit.Fatalf("No output from property fetch\n") } prop_mountpoint := removeDash(lines[0][0]) //prop_type := removeDash(lines[0][1]) prop_tag := removeDash(lines[0][2]) prop_prestop := removeDash(lines[0][3]) prop_exec_stop := removeDash(lines[0][4]) prop_poststop := removeDash(lines[0][5]) prop_vnet := removeDash(lines[0][6]) prop_ip4 := removeDash(lines[0][7]) // set a default path environ := []string{ "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin", } fmt.Printf("* Stopping %s (%s)\n", jail.HostUUID, prop_tag) if prop_prestop != "" { fmt.Printf(" + Running pre-stop\n") preStop := core.SplitFieldsQuoteSafe(prop_prestop) excmd := exec.Command(preStop[0], preStop[1:]...) excmd.Env = environ err := excmd.Run() if err != nil { gologit.Printf("%s\n", err) } } fmt.Printf(" + Stopping services\n") jexec := []string{"/usr/sbin/jexec"} jexec = append(jexec, fmt.Sprintf("ioc-%s", jail.HostUUID)) jexec = append(jexec, core.SplitFieldsQuoteSafe(prop_exec_stop)...) out, err := exec.Command(jexec[0], jexec[1:]...).CombinedOutput() gologit.Debugln(string(out)) if err != nil { gologit.Printf("%s\n", err) } if prop_vnet == "on" { fmt.Printf(" + Tearing down VNET\n") // stop VNET networking } else if prop_ip4 != "inherit" { // stop standard networking (legacy?) lines := core.SplitOutput(core.ZFSMust( fmt.Errorf("Error listing jails"), "list", "-H", "-o", "org.freebsd.iocage:ip4_addr,org.freebsd.iocage:ip6_addr", jail.Path)) for _, ip_config := range lines[0] { if ip_config == "none" { continue } for _, addr := range strings.Split(ip_config, ",") { item := strings.Split(addr, "|") gologit.Debugln("/sbin/ifconfig", item[0], item[1], "-alias") out, err := exec.Command("/sbin/ifconfig", item[0], item[1], "-alias").CombinedOutput() gologit.Debugln(string(out)) if err != nil { gologit.Printf("%s\n", err) } } } } fmt.Printf(" + Removing jail process\n") jrexec := []string{"/usr/sbin/jail", "-r", fmt.Sprintf("ioc-%s", jail.HostUUID)} out, err = exec.Command(jrexec[0], jrexec[1:]...).CombinedOutput() if err != nil { gologit.Printf("%s\n", err) } if prop_poststop != "" { fmt.Printf(" + Running post-stop\n") postStop := core.SplitFieldsQuoteSafe(prop_poststop) excmd := exec.Command(postStop[0], postStop[1:]...) excmd.Env = environ err := excmd.Run() if err != nil { gologit.Printf("%s\n", err) } } fmt.Printf(" + Tearing down mounts\n") umountCmd("-afvF", path.Join(prop_mountpoint, "fstab")) umountCmd(path.Join(prop_mountpoint, "root/dev/fd")) umountCmd(path.Join(prop_mountpoint, "root/dev")) umountCmd(path.Join(prop_mountpoint, "root/proc")) // TODO: basejail here? // TODO: rctl stuff here... }
func getCmdRun(cmd *cobra.Command, args []string) { headers := getOutputColsFlag.GetCols() if len(headers) == 0 { headers = getOutputColsFlag.GetValidCols() } var allTags bool desiredTags := make(map[string]bool) if len(args) == 0 || args[0] == "all" { allTags = true } else { allTags = false for _, prop := range strings.Split(args[0], ",") { desiredTags[prop] = true } } var jails []*core.JailMeta if len(args) < 2 { jails = core.GetAllJails() } else { jail, err := core.FindJail(args[1]) if err != nil { gologit.Fatalf("No jail found by '%s'\n", args[1]) } jails = append(jails, jail) } twf := core.NewTemplateOutputWriter(headers, MachineOutput) for _, jail := range jails { zfsArgs := []string{"get", "-H"} if ParsableValues { zfsArgs = append(zfsArgs, "-p") } zfsArgs = append(zfsArgs, "all", jail.Path) out := core.ZFSMust( fmt.Errorf("Error getting properties"), zfsArgs...) properties := make([][]string, 0) for _, line := range strings.Split(string(out), "\n") { if line == "" { continue } cols := strings.Split(line, "\t") property := cols[1] if strings.HasPrefix(property, "org.freebsd.iocage:") { property = strings.Split(property, ":")[1] } if property == "tag" { continue } if property == "host_hostuuid" { continue } if allTags || desiredTags[property] { properties = append(properties, []string{property, cols[2]}) } } for _, prop := range properties { twf.WriteTemplate(&struct { Uuid string Tag string Property string Value string }{ Uuid: jail.HostUUID, Tag: jail.Tag, Property: prop[0], Value: prop[1], }) } } twf.Flush() }