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