Merge pull request #270 from ashahab-altiscale/raw-network-handler

Raw cgroup handler network support using external hints file
This commit is contained in:
Vish Kannan 2014-10-17 09:00:38 +02:00
commit 08d0aa41d6
5 changed files with 157 additions and 1 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
cadvisor
*.swp
*.idea
*.iml

View File

@ -0,0 +1,55 @@
// Copyright 2014 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.
// Unmarshal's a Containers description json file. The json file contains
// an array of ContainerHint structs, each with a container's id and networkInterface
// This allows collecting stats about network interfaces configured outside docker
// and lxc
package raw
import (
"encoding/json"
"flag"
"io/ioutil"
"os"
)
var argContainerHints = flag.String("container_hints", "/etc/cadvisor/container_hints.json", "container hints file")
type containerHints struct {
AllHosts []containerHint `json:"all_hosts,omitempty"`
}
type containerHint struct {
FullName string `json:"full_path,omitempty"`
NetworkInterface *networkInterface `json:"network_interface,omitempty"`
}
type networkInterface struct {
VethHost string `json:"veth_host,omitempty"`
VethChild string `json:"veth_child,omitempty"`
}
func getContainerHintsFromFile(containerHintsFile string) (containerHints, error) {
dat, err := ioutil.ReadFile(containerHintsFile)
if os.IsNotExist(err) {
return containerHints{}, nil
}
var cHints containerHints
if err == nil {
err = json.Unmarshal(dat, &cHints)
}
return cHints, err
}

View File

@ -0,0 +1,28 @@
package raw
import (
"testing"
)
func TestGetContainerHintsFromFile(t *testing.T) {
cHints, err := getContainerHintsFromFile("test_resources/container_hints.json")
if err != nil {
t.Fatalf("Error in unmarshalling: %s", err)
}
if cHints.AllHosts[0].NetworkInterface.VethHost != "veth24031eth1" &&
cHints.AllHosts[0].NetworkInterface.VethChild != "eth1" {
t.Errorf("Cannot find network interface in %s", cHints)
}
}
func TestFileNotExist(t *testing.T) {
cHints, err := getContainerHintsFromFile("/file_does_not_exist.json")
if err != nil {
t.Fatalf("getContainerHintsFromFile must not error for blank file: %s", err)
}
for _, container := range cHints.AllHosts {
t.Logf("Container: %s", container)
}
}

View File

@ -23,8 +23,10 @@ import (
"strings"
"code.google.com/p/go.exp/inotify"
dockerlibcontainer "github.com/docker/libcontainer"
"github.com/docker/libcontainer/cgroups"
cgroup_fs "github.com/docker/libcontainer/cgroups/fs"
"github.com/docker/libcontainer/network"
"github.com/golang/glog"
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/container/libcontainer"
@ -42,6 +44,7 @@ type rawContainerHandler struct {
stopWatcher chan error
watches map[string]struct{}
fsInfo fs.FsInfo
networkInterface *networkInterface
}
func newRawContainerHandler(name string, cgroupSubsystems *cgroupSubsystems, machineInfoFactory info.MachineInfoFactory) (container.ContainerHandler, error) {
@ -49,6 +52,17 @@ func newRawContainerHandler(name string, cgroupSubsystems *cgroupSubsystems, mac
if err != nil {
return nil, err
}
cHints, err := getContainerHintsFromFile(*argContainerHints)
if err != nil {
return nil, err
}
var networkInterface *networkInterface
for _, container := range cHints.AllHosts {
if name == container.FullName {
networkInterface = container.NetworkInterface
break
}
}
return &rawContainerHandler{
name: name,
cgroup: &cgroups.Cgroup{
@ -60,6 +74,7 @@ func newRawContainerHandler(name string, cgroupSubsystems *cgroupSubsystems, mac
stopWatcher: make(chan error),
watches: make(map[string]struct{}),
fsInfo: fsInfo,
networkInterface: networkInterface,
}, nil
}
@ -152,11 +167,27 @@ func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
if self.name == "/" {
spec.HasFilesystem = true
}
//Network
if self.networkInterface != nil {
spec.HasNetwork = true
}
return spec, nil
}
func (self *rawContainerHandler) GetStats() (*info.ContainerStats, error) {
stats, err := libcontainer.GetStatsCgroupOnly(self.cgroup)
state := dockerlibcontainer.State{}
if self.networkInterface != nil {
state = dockerlibcontainer.State{
NetworkState: network.NetworkState{
VethHost: self.networkInterface.VethHost,
VethChild: self.networkInterface.VethChild,
NsPath: "unknown",
},
}
}
stats, err := libcontainer.GetStats(self.cgroup, &state)
if err != nil {
return nil, err
}

View File

@ -0,0 +1,40 @@
{
"name": "Container Hints",
"description": "Container hints file",
"all_hosts": [
{
"network_interface": {
"veth_child": "eth1",
"veth_host": "veth24031eth1"
},
"mounts": [
{
"host-dir": "/var/run/nm-sdc1",
"container-dir": "/var/run/nm-sdc1",
"permission": "rw"
},
{
"host-dir": "/var/run/nm-sdb3",
"container-dir": "/var/run/nm-sdb3",
"permission": "rw"
},
{
"host-dir": "/var/run/nm-sda3",
"container-dir": "/var/run/nm-sda3",
"permission": "rw"
},
{
"host-dir": "/var/run/netns/root",
"container-dir": "/var/run/netns/root",
"permission": "ro"
},
{
"host-dir": "/var/run/openvswitch/db.sock",
"container-dir": "/var/run/openvswitch/db.sock",
"permission": "rw"
}
],
"full_path": "18a4585950db428e4d5a65c216a5d708d241254709626f4cb300ee963fb4b144"
}
]
}