Skip to content

Commit

Permalink
Add metrics support for a few network based volumes.
Browse files Browse the repository at this point in the history
Signed-off-by: Vishnu Kannan <vishnuk@google.com>
  • Loading branch information
vishh committed May 23, 2016
1 parent efc5bbc commit baa8ac4
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 122 deletions.
40 changes: 22 additions & 18 deletions pkg/volume/aws_ebs/aws_ebs.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util/exec"
"k8s.io/kubernetes/pkg/util/mount"
utilstrings "k8s.io/kubernetes/pkg/util/strings"
kstrings "k8s.io/kubernetes/pkg/util/strings"
"k8s.io/kubernetes/pkg/volume"
)

Expand All @@ -52,6 +52,10 @@ const (
awsElasticBlockStorePluginName = "kubernetes.io/aws-ebs"
)

func getPath(uid types.UID, volName string, host volume.VolumeHost) string {
return host.GetPodVolumeDir(uid, kstrings.EscapeQualifiedNameForDisk(awsElasticBlockStorePluginName), volName)
}

func (plugin *awsElasticBlockStorePlugin) Init(host volume.VolumeHost) error {
plugin.host = host
return nil
Expand Down Expand Up @@ -99,13 +103,14 @@ func (plugin *awsElasticBlockStorePlugin) newMounterInternal(spec *volume.Spec,

return &awsElasticBlockStoreMounter{
awsElasticBlockStore: &awsElasticBlockStore{
podUID: podUID,
volName: spec.Name(),
volumeID: volumeID,
partition: partition,
manager: manager,
mounter: mounter,
plugin: plugin,
podUID: podUID,
volName: spec.Name(),
volumeID: volumeID,
partition: partition,
manager: manager,
mounter: mounter,
plugin: plugin,
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)),
},
fsType: fsType,
readOnly: readOnly,
Expand All @@ -119,11 +124,12 @@ func (plugin *awsElasticBlockStorePlugin) NewUnmounter(volName string, podUID ty

func (plugin *awsElasticBlockStorePlugin) newUnmounterInternal(volName string, podUID types.UID, manager ebsManager, mounter mount.Interface) (volume.Unmounter, error) {
return &awsElasticBlockStoreUnmounter{&awsElasticBlockStore{
podUID: podUID,
volName: volName,
manager: manager,
mounter: mounter,
plugin: plugin,
podUID: podUID,
volName: volName,
manager: manager,
mounter: mounter,
plugin: plugin,
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, volName, plugin.host)),
}}, nil
}

Expand Down Expand Up @@ -187,7 +193,7 @@ type awsElasticBlockStore struct {
// Mounter interface that provides system calls to mount the global path to the pod local path.
mounter mount.Interface
plugin *awsElasticBlockStorePlugin
volume.MetricsNil
volume.MetricsProvider
}

