diff --git a/container/raw/handler.go b/container/raw/handler.go index 62ca1937..62c5c8c8 100644 --- a/container/raw/handler.go +++ b/container/raw/handler.go @@ -166,9 +166,11 @@ func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) { } func fsToFsStats(fs *fs.Fs) info.FsStats { + inodes := uint64(0) inodesFree := uint64(0) hasInodes := fs.InodesFree != nil if hasInodes { + inodes = *fs.Inodes inodesFree = *fs.InodesFree } return info.FsStats{ @@ -177,6 +179,7 @@ func fsToFsStats(fs *fs.Fs) info.FsStats { Limit: fs.Capacity, Usage: fs.Capacity - fs.Free, HasInodes: hasInodes, + Inodes: inodes, InodesFree: inodesFree, Available: fs.Available, ReadsCompleted: fs.DiskStats.ReadsCompleted, diff --git a/container/raw/handler_test.go b/container/raw/handler_test.go new file mode 100644 index 00000000..edb78f49 --- /dev/null +++ b/container/raw/handler_test.go @@ -0,0 +1,126 @@ +// Copyright 2016 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. + +// Handler for "raw" containers. +package raw + +import ( + "reflect" + "testing" + + "github.com/google/cadvisor/fs" + info "github.com/google/cadvisor/info/v1" +) + +func TestFsToFsStats(t *testing.T) { + inodes := uint64(100) + inodesFree := uint64(50) + testCases := map[string]struct { + fs *fs.Fs + expected info.FsStats + }{ + "has_inodes": { + fs: &fs.Fs{ + DeviceInfo: fs.DeviceInfo{Device: "123"}, + Type: fs.VFS, + Capacity: uint64(1024 * 1024), + Free: uint64(1024), + Available: uint64(1024), + Inodes: &inodes, + InodesFree: &inodesFree, + DiskStats: fs.DiskStats{ + ReadsCompleted: uint64(100), + ReadsMerged: uint64(100), + SectorsRead: uint64(100), + ReadTime: uint64(100), + WritesCompleted: uint64(100), + WritesMerged: uint64(100), + SectorsWritten: uint64(100), + WriteTime: uint64(100), + IoInProgress: uint64(100), + IoTime: uint64(100), + WeightedIoTime: uint64(100), + }, + }, + expected: info.FsStats{ + Device: "123", + Type: fs.VFS.String(), + Limit: uint64(1024 * 1024), + Usage: uint64(1024*1024) - uint64(1024), + HasInodes: true, + Inodes: inodes, + InodesFree: inodesFree, + Available: uint64(1024), + ReadsCompleted: uint64(100), + ReadsMerged: uint64(100), + SectorsRead: uint64(100), + ReadTime: uint64(100), + WritesCompleted: uint64(100), + WritesMerged: uint64(100), + SectorsWritten: uint64(100), + WriteTime: uint64(100), + IoInProgress: uint64(100), + IoTime: uint64(100), + WeightedIoTime: uint64(100), + }, + }, + "has_no_inodes": { + fs: &fs.Fs{ + DeviceInfo: fs.DeviceInfo{Device: "123"}, + Type: fs.DeviceMapper, + Capacity: uint64(1024 * 1024), + Free: uint64(1024), + Available: uint64(1024), + DiskStats: fs.DiskStats{ + ReadsCompleted: uint64(100), + ReadsMerged: uint64(100), + SectorsRead: uint64(100), + ReadTime: uint64(100), + WritesCompleted: uint64(100), + WritesMerged: uint64(100), + SectorsWritten: uint64(100), + WriteTime: uint64(100), + IoInProgress: uint64(100), + IoTime: uint64(100), + WeightedIoTime: uint64(100), + }, + }, + expected: info.FsStats{ + Device: "123", + Type: fs.DeviceMapper.String(), + Limit: uint64(1024 * 1024), + Usage: uint64(1024*1024) - uint64(1024), + HasInodes: false, + Available: uint64(1024), + ReadsCompleted: uint64(100), + ReadsMerged: uint64(100), + SectorsRead: uint64(100), + ReadTime: uint64(100), + WritesCompleted: uint64(100), + WritesMerged: uint64(100), + SectorsWritten: uint64(100), + WriteTime: uint64(100), + IoInProgress: uint64(100), + IoTime: uint64(100), + WeightedIoTime: uint64(100), + }, + }, + } + for testName, testCase := range testCases { + actual := fsToFsStats(testCase.fs) + if !reflect.DeepEqual(testCase.expected, actual) { + t.Errorf("test case=%v, expected=%v, actual=%v", testName, testCase.expected, actual) + } + } +} diff --git a/info/v1/container.go b/info/v1/container.go index ad57c8f4..f29f5bdf 100644 --- a/info/v1/container.go +++ b/info/v1/container.go @@ -418,6 +418,9 @@ type FsStats struct { // HasInodes when true, indicates that Inodes info will be available. HasInodes bool `json:"has_inodes"` + // Number of Inodes + Inodes uint64 `json:"inodes"` + // Number of available Inodes InodesFree uint64 `json:"inodes_free"` diff --git a/info/v2/container.go b/info/v2/container.go index d900d94c..c521e35f 100644 --- a/info/v2/container.go +++ b/info/v2/container.go @@ -217,6 +217,9 @@ type FsInfo struct { // Labels associated with this filesystem. Labels []string `json:"labels"` + // Number of Inodes. + Inodes *uint64 `json:"inodes,omitempty"` + // Number of available Inodes (if known) InodesFree *uint64 `json:"inodes_free,omitempty"` } diff --git a/manager/manager.go b/manager/manager.go index e41cf990..3622b060 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -695,6 +695,7 @@ func (self *manager) GetFsInfo(label string) ([]v2.FsInfo, error) { Labels: labels, } if fs.HasInodes { + fi.Inodes = &fs.Inodes fi.InodesFree = &fs.InodesFree } fsInfo = append(fsInfo, fi)