func runInstall(cmd *cobra.Command, args []string) (exit int) { gid, err := common.LookupGid(common.RktGroup) if err != nil { stderr("install: error looking up rkt gid: %v", err) return 1 } if err := createDirStructure(gid); err != nil { stderr("install: error creating rkt directory structure: %v", err) return 1 } casDbPath := filepath.Join(getDataDir(), "cas", "db") if err := setCasDbFilesPermissions(casDbPath, gid, casDbPerm); err != nil { stderr("install: error setting cas db permissions: %v", err) return 1 } if err := createDbFiles(casDbPath, gid, casDbPerm); err != nil { stderr("install: error creating db files: %v", err) return 1 } stderr("rkt directory structure successfully created.") return 0 }
func startAPIService(t *testing.T, ctx *testutils.RktRunCtx) *gexpect.ExpectSubprocess { noUidGid := false gid, err := common.LookupGid(common.RktGroup) if err != nil { t.Logf("no %q group, will run api service with root, ONLY DO THIS FOR TESTING!", common.RktGroup) noUidGid = true } else { if err := ctx.SetupDataDir(); err != nil { t.Fatalf("failed to setup data directory: %v", err) } } u, err := user.Lookup("nobody") if err != nil { t.Logf(`no "nobody" user, will run api service with root, ONLY DO THIS FOR TESTING!`) noUidGid = true } uid, err := strconv.Atoi(u.Uid) if err != nil { t.Fatalf(`failed to parse "nobody" UID: %v`, err) } t.Logf("Running rkt api service") apisvcCmd := fmt.Sprintf("%s api-service", ctx.Cmd()) if noUidGid { return startRktAndCheckOutput(t, apisvcCmd, "API service running") } return startRktAsUidGidAndCheckOutput(t, apisvcCmd, "API service running", false, uid, gid) }
// SetJournalPermissions sets ACLs and permissions so the rkt group can access // the pod's logs func SetJournalPermissions(p *stage1commontypes.Pod) error { s1 := common.Stage1ImagePath(p.Root) rktgid, err := common.LookupGid(common.RktGroup) if err != nil { return fmt.Errorf("group %q not found", common.RktGroup) } journalPath := filepath.Join(s1, "rootfs", "var", "log", "journal") if err := os.MkdirAll(journalPath, os.FileMode(0755)); err != nil { return fmt.Errorf("error creating journal dir: %v", err) } a, err := acl.Parse(fmt.Sprintf("g:%d:r-x,m:r-x", rktgid)) if err != nil { panic(fmt.Sprintf("error parsing ACL string: %v", err)) } defer a.Free() if err := a.SetFileDefault(journalPath); err != nil { return err } return nil }
// TestNonRootReadInfo tests that non-root users that can do rkt list, rkt image list. func TestNonRootReadInfo(t *testing.T) { if !common.SupportsUserNS() { t.Skip("User namespaces are not supported on this host.") } if err := checkUserNS(); err != nil { t.Skip("User namespaces don't work on this host.") } ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() gid, err := common.LookupGid(common.RktGroup) if err != nil { t.Skipf("Skipping the test because there's no %q group", common.RktGroup) } if err := ctx.SetupDataDir(); err != nil { t.Fatalf("failed to setup data dir: %v", err) } // Launch some pods, this creates the environment for later testing. imgs := []struct { name string msg string exitCode string imgFile string }{ {name: "inspect-1", msg: "foo-1", exitCode: "1"}, {name: "inspect-2", msg: "foo-2", exitCode: "2"}, {name: "inspect-3", msg: "foo-3", exitCode: "3"}, } for i, img := range imgs { imgName := fmt.Sprintf("rkt-%s.aci", img.name) imgs[i].imgFile = patchTestACI(imgName, fmt.Sprintf("--name=%s", img.name), fmt.Sprintf("--exec=/inspect --print-msg=%s --exit-code=%s", img.msg, img.exitCode)) defer os.Remove(imgs[i].imgFile) } runCmds := []string{ // Run with overlay, without private-users. fmt.Sprintf("%s --insecure-options=image run --mds-register=false %s", ctx.Cmd(), imgs[0].imgFile), // Run without overlay, without private-users. fmt.Sprintf("%s --insecure-options=image run --no-overlay --mds-register=false %s", ctx.Cmd(), imgs[1].imgFile), // Run without overlay, with private-users. fmt.Sprintf("%s --insecure-options=image run --no-overlay --private-users --mds-register=false %s", ctx.Cmd(), imgs[2].imgFile), } for i, cmd := range runCmds { t.Logf("#%d: Running %s", i, cmd) runRktAndCheckOutput(t, cmd, imgs[i].msg, false) } imgListCmd := fmt.Sprintf("%s image list", ctx.Cmd()) t.Logf("Running %s", imgListCmd) runRktAsGidAndCheckOutput(t, imgListCmd, "inspect-", false, gid) }
// TestNonRootReadInfo tests that non-root users that can do rkt list, rkt image list. func TestNonRootReadInfo(t *testing.T) { ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() gid, err := common.LookupGid(common.RktGroup) if err != nil { t.Skipf("Skipping the test because there's no %q group", common.RktGroup) } // Do 'rkt install. and launch some pods in root'. cmd := fmt.Sprintf("%s install", ctx.Cmd()) t.Logf("Running rkt install") runRktAndCheckOutput(t, cmd, "rkt directory structure successfully created", false) // Launch some pods, this creates the environment for later testing, // also it exercises 'rkt install'. imgs := []struct { name string msg string exitCode string imgFile string }{ {name: "inspect-1", msg: "foo-1", exitCode: "1"}, {name: "inspect-2", msg: "foo-2", exitCode: "2"}, {name: "inspect-3", msg: "foo-3", exitCode: "3"}, } for i, img := range imgs { imgName := fmt.Sprintf("rkt-%s.aci", img.name) imgs[i].imgFile = patchTestACI(imgName, fmt.Sprintf("--name=%s", img.name), fmt.Sprintf("--exec=/inspect --print-msg=%s --exit-code=%s", img.msg, img.exitCode)) defer os.Remove(imgs[i].imgFile) } runCmds := []string{ // Run with overlay, without private-users. fmt.Sprintf("%s --insecure-options=image run --mds-register=false %s", ctx.Cmd(), imgs[0].imgFile), // Run without overlay, without private-users. fmt.Sprintf("%s --insecure-options=image run --no-overlay --mds-register=false %s", ctx.Cmd(), imgs[1].imgFile), // Run without overlay, with private-users. fmt.Sprintf("%s --insecure-options=image run --no-overlay --private-users --mds-register=false %s", ctx.Cmd(), imgs[2].imgFile), } for i, cmd := range runCmds { t.Logf("#%d: Running %s", i, cmd) runRktAndCheckOutput(t, cmd, imgs[i].msg, false) } imgListCmd := fmt.Sprintf("%s image list", ctx.Cmd()) t.Logf("Running %s", imgListCmd) runRktAsGidAndCheckOutput(t, imgListCmd, "inspect-", false, gid) }
// TestNonRootFetchRmGCImage tests that non-root users can remove all images but // cannot gc images. func TestNonRootFetchRmGCImage(t *testing.T) { ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() gid, err := common.LookupGid(common.RktGroup) if err != nil { t.Skipf("Skipping the test because there's no %q group", common.RktGroup) } if err := ctx.SetupDataDir(); err != nil { t.Fatalf("failed to setup data dir: %v", err) } rootImg := patchTestACI("rkt-inspect-root-rm.aci", "--exec=/inspect --print-msg=foobar") defer os.Remove(rootImg) rootImgHash, err := importImageAndFetchHash(t, ctx, "", rootImg) if err != nil { t.Fatalf("%v", err) } // Launch/gc a pod so we can test non-root image gc. runCmd := fmt.Sprintf("%s --insecure-options=image run --mds-register=false %s", ctx.Cmd(), rootImg) runRktAndCheckOutput(t, runCmd, "foobar", false) ctx.RunGC() // Should not be able to do image gc. // We can't touch the treestores even as members of the rkt group. imgGCCmd := fmt.Sprintf("%s image gc", ctx.Cmd()) t.Logf("Running %s", imgGCCmd) runRktAsGidAndCheckOutput(t, imgGCCmd, "permission denied", true, gid) // Should be able to remove the image fetched by root since we're in the rkt group. imgRmCmd := fmt.Sprintf("%s image rm %s", ctx.Cmd(), rootImgHash) t.Logf("Running %s", imgRmCmd) runRktAsGidAndCheckOutput(t, imgRmCmd, "successfully removed", false, gid) // Should be able to remove the image fetched by ourselves. nonrootImg := patchTestACI("rkt-inspect-non-root-rm.aci", "--exec=/inspect") defer os.Remove(nonrootImg) nonrootImgHash, err := importImageAndFetchHashAsGid(t, ctx, nonrootImg, "", gid) if err != nil { t.Fatalf("%v", err) } imgRmCmd = fmt.Sprintf("%s image rm %s", ctx.Cmd(), nonrootImgHash) t.Logf("Running %s", imgRmCmd) runRktAsGidAndCheckOutput(t, imgRmCmd, "successfully removed", false, gid) }
// TestNonRootFetchRmGcImage tests that non-root users can remove images fetched by themselves but // cannot remove images fetched by root, or gc any images. func TestNonRootFetchRmGcImage(t *testing.T) { ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() gid, err := common.LookupGid(common.RktGroup) if err != nil { t.Skipf("Skipping the test because there's no %q group", common.RktGroup) } // Do `rkt install` and fetch an image with root. cmd := fmt.Sprintf("%s install", ctx.Cmd()) t.Logf("Running rkt install") runRktAndCheckOutput(t, cmd, "rkt directory structure successfully created", false) rootImg := patchTestACI("rkt-inspect-root-rm.aci", "--exec=/inspect --print-msg=foobar") defer os.Remove(rootImg) rootImgHash := importImageAndFetchHash(t, ctx, rootImg) // Launch/gc a pod so we can test non-root image gc. runCmd := fmt.Sprintf("%s --insecure-options=image run --mds-register=false %s", ctx.Cmd(), rootImg) runRktAndCheckOutput(t, runCmd, "foobar", false) ctx.RunGC() // Should not be able to do image gc. imgGcCmd := fmt.Sprintf("%s image gc", ctx.Cmd()) t.Logf("Running %s", imgGcCmd) runRktAsGidAndCheckOutput(t, imgGcCmd, "permission denied", true, gid) // Should not be able to remove the image fetched by root. imgRmCmd := fmt.Sprintf("%s image rm %s", ctx.Cmd(), rootImgHash) t.Logf("Running %s", imgRmCmd) runRktAsGidAndCheckOutput(t, imgRmCmd, "permission denied", true, gid) // Should be able to remove the image fetched by ourselves. nonrootImg := patchTestACI("rkt-inspect-non-root-rm.aci", "--exec=/inspect") defer os.Remove(nonrootImg) nonrootImgHash := importImageAndFetchHashAsGid(t, ctx, nonrootImg, gid) imgRmCmd = fmt.Sprintf("%s image rm %s", ctx.Cmd(), nonrootImgHash) t.Logf("Running %s", imgRmCmd) runRktAsGidAndCheckOutput(t, imgRmCmd, "successfully removed", false, gid) }
func startAPIService(t *testing.T, ctx *testutils.RktRunCtx) *gexpect.ExpectSubprocess { noGid := false gid, err := common.LookupGid(common.RktGroup) if err != nil { t.Logf("no %q group, will run api service with root, ONLY DO THIS FOR TESTING!", common.RktGroup) noGid = true } else { t.Logf("Running rkt install") installCmd := fmt.Sprintf("%s install", ctx.Cmd()) runRktAndCheckOutput(t, installCmd, "rkt directory structure successfully created", false) } t.Logf("Running rkt api service") apisvcCmd := fmt.Sprintf("%s api-service", ctx.Cmd()) if noGid { return startRktAndCheckOutput(t, apisvcCmd, "API service running") } return startRktAsGidAndCheckOutput(t, apisvcCmd, "API service running", gid) }
// SetJournalPermissions sets ACLs and permissions so the rkt group can access // the pod's logs func SetJournalPermissions(p *stage1commontypes.Pod) error { s1 := common.Stage1ImagePath(p.Root) rktgid, err := common.LookupGid(common.RktGroup) if err != nil { return fmt.Errorf("group %q not found", common.RktGroup) } journalPath := filepath.Join(s1, "rootfs", "var", "log", "journal") if err := os.MkdirAll(journalPath, os.FileMode(0755)); err != nil { return errwrap.Wrap(errors.New("error creating journal dir"), err) } a, err := acl.InitACL() if err != nil { return err } defer a.Free() if err := a.ParseACL(fmt.Sprintf("g:%d:r-x,m:r-x", rktgid)); err != nil { return errwrap.Wrap(errors.New("error parsing ACL string"), err) } if err := a.AddBaseEntries(journalPath); err != nil { return errwrap.Wrap(errors.New("error adding base ACL entries"), err) } if err := a.Valid(); err != nil { return err } if err := a.SetFileACLDefault(journalPath); err != nil { return errwrap.Wrap(fmt.Errorf("error setting default ACLs on %q", journalPath), err) } return nil }
func runRun(cmd *cobra.Command, args []string) (exit int) { privateUsers := user.NewBlankUidRange() err := parseApps(&rktApps, args, cmd.Flags(), true) if err != nil { stderr.PrintE("error parsing app image arguments", err) return 1 } if flagStoreOnly && flagNoStore { stderr.Print("both --store-only and --no-store specified") return 1 } if flagPrivateUsers { if !common.SupportsUserNS() { stderr.Print("--private-users is not supported, kernel compiled without user namespace support") return 1 } privateUsers.SetRandomUidRange(user.DefaultRangeCount) } if len(flagPorts) > 0 && flagNet.None() { stderr.Print("--port flag does not work with 'none' networking") return 1 } if len(flagPorts) > 0 && flagNet.Host() { stderr.Print("--port flag does not work with 'host' networking") return 1 } if flagMDSRegister && flagNet.None() { stderr.Print("--mds-register flag does not work with --net=none. Please use 'host', 'default' or an equivalent network") return 1 } if len(flagPodManifest) > 0 && (len(flagPorts) > 0 || rktApps.Count() > 0 || flagStoreOnly || flagNoStore || flagInheritEnv || !flagExplicitEnv.IsEmpty() || !flagEnvFromFile.IsEmpty() || (*appsVolume)(&rktApps).String() != "" || (*appMount)(&rktApps).String() != "" || (*appExec)(&rktApps).String() != "" || (*appUser)(&rktApps).String() != "" || (*appGroup)(&rktApps).String() != "" || (*appCapsRetain)(&rktApps).String() != "" || (*appCapsRemove)(&rktApps).String() != "") { stderr.Print("conflicting flags set with --pod-manifest (see --help)") return 1 } if flagInteractive && rktApps.Count() > 1 { stderr.Print("interactive option only supports one image") return 1 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr.Print("must provide at least one image or specify the pod manifest") return 1 } s, err := imagestore.NewStore(storeDir()) if err != nil { stderr.PrintE("cannot open store", err) return 1 } ts, err := treestore.NewStore(treeStoreDir(), s) if err != nil { stderr.PrintE("cannot open treestore", err) return 1 } config, err := getConfig() if err != nil { stderr.PrintE("cannot get configuration", err) return 1 } s1img, err := getStage1Hash(s, ts, config) if err != nil { stderr.Error(err) return 1 } fn := &image.Finder{ S: s, Ts: ts, Ks: getKeystore(), Headers: config.AuthPerHost, DockerAuth: config.DockerCredentialsPerRegistry, InsecureFlags: globalFlags.InsecureFlags, Debug: globalFlags.Debug, TrustKeysFromHTTPS: globalFlags.TrustKeysFromHTTPS, StoreOnly: flagStoreOnly, NoStore: flagNoStore, WithDeps: true, } if err := fn.FindImages(&rktApps); err != nil { stderr.Error(err) return 1 } p, err := newPod() if err != nil { stderr.PrintE("error creating new pod", err) return 1 } // if requested, write out pod UUID early so "rkt rm" can // clean it up even if something goes wrong if flagUUIDFileSave != "" { if err := writeUUIDToFile(p.uuid, flagUUIDFileSave); err != nil { stderr.PrintE("error saving pod UUID to file", err) return 1 } } processLabel, mountLabel, err := label.InitLabels([]string{"mcsdir:/var/run/rkt/mcs"}) if err != nil { stderr.PrintE("error initialising SELinux", err) return 1 } p.mountLabel = mountLabel cfg := stage0.CommonConfig{ MountLabel: mountLabel, ProcessLabel: processLabel, Store: s, TreeStore: ts, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, } pcfg := stage0.PrepareConfig{ CommonConfig: &cfg, UseOverlay: !flagNoOverlay && common.SupportsOverlay() && common.FSSupportsOverlay(getDataDir()), PrivateUsers: privateUsers, SkipTreeStoreCheck: globalFlags.InsecureFlags.SkipOnDiskCheck(), } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.EnvFromFile = flagEnvFromFile.Strings() pcfg.Apps = &rktApps } if globalFlags.Debug { stage0.InitDebug() } keyLock, err := lock.SharedKeyLock(lockDir(), common.PrepareLock) if err != nil { stderr.PrintE("cannot get shared prepare lock", err) return 1 } err = stage0.Prepare(pcfg, p.path(), p.uuid) if err != nil { stderr.PrintE("error setting up stage0", err) keyLock.Close() return 1 } keyLock.Close() // get the lock fd for run lfd, err := p.Fd() if err != nil { stderr.PrintE("error getting pod lock fd", err) return 1 } // skip prepared by jumping directly to run, we own this pod if err := p.xToRun(); err != nil { stderr.PrintE("unable to transition to run", err) return 1 } rktgid, err := common.LookupGid(common.RktGroup) if err != nil { stderr.Printf("group %q not found, will use default gid when rendering images", common.RktGroup) rktgid = -1 } rcfg := stage0.RunConfig{ CommonConfig: &cfg, Net: flagNet, LockFd: lfd, Interactive: flagInteractive, DNS: flagDNS, DNSSearch: flagDNSSearch, DNSOpt: flagDNSOpt, MDSRegister: flagMDSRegister, LocalConfig: globalFlags.LocalConfigDir, RktGid: rktgid, Hostname: flagHostname, } apps, err := p.getApps() if err != nil { stderr.PrintE("cannot get the appList in the pod manifest", err) return 1 } rcfg.Apps = apps stage0.Run(rcfg, p.path(), getDataDir()) // execs, never returns return 1 }
func runRun(cmd *cobra.Command, args []string) (exit int) { privateUsers := uid.NewBlankUidRange() err := parseApps(&rktApps, args, cmd.Flags(), true) if err != nil { stderr("run: error parsing app image arguments: %v", err) return 1 } if flagStoreOnly && flagNoStore { stderr("both --store-only and --no-store specified") return 1 } if flagPrivateUsers { if !common.SupportsUserNS() { stderr("run: --private-users is not supported, kernel compiled without user namespace support") return 1 } privateUsers.SetRandomUidRange(uid.DefaultRangeCount) } if len(flagPorts) > 0 && flagNet.None() { stderr("--port flag does not work with 'none' networking") return 1 } if len(flagPorts) > 0 && flagNet.Host() { stderr("--port flag does not work with 'host' networking") return 1 } if flagMDSRegister && flagNet.None() { stderr("--mds-register flag does not work with --net=none. Please use 'host', 'default' or an equivalent network") return 1 } if len(flagPodManifest) > 0 && (len(flagPorts) > 0 || flagInheritEnv || !flagExplicitEnv.IsEmpty() || rktApps.Count() > 0 || flagStoreOnly || flagNoStore) { stderr("conflicting flags set with --pod-manifest (see --help)") return 1 } if flagInteractive && rktApps.Count() > 1 { stderr("run: interactive option only supports one image") return 1 } if rktApps.Count() < 1 && len(flagPodManifest) == 0 { stderr("run: must provide at least one image or specify the pod manifest") return 1 } s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("run: cannot open store: %v", err) return 1 } config, err := getConfig() if err != nil { stderr("run: cannot get configuration: %v", err) return 1 } fn := &finder{ imageActionData: imageActionData{ s: s, headers: config.AuthPerHost, dockerAuth: config.DockerCredentialsPerRegistry, insecureSkipVerify: globalFlags.InsecureSkipVerify, debug: globalFlags.Debug, }, storeOnly: flagStoreOnly, noStore: flagNoStore, withDeps: false, } s1img, err := getStage1Hash(s, cmd) if err != nil { stderr("%v", err) return 1 } fn.ks = getKeystore() fn.withDeps = true if err := fn.findImages(&rktApps); err != nil { stderr("%v", err) return 1 } p, err := newPod() if err != nil { stderr("Error creating new pod: %v", err) return 1 } // if requested, write out pod UUID early so "rkt rm" can // clean it up even if something goes wrong if flagUUIDFileSave != "" { if err := writeUUIDToFile(p.uuid, flagUUIDFileSave); err != nil { stderr("Error saving pod UUID to file: %v", err) return 1 } } processLabel, mountLabel, err := label.InitLabels(nil) if err != nil { stderr("Error initialising SELinux: %v", err) return 1 } cfg := stage0.CommonConfig{ MountLabel: mountLabel, ProcessLabel: processLabel, Store: s, Stage1Image: *s1img, UUID: p.uuid, Debug: globalFlags.Debug, } pcfg := stage0.PrepareConfig{ CommonConfig: cfg, UseOverlay: !flagNoOverlay && common.SupportsOverlay(), PrivateUsers: privateUsers, } if len(flagPodManifest) > 0 { pcfg.PodManifest = flagPodManifest } else { pcfg.Ports = []types.ExposedPort(flagPorts) pcfg.InheritEnv = flagInheritEnv pcfg.ExplicitEnv = flagExplicitEnv.Strings() pcfg.Apps = &rktApps } if globalFlags.Debug { stage0.InitDebug() } keyLock, err := lock.SharedKeyLock(lockDir(), common.PrepareLock) if err != nil { stderr("rkt: cannot get shared prepare lock: %v", err) return 1 } err = stage0.Prepare(pcfg, p.path(), p.uuid) if err != nil { stderr("run: error setting up stage0: %v", err) keyLock.Close() return 1 } keyLock.Close() // get the lock fd for run lfd, err := p.Fd() if err != nil { stderr("Error getting pod lock fd: %v", err) return 1 } // skip prepared by jumping directly to run, we own this pod if err := p.xToRun(); err != nil { stderr("run: unable to transition to run: %v", err) return 1 } rktgid, err := common.LookupGid(common.RktGroup) if err != nil { stderr("run: group %q not found, will use default gid when rendering images", common.RktGroup) rktgid = -1 } rcfg := stage0.RunConfig{ CommonConfig: cfg, Net: flagNet, LockFd: lfd, Interactive: flagInteractive, MDSRegister: flagMDSRegister, LocalConfig: globalFlags.LocalConfigDir, RktGid: rktgid, } apps, err := p.getApps() if err != nil { stderr("run: cannot get the appList in the pod manifest: %v", err) return 1 } rcfg.Apps = apps stage0.Run(rcfg, p.path(), globalFlags.Dir) // execs, never returns return 1 }
func runRunPrepared(cmd *cobra.Command, args []string) (exit int) { if len(args) != 1 { cmd.Usage() return 1 } p, err := getPodFromUUIDString(args[0]) if err != nil { stderr("prepared-run: problem retrieving pod: %v", err) return 1 } defer p.Close() s, err := store.NewStore(globalFlags.Dir) if err != nil { stderr("prepared-run: cannot open store: %v", err) return 1 } if !p.isPrepared { stderr("prepared-run: pod %q is not prepared", p.uuid) return 1 } if flagInteractive { ac, err := p.getAppCount() if err != nil { stderr("prepared-run: cannot get pod's app count: %v", err) return 1 } if ac > 1 { stderr("prepared-run: interactive option only supports pods with one app") return 1 } } // Make sure we have a metadata service available before we move to // run state so that the user can rerun the command without needing // to prepare the image again. if flagMDSRegister { if err := stage0.CheckMdsAvailability(); err != nil { stderr("prepare-run: %v", err) return 1 } } if err := p.xToRun(); err != nil { stderr("prepared-run: cannot transition to run: %v", err) return 1 } lfd, err := p.Fd() if err != nil { stderr("prepared-run: unable to get lock fd: %v", err) return 1 } apps, err := p.getApps() if err != nil { stderr("prepared-run: unable to get app list: %v", err) return 1 } rktgid, err := common.LookupGid(common.RktGroup) if err != nil { stderr("prepared-run: group %q not found, will use default gid when rendering images", common.RktGroup) rktgid = -1 } rcfg := stage0.RunConfig{ CommonConfig: stage0.CommonConfig{ Store: s, UUID: p.uuid, Debug: globalFlags.Debug, }, Net: flagNet, LockFd: lfd, Interactive: flagInteractive, MDSRegister: flagMDSRegister, Apps: apps, RktGid: rktgid, } if globalFlags.Debug { stage0.InitDebug() } stage0.Run(rcfg, p.path(), globalFlags.Dir) // execs, never returns return 1 }
func runAppAdd(cmd *cobra.Command, args []string) (exit int) { if len(args) < 2 { stderr.Print("must provide the pod UUID and an IMAGEID") return 254 } err := parseApps(&rktApps, args[1:], cmd.Flags(), true) if err != nil { stderr.PrintE("error parsing app image arguments", err) return 254 } if rktApps.Count() > 1 { stderr.Print("must give only one app") return 254 } p, err := pkgPod.PodFromUUIDString(getDataDir(), args[0]) if err != nil { stderr.PrintE("problem retrieving pod", err) return 254 } defer p.Close() if p.State() != pkgPod.Running { stderr.Printf("pod %q isn't currently running", p.UUID) return 254 } if !p.IsSupervisorReady() { stderr.Printf("supervisor for pod %q is not yet ready", p.UUID) return 254 } s, err := imagestore.NewStore(storeDir()) if err != nil { stderr.PrintE("cannot open store", err) return 254 } ts, err := treestore.NewStore(treeStoreDir(), s) if err != nil { stderr.PrintE("cannot open treestore", err) return 254 } fn := &image.Finder{ S: s, Ts: ts, Ks: getKeystore(), StoreOnly: true, NoStore: false, } img, err := fn.FindImage(args[1], "") if err != nil { stderr.PrintE("error finding images", err) return 254 } podPID, err := p.ContainerPid1() if err != nil { stderr.PrintE(fmt.Sprintf("unable to determine the pid for pod %q", p.UUID), err) return 254 } ccfg := stage0.CommonConfig{ DataDir: getDataDir(), Store: s, TreeStore: ts, UUID: p.UUID, Debug: globalFlags.Debug, } rktgid, err := common.LookupGid(common.RktGroup) if err != nil { stderr.Printf("group %q not found, will use default gid when rendering images", common.RktGroup) rktgid = -1 } cfg := stage0.AddConfig{ CommonConfig: &ccfg, Image: *img, Apps: &rktApps, RktGid: rktgid, UsesOverlay: p.UsesOverlay(), PodPath: p.Path(), PodPID: podPID, } if globalFlags.Debug { stage0.InitDebug() } err = stage0.AddApp(cfg) if err != nil { stderr.PrintE("error adding app to pod", err) return 254 } return 0 }
func runRunPrepared(cmd *cobra.Command, args []string) (exit int) { if len(args) != 1 { cmd.Usage() return 254 } p, err := pkgPod.PodFromUUIDString(getDataDir(), args[0]) if err != nil { stderr.PrintE("problem retrieving pod", err) return 254 } defer p.Close() s, err := imagestore.NewStore(storeDir()) if err != nil { stderr.PrintE("cannot open store", err) return 254 } ts, err := treestore.NewStore(treeStoreDir(), s) if err != nil { stderr.PrintE("cannot open treestore", err) return 254 } if p.State() != pkgPod.Prepared { stderr.Printf("pod %q is not prepared", p.UUID) return 254 } _, manifest, err := p.PodManifest() if err != nil { stderr.PrintE("cannot read pod manifest", err) return 254 } if flagInteractive { if len(manifest.Apps) > 1 { stderr.Print("interactive option only supports pods with one app") return 254 } } // Make sure we have a metadata service available before we move to // run state so that the user can rerun the command without needing // to prepare the image again. if flagMDSRegister { if err := stage0.CheckMdsAvailability(); err != nil { stderr.Error(err) return 254 } } if err := p.ToRun(); err != nil { stderr.PrintE("cannot transition to run", err) return 254 } lfd, err := p.Fd() if err != nil { stderr.PrintE("unable to get lock fd", err) return 254 } rktgid, err := common.LookupGid(common.RktGroup) if err != nil { stderr.Printf("group %q not found, will use default gid when rendering images", common.RktGroup) rktgid = -1 } ovlOk := true if err := common.PathSupportsOverlay(getDataDir()); err != nil { if oerr, ok := err.(common.ErrOverlayUnsupported); ok { stderr.Printf("disabling overlay support: %q", oerr.Error()) ovlOk = false } else { stderr.PrintE("error determining overlay support", err) return 254 } } ovlPrep := p.UsesOverlay() // should not happen, maybe the data directory moved from an overlay-enabled fs to another location // between prepare and run-prepared if ovlPrep && !ovlOk { stderr.Print("unable to run prepared overlay-enabled pod: overlay not supported") return 254 } DNSConfMode, DNSConfig, HostsEntries, err := parseDNSFlags(flagHostsEntries, flagDNS, flagDNSSearch, flagDNSOpt, flagDNSDomain) if err != nil { stderr.PrintE("error with dns flags", err) return 254 } rcfg := stage0.RunConfig{ CommonConfig: &stage0.CommonConfig{ DataDir: getDataDir(), Store: s, TreeStore: ts, UUID: p.UUID, Debug: globalFlags.Debug, }, Net: flagNet, LockFd: lfd, Interactive: flagInteractive, DNSConfMode: DNSConfMode, DNSConfig: DNSConfig, HostsEntries: *HostsEntries, MDSRegister: flagMDSRegister, Apps: manifest.Apps, RktGid: rktgid, Hostname: flagHostname, InsecureCapabilities: globalFlags.InsecureFlags.SkipCapabilities(), InsecurePaths: globalFlags.InsecureFlags.SkipPaths(), InsecureSeccomp: globalFlags.InsecureFlags.SkipSeccomp(), UseOverlay: ovlPrep && ovlOk, } if globalFlags.Debug { stage0.InitDebug() } stage0.Run(rcfg, p.Path(), getDataDir()) // execs, never returns return 254 }
func runAppSandbox(cmd *cobra.Command, args []string) int { s, err := imagestore.NewStore(storeDir()) if err != nil { stderr.PrintE("cannot open store", err) return 1 } ts, err := treestore.NewStore(treeStoreDir(), s) if err != nil { stderr.PrintE("cannot open treestore", err) return 1 } config, err := getConfig() if err != nil { stderr.PrintE("cannot get configuration", err) return 1 } s1img, err := getStage1Hash(s, ts, config) if err != nil { stderr.Error(err) return 1 } p, err := pod.NewPod(getDataDir()) if err != nil { stderr.PrintE("error creating new pod", err) return 1 } if flagUUIDFileSave != "" { if err := pod.WriteUUIDToFile(p.UUID, flagUUIDFileSave); err != nil { stderr.PrintE("error saving pod UUID to file", err) return 1 } } processLabel, mountLabel, err := label.InitLabels("/var/run/rkt/mcs", []string{}) if err != nil { stderr.PrintE("error initialising SELinux", err) return 1 } p.MountLabel = mountLabel cfg := stage0.CommonConfig{ DataDir: getDataDir(), MountLabel: mountLabel, ProcessLabel: processLabel, Store: s, TreeStore: ts, Stage1Image: *s1img, UUID: p.UUID, Debug: globalFlags.Debug, Mutable: true, } ovlOk := true if err := common.PathSupportsOverlay(getDataDir()); err != nil { if oerr, ok := err.(common.ErrOverlayUnsupported); ok { stderr.Printf("disabling overlay support: %q", oerr.Error()) ovlOk = false } else { stderr.PrintE("error determining overlay support", err) return 1 } } useOverlay := !flagNoOverlay && ovlOk pcfg := stage0.PrepareConfig{ CommonConfig: &cfg, UseOverlay: useOverlay, PrivateUsers: user.NewBlankUidRange(), SkipTreeStoreCheck: globalFlags.InsecureFlags.SkipOnDiskCheck(), Apps: &rktApps, Ports: []types.ExposedPort(flagAppPorts), UserAnnotations: parseAnnotations(&flagAnnotations), UserLabels: parseLabels(&flagLabels), } if globalFlags.Debug { stage0.InitDebug() } keyLock, err := lock.SharedKeyLock(lockDir(), common.PrepareLock) if err != nil { stderr.PrintE("cannot get shared prepare lock", err) return 1 } err = stage0.Prepare(pcfg, p.Path(), p.UUID) if err != nil { stderr.PrintE("error setting up stage0", err) keyLock.Close() return 1 } keyLock.Close() // get the lock fd for run lfd, err := p.Fd() if err != nil { stderr.PrintE("error getting pod lock fd", err) return 1 } // skip prepared by jumping directly to run, we own this pod if err := p.ToRun(); err != nil { stderr.PrintE("unable to transition to run", err) return 1 } rktgid, err := common.LookupGid(common.RktGroup) if err != nil { stderr.Printf("group %q not found, will use default gid when rendering images", common.RktGroup) rktgid = -1 } DNSConfMode, DNSConfig, HostsEntries, err := parseDNSFlags(flagHostsEntries, flagDNS, flagDNSSearch, flagDNSOpt, flagDNSDomain) if err != nil { stderr.PrintE("error with dns flags", err) return 1 } rcfg := stage0.RunConfig{ CommonConfig: &cfg, Net: flagNet, LockFd: lfd, Interactive: true, DNSConfMode: DNSConfMode, DNSConfig: DNSConfig, MDSRegister: false, LocalConfig: globalFlags.LocalConfigDir, RktGid: rktgid, Hostname: flagHostname, InsecureCapabilities: globalFlags.InsecureFlags.SkipCapabilities(), InsecurePaths: globalFlags.InsecureFlags.SkipPaths(), InsecureSeccomp: globalFlags.InsecureFlags.SkipSeccomp(), UseOverlay: useOverlay, HostsEntries: *HostsEntries, } _, manifest, err := p.PodManifest() if err != nil { stderr.PrintE("cannot get the pod manifest", err) return 1 } rcfg.Apps = manifest.Apps stage0.Run(rcfg, p.Path(), getDataDir()) // execs, never returns return 1 }