diff --git a/api.go b/api.go index 481c9a56..36fc2199 100644 --- a/api.go +++ b/api.go @@ -6,14 +6,14 @@ import ( ) // Returns all available stats for the given container. -func GetContainerStats(container *Config, runtimeCkpt *RuntimeCkpt) (*ContainerStats, error) { +func GetContainerStats(container *Config, state *State) (*ContainerStats, error) { containerStats := NewContainerStats() stats, err := fs.GetStats(container.Cgroups) if err != nil { return containerStats, err } containerStats.CgroupStats = stats - networkStats, err := network.GetStats(&runtimeCkpt.NetworkCkpt) + networkStats, err := network.GetStats(&state.NetworkState) if err != nil { return containerStats, err } diff --git a/checkpoint.go b/checkpoint.go deleted file mode 100644 index 9baae65f..00000000 --- a/checkpoint.go +++ /dev/null @@ -1,65 +0,0 @@ -package libcontainer - -import ( - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - - "github.com/docker/libcontainer/network" -) - -// A checkpoint struct that will contain all runtime checkpointed information. -type RuntimeCkpt struct { - NetworkCkpt network.NetworkCkpt `json:"network_ckpt,omitempty"` -} - -// The name of the network checkpoint file -const runtimeCkptFile = "runtimeCkpt.json" - -var ErrRuntimeCkptNotFound = errors.New("Runtime Checkpoint not found") - -// Returns the path to the network checkpoint given the path to the base directory of network checkpoint. -func getRuntimeCkptPath(basePath string) string { - return filepath.Join(basePath, runtimeCkptFile) -} - -// Updates the Runtime Checkpoint with current checkpoint information from all the subsystems. -func UpdateRuntimeCkpt(basePath string) error { - runtimeCkpt := &RuntimeCkpt{ - NetworkCkpt: *network.NetworkCkptImpl.GetNetworkCkpt(), - } - data, err := json.Marshal(runtimeCkpt) - if err != nil { - return fmt.Errorf("Failed to checkpoint runtime information - %s", err) - } - return ioutil.WriteFile(getRuntimeCkptPath(basePath), data, 0655) -} - -// Loads and returns the rutime checkpointing existing inside basePath. Returns ErrRuntimeCkptNotFound -// if the runtime checkpoint does not exist. -func GetRuntimeCkpt(basePath string) (*RuntimeCkpt, error) { - runtimeCkpt := &RuntimeCkpt{} - checkpointPath := getRuntimeCkptPath(basePath) - f, err := os.Open(checkpointPath) - if err != nil { - if os.IsNotExist(err) { - return runtimeCkpt, ErrRuntimeCkptNotFound - } - return runtimeCkpt, err - } - defer f.Close() - - if err := json.NewDecoder(f).Decode(runtimeCkpt); err != nil { - return runtimeCkpt, err - } - - return runtimeCkpt, nil -} - -// Deletes the runtime checkpoint under basePath -func DeleteNetworkRuntimeInfo(basePath string) error { - return os.Remove(getRuntimeCkptPath(basePath)) -} diff --git a/namespaces/exec.go b/namespaces/exec.go index 4e5d2677..e5e2575d 100644 --- a/namespaces/exec.go +++ b/namespaces/exec.go @@ -57,18 +57,6 @@ func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string return -1, err } - state := &libcontainer.State{ - InitPid: command.Process.Pid, - InitStartTime: started, - } - - if err := libcontainer.SaveState(dataPath, state); err != nil { - command.Process.Kill() - command.Wait() - return -1, err - } - defer libcontainer.DeleteState(dataPath) - // Do this before syncing with child so that no children // can escape the cgroup cleaner, err := SetupCgroups(container, command.Process.Pid) @@ -87,12 +75,18 @@ func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string return -1, err } - // Update the runtime checkpoint. - if err = libcontainer.UpdateRuntimeCkpt(dataPath); err != nil { + state := &libcontainer.State{ + InitPid: command.Process.Pid, + InitStartTime: started, + NetworkState: *network.NetworkStateImpl.GetNetworkState(), + } + + if err := libcontainer.SaveState(dataPath, state); err != nil { command.Process.Kill() command.Wait() return -1, err } + defer libcontainer.DeleteState(dataPath) // Sync with child syncPipe.Close() diff --git a/network/checkpoint.go b/network/checkpoint.go deleted file mode 100644 index f9f9c3a1..00000000 --- a/network/checkpoint.go +++ /dev/null @@ -1,25 +0,0 @@ -package network - -// Struct describing the network specific checkpoint that will be maintained by libcontainer for all running containers -// This is an internal checkpoint, so do not depend on it outside of libcontainer. -type NetworkCkpt struct { - // The name of the veth interface on the Host. - VethHost string `json:"veth_host,omitempty"` - // The name of the veth interface created inside the container for the child. - VethChild string `json:"veth_child,omitempty"` -} - -type NetworkCkptIntImpl struct{} - -var ( - networkCkptInfo = &NetworkCkpt{} - NetworkCkptImpl = &NetworkCkptIntImpl{} -) - -func (NetworkCkptIntImpl) GetNetworkCkpt() *NetworkCkpt { - return networkCkptInfo -} - -func (NetworkCkptIntImpl) updateNetworkCkpt(n *NetworkCkpt) { - networkCkptInfo = n -} diff --git a/network/state.go b/network/state.go new file mode 100644 index 00000000..71ee012e --- /dev/null +++ b/network/state.go @@ -0,0 +1,25 @@ +package network + +// Struct describing the network specific runtime state that will be maintained by libcontainer for all running containers +// Do not depend on it outside of libcontainer. +type NetworkState struct { + // The name of the veth interface on the Host. + VethHost string `json:"veth_host,omitempty"` + // The name of the veth interface created inside the container for the child. + VethChild string `json:"veth_child,omitempty"` +} + +type networkStateIntImpl struct{} + +var ( + networkState = &NetworkState{} + NetworkStateImpl = &networkStateIntImpl{} +) + +func (networkStateIntImpl) GetNetworkState() *NetworkState { + return networkState +} + +func (networkStateIntImpl) updateNetworkState(n *NetworkState) { + networkState = n +} diff --git a/network/stats.go b/network/stats.go index 3481100f..37fc6a27 100644 --- a/network/stats.go +++ b/network/stats.go @@ -20,12 +20,12 @@ type NetworkStats struct { } // Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo. -func GetStats(networkCkpt *NetworkCkpt) (NetworkStats, error) { +func GetStats(networkState *NetworkState) (NetworkStats, error) { // This can happen if the network runtime information is missing - possible if the container was created by an old version of libcontainer. - if networkCkpt.VethHost == "" { + if networkState.VethHost == "" { return NetworkStats{}, nil } - data, err := readSysfsNetworkStats(networkCkpt.VethHost) + data, err := readSysfsNetworkStats(networkState.VethHost) if err != nil { return NetworkStats{}, err } diff --git a/network/veth.go b/network/veth.go index 94b0d3ce..e2167a52 100644 --- a/network/veth.go +++ b/network/veth.go @@ -45,10 +45,10 @@ func (v *Veth) Create(n *Network, nspid int, context map[string]string, dataPath if err := SetInterfaceInNamespacePid(name2, nspid); err != nil { return err } - networkCkpt := NetworkCkptImpl.GetNetworkCkpt() - networkCkpt.VethHost = name1 - networkCkpt.VethChild = name2 - NetworkCkptImpl.updateNetworkCkpt(networkCkpt) + networkState := NetworkStateImpl.GetNetworkState() + networkState.VethHost = name1 + networkState.VethChild = name2 + NetworkStateImpl.updateNetworkState(networkState) return nil } diff --git a/nsinit/stats.go b/nsinit/stats.go index 6554cb11..5a90b599 100644 --- a/nsinit/stats.go +++ b/nsinit/stats.go @@ -21,7 +21,7 @@ func statsAction(context *cli.Context) { log.Fatal(err) } - runtimeCkpt, err := libcontainer.GetRuntimeCkpt(dataPath) + runtimeCkpt, err := libcontainer.GetState(dataPath) if err != nil { log.Fatal(err) } @@ -35,8 +35,8 @@ func statsAction(context *cli.Context) { } // returns the container stats in json format. -func getContainerStats(container *libcontainer.Config, runtimeCkpt *libcontainer.RuntimeCkpt) (string, error) { - stats, err := libcontainer.GetContainerStats(container, runtimeCkpt) +func getContainerStats(container *libcontainer.Config, state *libcontainer.State) (string, error) { + stats, err := libcontainer.GetContainerStats(container, state) if err != nil { return "", err } diff --git a/state.go b/state.go index b60b901c..a055bb0f 100644 --- a/state.go +++ b/state.go @@ -4,6 +4,8 @@ import ( "encoding/json" "os" "path/filepath" + + "github.com/docker/libcontainer/network" ) // State represents a running container's state @@ -12,12 +14,17 @@ type State struct { InitPid int `json:"init_pid,omitempty"` // InitStartTime is the init process start time InitStartTime string `json:"init_start_time,omitempty"` + // Network runtime state. + NetworkState network.NetworkState `json:"network_state,omitempty"` } +// The name of the runtime state file +const stateFile = "state.json" + // SaveState writes the container's runtime state to a state.json file // in the specified path func SaveState(basePath string, state *State) error { - f, err := os.Create(filepath.Join(basePath, "state.json")) + f, err := os.Create(filepath.Join(basePath, stateFile)) if err != nil { return err } @@ -28,7 +35,7 @@ func SaveState(basePath string, state *State) error { // GetState reads the state.json file for a running container func GetState(basePath string) (*State, error) { - f, err := os.Open(filepath.Join(basePath, "state.json")) + f, err := os.Open(filepath.Join(basePath, stateFile)) if err != nil { return nil, err } @@ -44,5 +51,5 @@ func GetState(basePath string) (*State, error) { // DeleteState deletes the state.json file func DeleteState(basePath string) error { - return os.Remove(filepath.Join(basePath, "state.json")) + return os.Remove(filepath.Join(basePath, stateFile)) }