コード例 #1
1
ファイル: config.go プロジェクト: MichaelAronsen/rollcage
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)
	}
}
コード例 #2
0
ファイル: cmd_set.go プロジェクト: MichaelAronsen/rollcage
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...)
	}
}
コード例 #3
0
ファイル: cmd_release.go プロジェクト: cactus/rollcage
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)
}
コード例 #4
0
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...)
}
コード例 #5
0
ファイル: cmd_stop.go プロジェクト: MichaelAronsen/rollcage
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...
}
コード例 #6
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)
	}
}
コード例 #7
0
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)
}
コード例 #8
0
ファイル: cmd_exec.go プロジェクト: cactus/rollcage
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)
	}
}
コード例 #9
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)
	}
}
コード例 #10
0
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)
	}
}
コード例 #11
0
ファイル: zfs.go プロジェクト: MichaelAronsen/rollcage
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
}
コード例 #12
0
ファイル: cmd_df.go プロジェクト: MichaelAronsen/rollcage
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()
}
コード例 #13
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()
}
コード例 #14
0
ファイル: cmd_reboot.go プロジェクト: MichaelAronsen/rollcage
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)
}
コード例 #15
0
ファイル: cmd_chroot.go プロジェクト: MichaelAronsen/rollcage
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)
	}
}
コード例 #16
0
ファイル: cmd_destroy.go プロジェクト: zenny/rollcage
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)
}
コード例 #17
0
ファイル: jail.go プロジェクト: MichaelAronsen/rollcage
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
}
コード例 #18
0
ファイル: cmd_start.go プロジェクト: MichaelAronsen/rollcage
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)
}
コード例 #19
0
ファイル: cmd_release.go プロジェクト: cactus/rollcage
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")
}
コード例 #20
0
ファイル: cmd_release.go プロジェクト: cactus/rollcage
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")
	}
}
コード例 #21
0
ファイル: cmd_update.go プロジェクト: zenny/rollcage
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!")
}
コード例 #22
0
ファイル: cmd_stop.go プロジェクト: zenny/rollcage
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...
}
コード例 #23
0
ファイル: cmd_get.go プロジェクト: MichaelAronsen/rollcage
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()
}