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 validateURL(hmackey *[]byte, macbytes *[]byte, urlbytes *[]byte) bool { mac := hmac.New(sha1.New, *hmackey) mac.Write(*urlbytes) macSum := mac.Sum(nil) // ensure lengths are equal. if not, return false if len(macSum) != len(*macbytes) { gologit.Debugf("Bad signature: %x != %x\n", macSum, macbytes) return false } if subtle.ConstantTimeCompare(macSum, *macbytes) != 1 { gologit.Debugf("Bad signature: %x != %x\n", macSum, macbytes) return false } return true }
func Cmd(name string, arg ...string) (string, error) { cmd := exec.Command(name, arg...) stdout := &bytes.Buffer{} stderr := &bytes.Buffer{} cmd.Stdout = stdout cmd.Stderr = stderr err := cmd.Run() gologit.Debugf("cmd: %s\nstdout: %s\nstderr: %s", cmd.Args, stdout, stderr) return strings.TrimSpace(stdout.String()), err }
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 umountCmd(args ...string) { cmd := exec.Command("/sbin/umount", args...) gologit.Debugln(append([]string{"/sbin/umount"}, args...)) out, err := cmd.CombinedOutput() for _, line := range strings.Split(string(out), "\n") { if line != "" { gologit.Debugln(line) } } if err != nil { // some mounts are not present, so just fail // do not log exit status 1 unless debug logging gologit.Debugf("%s\n", err) } }
// Fetch http file url to destination dest, with or without progress. func FetchHTTPFile(url string, dest string, progress bool) (err error) { gologit.Debugf("Creating file: %s\n", dest) out, err := os.Create(dest) if err != nil { return err } defer out.Close() var r io.Reader gologit.Debugf("Fetching url: %s\n", url) resp, err := http.Get(url) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return fmt.Errorf("Server return non-200 status: %v", resp.Status) } msgPrefix := fmt.Sprintf("%s: ", path.Base(dest)) var bar *pb.ProgressBar i, _ := strconv.Atoi(resp.Header.Get("Content-Length")) if i > 0 && progress { bar = pb.New(i).Prefix(msgPrefix).SetUnits(pb.U_BYTES) bar.ShowSpeed = true bar.RefreshRate = time.Millisecond * 700 bar.ShowFinalTime = false bar.ShowTimeLeft = false bar.Start() defer bar.Finish() r = bar.NewProxyReader(resp.Body) } else { r = resp.Body } _, err = io.Copy(out, r) return err }
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 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") } }