コード例 #1
1
ファイル: dockerfetcher.go プロジェクト: coderhaoxin/rkt
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
}
コード例 #2
0
ファイル: pod.go プロジェクト: yanghongkjxy/rkt
// 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
}
コード例 #3
0
ファイル: podenv.go プロジェクト: nak3/rkt
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
}
コード例 #4
0
ファイル: cgroup.go プロジェクト: intelsdi-x/rkt
// 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
}
コード例 #5
0
ファイル: enter.go プロジェクト: hwinkel/rkt
// 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= ...\"")
}
コード例 #6
0
ファイル: gc.go プロジェクト: sinfomicien/rkt
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
}
コード例 #7
0
ファイル: resolver.go プロジェクト: nak3/rkt
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
}
コード例 #8
0
ファイル: pod.go プロジェクト: sinfomicien/rkt
// 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
}
コード例 #9
0
ファイル: migrate.go プロジェクト: yanghongkjxy/rkt
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
}
コード例 #10
0
ファイル: tree.go プロジェクト: intelsdi-x/rkt
// 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
}
コード例 #11
0
ファイル: filefetcher.go プロジェクト: intelsdi-x/rkt
// 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
}
コード例 #12
0
ファイル: kvm.go プロジェクト: nhlfr/rkt
// 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
}
コード例 #13
0
ファイル: gc.go プロジェクト: intelsdi-x/rkt
// 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
}
コード例 #14
0
ファイル: app-add.go プロジェクト: joshix/rkt
// 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
}
コード例 #15
0
ファイル: run.go プロジェクト: intelsdi-x/rkt
// 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
}
コード例 #16
0
ファイル: pod.go プロジェクト: intelsdi-x/rkt
// 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
}
コード例 #17
0
ファイル: tar.go プロジェクト: sinfomicien/rkt
// 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)
		}
	}
}
コード例 #18
0
ファイル: store.go プロジェクト: nhlfr/rkt
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)
}
コード例 #19
0
ファイル: pod.go プロジェクト: sinfomicien/rkt
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
}
コード例 #20
0
ファイル: aciarchive.go プロジェクト: intelsdi-x/rkt
// 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
}
コード例 #21
0
ファイル: gc.go プロジェクト: yanghongkjxy/rkt
// 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
}
コード例 #22
0
ファイル: api_service.go プロジェクト: intelsdi-x/rkt
// 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
}
コード例 #23
0
ファイル: run.go プロジェクト: sinfomicien/rkt
// 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
}
コード例 #24
0
ファイル: keystore.go プロジェクト: hwinkel/rkt
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
}
コード例 #25
0
ファイル: metadata_service.go プロジェクト: hwinkel/rkt
// 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,
		})
	}
}
コード例 #26
0
ファイル: downloader.go プロジェクト: intelsdi-x/rkt
// 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
}
コード例 #27
0
ファイル: filefetcher.go プロジェクト: sinfomicien/rkt
// 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
}
コード例 #28
0
ファイル: image_gc.go プロジェクト: sinfomicien/rkt
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
}
コード例 #29
0
ファイル: image_gc.go プロジェクト: sinfomicien/rkt
// 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
}
コード例 #30
0
ファイル: main.go プロジェクト: sinfomicien/rkt
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
}