示例#1
0
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)
}
示例#2
0
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)
	}
}
示例#3
0
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)
	}
}
示例#4
0
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)
	}
}
示例#5
0
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()
}
示例#6
0
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...
}