Expose multiple network interfaces in API.

Part of #686
This commit is contained in:
Victor Marmol 2015-06-04 10:58:32 -07:00
parent 48f14dcde6
commit b923eff11c
8 changed files with 82 additions and 44 deletions

View File

@ -426,8 +426,7 @@ func convertStats(cont *info.ContainerInfo) []v2.ContainerStats {
stat.Memory = val.Memory
}
if stat.HasNetwork {
// TODO(rjnagal): Return stats about all network interfaces.
stat.Network = append(stat.Network, val.Network)
stat.Network.Interfaces = val.Network.Interfaces
}
if stat.HasFilesystem {
stat.Filesystem = val.Filesystem

View File

@ -261,17 +261,10 @@ func (self *dockerContainerHandler) GetStats() (*info.ContainerStats, error) {
}
// TODO(rjnagal): Remove the conversion when network stats are read from libcontainer.
net := stats.Network
// Ingress for host veth is from the container.
// Hence tx_bytes stat on the host veth is actually number of bytes received by the container.
stats.Network.RxBytes = net.TxBytes
stats.Network.RxPackets = net.TxPackets
stats.Network.RxErrors = net.TxErrors
stats.Network.RxDropped = net.TxDropped
stats.Network.TxBytes = net.RxBytes
stats.Network.TxPackets = net.RxPackets
stats.Network.TxErrors = net.RxErrors
stats.Network.TxDropped = net.RxDropped
convertInterfaceStats(&stats.Network.InterfaceStats)
for i := range stats.Network.Interfaces {
convertInterfaceStats(&stats.Network.Interfaces[i])
}
// Get filesystem stats.
err = self.getFsStats(stats)
@ -282,6 +275,21 @@ func (self *dockerContainerHandler) GetStats() (*info.ContainerStats, error) {
return stats, nil
}
func convertInterfaceStats(stats *info.InterfaceStats) {
net := stats
// Ingress for host veth is from the container.
// Hence tx_bytes stat on the host veth is actually number of bytes received by the container.
stats.RxBytes = net.TxBytes
stats.RxPackets = net.TxPackets
stats.RxErrors = net.TxErrors
stats.RxDropped = net.TxDropped
stats.TxBytes = net.RxBytes
stats.TxPackets = net.RxPackets
stats.TxErrors = net.RxErrors
stats.TxDropped = net.RxDropped
}
func (self *dockerContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
if self.name != "/docker" {
return []info.ContainerReference{}, nil

View File

@ -84,15 +84,20 @@ func GetStats(cgroupManager cgroups.Manager, networkInterfaces []string) (*info.
}
stats := toContainerStats(libcontainerStats)
if len(networkInterfaces) != 0 {
// ContainerStats only reports stat for one network device.
// TODO(rjnagal): Handle multiple physical network devices.
// TODO(rjnagal): Use networking stats directly from libcontainer.
stats.Network, err = sysinfo.GetNetworkStats(networkInterfaces[0])
// TODO(rjnagal): Use networking stats directly from libcontainer.
stats.Network.Interfaces = make([]info.InterfaceStats, len(networkInterfaces))
for i := range networkInterfaces {
interfaceStats, err := sysinfo.GetNetworkStats(networkInterfaces[i])
if err != nil {
return stats, err
}
stats.Network.Interfaces[i] = interfaceStats
}
// For backwards compatability.
if len(networkInterfaces) > 0 {
stats.Network.InterfaceStats = stats.Network.Interfaces[0]
}
return stats, nil
}
@ -213,15 +218,25 @@ func toContainerStats2(s *cgroups.Stats, ret *info.ContainerStats) {
}
func toContainerStats3(libcontainerStats *libcontainer.Stats, ret *info.ContainerStats) {
// TODO(vmarmol): Handle multiple interfaces.
ret.Network.RxBytes = libcontainerStats.Interfaces[0].RxBytes
ret.Network.RxPackets = libcontainerStats.Interfaces[0].RxPackets
ret.Network.RxErrors = libcontainerStats.Interfaces[0].RxErrors
ret.Network.RxDropped = libcontainerStats.Interfaces[0].RxDropped
ret.Network.TxBytes = libcontainerStats.Interfaces[0].TxBytes
ret.Network.TxPackets = libcontainerStats.Interfaces[0].TxPackets
ret.Network.TxErrors = libcontainerStats.Interfaces[0].TxErrors
ret.Network.TxDropped = libcontainerStats.Interfaces[0].TxDropped
ret.Network.Interfaces = make([]info.InterfaceStats, len(libcontainerStats.Interfaces))
for i := range libcontainerStats.Interfaces {
ret.Network.Interfaces[i] = info.InterfaceStats{
Name: libcontainerStats.Interfaces[i].Name,
RxBytes: libcontainerStats.Interfaces[i].RxBytes,
RxPackets: libcontainerStats.Interfaces[i].RxPackets,
RxErrors: libcontainerStats.Interfaces[i].RxErrors,
RxDropped: libcontainerStats.Interfaces[i].RxDropped,
TxBytes: libcontainerStats.Interfaces[i].TxBytes,
TxPackets: libcontainerStats.Interfaces[i].TxPackets,
TxErrors: libcontainerStats.Interfaces[i].TxErrors,
TxDropped: libcontainerStats.Interfaces[i].TxDropped,
}
}
// Add to base struct for backwards compatability.
if len(ret.Network.Interfaces) > 0 {
ret.Network.InterfaceStats = ret.Network.Interfaces[0]
}
}
func toContainerStats(libcontainerStats *libcontainer.Stats) *info.ContainerStats {

View File

@ -312,7 +312,9 @@ type MemoryStatsMemoryData struct {
Pgmajfault uint64 `json:"pgmajfault"`
}
type NetworkStats struct {
type InterfaceStats struct {
// The name of the interface.
Name string `json:"name"`
// Cumulative count of bytes received.
RxBytes uint64 `json:"rx_bytes"`
// Cumulative count of packets received.
@ -331,6 +333,11 @@ type NetworkStats struct {
TxDropped uint64 `json:"tx_dropped"`
}
type NetworkStats struct {
InterfaceStats `json:",inline"`
Interfaces []InterfaceStats `json:"interfaces,omitempty"`
}
type FsStats struct {
// The block device name associated with the filesystem.
Device string `json:"device,omitempty"`

View File

@ -92,8 +92,8 @@ type ContainerStats struct {
HasMemory bool `json:"has_memory"`
Memory v1.MemoryStats `json:"memory,omitempty"`
// Network statistics
HasNetwork bool `json:"has_network"`
Network []v1.NetworkStats `json:"network,omitempty"`
HasNetwork bool `json:"has_network"`
Network NetworkStats `json:"network,omitempty"`
// Filesystem statistics
HasFilesystem bool `json:"has_filesystem"`
Filesystem []v1.FsStats `json:"filesystem,omitempty"`
@ -189,3 +189,8 @@ type ProcessInfo struct {
CgroupPath string `json:"cgroup_path"`
Cmd string `json:"cmd"`
}
type NetworkStats struct {
// Network stats by interface.
Interfaces []v1.InterfaceStats `json:"interfaces,omitempty"`
}

View File

@ -57,14 +57,17 @@ func (p testSubcontainersInfoProvider) SubcontainersInfo(string, *info.Container
},
},
Network: info.NetworkStats{
RxBytes: 14,
RxPackets: 15,
RxErrors: 16,
RxDropped: 17,
TxBytes: 18,
TxPackets: 19,
TxErrors: 20,
TxDropped: 21,
InterfaceStats: info.InterfaceStats{
Name: "eth0",
RxBytes: 14,
RxPackets: 15,
RxErrors: 16,
RxDropped: 17,
TxBytes: 18,
TxPackets: 19,
TxErrors: 20,
TxDropped: 21,
},
},
Filesystem: []info.FsStats{
{

View File

@ -157,19 +157,19 @@ func GetCacheInfo(sysFs sysfs.SysFs, id int) ([]sysfs.CacheInfo, error) {
return info, nil
}
func GetNetworkStats(name string) (info.NetworkStats, error) {
stats := info.NetworkStats{}
func GetNetworkStats(name string) (info.InterfaceStats, error) {
// TODO(rjnagal): Take syfs as an argument.
sysFs, err := sysfs.NewRealSysFs()
if err != nil {
return stats, err
return info.InterfaceStats{}, err
}
return getNetworkStats(name, sysFs)
}
func getNetworkStats(name string, sysFs sysfs.SysFs) (info.NetworkStats, error) {
stats := info.NetworkStats{}
func getNetworkStats(name string, sysFs sysfs.SysFs) (info.InterfaceStats, error) {
var stats info.InterfaceStats
var err error
stats.Name = name
stats.RxBytes, err = sysFs.GetNetworkStatValue(name, "rx_bytes")
if err != nil {
return stats, err

View File

@ -110,7 +110,8 @@ func TestGetCacheInfo(t *testing.T) {
}
func TestGetNetworkStats(t *testing.T) {
expected_stats := info.NetworkStats{
expected_stats := info.InterfaceStats{
Name: "eth0",
RxBytes: 1024,
RxPackets: 1024,
RxErrors: 1024,