Merge pull request #990 from carmark/old_config

fix unmarshal container config failure with Docker 1.8.3
This commit is contained in:
Jimmi Dyson 2015-12-02 08:40:55 +00:00
commit 8df37ece9b
4 changed files with 151 additions and 3 deletions

View File

@ -144,6 +144,40 @@ type preAPINetwork struct {
TxQueueLen int `json:"txqueuelen,omitempty"`
}
type v1Cgroup struct {
configs.Cgroup
// Weight per cgroup per device, can override BlkioWeight.
BlkioWeightDevice string `json:"blkio_weight_device"`
// IO read rate limit per cgroup per device, bytes per second.
BlkioThrottleReadBpsDevice string `json:"blkio_throttle_read_bps_device"`
// IO write rate limit per cgroup per divice, bytes per second.
BlkioThrottleWriteBpsDevice string `json:"blkio_throttle_write_bps_device"`
// IO read rate limit per cgroup per device, IO per second.
BlkioThrottleReadIOPSDevice string `json:"blkio_throttle_read_iops_device"`
// IO write rate limit per cgroup per device, IO per second.
BlkioThrottleWriteIOPSDevice string `json:"blkio_throttle_write_iops_device"`
}
type v1Config struct {
configs.Config
// Cgroups specifies specific cgroup settings for the various subsystems that the container is
// placed into to limit the resources the container has available
Cgroup *v1Cgroup `json:"cgroups"`
}
// State represents a running container's state
type v1State struct {
libcontainer.State
// Config is the container's configuration.
Config v1Config `json:"config"`
}
// Relative path to the libcontainer execdriver directory.
const libcontainerExecDriverPath = "execdriver/native"
@ -158,9 +192,20 @@ func ReadConfig(dockerRoot, dockerRun, containerID string) (*configs.Config, err
}
var state libcontainer.State
err = json.Unmarshal(out, &state)
if err != nil {
return nil, err
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
}
@ -234,6 +279,51 @@ func ReadConfig(dockerRoot, dockerRun, containerID string) (*configs.Config, err
return &result, nil
}
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,
AllowAllDevices: old.AllowAllDevices,
AllowedDevices: old.AllowedDevices,
DeniedDevices: old.DeniedDevices,
Memory: old.Memory,
MemoryReservation: old.MemoryReservation,
MemorySwap: old.MemorySwap,
KernelMemory: old.KernelMemory,
CpuShares: old.CpuShares,
CpuQuota: old.CpuQuota,
CpuPeriod: old.CpuPeriod,
CpuRtRuntime: old.CpuRtRuntime,
CpuRtPeriod: old.CpuRtPeriod,
CpusetCpus: old.CpusetCpus,
CpusetMems: old.CpusetMems,
BlkioWeight: old.BlkioWeight,
BlkioLeafWeight: old.BlkioLeafWeight,
Freezer: old.Freezer,
HugetlbLimit: old.HugetlbLimit,
Slice: old.Slice,
OomKillDisable: old.OomKillDisable,
MemorySwappiness: old.MemorySwappiness,
NetPrioIfpriomap: old.NetPrioIfpriomap,
NetClsClassid: old.NetClsClassid,
}
result.Cgroups = newCgroup
return &result
}
func readState(dockerRoot, containerID string) (preAPIState, error) {
// pre-API libcontainer changed how its state was stored, try the old way of a "pid" file
statePath := path.Join(dockerRoot, libcontainerExecDriverPath, containerID, "state.json")

View File

@ -0,0 +1,56 @@
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package libcontainer
import (
"path/filepath"
"testing"
)
func TestReadConfig(t *testing.T) {
var (
testdata string = "testdata"
containerID string = "1"
)
// Test with using the new config of docker v1.9.0
dockerRoot := filepath.Join(testdata, "docker-v1.9.1")
dockerRun := filepath.Join(testdata, "docker-v1.9.1")
config, err := ReadConfig(dockerRoot, dockerRun, containerID)
if err != nil {
t.Error(err)
}
if config.Hostname != containerID {
t.Errorf("Expected container hostname is %s, but got %s", containerID, config.Hostname)
}
// Test with using the pre config of docker v1.8.3
dockerRoot = filepath.Join(testdata, "docker-v1.8.3")
dockerRun = filepath.Join(testdata, "docker-v1.8.3")
config, err = ReadConfig(dockerRoot, dockerRun, containerID)
if err != nil {
t.Error(err)
}
if config.Hostname != containerID {
t.Errorf("Expected container hostname is %s, but got %s", containerID, config.Hostname)
}
// Test with using non-existed old config, return an error
dockerRoot = filepath.Join(testdata, "docker-v1.8.0")
dockerRun = filepath.Join(testdata, "docker-v1.8.0")
config, err = ReadConfig(dockerRoot, dockerRun, containerID)
if err == nil {
t.Error("Expected an error, but got nil")
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long