Beispiel #1
0
func NewDriver(root, initPath string) (*driver, error) {
	meminfo, err := sysinfo.ReadMemInfo()
	if err != nil {
		return nil, err
	}

	if err := os.MkdirAll(root, 0700); err != nil {
		return nil, err
	}
	// native driver root is at docker_root/execdriver/native. Put apparmor at docker_root
	if err := apparmor.InstallDefaultProfile(); err != nil {
		return nil, err
	}
	cgm := libcontainer.Cgroupfs
	if systemd.UseSystemd() {
		cgm = libcontainer.SystemdCgroups
	}

	f, err := libcontainer.New(
		root,
		cgm,
		libcontainer.InitPath(reexec.Self(), DriverName),
	)
	if err != nil {
		return nil, err
	}

	return &driver{
		root:             root,
		initPath:         initPath,
		activeContainers: make(map[string]libcontainer.Container),
		machineMemory:    meminfo.MemTotal,
		factory:          f,
	}, nil
}
Beispiel #2
0
func TestMain(m *testing.M) {
	var (
		err error
		ret int = 0
	)

	log.SetOutput(os.Stderr)
	log.SetLevel(log.InfoLevel)

	factory, err = libcontainer.New(".", libcontainer.Cgroupfs)
	if err != nil {
		log.Error(err)
		os.Exit(1)
	}
	if systemd.UseSystemd() {
		systemdFactory, err = libcontainer.New(".", libcontainer.SystemdCgroups)
		if err != nil {
			log.Error(err)
			os.Exit(1)
		}
	}

	ret = m.Run()
	os.Exit(ret)
}
Beispiel #3
0
// Register root container before running this function!
func Register(factory info.MachineInfoFactory) error {
	client, err := docker.NewClient(*ArgDockerEndpoint)
	if err != nil {
		return fmt.Errorf("unable to communicate with docker daemon: %v", err)
	}
	if version, err := client.Version(); err != nil {
		return fmt.Errorf("unable to communicate with docker daemon: %v", err)
	} else {
		expected_version := []int{0, 11, 1}
		version_string := version.Get("Version")
		version, err := parseDockerVersion(version_string)
		if err != nil {
			return fmt.Errorf("Couldn't parse docker version: %v", err)
		}
		for index, number := range version {
			if number > expected_version[index] {
				break
			} else if number < expected_version[index] {
				return fmt.Errorf("cAdvisor requires docker version above %v but we have found version %v reported as \"%v\"", expected_version, version, version_string)
			}
		}
	}
	f := &dockerFactory{
		machineInfoFactory: factory,
		useSystemd:         systemd.UseSystemd(),
		client:             client,
	}
	if f.useSystemd {
		log.Printf("System is using systemd")
	}
	log.Printf("Registering Docker factory")
	container.RegisterContainerHandlerFactory(f)
	return nil
}
Beispiel #4
0
// killAllPids itterates over all of the container's processes
// sending a SIGKILL to each process.
func killAllPids(container *libcontainer.Config) error {
	var (
		procs   []*os.Process
		freeze  = fs.Freeze
		getPids = fs.GetPids
	)
	if systemd.UseSystemd() {
		freeze = systemd.Freeze
		getPids = systemd.GetPids
	}
	freeze(container.Cgroups, cgroups.Frozen)
	pids, err := getPids(container.Cgroups)
	if err != nil {
		return err
	}
	for _, pid := range pids {
		// TODO: log err without aborting if we are unable to find
		// a single PID
		if p, err := os.FindProcess(pid); err == nil {
			procs = append(procs, p)
			p.Kill()
		}
	}
	freeze(container.Cgroups, cgroups.Thawed)
	for _, p := range procs {
		p.Wait()
	}
	return err
}
Beispiel #5
0
func (self *dockerContainerHandler) GetStats() (stats *info.ContainerStats, err error) {
	if !self.isDockerContainer() {
		// Return empty stats for root containers.
		stats = new(info.ContainerStats)
		stats.Timestamp = time.Now()
		return
	}
	mi, err := self.machineInfoFactory.GetMachineInfo()
	if err != nil {
		return
	}
	parent, id, err := self.splitName()
	if err != nil {
		return
	}
	cg := &cgroups.Cgroup{
		Parent: parent,
		Name:   id,
	}

	// TODO(vmarmol): Use libcontainer's Stats() in the new API when that is ready.
	// Use systemd paths if systemd is being used.
	var s *cgroups.Stats
	if systemd.UseSystemd() {
		s, err = systemd.GetStats(cg)
	} else {
		s, err = fs.GetStats(cg)
	}
	if err != nil {
		return
	}
	stats = libcontainerToContainerStats(s, mi)
	return
}
Beispiel #6
0
// SetupCgroups applies the cgroup restrictions to the process running in the container based
// on the container's configuration
func SetupCgroups(container *libcontainer.Config, nspid int) (map[string]string, error) {
	if container.Cgroups != nil {
		c := container.Cgroups
		if systemd.UseSystemd() {
			return systemd.Apply(c, nspid)
		}
		return fs.Apply(c, nspid)
	}
	return map[string]string{}, nil
}
Beispiel #7
0
// SetupCgroups applies the cgroup restrictions to the process running in the container based
// on the container's configuration
func SetupCgroups(container *libcontainer.Config, nspid int) (cgroups.ActiveCgroup, error) {
	if container.Cgroups != nil {
		c := container.Cgroups
		if systemd.UseSystemd() {
			return systemd.Apply(c, nspid)
		}
		return fs.Apply(c, nspid)
	}
	return nil, nil
}
Beispiel #8
0
func loadFactory(context *cli.Context) (libcontainer.Factory, error) {
	cgm := libcontainer.Cgroupfs
	if context.Bool("systemd") {
		if systemd.UseSystemd() {
			cgm = libcontainer.SystemdCgroups
		} else {
			logrus.Warn("systemd cgroup flag passed, but systemd support for managing cgroups is not available.")
		}
	}
	return libcontainer.New(context.GlobalString("root"), cgm)
}
Beispiel #9
0
func (d *driver) Unpause(c *execdriver.Command) error {
	active := d.activeContainers[c.ID]
	if active == nil {
		return fmt.Errorf("active container for %s does not exist", c.ID)
	}
	active.container.Cgroups.Freezer = "THAWED"
	if systemd.UseSystemd() {
		return systemd.Freeze(active.container.Cgroups, active.container.Cgroups.Freezer)
	}
	return fs.Freeze(active.container.Cgroups, active.container.Cgroups.Freezer)
}
Beispiel #10
0
func init() {
	useSystemd = systemd.UseSystemd()
	if !useSystemd {
		// Second attempt at checking for systemd, check for a "name=systemd" cgroup.
		mnt, err := cgroups.FindCgroupMountpoint("cpu")
		if err == nil {
			// systemd presence does not mean systemd controls cgroups.
			// If system.slice cgroup exists, then systemd is taking control.
			// This breaks if user creates system.slice manually :)
			useSystemd = utils.FileExists(mnt + "/system.slice")
		}
	}
}
Beispiel #11
0
// Register root container before running this function!
func Register(factory info.MachineInfoFactory) error {
	client, err := docker.NewClient(*ArgDockerEndpoint)
	if err != nil {
		return fmt.Errorf("unable to communicate with docker daemon: %v", err)
	}
	if version, err := client.Version(); err != nil {
		return fmt.Errorf("unable to communicate with docker daemon: %v", err)
	} else {
		expected_version := []int{0, 11, 1}
		version_string := version.Get("Version")
		version, err := parseDockerVersion(version_string)
		if err != nil {
			return fmt.Errorf("Couldn't parse docker version: %v", err)
		}
		for index, number := range version {
			if number > expected_version[index] {
				break
			} else if number < expected_version[index] {
				return fmt.Errorf("cAdvisor requires docker version above %v but we have found version %v reported as \"%v\"", expected_version, version, version_string)
			}
		}
	}

	// Check that the libcontainer execdriver is used.
	information, err := client.Info()
	if err != nil {
		return fmt.Errorf("failed to detect Docker info: %v", err)
	}
	usesNativeDriver := false
	for _, val := range *information {
		if strings.Contains(val, "ExecutionDriver=") && strings.Contains(val, "native") {
			usesNativeDriver = true
			break
		}
	}
	if !usesNativeDriver {
		return fmt.Errorf("Docker found, but not using native exec driver")
	}

	f := &dockerFactory{
		machineInfoFactory: factory,
		useSystemd:         systemd.UseSystemd(),
		client:             client,
	}
	if f.useSystemd {
		glog.Infof("System is using systemd")
	}
	glog.Infof("Registering Docker factory")
	container.RegisterContainerHandlerFactory(f)
	return nil
}
Beispiel #12
0
func toggle(state cgroups.FreezerState) error {
	container, err := loadConfig()
	if err != nil {
		return err
	}

	if systemd.UseSystemd() {
		err = systemd.Freeze(container.Cgroups, state)
	} else {
		err = fs.Freeze(container.Cgroups, state)
	}

	return err
}
Beispiel #13
0
func destroyAction(context *cli.Context) {
	config, err := getConfig(context)
	if err != nil {
		log.Fatal(err)
	}

	killAll(config)
	// Systemd will clean up cgroup state for empty container.
	if !systemd.UseSystemd() {
		err := fs.Cleanup(config)
		if err != nil {
			log.Fatal(err)
		}
	}
}
Beispiel #14
0
func setFreezerState(context *cli.Context, state cgroups.FreezerState) {
	config, err := getConfig(context)
	if err != nil {
		log.Fatal(err)
	}

	if systemd.UseSystemd() {
		err = systemd.Freeze(config, state)
	} else {
		err = fs.Freeze(config, state)
	}
	if err != nil {
		log.Fatal(err)
	}
}
Beispiel #15
0
func (d *driver) GetPidsForContainer(id string) ([]int, error) {
	d.Lock()
	active := d.activeContainers[id]
	d.Unlock()

	if active == nil {
		return nil, fmt.Errorf("active container for %s does not exist", id)
	}
	c := active.container.Cgroups

	if systemd.UseSystemd() {
		return systemd.GetPids(c)
	}
	return fs.GetPids(c)
}
Beispiel #16
0
func loadFactory(context *cli.Context) (libcontainer.Factory, error) {
	cgm := libcontainer.Cgroupfs
	if context.Bool("systemd") {
		if systemd.UseSystemd() {
			cgm = libcontainer.SystemdCgroups
		} else {
			logrus.Warn("systemd cgroup flag passed, but systemd support for managing cgroups is not available.")
		}
	}
	root := context.GlobalString("root")
	abs, err := filepath.Abs(root)
	if err != nil {
		return nil, err
	}
	return libcontainer.New(abs, cgm, func(l *libcontainer.LinuxFactory) error {
		l.CriuPath = context.GlobalString("criu")
		return nil
	})
}
Beispiel #17
0
// TODO(vmarmol): Complete Stats() in final libcontainer API and move users to that.
// DEPRECATED: The below portions are only to be used during the transition to the official API.
// Returns all available stats for the given container.
func GetStats(container *Config, state *State) (*ContainerStats, error) {
	var (
		err   error
		stats = &ContainerStats{}
	)

	if systemd.UseSystemd() {
		stats.CgroupStats, err = systemd.GetStats(container.Cgroups)
	} else {
		stats.CgroupStats, err = fs.GetStats(container.Cgroups)
	}

	if err != nil {
		return stats, err
	}

	stats.NetworkStats, err = network.GetStats(&state.NetworkState)

	return stats, err
}
Beispiel #18
0
func createAction(context *cli.Context) {
	config, err := getConfigFromFile(context)
	if err != nil {
		log.Fatal(err)
	}
	pid := context.Int("pid")
	if pid <= 0 {
		log.Fatal(fmt.Errorf("Invalid pid : %d", pid))
	}
	if systemd.UseSystemd() {
		_, err := systemd.Apply(config, pid)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		_, err := fs.Apply(config, pid)
		if err != nil {
			log.Fatal(err)
		}
	}
}
Beispiel #19
0
func NewDriver(root, initPath string, options []string) (*driver, error) {
	meminfo, err := sysinfo.ReadMemInfo()
	if err != nil {
		return nil, err
	}

	if err := sysinfo.MkdirAll(root, 0700); err != nil {
		return nil, err
	}
	// native driver root is at docker_root/execdriver/native. Put apparmor at docker_root
	if err := apparmor.InstallDefaultProfile(); err != nil {
		return nil, err
	}

	// choose cgroup manager
	// this makes sure there are no breaking changes to people
	// who upgrade from versions without native.cgroupdriver opt
	cgm := libcontainer.Cgroupfs
	if systemd.UseSystemd() {
		cgm = libcontainer.SystemdCgroups
	}

	// parse the options
	for _, option := range options {
		key, val, err := parsers.ParseKeyValueOpt(option)
		if err != nil {
			return nil, err
		}
		key = strings.ToLower(key)
		switch key {
		case "native.cgroupdriver":
			// override the default if they set options
			switch val {
			case "systemd":
				if systemd.UseSystemd() {
					cgm = libcontainer.SystemdCgroups
				} else {
					// warn them that they chose the wrong driver
					logrus.Warn("You cannot use systemd as native.cgroupdriver, using cgroupfs instead")
				}
			case "cgroupfs":
				cgm = libcontainer.Cgroupfs
			default:
				return nil, fmt.Errorf("Unknown native.cgroupdriver given %q. try cgroupfs or systemd", val)
			}
		default:
			return nil, fmt.Errorf("Unknown option %s\n", key)
		}
	}

	logrus.Debugf("Using %v as native.cgroupdriver", cgm)

	f, err := libcontainer.New(
		root,
		cgm,
		libcontainer.InitPath(reexec.Self(), DriverName),
	)
	if err != nil {
		return nil, err
	}

	return &driver{
		root:             root,
		initPath:         initPath,
		activeContainers: make(map[string]libcontainer.Container),
		machineMemory:    meminfo.MemTotal,
		factory:          f,
	}, nil
}
Beispiel #20
0
func init() {
	useSystemd = systemd.UseSystemd()
	if useSystemd {
		glog.Infof("System is using systemd")
	}
}
Beispiel #21
0
func TestRunWithKernelMemorySystemd(t *testing.T) {
	if !systemd.UseSystemd() {
		t.Skip("Systemd is unsupported")
	}
	testRunWithKernelMemory(t, true)
}
Beispiel #22
0
func TestCpuSharesSystemd(t *testing.T) {
	if !systemd.UseSystemd() {
		t.Skip("Systemd is unsupported")
	}
	testCpuShares(t, true)
}
Beispiel #23
0
func TestSystemdFreeze(t *testing.T) {
	if !systemd.UseSystemd() {
		t.Skip("Systemd is unsupported")
	}
	testFreeze(t, true)
}