func detachDiskLogError(ebs *awsElasticBlockStore) {
Expand Down Expand Up @@ -313,8 +319,7 @@ func getVolumeIDFromGlobalMount(host volume.VolumeHost, globalPath string) (stri
}

func (ebs *awsElasticBlockStore) GetPath() string {
name := awsElasticBlockStorePluginName
return ebs.plugin.host.GetPodVolumeDir(ebs.podUID, utilstrings.EscapeQualifiedNameForDisk(name), ebs.volName)
return getPath(ebs.podUID, ebs.volName, ebs.plugin.host)
}

type awsElasticBlockStoreUnmounter struct {
Expand Down Expand Up @@ -392,8 +397,7 @@ type awsElasticBlockStoreDeleter struct {
var _ volume.Deleter = &awsElasticBlockStoreDeleter{}

func (d *awsElasticBlockStoreDeleter) GetPath() string {
name := awsElasticBlockStorePluginName
return d.plugin.host.GetPodVolumeDir(d.podUID, utilstrings.EscapeQualifiedNameForDisk(name), d.volName)
return getPath(d.podUID, d.volName, d.plugin.host)
}

func (d *awsElasticBlockStoreDeleter) Delete() error {
Expand Down
29 changes: 17 additions & 12 deletions pkg/volume/azure_file/azure_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/util/strings"
kstrings "k8s.io/kubernetes/pkg/util/strings"
"k8s.io/kubernetes/pkg/volume"

"github.com/golang/glog"
Expand All @@ -45,6 +45,10 @@ const (
azureFilePluginName = "kubernetes.io/azure-file"
)

func getPath(uid types.UID, volName string, host volume.VolumeHost) string {
return host.GetPodVolumeDir(uid, kstrings.EscapeQualifiedNameForDisk(azureFilePluginName), volName)
}

func (plugin *azureFilePlugin) Init(host volume.VolumeHost) error {
plugin.host = host
return nil
Expand Down Expand Up @@ -84,10 +88,11 @@ func (plugin *azureFilePlugin) newMounterInternal(spec *volume.Spec, pod *api.Po
}
return &azureFileMounter{
azureFile: &azureFile{
volName: spec.Name(),
mounter: mounter,
pod: pod,
plugin: plugin,
volName: spec.Name(),
mounter: mounter,
pod: pod,
plugin: plugin,
MetricsProvider: volume.NewMetricsStatFS(getPath(pod.UID, spec.Name(), plugin.host)),
},
util: util,
secretName: source.SecretName,
Expand All @@ -102,10 +107,11 @@ func (plugin *azureFilePlugin) NewUnmounter(volName string, podUID types.UID) (v

func (plugin *azureFilePlugin) newUnmounterInternal(volName string, podUID types.UID, mounter mount.Interface) (volume.Unmounter, error) {
return &azureFileUnmounter{&azureFile{
volName: volName,
mounter: mounter,
pod: &api.Pod{ObjectMeta: api.ObjectMeta{UID: podUID}},
plugin: plugin,
volName: volName,
mounter: mounter,
pod: &api.Pod{ObjectMeta: api.ObjectMeta{UID: podUID}},
plugin: plugin,
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, volName, plugin.host)),
}}, nil
}

Expand All @@ -115,12 +121,11 @@ type azureFile struct {
pod *api.Pod
mounter mount.Interface
plugin *azureFilePlugin
volume.MetricsNil
volume.MetricsProvider
}

func (azureFileVolume *azureFile) GetPath() string {
name := azureFilePluginName
return azureFileVolume.plugin.host.GetPodVolumeDir(azureFileVolume.pod.UID, strings.EscapeQualifiedNameForDisk(name), azureFileVolume.volName)
return getPath(azureFileVolume.pod.UID, azureFileVolume.volName, azureFileVolume.plugin.host)
}

type azureFileMounter struct {
Expand Down
15 changes: 7 additions & 8 deletions pkg/volume/empty_dir/empty_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ const (
emptyDirPluginName = "kubernetes.io/empty-dir"
)

func getPath(uid types.UID, volName string, host volume.VolumeHost) string {
return host.GetPodVolumeDir(uid, strings.EscapeQualifiedNameForDisk(emptyDirPluginName), volName)
}

func (plugin *emptyDirPlugin) Init(host volume.VolumeHost) error {
plugin.host = host

Expand Down Expand Up @@ -88,7 +92,7 @@ func (plugin *emptyDirPlugin) newMounterInternal(spec *volume.Spec, pod *api.Pod
mountDetector: mountDetector,
plugin: plugin,
rootContext: opts.RootContext,
MetricsProvider: volume.NewMetricsDu(GetPath(pod.UID, spec.Name(), plugin.host)),
MetricsProvider: volume.NewMetricsDu(getPath(pod.UID, spec.Name(), plugin.host)),
}, nil
}

Expand All @@ -105,7 +109,7 @@ func (plugin *emptyDirPlugin) newUnmounterInternal(volName string, podUID types.
mounter: mounter,
mountDetector: mountDetector,
plugin: plugin,
MetricsProvider: volume.NewMetricsDu(GetPath(podUID, volName, plugin.host)),
MetricsProvider: volume.NewMetricsDu(getPath(podUID, volName, plugin.host)),
}
return ed, nil
}
Expand Down Expand Up @@ -271,12 +275,7 @@ func (ed *emptyDir) setupDir(dir string) error {
}

func (ed *emptyDir) GetPath() string {
return GetPath(ed.pod.UID, ed.volName, ed.plugin.host)
}

func GetPath(uid types.UID, volName string, host volume.VolumeHost) string {
name := emptyDirPluginName
return host.GetPodVolumeDir(uid, strings.EscapeQualifiedNameForDisk(name), volName)
return getPath(ed.pod.UID, ed.volName, ed.plugin.host)
}

// TearDown simply discards everything in the directory.
Expand Down
47 changes: 28 additions & 19 deletions pkg/volume/gce_pd/gce_pd.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ const (
gcePersistentDiskPluginName = "kubernetes.io/gce-pd"
)

func getPath(uid types.UID, volName string, host volume.VolumeHost) string {
return host.GetPodVolumeDir(uid, strings.EscapeQualifiedNameForDisk(gcePersistentDiskPluginName), volName)
}

func (plugin *gcePersistentDiskPlugin) Init(host volume.VolumeHost) error {
plugin.host = host
return nil
Expand Down Expand Up @@ -103,13 +107,14 @@ func (plugin *gcePersistentDiskPlugin) newMounterInternal(spec *volume.Spec, pod

return &gcePersistentDiskMounter{
gcePersistentDisk: &gcePersistentDisk{
podUID: podUID,
volName: spec.Name(),
pdName: pdName,
partition: partition,
mounter: mounter,
manager: manager,
plugin: plugin,
podUID: podUID,
volName: spec.Name(),
pdName: pdName,
partition: partition,
mounter: mounter,
manager: manager,
plugin: plugin,
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)),
},
readOnly: readOnly}, nil
}
Expand All @@ -121,11 +126,12 @@ func (plugin *gcePersistentDiskPlugin) NewUnmounter(volName string, podUID types

func (plugin *gcePersistentDiskPlugin) newUnmounterInternal(volName string, podUID types.UID, manager pdManager, mounter mount.Interface) (volume.Unmounter, error) {
return &gcePersistentDiskUnmounter{&gcePersistentDisk{
podUID: podUID,
volName: volName,
manager: manager,
mounter: mounter,
plugin: plugin,
podUID: podUID,
volName: volName,
manager: manager,
mounter: mounter,
plugin: plugin,
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, volName, plugin.host)),
}}, nil
}

Expand Down Expand Up @@ -185,7 +191,7 @@ type gcePersistentDisk struct {
// Mounter interface that provides system calls to mount the global path to the pod local path.
mounter mount.Interface
plugin *gcePersistentDiskPlugin
volume.MetricsNil
volume.MetricsProvider
}

type gcePersistentDiskMounter struct {
Expand Down Expand Up @@ -270,9 +276,8 @@ func makeGlobalPDName(host volume.VolumeHost, devName string) string {
return path.Join(host.GetPluginDir(gcePersistentDiskPluginName), "mounts", devName)
}

func (pd *gcePersistentDisk) GetPath() string {
name := gcePersistentDiskPluginName
return pd.plugin.host.GetPodVolumeDir(pd.podUID, strings.EscapeQualifiedNameForDisk(name), pd.volName)
func (b *gcePersistentDiskMounter) GetPath() string {
return getPath(b.podUID, b.volName, b.plugin.host)
}

type gcePersistentDiskUnmounter struct {
Expand All @@ -281,7 +286,12 @@ type gcePersistentDiskUnmounter struct {

var _ volume.Unmounter = &gcePersistentDiskUnmounter{}

// TearDown unmounts the bind mount
func (c *gcePersistentDiskUnmounter) GetPath() string {
return getPath(c.podUID, c.volName, c.plugin.host)
}

// Unmounts the bind mount, and detaches the disk only if the PD
// resource was the last reference to that disk on the kubelet.
func (c *gcePersistentDiskUnmounter) TearDown() error {
return c.TearDownAt(c.GetPath())
}
Expand Down Expand Up @@ -316,8 +326,7 @@ type gcePersistentDiskDeleter struct {
var _ volume.Deleter = &gcePersistentDiskDeleter{}

func (d *gcePersistentDiskDeleter) GetPath() string {
name := gcePersistentDiskPluginName
return d.plugin.host.GetPodVolumeDir(d.podUID, strings.EscapeQualifiedNameForDisk(name), d.volName)
return getPath(d.podUID, d.volName, d.plugin.host)
}

func (d *gcePersistentDiskDeleter) Delete() error {
Expand Down
2 changes: 1 addition & 1 deletion pkg/volume/metrics_du.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (md *metricsDu) runDu(metrics *Metrics) error {

// getFsInfo writes metrics.Capacity and metrics.Available from the filesystem info
func (md *metricsDu) getFsInfo(metrics *Metrics) error {
available, capacity, err := util.FsInfo(md.path)
available, capacity, _, err := util.FsInfo(md.path)
if err != nil {
return fmt.Errorf("Failed to get FsInfo due to error %v", err)
}
Expand Down
68 changes: 68 additions & 0 deletions pkg/volume/metrics_statfs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
Copyright 2016 The Kubernetes Authors 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.
*/

package volume

import (
"errors"
"fmt"

"k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/volume/util"
)

var _ MetricsProvider = &metricsStatFS{}

// metricsStatFS represents a MetricsProvider that calculates the used and available
// Volume space by stat'ing and gathering filesystem info for the Volume path.
type metricsStatFS struct {
// the directory path the volume is mounted to.
path string
}

// NewMetricsStatfs creates a new metricsStatFS with the Volume path.
func NewMetricsStatFS(path string) MetricsProvider {
return &metricsStatFS{path}
}

// See MetricsProvider.GetMetrics
// 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{}
if md.path == "" {
return metrics, errors.New("no path defined for disk usage metrics.")
}

err := md.getFsInfo(metrics)
if err != nil {
return metrics, err
}

return metrics, nil
}

// getFsInfo writes metrics.Capacity, metrics.Used and metrics.Available from the filesystem info
func (md *metricsStatFS) getFsInfo(metrics *Metrics) error {
available, capacity, usage, err := util.FsInfo(md.path)
if err != nil {
return fmt.Errorf("Failed to get FsInfo due to error %v", err)
}
metrics.Available = resource.NewQuantity(available, resource.BinarySI)
metrics.Capacity = resource.NewQuantity(capacity, resource.BinarySI)
metrics.Used = resource.NewQuantity(usage, resource.BinarySI)
return nil
}
Loading

0 comments on commit baa8ac4

Please sign in to comment.