add volume timestamps

pull/6/head
David Ashpole 2017-03-02 15:01:59 -08:00
parent c5faf1c156
commit a90c7951d4
11 changed files with 41 additions and 17 deletions

View File

@ -192,7 +192,7 @@ type VolumeStats struct {
// FsStats contains data about filesystem usage.
type FsStats struct {
// The time at which these stats were updated.
Time unversioned.Time `json:"time"`
Time metav1.Time `json:"time"`
// AvailableBytes represents the storage space available (bytes) for the filesystem.
// +optional
AvailableBytes *uint64 `json:"availableBytes,omitempty"`

View File

@ -135,7 +135,7 @@ func (sb *summaryBuilder) build() (*stats.Summary, error) {
Memory: rootStats.Memory,
Network: sb.containerInfoV2ToNetworkStats("node:"+sb.node.Name, &rootInfo),
Fs: &stats.FsStats{
Time: unversioned.NewTime(cStats.Timestamp),
Time: metav1.NewTime(cStats.Timestamp),
AvailableBytes: &sb.rootFsInfo.Available,
CapacityBytes: &sb.rootFsInfo.Capacity,
UsedBytes: &sb.rootFsInfo.Usage,
@ -146,7 +146,7 @@ func (sb *summaryBuilder) build() (*stats.Summary, error) {
StartTime: rootStats.StartTime,
Runtime: &stats.RuntimeStats{
ImageFs: &stats.FsStats{
Time: unversioned.NewTime(cStats.Timestamp),
Time: metav1.NewTime(cStats.Timestamp),
AvailableBytes: &sb.imageFsInfo.Available,
CapacityBytes: &sb.imageFsInfo.Capacity,
UsedBytes: &sb.imageStats.TotalStorageBytes,
@ -191,7 +191,7 @@ func (sb *summaryBuilder) containerInfoV2FsStats(
// The container logs live on the node rootfs device
cs.Logs = &stats.FsStats{
Time: unversioned.NewTime(lcs.Timestamp),
Time: metav1.NewTime(lcs.Timestamp),
AvailableBytes: &sb.rootFsInfo.Available,
CapacityBytes: &sb.rootFsInfo.Capacity,
InodesFree: sb.rootFsInfo.InodesFree,
@ -205,7 +205,7 @@ func (sb *summaryBuilder) containerInfoV2FsStats(
// The container rootFs lives on the imageFs devices (which may not be the node root fs)
cs.Rootfs = &stats.FsStats{
Time: unversioned.NewTime(lcs.Timestamp),
Time: metav1.NewTime(lcs.Timestamp),
AvailableBytes: &sb.imageFsInfo.Available,
CapacityBytes: &sb.imageFsInfo.Capacity,
InodesFree: sb.imageFsInfo.InodesFree,

View File

@ -120,7 +120,7 @@ func (s *volumeStatCalculator) parsePodVolumeStats(podName string, metric *volum
inodesUsed := uint64(metric.InodesUsed.Value())
return stats.VolumeStats{
Name: podName,
FsStats: stats.FsStats{AvailableBytes: &available, CapacityBytes: &capacity, UsedBytes: &used,
Inodes: &inodes, InodesFree: &inodesFree, InodesUsed: &inodesUsed},
FsStats: stats.FsStats{Time: metric.Time, AvailableBytes: &available, CapacityBytes: &capacity,
UsedBytes: &used, Inodes: &inodes, InodesFree: &inodesFree, InodesUsed: &inodesUsed},
}
}

View File

@ -50,7 +50,6 @@ go_test(
name = "go_default_test",
srcs = [
"metrics_nil_test.go",
"metrics_statfs_test.go",
"plugins_test.go",
"util_test.go",
],
@ -66,13 +65,15 @@ go_test(
"//vendor:k8s.io/apimachinery/pkg/types",
"//vendor:k8s.io/apimachinery/pkg/util/sets",
"//vendor:k8s.io/apimachinery/pkg/watch",
"//vendor:k8s.io/client-go/util/testing",
],
)
go_test(
name = "go_default_xtest",
srcs = ["metrics_du_test.go"],
srcs = [
"metrics_du_test.go",
"metrics_statfs_test.go",
],
tags = ["automanaged"],
deps = [
"//pkg/volume:go_default_library",

View File

@ -18,6 +18,7 @@ package volume
import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/volume/util"
)
@ -40,7 +41,7 @@ func NewMetricsDu(path string) MetricsProvider {
// and gathering filesystem info for the Volume path.
// See MetricsProvider.GetMetrics
func (md *metricsDu) GetMetrics() (*Metrics, error) {
metrics := &Metrics{}
metrics := &Metrics{Time: metav1.Now()}
if md.path == "" {
return metrics, NewNoPathDefinedError()
}

View File

@ -80,7 +80,7 @@ func TestMetricsDuRequirePath(t *testing.T) {
metrics := NewMetricsDu("")
actual, err := metrics.GetMetrics()
expected := &Metrics{}
if *actual != *expected {
if !volumetest.MetricsEqualIgnoreTimestamp(actual, expected) {
t.Errorf("Expected empty Metrics from uninitialized MetricsDu, actual %v", *actual)
}
if err == nil {
@ -94,7 +94,7 @@ func TestMetricsDuRequireRealDirectory(t *testing.T) {
metrics := NewMetricsDu("/not/a/real/directory")
actual, err := metrics.GetMetrics()
expected := &Metrics{}
if *actual != *expected {
if !volumetest.MetricsEqualIgnoreTimestamp(actual, expected) {
t.Errorf("Expected empty Metrics from incorrectly initialized MetricsDu, actual %v", *actual)
}
if err == nil {

View File

@ -18,6 +18,7 @@ package volume
import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/volume/util"
)
@ -39,7 +40,7 @@ func NewMetricsStatFS(path string) MetricsProvider {
// GetMetrics calculates the volume usage and device free space by executing "du"
// and gathering filesystem info for the Volume path.
func (md *metricsStatFS) GetMetrics() (*Metrics, error) {
metrics := &Metrics{}
metrics := &Metrics{Time: metav1.Now()}
if md.path == "" {
return metrics, NewNoPathDefinedError()
}

View File

@ -14,20 +14,22 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package volume
package volume_test
import (
"os"
"testing"
utiltesting "k8s.io/client-go/util/testing"
. "k8s.io/kubernetes/pkg/volume"
volumetest "k8s.io/kubernetes/pkg/volume/testing"
)
func TestGetMetricsStatFS(t *testing.T) {
metrics := NewMetricsStatFS("")
actual, err := metrics.GetMetrics()
expected := &Metrics{}
if *actual != *expected {
if !volumetest.MetricsEqualIgnoreTimestamp(actual, expected) {
t.Errorf("Expected empty Metrics from uninitialized MetricsStatFS, actual %v", *actual)
}
if err == nil {
@ -36,7 +38,7 @@ func TestGetMetricsStatFS(t *testing.T) {
metrics = NewMetricsStatFS("/not/a/real/directory")
actual, err = metrics.GetMetrics()
if *actual != *expected {
if !volumetest.MetricsEqualIgnoreTimestamp(actual, expected) {
t.Errorf("Expected empty Metrics from incorrectly initialized MetricsStatFS, actual %v", *actual)
}
if err == nil {

View File

@ -750,3 +750,13 @@ func CreateTestPVC(capacity string, accessModes []v1.PersistentVolumeAccessMode)
}
return &claim
}
func MetricsEqualIgnoreTimestamp(a *Metrics, b *Metrics) bool {
available := a.Available == b.Available
capacity := a.Capacity == b.Capacity
used := a.Used == b.Used
inodes := a.Inodes == b.Inodes
inodesFree := a.InodesFree == b.InodesFree
inodesUsed := a.InodesUsed == b.InodesUsed
return available && capacity && used && inodes && inodesFree && inodesUsed
}

View File

@ -26,6 +26,7 @@ import (
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/api/v1"
)
@ -52,6 +53,9 @@ type MetricsProvider interface {
// Metrics represents the used and available bytes of the Volume.
type Metrics struct {
// The time at which these stats were updated.
Time metav1.Time
// Used represents the total bytes used by the Volume.
// Note: For block devices this maybe more than the total size of the files.
Used *resource.Quantity

View File

@ -116,6 +116,7 @@ var _ = framework.KubeDescribe("Summary API", func() {
"MajorPageFaults": bounded(0, 10),
}),
"Rootfs": ptrMatchAllFields(gstruct.Fields{
"Time": recent(maxStatsAge),
"AvailableBytes": fsCapacityBounds,
"CapacityBytes": fsCapacityBounds,
"UsedBytes": bounded(kb, 10*mb),
@ -124,6 +125,7 @@ var _ = framework.KubeDescribe("Summary API", func() {
"InodesUsed": bounded(0, 1E8),
}),
"Logs": ptrMatchAllFields(gstruct.Fields{
"Time": recent(maxStatsAge),
"AvailableBytes": fsCapacityBounds,
"CapacityBytes": fsCapacityBounds,
"UsedBytes": bounded(kb, 10*mb),
@ -145,6 +147,7 @@ var _ = framework.KubeDescribe("Summary API", func() {
"test-empty-dir": gstruct.MatchAllFields(gstruct.Fields{
"Name": Equal("test-empty-dir"),
"FsStats": gstruct.MatchAllFields(gstruct.Fields{
"Time": recent(maxStatsAge),
"AvailableBytes": fsCapacityBounds,
"CapacityBytes": fsCapacityBounds,
"UsedBytes": bounded(kb, 1*mb),
@ -183,6 +186,7 @@ var _ = framework.KubeDescribe("Summary API", func() {
"TxErrors": bounded(0, 100000),
})),
"Fs": ptrMatchAllFields(gstruct.Fields{
"Time": recent(maxStatsAge),
"AvailableBytes": fsCapacityBounds,
"CapacityBytes": fsCapacityBounds,
"UsedBytes": bounded(kb, 10*gb),
@ -192,6 +196,7 @@ var _ = framework.KubeDescribe("Summary API", func() {
}),
"Runtime": ptrMatchAllFields(gstruct.Fields{
"ImageFs": ptrMatchAllFields(gstruct.Fields{
"Time": recent(maxStatsAge),
"AvailableBytes": fsCapacityBounds,
"CapacityBytes": fsCapacityBounds,
"UsedBytes": bounded(kb, 10*gb),