Example #1
0
func (p *LinuxResourcePool) setupRootfs(spec garden.ContainerSpec, id string, resources *linux_backend.Resources, pLog lager.Logger) (string, process.Env, error) {
	rootFSURL, err := url.Parse(spec.RootFSPath)
	if err != nil {
		pLog.Error("parse-rootfs-path-failed", err, lager.Data{
			"RootFSPath": spec.RootFSPath,
		})

		return "", nil, err
	}

	rootFSSpec := rootfs_provider.Spec{
		RootFS:     rootFSURL,
		Namespaced: resources.RootUID != 0,
		QuotaSize:  int64(spec.Limits.Disk.ByteHard),
		QuotaScope: rootfs_provider.QuotaScope(spec.Limits.Disk.Scope),
	}

	pLog.Debug("provide-rootfs-starting")
	rootFSPath, rootFSEnvVars, err := p.rootFSProvider.Create(pLog, id, rootFSSpec)
	if err != nil {
		pLog.Error("provide-rootfs-failed", err)

		return "", nil, err
	}
	pLog.Debug("provide-rootfs-ended")

	rootFSProcessEnv, err := process.NewEnv(rootFSEnvVars)
	if err != nil {
		pLog.Error("rootfs-env-malformed", err)

		return "", nil, err
	}

	return rootFSPath, rootFSProcessEnv, nil
}
Example #2
0
func (c *LinuxContainer) Run(spec garden.ProcessSpec, processIO garden.ProcessIO) (garden.Process, error) {
	wshPath := path.Join(c.ContainerPath, "bin", "wsh")
	sockPath := path.Join(c.ContainerPath, "run", "wshd.sock")

	if spec.User == "" {
		c.logger.Error("linux_container: Run:", errors.New("linux_container: Run: A User for the process to run as must be specified."))
		return nil, errors.New("A User for the process to run as must be specified.")
	}

	args := []string{"--socket", sockPath, "--readSignals", "--user", spec.User}

	specEnv, err := process.NewEnv(spec.Env)
	if err != nil {
		return nil, err
	}

	procEnv, err := process.NewEnv(c.Env)
	if err != nil {
		return nil, err
	}

	processEnv := procEnv.Merge(specEnv)

	for _, envVar := range processEnv.Array() {
		args = append(args, "--env", envVar)
	}

	if spec.Dir != "" {
		args = append(args, "--dir", spec.Dir)
	}

	processID := c.processIDPool.Next()
	c.logger.Info("next pid", lager.Data{"pid": processID})

	if c.Version.Compare(MissingVersion) == 0 {
		pidfile := path.Join(c.ContainerPath, "processes", fmt.Sprintf("%d.pid", processID))
		args = append(args, "--pidfile", pidfile)
	}

	args = append(args, spec.Path)

	wsh := exec.Command(wshPath, append(args, spec.Args...)...)

	setRLimitsEnv(wsh, spec.Limits)

	return c.processTracker.Run(fmt.Sprintf("%d", processID), wsh, processIO, spec.TTY, c.processSignaller())
}
Example #3
0
func (p *LinuxResourcePool) Acquire(spec garden.ContainerSpec) (linux_backend.LinuxContainerSpec, error) {
	id := <-p.containerIDs
	containerPath := path.Join(p.depotPath, id)
	pLog := p.logger.Session(id)

	pLog.Info("creating")

	resources, err := p.acquirePoolResources(spec, id)
	if err != nil {
		return linux_backend.LinuxContainerSpec{}, err
	}
	defer cleanup(&err, func() {
		p.releasePoolResources(resources)
	})

	pLog.Info("acquired-pool-resources")

	handle := getHandle(spec.Handle, id)

	var quota int64 = int64(spec.Limits.Disk.ByteHard)
	if quota == 0 {
		quota = math.MaxInt64
	}

	containerRootFSPath, rootFSEnv, err := p.acquireSystemResources(id, handle, containerPath, spec.RootFSPath, resources, spec.BindMounts, quota, pLog)
	if err != nil {
		return linux_backend.LinuxContainerSpec{}, err
	}

	pLog.Info("created")

	specEnv, err := process.NewEnv(spec.Env)
	if err != nil {
		p.tryReleaseSystemResources(p.logger, id)
		return linux_backend.LinuxContainerSpec{}, err
	}

	pLog.Debug("calculate-environment", lager.Data{
		"rootfs-env": rootFSEnv,
	})

	spec.Env = rootFSEnv.Merge(specEnv).Array()
	spec.Handle = handle

	return linux_backend.LinuxContainerSpec{
		ID:                  id,
		ContainerPath:       containerPath,
		ContainerRootFSPath: containerRootFSPath,
		Resources:           resources,
		Events:              []string{},
		Version:             p.currentContainerVersion,
		State:               linux_backend.StateBorn,

		ContainerSpec: spec,
	}, nil
}
Example #4
0
func filterEnv(env []string, logger lager.Logger) process.Env {
	var filtered []string
	for _, e := range env {
		segs := strings.SplitN(e, "=", 2)
		if len(segs) != 2 {
			// malformed docker image metadata?
			logger.Info("Unrecognised environment variable", lager.Data{"e": e})
			continue
		}
		filtered = append(filtered, e)
	}

	filteredWithNoDups, err := process.NewEnv(filtered)
	if err != nil {
		logger.Error("Invalid environment", err)
	}
	return filteredWithNoDups
}
Example #5
0
func createEnvironment(specEnv []string, usr parsedUser) (process.Env, error) {
	env, err := process.NewEnv(specEnv)
	if err != nil {
		return process.Env{}, fmt.Errorf("invalid environment %v: %s", specEnv, err)
	}

	env["USER"] = usr.username
	_, hasHome := env["HOME"]
	if !hasHome {
		env["HOME"] = usr.homeDir
	}

	_, hasPath := env["PATH"]
	if !hasPath {
		if usr.uid == 0 {
			env["PATH"] = DefaultRootPATH
		} else {
			env["PATH"] = DefaultUserPath
		}
	}

	return env, nil
}
Example #6
0
func (p *LinuxResourcePool) Acquire(spec garden.ContainerSpec) (linux_backend.LinuxContainerSpec, error) {
	id := <-p.containerIDs
	containerPath := path.Join(p.depotPath, id)
	handle := getHandle(spec.Handle, id)
	pLog := p.logger.Session("acquire", lager.Data{"handle": handle})

	iptablesCh := make(chan error, 1)

	go func(iptablesCh chan error) {
		pLog.Debug("setup-iptables-starting")
		if err := p.filterProvider.ProvideFilter(id).Setup(handle); err != nil {
			pLog.Error("setup-iptables-failed", err)
			iptablesCh <- fmt.Errorf("resource_pool: set up filter: %v", err)
		} else {
			pLog.Debug("setup-iptables-ended")
			iptablesCh <- nil
		}
	}(iptablesCh)

	pLog.Info("creating")

	resources, err := p.acquirePoolResources(spec, id, pLog)
	if err != nil {
		return linux_backend.LinuxContainerSpec{}, err
	}
	defer cleanup(&err, func() {
		p.releasePoolResources(resources, pLog)
	})

	pLog.Info("acquired-pool-resources")

	pLog.Info("running-graph-cleanup")
	if err := p.rootFSProvider.GC(pLog); err != nil {
		pLog.Error("graph-cleanup-failed", err)
	}

	containerRootFSPath, rootFSEnv, err := p.acquireSystemResources(
		spec, id, resources, pLog,
	)
	if err != nil {
		return linux_backend.LinuxContainerSpec{}, err
	}

	err = <-iptablesCh
	if err != nil {
		p.tryReleaseSystemResources(p.logger, id)
		return linux_backend.LinuxContainerSpec{}, err
	}

	pLog.Info("created")

	specEnv, err := process.NewEnv(spec.Env)
	if err != nil {
		p.tryReleaseSystemResources(p.logger, id)
		return linux_backend.LinuxContainerSpec{}, err
	}

	spec.Env = rootFSEnv.Merge(specEnv).Array()
	spec.Handle = handle

	return linux_backend.LinuxContainerSpec{
		ID:                  id,
		ContainerPath:       containerPath,
		ContainerRootFSPath: containerRootFSPath,
		Resources:           resources,
		Events:              []string{},
		Version:             p.currentContainerVersion,
		State:               linux_backend.StateBorn,

		ContainerSpec: spec,
	}, nil
}
Example #7
0
		Context("when the file is empty", func() {
			It("returns an empty env", func() {
				cwd, err := os.Getwd()
				Expect(err).ToNot(HaveOccurred())
				pathToTestFile := filepath.Join(cwd, "test-assets", "empty")
				result, err := process.EnvFromFile(pathToTestFile)
				Expect(err).ToNot(HaveOccurred())
				Expect(result).To(Equal(process.Env{}))
			})
		})
	})

	Context("when using the constructor", func() {
		It("can be constructed from an array", func() {
			env, err := process.NewEnv([]string{
				"HOME=/home/alice",
				"USER=alice",
			})
			Expect(err).ToNot(HaveOccurred())

			Expect(env.Array()).To(ConsistOf(
				"HOME=/home/alice",
				"USER=alice",
			))
		})

		It("removes duplicate entries (last one wins)", func() {
			env, err := process.NewEnv([]string{
				"HOME=/home/wrong",
				"HOME=/home/alice",
			})
			Expect(err).ToNot(HaveOccurred())