func convertOldConfigToNew(config v1Config) *configs.Config { var ( result configs.Config old *v1Cgroup = config.Cgroup ) result.Rootfs = config.Config.Rootfs result.Hostname = config.Config.Hostname result.Namespaces = config.Config.Namespaces result.Capabilities = config.Config.Capabilities result.Networks = config.Config.Networks result.Routes = config.Config.Routes var newCgroup = &configs.Cgroup{ Name: old.Name, Parent: old.Parent, Resources: &configs.Resources{ AllowAllDevices: old.Resources.AllowAllDevices, AllowedDevices: old.Resources.AllowedDevices, DeniedDevices: old.Resources.DeniedDevices, Memory: old.Resources.Memory, MemoryReservation: old.Resources.MemoryReservation, MemorySwap: old.Resources.MemorySwap, KernelMemory: old.Resources.KernelMemory, CpuShares: old.Resources.CpuShares, CpuQuota: old.Resources.CpuQuota, CpuPeriod: old.Resources.CpuPeriod, CpuRtRuntime: old.Resources.CpuRtRuntime, CpuRtPeriod: old.Resources.CpuRtPeriod, CpusetCpus: old.Resources.CpusetCpus, CpusetMems: old.Resources.CpusetMems, BlkioWeight: old.Resources.BlkioWeight, BlkioLeafWeight: old.Resources.BlkioLeafWeight, Freezer: old.Resources.Freezer, HugetlbLimit: old.Resources.HugetlbLimit, OomKillDisable: old.Resources.OomKillDisable, MemorySwappiness: old.Resources.MemorySwappiness, NetPrioIfpriomap: old.Resources.NetPrioIfpriomap, NetClsClassid: old.Resources.NetClsClassid, }, } result.Cgroups = newCgroup return &result }
func runContainer(name string, args []string, wd string, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { var err error var id string id = path.Base(wd) // mount base rootfs with working directory rootfs := master_config.Rootfs lowerdir := rootfs upperdir, err := filepath.Abs(wd) if err != nil { return err } workdir, err := filepath.Abs(fmt.Sprintf("%s-%s", wd, "work")) if err != nil { return err } err = os.Mkdir(workdir, 0775) if err != nil && !os.IsExist(err) { return err } defer os.RemoveAll(workdir) opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerdir, upperdir, workdir) err = syscall.Mount("overlay", upperdir, "overlay", syscall.MS_MGC_VAL, opts) if err != nil { return err } defer func() { err := syscall.Unmount(upperdir, 0) if err != nil { return } }() // set cgroup path var config configs.Config config = *master_config config.Cgroups.Path = fmt.Sprintf("%s/%s", config.Cgroups.Path, id) config.Rootfs = upperdir container, err := factory.Create(id, &config) if err != nil { return err } defer container.Destroy() args = append([]string{name}, args...) process := &libcontainer.Process{ Args: args, Env: []string{"PATH=/bin:/sbin:/usr/bin:/usr/sbin"}, User: "******", Stdin: stdin, Stdout: stdout, Stderr: stderr, } err = container.Run(process) if err != nil { return err } _, err = process.Wait() if err != nil { return err } return nil }
// TODO(vmarmol): Deprecate over time as old Dockers are phased out. func ReadConfig(dockerRoot, dockerRun, containerID string) (*configs.Config, error) { // Try using the new config if it is available. configPath := configPath(dockerRun, containerID) if utils.FileExists(configPath) { out, err := ioutil.ReadFile(configPath) if err != nil { return nil, err } var state libcontainer.State if err = json.Unmarshal(out, &state); err != nil { if _, ok := err.(*json.UnmarshalTypeError); ok { // Since some fields changes in Cgroup struct, it will be failed while unmarshalling to libcontainer.State struct. // This failure is caused by a change of runc(https://github.com/opencontainers/runc/commit/c6e406af243fab0c9636539c1cb5f4d60fe0787f). // If we encountered the UnmarshalTypeError, try to unmarshal it again to v1State struct and convert it. var state v1State err2 := json.Unmarshal(out, &state) if err2 != nil { return nil, err } return convertOldConfigToNew(state.Config), nil } else { return nil, err } } return &state.Config, nil } // Fallback to reading the old config which is comprised of the state and config files. oldConfigPath := oldConfigPath(dockerRoot, containerID) out, err := ioutil.ReadFile(oldConfigPath) if err != nil { return nil, err } // Try reading the preAPIConfig. var config preAPIConfig err = json.Unmarshal(out, &config) if err != nil { // Try to parse the old pre-API config. The main difference is that namespaces used to be a map, now it is a slice of structs. // The JSON marshaler will use the non-nested field before the nested one. type oldLibcontainerConfig struct { preAPIConfig OldNamespaces map[string]bool `json:"namespaces,omitempty"` } var oldConfig oldLibcontainerConfig err2 := json.Unmarshal(out, &oldConfig) if err2 != nil { // Use original error. return nil, err } // Translate the old pre-API config into the new config. config = oldConfig.preAPIConfig for ns := range oldConfig.OldNamespaces { config.Namespaces = append(config.Namespaces, configs.Namespace{ Type: configs.NamespaceType(ns), }) } } // Read the old state file as well. state, err := readState(dockerRoot, containerID) if err != nil { return nil, err } // Convert preAPIConfig + old state file to Config. // This only converts some of the fields, the ones we use. // You may need to add fields if the one you're interested in is not available. var result configs.Config result.Cgroups = new(configs.Cgroup) result.Rootfs = config.RootFs result.Hostname = config.Hostname result.Namespaces = config.Namespaces result.Capabilities = config.Capabilities for _, net := range config.Networks { n := &configs.Network{ Name: state.NetworkState.VethChild, Bridge: net.Bridge, MacAddress: net.MacAddress, Address: net.Address, Gateway: net.Gateway, IPv6Address: net.IPv6Address, IPv6Gateway: net.IPv6Gateway, HostInterfaceName: state.NetworkState.VethHost, } result.Networks = append(result.Networks, n) } result.Routes = config.Routes if config.Cgroups != nil { result.Cgroups = config.Cgroups } return &result, nil }