func (f *dockerFetcher) fetch(u *url.URL) (*os.File, error) { tmpDir, err := f.getTmpDir() if err != nil { return nil, err } defer os.RemoveAll(tmpDir) registryURL := strings.TrimPrefix(u.String(), "docker://") user, password := f.getCreds(registryURL) config := docker2aci.RemoteConfig{ Username: user, Password: password, Insecure: f.InsecureFlags.AllowHTTP(), CommonConfig: docker2aci.CommonConfig{ Squash: true, OutputDir: tmpDir, TmpDir: tmpDir, Compression: d2acommon.NoCompression, }, } acis, err := docker2aci.ConvertRemoteRepo(registryURL, config) if err != nil { return nil, errwrap.Wrap(errors.New("error converting docker image to ACI"), err) } aciFile, err := os.Open(acis[0]) if err != nil { return nil, errwrap.Wrap(errors.New("error opening squashed ACI file"), err) } return aciFile, nil }
// findBinPath takes a binary path and returns a the absolute path of the // binary relative to the app rootfs. This can be passed to ExecStart on the // app's systemd service file directly. func findBinPath(p *stage1commontypes.Pod, appName types.ACName, app types.App, workDir string, bin string) (string, error) { var binPath string switch { // absolute path, just use it case filepath.IsAbs(bin): binPath = bin // non-absolute path containing a slash, look in the working dir case strings.Contains(bin, "/"): binPath = filepath.Join(workDir, bin) // filename, search in the app's $PATH default: absRoot, err := filepath.Abs(p.Root) if err != nil { return "", errwrap.Wrap(errors.New("could not get pod's root absolute path"), err) } appRootfs := common.AppRootfsPath(absRoot, appName) appPathDirs := appSearchPaths(p, workDir, app) appPath := strings.Join(appPathDirs, ":") binPath, err = lookupPathInsideApp(bin, appPath, appRootfs, workDir) if err != nil { return "", errwrap.Wrap(fmt.Errorf("error looking up %q", bin), err) } } return binPath, nil }
func (e *podEnv) setupNets(nets []activeNet) error { err := os.MkdirAll(e.netDir(), 0755) if err != nil { return err } i := 0 defer func() { if err != nil { e.teardownNets(nets[:i]) } }() n := activeNet{} for i, n = range nets { stderr.Printf("loading network %v with type %v", n.conf.Name, n.conf.Type) n.runtime.IfName = fmt.Sprintf(IfNamePattern, i) if n.runtime.ConfPath, err = copyFileToDir(n.runtime.ConfPath, e.netDir()); err != nil { return errwrap.Wrap(fmt.Errorf("error copying %q to %q", n.runtime.ConfPath, e.netDir()), err) } n.runtime.IP, n.runtime.HostIP, err = e.netPluginAdd(&n, e.podNS.Path()) if err != nil { return errwrap.Wrap(fmt.Errorf("error adding network %q", n.conf.Name), err) } } return nil }
// IsIsolatorSupported returns whether an isolator is supported in the kernel func IsIsolatorSupported(isolator string) (bool, error) { isUnified, err := IsCgroupUnified("/") if err != nil { return false, errwrap.Wrap(errors.New("error determining cgroup version"), err) } if isUnified { controllers, err := v2.GetEnabledControllers() if err != nil { return false, errwrap.Wrap(errors.New("error determining enabled controllers"), err) } for _, c := range controllers { if c == isolator { return true, nil } } return false, nil } if files := v1.CgroupControllerRWFiles(isolator); len(files) > 0 { for _, f := range files { isolatorPath := filepath.Join("/sys/fs/cgroup/", isolator, f) if _, err := os.Stat(isolatorPath); os.IsNotExist(err) { return false, nil } } return true, nil } return false, nil }
// getAppName returns the app name to enter // If one was supplied in the flags then it's simply returned // If the PM contains a single app, that app's name is returned // If the PM has multiple apps, the names are printed and an error is returned func getAppName(p *pod) (*types.ACName, error) { if flagAppName != "" { return types.NewACName(flagAppName) } // figure out the app name, or show a list if multiple are present b, err := ioutil.ReadFile(common.PodManifestPath(p.path())) if err != nil { return nil, errwrap.Wrap(errors.New("error reading pod manifest"), err) } m := schema.PodManifest{} if err = m.UnmarshalJSON(b); err != nil { return nil, errwrap.Wrap(errors.New("invalid pod manifest"), err) } switch len(m.Apps) { case 0: return nil, fmt.Errorf("pod contains zero apps") case 1: return &m.Apps[0].Name, nil default: } stderr.Print("pod contains multiple apps:") for _, ra := range m.Apps { stderr.Printf("\t%v", ra.Name) } return nil, fmt.Errorf("specify app using \"rkt enter --app= ...\"") }
func gcNetworking(podID *types.UUID) error { var flavor string // we first try to read the flavor from stage1 for backwards compatibility flavor, err := os.Readlink(filepath.Join(common.Stage1RootfsPath("."), "flavor")) if err != nil { // if we couldn't read the flavor from stage1 it could mean the overlay // filesystem is already unmounted (e.g. the system has been rebooted). // In that case we try to read it from the pod's root directory flavor, err = os.Readlink("flavor") if err != nil { return errwrap.Wrap(errors.New("failed to get stage1 flavor"), err) } } n, err := networking.Load(".", podID) switch { case err == nil: n.Teardown(flavor, debug) case os.IsNotExist(err): // probably ran with --net=host default: return errwrap.Wrap(errors.New("failed loading networking state"), err) } return nil }
func (s idsFromStat) IDs() (int, int, error) { var stat syscall.Stat_t if err := syscall.Lstat(s.path, &stat); err != nil { return -1, -1, errwrap.Wrap( fmt.Errorf("unable to stat file %q", s.path), err, ) } if s.r == nil { return int(stat.Uid), int(stat.Gid), nil } uid, _, err := s.r.UnshiftRange(stat.Uid, stat.Gid) if err != nil { return -1, -1, errwrap.Wrap(errors.New("unable to determine real uid"), err) } _, gid, err := s.r.UnshiftRange(stat.Uid, stat.Gid) if err != nil { return -1, -1, errwrap.Wrap(errors.New("unable to determine real gid"), err) } return int(uid), int(gid), nil }
// WritePrepareAppTemplate writes service unit files for preparing the pod's applications func WritePrepareAppTemplate(p *stage1commontypes.Pod) error { opts := []*unit.UnitOption{ unit.NewUnitOption("Unit", "Description", "Prepare minimum environment for chrooted applications"), unit.NewUnitOption("Unit", "DefaultDependencies", "false"), unit.NewUnitOption("Unit", "OnFailureJobMode", "fail"), unit.NewUnitOption("Unit", "Requires", "systemd-journald.service"), unit.NewUnitOption("Unit", "After", "systemd-journald.service"), unit.NewUnitOption("Service", "Type", "oneshot"), unit.NewUnitOption("Service", "Restart", "no"), unit.NewUnitOption("Service", "ExecStart", "/prepare-app %I"), unit.NewUnitOption("Service", "User", "0"), unit.NewUnitOption("Service", "Group", "0"), unit.NewUnitOption("Service", "CapabilityBoundingSet", "CAP_SYS_ADMIN CAP_DAC_OVERRIDE"), } unitsPath := filepath.Join(common.Stage1RootfsPath(p.Root), UnitsDir) file, err := os.OpenFile(filepath.Join(unitsPath, "[email protected]"), os.O_WRONLY|os.O_CREATE, 0644) if err != nil { return errwrap.Wrap(errors.New("failed to create service unit file"), err) } defer file.Close() if _, err = io.Copy(file, unit.Serialize(opts)); err != nil { return errwrap.Wrap(errors.New("failed to write service unit file"), err) } return nil }
func migrate(tx *sql.Tx, finalVersion int) error { if finalVersion > dbVersion { return fmt.Errorf("required migrate final version greater than the last supported db version") } version, err := getDBVersion(tx) if err != nil { return err } for v := version + 1; v <= finalVersion; v++ { migrate, ok := migrateTable[v] if !ok { return fmt.Errorf("missing migrate function for version %d", v) } if err := migrate(tx); err != nil { return errwrap.Wrap(fmt.Errorf("failed to migrate db to version %d", v), err) } if err := updateDBVersion(tx, v); err != nil { return errwrap.Wrap(fmt.Errorf("updateDBVersion() failed to update the db to version %d", v), err) } } return nil }
// Render renders a treestore for the given image key if it's not // already fully rendered. // Users of treestore should call s.Render before using it to ensure // that the treestore is completely rendered. // Returns the id and hash of the rendered treestore if it is newly rendered, // and only the id if it is already rendered. func (ts *Store) Render(key string, rebuild bool) (id string, hash string, err error) { id, err = ts.GetID(key) if err != nil { return "", "", errwrap.Wrap(errors.New("cannot calculate treestore id"), err) } // this lock references the treestore dir for the specified id. treeStoreKeyLock, err := lock.ExclusiveKeyLock(ts.lockDir, id) if err != nil { return "", "", errwrap.Wrap(errors.New("error locking tree store"), err) } defer treeStoreKeyLock.Close() if !rebuild { rendered, err := ts.IsRendered(id) if err != nil { return "", "", errwrap.Wrap(errors.New("cannot determine if tree is already rendered"), err) } if rendered { return id, "", nil } } // Firstly remove a possible partial treestore if existing. // This is needed as a previous ACI removal operation could have failed // cleaning the tree store leaving some stale files. if err := ts.remove(id); err != nil { return "", "", err } if hash, err = ts.render(id, key); err != nil { return "", "", err } return id, hash, nil }
// fetch opens and verifies the ACI. func (f *fileFetcher) getVerifiedFile(aciPath string, a *asc) (*os.File, error) { var aciFile *os.File // closed on error var errClose error // error signaling to close aciFile f.maybeOverrideAsc(aciPath, a) ascFile, err := a.Get() if err != nil { return nil, errwrap.Wrap(errors.New("error opening signature file"), err) } defer ascFile.Close() aciFile, err = os.Open(aciPath) if err != nil { return nil, errwrap.Wrap(errors.New("error opening ACI file"), err) } defer func() { if errClose != nil { aciFile.Close() } }() validator, errClose := newValidator(aciFile) if errClose != nil { return nil, errClose } entity, errClose := validator.ValidateWithSignature(f.Ks, ascFile) if errClose != nil { return nil, errwrap.Wrap(fmt.Errorf("image %q verification failed", validator.ImageName()), errClose) } printIdentities(entity) return aciFile, nil }
// kvmSetupNetAddressing calls IPAM plugin (with a hack) to reserve an IP to be // used by newly create tuntap pair // in result it updates activeNet.runtime configuration func kvmSetupNetAddressing(network *Networking, n activeNet, ifName string) error { // TODO: very ugly hack, that go through upper plugin, down to ipam plugin if err := ip.EnableIP4Forward(); err != nil { return errwrap.Wrap(errors.New("failed to enable forwarding"), err) } // patch plugin type only for single IPAM run time, then revert this change original_type := n.conf.Type n.conf.Type = n.conf.IPAM.Type output, err := network.execNetPlugin("ADD", &n, ifName) n.conf.Type = original_type if err != nil { return errwrap.Wrap(fmt.Errorf("problem executing network plugin %q (%q)", n.conf.IPAM.Type, ifName), err) } result := cnitypes.Result{} if err = json.Unmarshal(output, &result); err != nil { return errwrap.Wrap(fmt.Errorf("error parsing %q result", n.conf.Name), err) } if result.IP4 == nil { return fmt.Errorf("net-plugin returned no IPv4 configuration") } n.runtime.MergeCNIResult(result) return nil }
// MountGC removes mounts from pods that couldn't be GCed cleanly. func MountGC(path, uuid string) error { mnts, err := mountinfo.ParseMounts(0) if err != nil { return errwrap.Wrap(fmt.Errorf("error getting mounts for pod %s from mountinfo", uuid), err) } mnts = mnts.Filter(mountinfo.HasPrefix(path)) for i := len(mnts) - 1; i >= 0; i-- { mnt := mnts[i] if mnt.NeedsRemountPrivate() { if err := syscall.Mount("", mnt.MountPoint, "", syscall.MS_PRIVATE, ""); err != nil { return errwrap.Wrap(fmt.Errorf("could not remount at %v", mnt.MountPoint), err) } } } for _, mnt := range mnts { if err := syscall.Unmount(mnt.MountPoint, 0); err != nil { if err != syscall.ENOENT && err != syscall.EINVAL { return errwrap.Wrap(fmt.Errorf("could not unmount %v", mnt.MountPoint), err) } } } return nil }
// prepareAppCgroups makes the cgroups-v1 hierarchy for this application writable // by pod supervisor func prepareAppCgroups(p *stage1types.Pod, ra *schema.RuntimeApp, enterCmd []string) error { isUnified, err := cgroup.IsCgroupUnified("/") if err != nil { return errwrap.Wrap(errors.New("failed to determine cgroup version"), err) } if isUnified { return nil } enabledCgroups, err := v1.GetEnabledCgroups() if err != nil { return errwrap.Wrap(errors.New("error getting cgroups"), err) } b, err := ioutil.ReadFile(filepath.Join(p.Root, "subcgroup")) if err != nil { log.PrintE("continuing with per-app isolators disabled", err) return nil } subcgroup := string(b) serviceName := stage1initcommon.ServiceUnitName(ra.Name) if err := v1.RemountCgroupKnobsRW(enabledCgroups, subcgroup, serviceName, enterCmd); err != nil { return errwrap.Wrap(errors.New("error restricting application cgroups"), err) } return nil }
// ensureMtabExists creates a symlink from /etc/mtab -> /proc/self/mounts if // nothing exists at /etc/mtab. // Various tools, such as mount from util-linux 2.25, expect the mtab file to // be populated. func ensureMtabExists(rootfs string) error { stat, err := os.Stat(filepath.Join(rootfs, "etc")) if os.IsNotExist(err) { // If your image has no /etc you don't get /etc/mtab either return nil } if err != nil { return errwrap.Wrap(errors.New("error determining if /etc existed in the image"), err) } if !stat.IsDir() { return nil } mtabPath := filepath.Join(rootfs, "etc", "mtab") if _, err = os.Lstat(mtabPath); err == nil { // If the image already has an mtab, don't replace it return nil } if !os.IsNotExist(err) { return errwrap.Wrap(errors.New("error determining if /etc/mtab exists in the image"), err) } target := "../proc/self/mounts" err = os.Symlink(target, mtabPath) if err != nil { return errwrap.Wrap(errors.New("error creating mtab symlink"), err) } return nil }
// FindBinPath takes a binary path and returns a the absolute path of the // binary relative to the app rootfs. This can be passed to ExecStart on the // app's systemd service file directly. func FindBinPath(p *stage1commontypes.Pod, ra *schema.RuntimeApp) (string, error) { if len(ra.App.Exec) == 0 { return "", errors.New("app has no executable") } bin := ra.App.Exec[0] var binPath string switch { // absolute path, just use it case filepath.IsAbs(bin): binPath = bin // non-absolute path containing a slash, look in the working dir case strings.Contains(bin, "/"): binPath = filepath.Join(ra.App.WorkingDirectory, bin) // filename, search in the app's $PATH default: absRoot, err := filepath.Abs(p.Root) if err != nil { return "", errwrap.Wrap(errors.New("could not get pod's root absolute path"), err) } appRootfs := common.AppRootfsPath(absRoot, ra.Name) appPathDirs := appSearchPaths(p, ra.App.WorkingDirectory, *ra.App) appPath := strings.Join(appPathDirs, ":") binPath, err = lookupPathInsideApp(bin, appPath, appRootfs, ra.App.WorkingDirectory) if err != nil { return "", errwrap.Wrap(fmt.Errorf("error looking up %q", bin), err) } } return binPath, nil }
// extractFileFromTar extracts a regular file from the given tar, returning its // contents as a byte slice func extractFileFromTar(tr *tar.Reader, file string) ([]byte, error) { for { hdr, err := tr.Next() switch err { case io.EOF: return nil, fmt.Errorf("file not found") case nil: if filepath.Clean(hdr.Name) != filepath.Clean(file) { continue } switch hdr.Typeflag { case tar.TypeReg: case tar.TypeRegA: default: return nil, fmt.Errorf("requested file not a regular file") } buf, err := ioutil.ReadAll(tr) if err != nil { return nil, errwrap.Wrap(errors.New("error extracting tarball"), err) } return buf, nil default: return nil, errwrap.Wrap(errors.New("error extracting tarball"), err) } } }
func (s *Store) ReadStream(key string) (io.ReadCloser, error) { key, err := s.ResolveKey(key) if err != nil { return nil, errwrap.Wrap(errors.New("error resolving image ID"), err) } keyLock, err := lock.SharedKeyLock(s.imageLockDir, key) if err != nil { return nil, errwrap.Wrap(errors.New("error locking image"), err) } defer keyLock.Close() err = s.db.Do(func(tx *sql.Tx) error { aciinfo, found, err := GetACIInfoWithBlobKey(tx, key) if err != nil { return errwrap.Wrap(errors.New("error getting aciinfo"), err) } else if !found { return fmt.Errorf("cannot find image with key: %s", key) } aciinfo.LastUsed = time.Now() return WriteACIInfo(tx, aciinfo) }) if err != nil { return nil, errwrap.Wrap(fmt.Errorf("cannot get image info for %q from db", key), err) } return s.stores[blobType].ReadStream(key, false) }
func writeAppReaper(p *stage1commontypes.Pod, appName string) error { opts := []*unit.UnitOption{ unit.NewUnitOption("Unit", "Description", fmt.Sprintf("%s Reaper", appName)), unit.NewUnitOption("Unit", "DefaultDependencies", "false"), unit.NewUnitOption("Unit", "StopWhenUnneeded", "yes"), unit.NewUnitOption("Unit", "Wants", "shutdown.service"), unit.NewUnitOption("Unit", "After", "shutdown.service"), unit.NewUnitOption("Unit", "Conflicts", "exit.target"), unit.NewUnitOption("Unit", "Conflicts", "halt.target"), unit.NewUnitOption("Unit", "Conflicts", "poweroff.target"), unit.NewUnitOption("Service", "RemainAfterExit", "yes"), unit.NewUnitOption("Service", "ExecStop", fmt.Sprintf("/reaper.sh %s", appName)), } unitsPath := filepath.Join(common.Stage1RootfsPath(p.Root), UnitsDir) file, err := os.OpenFile(filepath.Join(unitsPath, fmt.Sprintf("reaper-%s.service", appName)), os.O_WRONLY|os.O_CREATE, 0644) if err != nil { return errwrap.Wrap(errors.New("failed to create service unit file"), err) } defer file.Close() if _, err = io.Copy(file, unit.Serialize(opts)); err != nil { return errwrap.Wrap(errors.New("failed to write service unit file"), err) } return nil }
// NewACIArchive creates a new aci-archive distribution from the provided distribution uri. func NewACIArchive(u *url.URL) (Distribution, error) { c, err := parseCIMD(u) if err != nil { return nil, fmt.Errorf("cannot parse URI: %q: %v", u.String(), err) } if c.Type != TypeACIArchive { return nil, fmt.Errorf("illegal ACI archive distribution type: %q", c.Type) } // This should be a valid URL data, err := url.QueryUnescape(c.Data) if err != nil { return nil, errwrap.Wrap(fmt.Errorf("error unescaping url %q", c.Data), err) } aciu, err := url.Parse(data) if err != nil { return nil, errwrap.Wrap(fmt.Errorf("error parsing url %q", c.Data), err) } // save the URI as sorted to make it ready for comparison purell.NormalizeURL(u, purell.FlagSortQuery) str := u.String() if path := aciu.String(); filepath.Ext(path) == schema.ACIExtension { str = path } return &ACIArchive{ cimdURL: u, transportURL: aciu, str: str, }, nil }
// MountGC removes mounts from pods that couldn't be GCed cleanly. func MountGC(path, uuid string) error { mi, err := os.Open("/proc/self/mountinfo") if err != nil { return err } defer mi.Close() mnts, err := getMountsForPrefix(path, mi) if err != nil { return errwrap.Wrap(fmt.Errorf("error getting mounts for pod %s from mountinfo", uuid), err) } for i := len(mnts) - 1; i >= 0; i -= 1 { mnt := mnts[i] if needsRemountPrivate(mnt) { if err := syscall.Mount("", mnt.mountPoint, "", syscall.MS_PRIVATE, ""); err != nil { return errwrap.Wrap(fmt.Errorf("could not remount at %v", mnt.mountPoint), err) } } } for _, mnt := range mnts { if err := syscall.Unmount(mnt.mountPoint, 0); err != nil { if err != syscall.ENOENT && err != syscall.EINVAL { return errwrap.Wrap(fmt.Errorf("could not unmount %v", mnt.mountPoint), err) } } } return nil }
// Open API sockets based on command line parameters and // the magic environment variable from systemd // // see sd_listen_fds(3) func openAPISockets() ([]net.Listener, error) { listeners := []net.Listener{} fds := systemdFDs(true) // Try to get the socket fds from systemd if len(fds) > 0 { if flagAPIServiceListenAddr != "" { return nil, fmt.Errorf("started under systemd.socket(5), but --listen passed! Quitting.") } stderr.Printf("Listening on %d systemd-provided socket(s)\n", len(fds)) for _, fd := range fds { l, err := net.FileListener(fd) if err != nil { return nil, errwrap.Wrap(fmt.Errorf("could not open listener"), err) } listeners = append(listeners, l) } } else { if flagAPIServiceListenAddr == "" { flagAPIServiceListenAddr = common.APIServiceListenAddr } stderr.Printf("Listening on %s\n", flagAPIServiceListenAddr) l, err := net.Listen("tcp", flagAPIServiceListenAddr) if err != nil { return nil, errwrap.Wrap(fmt.Errorf("could not open tcp socket"), err) } listeners = append(listeners, l) } return listeners, nil }
// validatePodManifest reads the user-specified pod manifest, prepares the app images // and validates the pod manifest. If the pod manifest passes validation, it returns // the manifest as []byte. // TODO(yifan): More validation in the future. func validatePodManifest(cfg PrepareConfig, dir string) ([]byte, error) { pmb, err := ioutil.ReadFile(cfg.PodManifest) if err != nil { return nil, errwrap.Wrap(errors.New("error reading pod manifest"), err) } var pm schema.PodManifest if err := json.Unmarshal(pmb, &pm); err != nil { return nil, errwrap.Wrap(errors.New("error unmarshaling pod manifest"), err) } appNames := make(map[types.ACName]struct{}) for _, ra := range pm.Apps { img := ra.Image if img.ID.Empty() { return nil, fmt.Errorf("no image ID for app %q", ra.Name) } am, err := cfg.Store.GetImageManifest(img.ID.String()) if err != nil { return nil, errwrap.Wrap(errors.New("error getting the image manifest from store"), err) } if err := prepareAppImage(cfg, ra.Name, img.ID, dir, cfg.UseOverlay); err != nil { return nil, errwrap.Wrap(fmt.Errorf("error setting up image %s", img), err) } if _, ok := appNames[ra.Name]; ok { return nil, fmt.Errorf("multiple apps with same name %s", ra.Name) } appNames[ra.Name] = struct{}{} if ra.App == nil && am.App == nil { return nil, fmt.Errorf("no app section in the pod manifest or the image manifest") } } return pmb, nil }
func checkSignature(ks *Keystore, prefix string, signed, signature io.ReadSeeker) (*openpgp.Entity, error) { acidentifier, err := types.NewACIdentifier(prefix) if err != nil { return nil, err } keyring, err := ks.loadKeyring(acidentifier.String()) if err != nil { return nil, errwrap.Wrap(errors.New("keystore: error loading keyring"), err) } entities, err := openpgp.CheckArmoredDetachedSignature(keyring, signed, signature) if err == io.EOF { // When the signature is binary instead of armored, the error is io.EOF. // Let's try with binary signatures as well if _, err := signed.Seek(0, 0); err != nil { return nil, errwrap.Wrap(errors.New("error seeking ACI file"), err) } if _, err := signature.Seek(0, 0); err != nil { return nil, errwrap.Wrap(errors.New("error seeking signature file"), err) } entities, err = openpgp.CheckDetachedSignature(keyring, signed, signature) } if err == io.EOF { // otherwise, the client failure is just "EOF", which is not helpful return nil, fmt.Errorf("keystore: no valid signatures found in signature file") } return entities, err }
// unixListener returns the listener used for registrations (over unix sock) func unixListener() (net.Listener, error) { s := os.Getenv("LISTEN_FDS") if s != "" { // socket activated lfds, err := strconv.ParseInt(s, 10, 16) if err != nil { return nil, errwrap.Wrap(errors.New("error parsing LISTEN_FDS env var"), err) } if lfds < 1 { return nil, fmt.Errorf("LISTEN_FDS < 1") } return net.FileListener(os.NewFile(uintptr(listenFdsStart), "listen")) } else { dir := filepath.Dir(common.MetadataServiceRegSock) err := os.MkdirAll(dir, 0755) if err != nil { return nil, errwrap.Wrap(fmt.Errorf("failed to create %v", dir), err) } return net.ListenUnix("unix", &net.UnixAddr{ Net: "unix", Name: common.MetadataServiceRegSock, }) } }
// Download tries to fetch the passed URL and write the contents into // a given writeSyncer instance. func (d *downloader) Download(u *url.URL, out writeSyncer) error { client, err := d.Session.Client() if err != nil { return err } req, err := d.Session.Request(u) if err != nil { return err } res, err := client.Do(req) if err != nil { return err } defer res.Body.Close() if stopNow, err := d.Session.HandleStatus(res); stopNow || err != nil { return err } reader, err := d.Session.BodyReader(res) if err != nil { return err } if _, err := io.Copy(out, reader); err != nil { return errwrap.Wrap(fmt.Errorf("failed to download %q", u.String()), err) } if err := out.Sync(); err != nil { return errwrap.Wrap(fmt.Errorf("failed to sync data from %q to disk", u.String()), err) } return nil }
// fetch opens and verifies the ACI. func (f *fileFetcher) getVerifiedFile(aciPath string, a *asc) (*os.File, error) { f.maybeOverrideAsc(aciPath, a) ascFile, err := a.Get() if err != nil { return nil, errwrap.Wrap(errors.New("error opening signature file"), err) } defer func() { maybeClose(ascFile) }() aciFile, err := os.Open(aciPath) if err != nil { return nil, errwrap.Wrap(errors.New("error opening ACI file"), err) } defer func() { maybeClose(aciFile) }() validator, err := newValidator(aciFile) if err != nil { return nil, err } entity, err := validator.ValidateWithSignature(f.Ks, ascFile) if err != nil { return nil, errwrap.Wrap(fmt.Errorf("image %q verification failed", validator.GetImageName()), err) } printIdentities(entity) retAciFile := aciFile aciFile = nil return retAciFile, nil }
func getReferencedTreeStoreIDs() (map[string]struct{}, error) { treeStoreIDs := map[string]struct{}{} var walkErr error // Consider pods in preparing, prepared, run, exitedgarbage state if err := walkPods(includeMostDirs, func(p *pod) { stage1TreeStoreID, err := p.getStage1TreeStoreID() if err != nil { walkErr = errwrap.Wrap(fmt.Errorf("cannot get stage1 treestoreID for pod %s", p.uuid), err) return } appsTreeStoreIDs, err := p.getAppsTreeStoreIDs() if err != nil { walkErr = errwrap.Wrap(fmt.Errorf("cannot get apps treestoreIDs for pod %s", p.uuid), err) return } allTreeStoreIDs := append(appsTreeStoreIDs, stage1TreeStoreID) for _, treeStoreID := range allTreeStoreIDs { treeStoreIDs[treeStoreID] = struct{}{} } }); err != nil { return nil, errwrap.Wrap(errors.New("failed to get pod handles"), err) } if walkErr != nil { return nil, walkErr } return treeStoreIDs, nil }
// gcTreeStore removes all treeStoreIDs not referenced by any non garbage // collected pod from the store. func gcTreeStore(s *store.Store) error { // Take an exclusive lock to block other pods being created. // This is needed to avoid races between the below steps (getting the // list of referenced treeStoreIDs, getting the list of treeStoreIDs // from the store, removal of unreferenced treeStoreIDs) and new // pods/treeStores being created/referenced keyLock, err := lock.ExclusiveKeyLock(lockDir(), common.PrepareLock) if err != nil { return errwrap.Wrap(errors.New("cannot get exclusive prepare lock"), err) } defer keyLock.Close() referencedTreeStoreIDs, err := getReferencedTreeStoreIDs() if err != nil { return errwrap.Wrap(errors.New("cannot get referenced treestoreIDs"), err) } treeStoreIDs, err := s.GetTreeStoreIDs() if err != nil { return errwrap.Wrap(errors.New("cannot get treestoreIDs from the store"), err) } for _, treeStoreID := range treeStoreIDs { if _, ok := referencedTreeStoreIDs[treeStoreID]; !ok { if err := s.RemoveTreeStore(treeStoreID); err != nil { stderr.PrintE(fmt.Sprintf("error removing treestore %q", treeStoreID), err) } else { stderr.Printf("removed treestore %q", treeStoreID) } } } return nil }
func getList(file string, proc processor) ([]string, error) { fd, err := os.Open(file) if err != nil { return nil, errwrap.Wrap(fmt.Errorf("failed to open %s list %q", proc.kind(), file), err) } defer fd.Close() sc := bufio.NewScanner(fd) sc.Split(bufio.ScanWords) if !sc.Scan() { if err := sc.Err(); err != nil { return nil, errwrap.Wrap(fmt.Errorf("failed to read %s list %q", proc.kind(), file), err) } return nil, fmt.Errorf("failed to parse %s list %q: premature end of file", proc.kind(), file) } num, err := strconv.Atoi(sc.Text()) if err != nil { return nil, errwrap.Wrap(fmt.Errorf("failed to parse first line of %s list %q", proc.kind(), file), err) } proc.setWordsNumber(num) for sc.Scan() { if err := proc.processWord(sc.Text()); err != nil { return nil, errwrap.Wrap(fmt.Errorf("failed to process %s from %s list %q", sc.Text(), proc.kind(), file), err) } } if err := sc.Err(); err != nil { return nil, errwrap.Wrap(fmt.Errorf("failed to read %s list %q", proc.kind(), file), err) } return proc.getList(), nil }