Created a global runtime checkpoint for libcontainer. Got rid of the network specific runtime checkpoint.

Docker-DCO-1.1-Signed-off-by: Vishnu Kannan <vishnuk@google.com> (github: vishh)
This commit is contained in:
Vishnu Kannan 2014-06-24 21:34:09 +00:00
parent 9253412ee1
commit 481552c02b
9 changed files with 98 additions and 77 deletions

View File

@ -1,21 +1,19 @@
package api
package libcontainer
import (
"github.com/docker/libcontainer"
"github.com/docker/libcontainer/cgroups/fs"
"github.com/docker/libcontainer/network"
)
// Returns all available stats for the given container.
func GetContainerStats(container *libcontainer.Container, networkInfo *network.NetworkRuntimeInfo) (*ContainerStats, error) {
func GetContainerStats(container *Config, runtimeCkpt *RuntimeCkpt) (*ContainerStats, error) {
containerStats := NewContainerStats()
stats, err := fs.GetStats(container.Cgroups)
if err != nil {
return containerStats, err
}
containerStats.CgroupStats = stats
networkStats, err := network.GetStats(networkInfo)
networkStats, err := network.GetStats(&runtimeCkpt.NetworkCkpt)
if err != nil {
return containerStats, err
}

65
checkpoint.go Normal file
View File

@ -0,0 +1,65 @@
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))
}

View File

@ -87,6 +87,13 @@ func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string
return -1, err
}
// Update the runtime checkpoint.
if err = libcontainer.UpdateRuntimeCkpt(dataPath); err != nil {
command.Process.Kill()
command.Wait()
return -1, err
}
// Sync with child
syncPipe.Close()

View File

@ -1,63 +1,25 @@
package network
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
)
// 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 NetworkRuntimeInfo struct {
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"`
}
// The name of the network checkpoint file
const networkInfoFile = "network.json"
type NetworkCkptIntImpl struct{}
var ErrNetworkRuntimeInfoNotFound = errors.New("Network Checkpoint not found")
var (
networkCkptInfo = &NetworkCkpt{}
NetworkCkptImpl = &NetworkCkptIntImpl{}
)
// Returns the path to the network checkpoint given the path to the base directory of network checkpoint.
func getNetworkRuntimeInfoPath(basePath string) string {
return filepath.Join(basePath, networkInfoFile)
func (NetworkCkptIntImpl) GetNetworkCkpt() *NetworkCkpt {
return networkCkptInfo
}
// Marshalls the input network runtime info struct into a json object and stores it inside basepath.
func writeNetworkRuntimeInfo(networkInfo *NetworkRuntimeInfo, basePath string) error {
data, err := json.Marshal(networkInfo)
if err != nil {
return fmt.Errorf("Failed to checkpoint network runtime information - %s", err)
}
return ioutil.WriteFile(getNetworkRuntimeInfoPath(basePath), data, 0655)
}
// Loads the network runtime info from the checkpoint and returns the unmarshaled content.
func LoadNetworkRuntimeInfo(basePath string) (NetworkRuntimeInfo, error) {
var networkRuntimeInfo NetworkRuntimeInfo
checkpointPath := getNetworkRuntimeInfoPath(basePath)
f, err := os.Open(checkpointPath)
if err != nil {
if os.IsNotExist(err) {
return networkRuntimeInfo, ErrNetworkRuntimeInfoNotFound
}
return networkRuntimeInfo, err
}
defer f.Close()
if err := json.NewDecoder(f).Decode(&networkRuntimeInfo); err != nil {
return networkRuntimeInfo, err
}
return networkRuntimeInfo, nil
}
// Deletes the network checkpoint under basePath
func deleteNetworkRuntimeInfo(basePath string) error {
return os.Remove(getNetworkRuntimeInfoPath(basePath))
func (NetworkCkptIntImpl) updateNetworkCkpt(n *NetworkCkpt) {
networkCkptInfo = n
}

View File

@ -20,12 +20,12 @@ type NetworkStats struct {
}
// Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo.
func GetStats(networkRuntimeInfo *NetworkRuntimeInfo) (NetworkStats, error) {
func GetStats(networkCkpt *NetworkCkpt) (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 networkRuntimeInfo.VethHost == "" {
if networkCkpt.VethHost == "" {
return NetworkStats{}, nil
}
data, err := readSysfsNetworkStats(networkRuntimeInfo.VethHost)
data, err := readSysfsNetworkStats(networkCkpt.VethHost)
if err != nil {
return NetworkStats{}, err
}

View File

@ -45,8 +45,11 @@ func (v *Veth) Create(n *Network, nspid int, context map[string]string, dataPath
if err := SetInterfaceInNamespacePid(name2, nspid); err != nil {
return err
}
networkRuntimeInfo := NetworkRuntimeInfo{VethHost: name1, VethChild: name2}
return writeNetworkRuntimeInfo(&networkRuntimeInfo, dataPath)
networkCkpt := NetworkCkptImpl.GetNetworkCkpt()
networkCkpt.VethHost = name1
networkCkpt.VethChild = name2
NetworkCkptImpl.updateNetworkCkpt(networkCkpt)
return nil
}
func (v *Veth) Initialize(config *Network, context map[string]string) error {

View File

@ -7,8 +7,6 @@ import (
"github.com/codegangsta/cli"
"github.com/docker/libcontainer"
"github.com/docker/libcontainer/api"
"github.com/docker/libcontainer/network"
)
var statsCommand = cli.Command{
@ -23,12 +21,12 @@ func statsAction(context *cli.Context) {
log.Fatal(err)
}
networkRuntimeInfo, err := loadNetworkRuntimeInfo()
runtimeCkpt, err := libcontainer.GetRuntimeCkpt(dataPath)
if err != nil {
log.Fatal(err)
}
stats, err := getContainerStats(container, &networkRuntimeInfo)
stats, err := getContainerStats(container, runtimeCkpt)
if err != nil {
log.Fatalf("Failed to get stats - %v\n", err)
}
@ -37,8 +35,8 @@ func statsAction(context *cli.Context) {
}
// returns the container stats in json format.
func getContainerStats(container *libcontainer.Config, networkRuntimeInfo *network.NetworkRuntimeInfo) (string, error) {
stats, err := libcontainer.GetContainerStats(container, networkRuntimeInfo)
func getContainerStats(container *libcontainer.Config, runtimeCkpt *libcontainer.RuntimeCkpt) (string, error) {
stats, err := libcontainer.GetContainerStats(container, runtimeCkpt)
if err != nil {
return "", err
}

View File

@ -7,7 +7,6 @@ import (
"path/filepath"
"github.com/docker/libcontainer"
"github.com/docker/libcontainer/network"
)
func loadContainer() (*libcontainer.Config, error) {
@ -25,17 +24,6 @@ func loadContainer() (*libcontainer.Config, error) {
return container, nil
}
func loadNetworkRuntimeInfo() (network.NetworkRuntimeInfo, error) {
data, err := network.LoadNetworkRuntimeInfo(dataPath)
if err != nil {
if err == network.ErrNetworkRuntimeInfoNotFound {
return network.NetworkRuntimeInfo{}, nil
}
return network.NetworkRuntimeInfo{}, err
}
return data, nil
}
func openLog(name string) error {
f, err := os.OpenFile(name, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0755)
if err != nil {

View File

@ -1,4 +1,4 @@
package api
package libcontainer
import (
"github.com/docker/libcontainer/cgroups"