Add generated file
This PR adds generated files under pkg/client and vendor folder.
This commit is contained in:
62
vendor/k8s.io/kubernetes/pkg/volume/portworx/BUILD
generated
vendored
Normal file
62
vendor/k8s.io/kubernetes/pkg/volume/portworx/BUILD
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["portworx_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/util/mount:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/testing:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"portworx.go",
|
||||
"portworx_util.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/portworx",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/util/mount:go_default_library",
|
||||
"//pkg/util/strings:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/libopenstorage/openstorage/api:go_default_library",
|
||||
"//vendor/github.com/libopenstorage/openstorage/api/client:go_default_library",
|
||||
"//vendor/github.com/libopenstorage/openstorage/api/client/volume:go_default_library",
|
||||
"//vendor/github.com/libopenstorage/openstorage/api/spec:go_default_library",
|
||||
"//vendor/github.com/libopenstorage/openstorage/volume:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
2
vendor/k8s.io/kubernetes/pkg/volume/portworx/OWNERS
generated
vendored
Normal file
2
vendor/k8s.io/kubernetes/pkg/volume/portworx/OWNERS
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
maintainers:
|
||||
- adityadani
|
||||
19
vendor/k8s.io/kubernetes/pkg/volume/portworx/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/volume/portworx/doc.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
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 portworx contains the internal representation of Portworx
|
||||
// Block Device volumes.
|
||||
package portworx
|
||||
431
vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx.go
generated
vendored
Normal file
431
vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx.go
generated
vendored
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
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 portworx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
kstrings "k8s.io/kubernetes/pkg/util/strings"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
||||
const (
|
||||
attachContextKey = "context"
|
||||
attachHostKey = "host"
|
||||
)
|
||||
|
||||
// This is the primary entrypoint for volume plugins.
|
||||
func ProbeVolumePlugins() []volume.VolumePlugin {
|
||||
return []volume.VolumePlugin{&portworxVolumePlugin{nil, nil}}
|
||||
}
|
||||
|
||||
type portworxVolumePlugin struct {
|
||||
host volume.VolumeHost
|
||||
util *PortworxVolumeUtil
|
||||
}
|
||||
|
||||
var _ volume.VolumePlugin = &portworxVolumePlugin{}
|
||||
var _ volume.PersistentVolumePlugin = &portworxVolumePlugin{}
|
||||
var _ volume.DeletableVolumePlugin = &portworxVolumePlugin{}
|
||||
var _ volume.ProvisionableVolumePlugin = &portworxVolumePlugin{}
|
||||
var _ volume.ExpandableVolumePlugin = &portworxVolumePlugin{}
|
||||
|
||||
const (
|
||||
portworxVolumePluginName = "kubernetes.io/portworx-volume"
|
||||
)
|
||||
|
||||
func getPath(uid types.UID, volName string, host volume.VolumeHost) string {
|
||||
return host.GetPodVolumeDir(uid, kstrings.EscapeQualifiedNameForDisk(portworxVolumePluginName), volName)
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) Init(host volume.VolumeHost) error {
|
||||
plugin.host = host
|
||||
plugin.util = &PortworxVolumeUtil{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) GetPluginName() string {
|
||||
return portworxVolumePluginName
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error) {
|
||||
volumeSource, _, err := getVolumeSource(spec)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return volumeSource.VolumeID, nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) CanSupport(spec *volume.Spec) bool {
|
||||
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.PortworxVolume != nil) ||
|
||||
(spec.Volume != nil && spec.Volume.PortworxVolume != nil)
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) RequiresRemount() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
|
||||
return []v1.PersistentVolumeAccessMode{
|
||||
v1.ReadWriteOnce,
|
||||
v1.ReadWriteMany,
|
||||
}
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) {
|
||||
return plugin.newMounterInternal(spec, pod.UID, plugin.util, plugin.host.GetMounter(plugin.GetPluginName()))
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager portworxManager, mounter mount.Interface) (volume.Mounter, error) {
|
||||
pwx, readOnly, err := getVolumeSource(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
volumeID := pwx.VolumeID
|
||||
fsType := pwx.FSType
|
||||
|
||||
return &portworxVolumeMounter{
|
||||
portworxVolume: &portworxVolume{
|
||||
podUID: podUID,
|
||||
volName: spec.Name(),
|
||||
volumeID: volumeID,
|
||||
manager: manager,
|
||||
mounter: mounter,
|
||||
plugin: plugin,
|
||||
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), plugin.host)),
|
||||
},
|
||||
fsType: fsType,
|
||||
readOnly: readOnly,
|
||||
diskMounter: util.NewSafeFormatAndMountFromHost(plugin.GetPluginName(), plugin.host)}, nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) {
|
||||
return plugin.newUnmounterInternal(volName, podUID, plugin.util, plugin.host.GetMounter(plugin.GetPluginName()))
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) newUnmounterInternal(volName string, podUID types.UID, manager portworxManager,
|
||||
mounter mount.Interface) (volume.Unmounter, error) {
|
||||
return &portworxVolumeUnmounter{
|
||||
&portworxVolume{
|
||||
podUID: podUID,
|
||||
volName: volName,
|
||||
manager: manager,
|
||||
mounter: mounter,
|
||||
plugin: plugin,
|
||||
MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, volName, plugin.host)),
|
||||
}}, nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) NewDeleter(spec *volume.Spec) (volume.Deleter, error) {
|
||||
return plugin.newDeleterInternal(spec, plugin.util)
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) newDeleterInternal(spec *volume.Spec, manager portworxManager) (volume.Deleter, error) {
|
||||
if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.PortworxVolume == nil {
|
||||
return nil, fmt.Errorf("spec.PersistentVolumeSource.PortworxVolume is nil")
|
||||
}
|
||||
|
||||
return &portworxVolumeDeleter{
|
||||
portworxVolume: &portworxVolume{
|
||||
volName: spec.Name(),
|
||||
volumeID: spec.PersistentVolume.Spec.PortworxVolume.VolumeID,
|
||||
manager: manager,
|
||||
plugin: plugin,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) {
|
||||
return plugin.newProvisionerInternal(options, plugin.util)
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) newProvisionerInternal(options volume.VolumeOptions, manager portworxManager) (volume.Provisioner, error) {
|
||||
return &portworxVolumeProvisioner{
|
||||
portworxVolume: &portworxVolume{
|
||||
manager: manager,
|
||||
plugin: plugin,
|
||||
},
|
||||
options: options,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) RequiresFSResize() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) ExpandVolumeDevice(
|
||||
spec *volume.Spec,
|
||||
newSize resource.Quantity,
|
||||
oldSize resource.Quantity) (resource.Quantity, error) {
|
||||
glog.V(4).Infof("Expanding: %s from %v to %v", spec.Name(), oldSize, newSize)
|
||||
err := plugin.util.ResizeVolume(spec, newSize, plugin.host)
|
||||
if err != nil {
|
||||
return oldSize, err
|
||||
}
|
||||
|
||||
glog.V(4).Infof("Successfully resized %s to %v", spec.Name(), newSize)
|
||||
return newSize, nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) {
|
||||
portworxVolume := &v1.Volume{
|
||||
Name: volumeName,
|
||||
VolumeSource: v1.VolumeSource{
|
||||
PortworxVolume: &v1.PortworxVolumeSource{
|
||||
VolumeID: volumeName,
|
||||
},
|
||||
},
|
||||
}
|
||||
return volume.NewSpecFromVolume(portworxVolume), nil
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) SupportsMountOption() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *portworxVolumePlugin) SupportsBulkVolumeVerification() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func getVolumeSource(
|
||||
spec *volume.Spec) (*v1.PortworxVolumeSource, bool, error) {
|
||||
if spec.Volume != nil && spec.Volume.PortworxVolume != nil {
|
||||
return spec.Volume.PortworxVolume, spec.Volume.PortworxVolume.ReadOnly, nil
|
||||
} else if spec.PersistentVolume != nil &&
|
||||
spec.PersistentVolume.Spec.PortworxVolume != nil {
|
||||
return spec.PersistentVolume.Spec.PortworxVolume, spec.ReadOnly, nil
|
||||
}
|
||||
|
||||
return nil, false, fmt.Errorf("Spec does not reference a Portworx Volume type")
|
||||
}
|
||||
|
||||
// Abstract interface to PD operations.
|
||||
type portworxManager interface {
|
||||
// Creates a volume
|
||||
CreateVolume(provisioner *portworxVolumeProvisioner) (volumeID string, volumeSizeGB int64, labels map[string]string, err error)
|
||||
// Deletes a volume
|
||||
DeleteVolume(deleter *portworxVolumeDeleter) error
|
||||
// Attach a volume
|
||||
AttachVolume(mounter *portworxVolumeMounter, attachOptions map[string]string) (string, error)
|
||||
// Detach a volume
|
||||
DetachVolume(unmounter *portworxVolumeUnmounter) error
|
||||
// Mount a volume
|
||||
MountVolume(mounter *portworxVolumeMounter, mountDir string) error
|
||||
// Unmount a volume
|
||||
UnmountVolume(unmounter *portworxVolumeUnmounter, mountDir string) error
|
||||
// Resize a volume
|
||||
ResizeVolume(spec *volume.Spec, newSize resource.Quantity, host volume.VolumeHost) error
|
||||
}
|
||||
|
||||
// portworxVolume volumes are portworx block devices
|
||||
// that are attached to the kubelet's host machine and exposed to the pod.
|
||||
type portworxVolume struct {
|
||||
volName string
|
||||
podUID types.UID
|
||||
// Unique id of the PD, used to find the disk resource in the provider.
|
||||
volumeID string
|
||||
// Utility interface that provides API calls to the provider to attach/detach disks.
|
||||
manager portworxManager
|
||||
// Mounter interface that provides system calls to mount the global path to the pod local path.
|
||||
mounter mount.Interface
|
||||
plugin *portworxVolumePlugin
|
||||
volume.MetricsProvider
|
||||
}
|
||||
|
||||
type portworxVolumeMounter struct {
|
||||
*portworxVolume
|
||||
// Filesystem type, optional.
|
||||
fsType string
|
||||
// Specifies whether the disk will be attached as read-only.
|
||||
readOnly bool
|
||||
// diskMounter provides the interface that is used to mount the actual block device.
|
||||
diskMounter *mount.SafeFormatAndMount
|
||||
}
|
||||
|
||||
var _ volume.Mounter = &portworxVolumeMounter{}
|
||||
|
||||
func (b *portworxVolumeMounter) GetAttributes() volume.Attributes {
|
||||
return volume.Attributes{
|
||||
ReadOnly: b.readOnly,
|
||||
Managed: !b.readOnly,
|
||||
// true ?
|
||||
SupportsSELinux: true,
|
||||
}
|
||||
}
|
||||
|
||||
// Checks prior to mount operations to verify that the required components (binaries, etc.)
|
||||
// to mount the volume are available on the underlying node.
|
||||
// If not, it returns an error
|
||||
func (b *portworxVolumeMounter) CanMount() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetUp attaches the disk and bind mounts to the volume path.
|
||||
func (b *portworxVolumeMounter) SetUp(fsGroup *int64) error {
|
||||
return b.SetUpAt(b.GetPath(), fsGroup)
|
||||
}
|
||||
|
||||
// SetUpAt attaches the disk and bind mounts to the volume path.
|
||||
func (b *portworxVolumeMounter) SetUpAt(dir string, fsGroup *int64) error {
|
||||
notMnt, err := b.mounter.IsLikelyNotMountPoint(dir)
|
||||
glog.Infof("Portworx Volume set up. Dir: %s %v %v", dir, !notMnt, err)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
glog.Errorf("Cannot validate mountpoint: %s", dir)
|
||||
return err
|
||||
}
|
||||
if !notMnt {
|
||||
return nil
|
||||
}
|
||||
|
||||
attachOptions := make(map[string]string)
|
||||
attachOptions[attachContextKey] = dir
|
||||
attachOptions[attachHostKey] = b.plugin.host.GetHostName()
|
||||
if _, err := b.manager.AttachVolume(b, attachOptions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
glog.V(4).Infof("Portworx Volume %s attached", b.volumeID)
|
||||
|
||||
if err := os.MkdirAll(dir, 0750); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := b.manager.MountVolume(b, dir); err != nil {
|
||||
return err
|
||||
}
|
||||
if !b.readOnly {
|
||||
volume.SetVolumeOwnership(b, fsGroup)
|
||||
}
|
||||
glog.Infof("Portworx Volume %s setup at %s", b.volumeID, dir)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pwx *portworxVolume) GetPath() string {
|
||||
return getPath(pwx.podUID, pwx.volName, pwx.plugin.host)
|
||||
}
|
||||
|
||||
type portworxVolumeUnmounter struct {
|
||||
*portworxVolume
|
||||
}
|
||||
|
||||
var _ volume.Unmounter = &portworxVolumeUnmounter{}
|
||||
|
||||
// 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 *portworxVolumeUnmounter) TearDown() error {
|
||||
return c.TearDownAt(c.GetPath())
|
||||
}
|
||||
|
||||
// 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 *portworxVolumeUnmounter) TearDownAt(dir string) error {
|
||||
glog.Infof("Portworx Volume TearDown of %s", dir)
|
||||
|
||||
if err := c.manager.UnmountVolume(c, dir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Call Portworx Detach Volume.
|
||||
if err := c.manager.DetachVolume(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type portworxVolumeDeleter struct {
|
||||
*portworxVolume
|
||||
}
|
||||
|
||||
var _ volume.Deleter = &portworxVolumeDeleter{}
|
||||
|
||||
func (d *portworxVolumeDeleter) GetPath() string {
|
||||
return getPath(d.podUID, d.volName, d.plugin.host)
|
||||
}
|
||||
|
||||
func (d *portworxVolumeDeleter) Delete() error {
|
||||
return d.manager.DeleteVolume(d)
|
||||
}
|
||||
|
||||
type portworxVolumeProvisioner struct {
|
||||
*portworxVolume
|
||||
options volume.VolumeOptions
|
||||
namespace string
|
||||
}
|
||||
|
||||
var _ volume.Provisioner = &portworxVolumeProvisioner{}
|
||||
|
||||
func (c *portworxVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) {
|
||||
if !util.AccessModesContainedInAll(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) {
|
||||
return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes())
|
||||
}
|
||||
|
||||
if util.CheckPersistentVolumeClaimModeBlock(c.options.PVC) {
|
||||
return nil, fmt.Errorf("%s does not support block volume provisioning", c.plugin.GetPluginName())
|
||||
}
|
||||
|
||||
volumeID, sizeGiB, labels, err := c.manager.CreateVolume(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pv := &v1.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: c.options.PVName,
|
||||
Labels: map[string]string{},
|
||||
Annotations: map[string]string{
|
||||
util.VolumeDynamicallyCreatedByKey: "portworx-volume-dynamic-provisioner",
|
||||
},
|
||||
},
|
||||
Spec: v1.PersistentVolumeSpec{
|
||||
PersistentVolumeReclaimPolicy: c.options.PersistentVolumeReclaimPolicy,
|
||||
AccessModes: c.options.PVC.Spec.AccessModes,
|
||||
Capacity: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGiB)),
|
||||
},
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||
PortworxVolume: &v1.PortworxVolumeSource{
|
||||
VolumeID: volumeID,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if len(labels) != 0 {
|
||||
if pv.Labels == nil {
|
||||
pv.Labels = make(map[string]string)
|
||||
}
|
||||
for k, v := range labels {
|
||||
pv.Labels[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.options.PVC.Spec.AccessModes) == 0 {
|
||||
pv.Spec.AccessModes = c.plugin.GetAccessModes()
|
||||
}
|
||||
|
||||
return pv, nil
|
||||
}
|
||||
237
vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_test.go
generated
vendored
Normal file
237
vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_test.go
generated
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
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 portworx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utiltesting "k8s.io/client-go/util/testing"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||
)
|
||||
|
||||
const (
|
||||
PortworxTestVolume = "portworx-test-vol"
|
||||
)
|
||||
|
||||
func TestCanSupport(t *testing.T) {
|
||||
tmpDir, err := utiltesting.MkTmpdir("portworxVolumeTest")
|
||||
if err != nil {
|
||||
t.Fatalf("can't make a temp dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
plugMgr := volume.VolumePluginMgr{}
|
||||
plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(tmpDir, nil, nil))
|
||||
|
||||
plug, err := plugMgr.FindPluginByName("kubernetes.io/portworx-volume")
|
||||
if err != nil {
|
||||
t.Errorf("Can't find the plugin by name")
|
||||
}
|
||||
if plug.GetPluginName() != "kubernetes.io/portworx-volume" {
|
||||
t.Errorf("Wrong name: %s", plug.GetPluginName())
|
||||
}
|
||||
if !plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{PortworxVolume: &v1.PortworxVolumeSource{}}}}) {
|
||||
t.Errorf("Expected true")
|
||||
}
|
||||
if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{PortworxVolume: &v1.PortworxVolumeSource{}}}}}) {
|
||||
t.Errorf("Expected true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccessModes(t *testing.T) {
|
||||
tmpDir, err := utiltesting.MkTmpdir("portworxVolumeTest")
|
||||
if err != nil {
|
||||
t.Fatalf("can't make a temp dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
plugMgr := volume.VolumePluginMgr{}
|
||||
plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(tmpDir, nil, nil))
|
||||
|
||||
plug, err := plugMgr.FindPersistentPluginByName("kubernetes.io/portworx-volume")
|
||||
if err != nil {
|
||||
t.Errorf("Can't find the plugin by name")
|
||||
}
|
||||
|
||||
if !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteOnce) {
|
||||
t.Errorf("Expected to support AccessModeTypes: %s", v1.ReadWriteOnce)
|
||||
}
|
||||
if !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteMany) {
|
||||
t.Errorf("Expected to support AccessModeTypes: %s", v1.ReadWriteMany)
|
||||
}
|
||||
if volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadOnlyMany) {
|
||||
t.Errorf("Expected not to support AccessModeTypes: %s", v1.ReadOnlyMany)
|
||||
}
|
||||
}
|
||||
|
||||
type fakePortworxManager struct {
|
||||
attachCalled bool
|
||||
mountCalled bool
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) AttachVolume(b *portworxVolumeMounter, attachOptions map[string]string) (string, error) {
|
||||
fake.attachCalled = true
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) DetachVolume(c *portworxVolumeUnmounter) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) MountVolume(b *portworxVolumeMounter, mountPath string) error {
|
||||
fake.mountCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) UnmountVolume(c *portworxVolumeUnmounter, mountPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) CreateVolume(c *portworxVolumeProvisioner) (volumeID string, volumeSizeGB int64, labels map[string]string, err error) {
|
||||
labels = make(map[string]string)
|
||||
labels["fakeportworxmanager"] = "yes"
|
||||
return PortworxTestVolume, 100, labels, nil
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) DeleteVolume(cd *portworxVolumeDeleter) error {
|
||||
if cd.volumeID != PortworxTestVolume {
|
||||
return fmt.Errorf("Deleter got unexpected volume name: %s", cd.volumeID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fake *fakePortworxManager) ResizeVolume(spec *volume.Spec, newSize resource.Quantity, volumeHost volume.VolumeHost) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestPlugin(t *testing.T) {
|
||||
tmpDir, err := utiltesting.MkTmpdir("portworxVolumeTest")
|
||||
if err != nil {
|
||||
t.Fatalf("can't make a temp dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
plugMgr := volume.VolumePluginMgr{}
|
||||
plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(tmpDir, nil, nil))
|
||||
|
||||
plug, err := plugMgr.FindPluginByName("kubernetes.io/portworx-volume")
|
||||
if err != nil {
|
||||
t.Errorf("Can't find the plugin by name")
|
||||
}
|
||||
spec := &v1.Volume{
|
||||
Name: "vol1",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
PortworxVolume: &v1.PortworxVolumeSource{
|
||||
VolumeID: PortworxTestVolume,
|
||||
FSType: "ext4",
|
||||
},
|
||||
},
|
||||
}
|
||||
fakeManager := &fakePortworxManager{}
|
||||
// Test Mounter
|
||||
fakeMounter := &mount.FakeMounter{}
|
||||
mounter, err := plug.(*portworxVolumePlugin).newMounterInternal(volume.NewSpecFromVolume(spec), types.UID("poduid"), fakeManager, fakeMounter)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to make a new Mounter: %v", err)
|
||||
}
|
||||
if mounter == nil {
|
||||
t.Errorf("Got a nil Mounter")
|
||||
}
|
||||
|
||||
volPath := path.Join(tmpDir, "pods/poduid/volumes/kubernetes.io~portworx-volume/vol1")
|
||||
path := mounter.GetPath()
|
||||
if path != volPath {
|
||||
t.Errorf("Got unexpected path: %s", path)
|
||||
}
|
||||
|
||||
if err := mounter.SetUp(nil); err != nil {
|
||||
t.Errorf("Expected success, got: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
t.Errorf("SetUp() failed, volume path not created: %s", path)
|
||||
} else {
|
||||
t.Errorf("SetUp() failed: %v", err)
|
||||
}
|
||||
}
|
||||
if !fakeManager.attachCalled {
|
||||
t.Errorf("Attach watch not called")
|
||||
}
|
||||
if !fakeManager.mountCalled {
|
||||
t.Errorf("Mount watch not called")
|
||||
}
|
||||
|
||||
// Test Unmounter
|
||||
fakeManager = &fakePortworxManager{}
|
||||
unmounter, err := plug.(*portworxVolumePlugin).newUnmounterInternal("vol1", types.UID("poduid"), fakeManager, fakeMounter)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to make a new Unmounter: %v", err)
|
||||
}
|
||||
if unmounter == nil {
|
||||
t.Errorf("Got a nil Unmounter")
|
||||
}
|
||||
|
||||
if err := unmounter.TearDown(); err != nil {
|
||||
t.Errorf("Expected success, got: %v", err)
|
||||
}
|
||||
|
||||
// Test Provisioner
|
||||
options := volume.VolumeOptions{
|
||||
PVC: volumetest.CreateTestPVC("100Gi", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}),
|
||||
PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete,
|
||||
}
|
||||
|
||||
provisioner, err := plug.(*portworxVolumePlugin).newProvisionerInternal(options, &fakePortworxManager{})
|
||||
if err != nil {
|
||||
t.Errorf("Error creating a new provisioner:%v", err)
|
||||
}
|
||||
persistentSpec, err := provisioner.Provision(nil, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Provision() failed: %v", err)
|
||||
}
|
||||
|
||||
if persistentSpec.Spec.PersistentVolumeSource.PortworxVolume.VolumeID != PortworxTestVolume {
|
||||
t.Errorf("Provision() returned unexpected volume ID: %s", persistentSpec.Spec.PersistentVolumeSource.PortworxVolume.VolumeID)
|
||||
}
|
||||
cap := persistentSpec.Spec.Capacity[v1.ResourceStorage]
|
||||
size := cap.Value()
|
||||
if size != 100*1024*1024*1024 {
|
||||
t.Errorf("Provision() returned unexpected volume size: %v", size)
|
||||
}
|
||||
|
||||
if persistentSpec.Labels["fakeportworxmanager"] != "yes" {
|
||||
t.Errorf("Provision() returned unexpected labels: %v", persistentSpec.Labels)
|
||||
}
|
||||
|
||||
// Test Deleter
|
||||
volSpec := &volume.Spec{
|
||||
PersistentVolume: persistentSpec,
|
||||
}
|
||||
deleter, err := plug.(*portworxVolumePlugin).newDeleterInternal(volSpec, &fakePortworxManager{})
|
||||
if err != nil {
|
||||
t.Errorf("Error creating a new Deleter:%v", err)
|
||||
}
|
||||
err = deleter.Delete()
|
||||
if err != nil {
|
||||
t.Errorf("Deleter() failed: %v", err)
|
||||
}
|
||||
}
|
||||
327
vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_util.go
generated
vendored
Normal file
327
vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx_util.go
generated
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
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 portworx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
osdapi "github.com/libopenstorage/openstorage/api"
|
||||
osdclient "github.com/libopenstorage/openstorage/api/client"
|
||||
volumeclient "github.com/libopenstorage/openstorage/api/client/volume"
|
||||
osdspec "github.com/libopenstorage/openstorage/api/spec"
|
||||
volumeapi "github.com/libopenstorage/openstorage/volume"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
||||
const (
|
||||
osdMgmtPort = "9001"
|
||||
osdDriverVersion = "v1"
|
||||
pxdDriverName = "pxd"
|
||||
pvcClaimLabel = "pvc"
|
||||
pvcNamespaceLabel = "namespace"
|
||||
pxServiceName = "portworx-service"
|
||||
pxDriverName = "pxd-sched"
|
||||
)
|
||||
|
||||
type PortworxVolumeUtil struct {
|
||||
portworxClient *osdclient.Client
|
||||
}
|
||||
|
||||
// CreateVolume creates a Portworx volume.
|
||||
func (util *PortworxVolumeUtil) CreateVolume(p *portworxVolumeProvisioner) (string, int64, map[string]string, error) {
|
||||
driver, err := util.getPortworxDriver(p.plugin.host, false /*localOnly*/)
|
||||
if err != nil || driver == nil {
|
||||
glog.Errorf("Failed to get portworx driver. Err: %v", err)
|
||||
return "", 0, nil, err
|
||||
}
|
||||
|
||||
glog.Infof("Creating Portworx volume for PVC: %v", p.options.PVC.Name)
|
||||
|
||||
capacity := p.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
|
||||
// Portworx Volumes are specified in GiB
|
||||
requestGiB := volutil.RoundUpToGiB(capacity)
|
||||
|
||||
// Perform a best-effort parsing of parameters. Portworx 1.2.9 and later parses volume parameters from
|
||||
// spec.VolumeLabels. So even if below SpecFromOpts() fails to parse certain parameters or
|
||||
// doesn't support new parameters, the server-side processing will parse it correctly.
|
||||
// We still need to call SpecFromOpts() here to handle cases where someone is running Portworx 1.2.8 and lower.
|
||||
specHandler := osdspec.NewSpecHandler()
|
||||
spec, locator, source, _ := specHandler.SpecFromOpts(p.options.Parameters)
|
||||
if spec == nil {
|
||||
spec = specHandler.DefaultSpec()
|
||||
}
|
||||
|
||||
// Pass all parameters as volume labels for Portworx server-side processing.
|
||||
spec.VolumeLabels = p.options.Parameters
|
||||
// Update the requested size in the spec
|
||||
spec.Size = uint64(requestGiB * volutil.GIB)
|
||||
|
||||
// Change the Portworx Volume name to PV name
|
||||
if locator == nil {
|
||||
locator = &osdapi.VolumeLocator{
|
||||
VolumeLabels: make(map[string]string),
|
||||
}
|
||||
}
|
||||
locator.Name = p.options.PVName
|
||||
|
||||
// Add claim Name as a part of Portworx Volume Labels
|
||||
locator.VolumeLabels[pvcClaimLabel] = p.options.PVC.Name
|
||||
locator.VolumeLabels[pvcNamespaceLabel] = p.options.PVC.Namespace
|
||||
|
||||
for k, v := range p.options.PVC.Annotations {
|
||||
if _, present := spec.VolumeLabels[k]; present {
|
||||
glog.Warningf("not saving annotation: %s=%s in spec labels due to an existing key", k, v)
|
||||
continue
|
||||
}
|
||||
spec.VolumeLabels[k] = v
|
||||
}
|
||||
|
||||
volumeID, err := driver.Create(locator, source, spec)
|
||||
if err != nil {
|
||||
glog.Errorf("Error creating Portworx Volume : %v", err)
|
||||
return "", 0, nil, err
|
||||
}
|
||||
|
||||
glog.Infof("Successfully created Portworx volume for PVC: %v", p.options.PVC.Name)
|
||||
return volumeID, requestGiB, nil, err
|
||||
}
|
||||
|
||||
// DeleteVolume deletes a Portworx volume
|
||||
func (util *PortworxVolumeUtil) DeleteVolume(d *portworxVolumeDeleter) error {
|
||||
driver, err := util.getPortworxDriver(d.plugin.host, false /*localOnly*/)
|
||||
if err != nil || driver == nil {
|
||||
glog.Errorf("Failed to get portworx driver. Err: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = driver.Delete(d.volumeID)
|
||||
if err != nil {
|
||||
glog.Errorf("Error deleting Portworx Volume (%v): %v", d.volName, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AttachVolume attaches a Portworx Volume
|
||||
func (util *PortworxVolumeUtil) AttachVolume(m *portworxVolumeMounter, attachOptions map[string]string) (string, error) {
|
||||
driver, err := util.getPortworxDriver(m.plugin.host, true /*localOnly*/)
|
||||
if err != nil || driver == nil {
|
||||
glog.Errorf("Failed to get portworx driver. Err: %v", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
devicePath, err := driver.Attach(m.volName, attachOptions)
|
||||
if err != nil {
|
||||
glog.Errorf("Error attaching Portworx Volume (%v): %v", m.volName, err)
|
||||
return "", err
|
||||
}
|
||||
return devicePath, nil
|
||||
}
|
||||
|
||||
// DetachVolume detaches a Portworx Volume
|
||||
func (util *PortworxVolumeUtil) DetachVolume(u *portworxVolumeUnmounter) error {
|
||||
driver, err := util.getPortworxDriver(u.plugin.host, true /*localOnly*/)
|
||||
if err != nil || driver == nil {
|
||||
glog.Errorf("Failed to get portworx driver. Err: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = driver.Detach(u.volName, false /*doNotForceDetach*/)
|
||||
if err != nil {
|
||||
glog.Errorf("Error detaching Portworx Volume (%v): %v", u.volName, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MountVolume mounts a Portworx Volume on the specified mountPath
|
||||
func (util *PortworxVolumeUtil) MountVolume(m *portworxVolumeMounter, mountPath string) error {
|
||||
driver, err := util.getPortworxDriver(m.plugin.host, true /*localOnly*/)
|
||||
if err != nil || driver == nil {
|
||||
glog.Errorf("Failed to get portworx driver. Err: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = driver.Mount(m.volName, mountPath)
|
||||
if err != nil {
|
||||
glog.Errorf("Error mounting Portworx Volume (%v) on Path (%v): %v", m.volName, mountPath, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmountVolume unmounts a Portworx Volume
|
||||
func (util *PortworxVolumeUtil) UnmountVolume(u *portworxVolumeUnmounter, mountPath string) error {
|
||||
driver, err := util.getPortworxDriver(u.plugin.host, true /*localOnly*/)
|
||||
if err != nil || driver == nil {
|
||||
glog.Errorf("Failed to get portworx driver. Err: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = driver.Unmount(u.volName, mountPath)
|
||||
if err != nil {
|
||||
glog.Errorf("Error unmounting Portworx Volume (%v) on Path (%v): %v", u.volName, mountPath, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (util *PortworxVolumeUtil) ResizeVolume(spec *volume.Spec, newSize resource.Quantity, volumeHost volume.VolumeHost) error {
|
||||
driver, err := util.getPortworxDriver(volumeHost, false /*localOnly*/)
|
||||
if err != nil || driver == nil {
|
||||
glog.Errorf("Failed to get portworx driver. Err: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
vols, err := driver.Inspect([]string{spec.Name()})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(vols) != 1 {
|
||||
return fmt.Errorf("failed to inspect Portworx volume: %s. Found: %d volumes", spec.Name(), len(vols))
|
||||
}
|
||||
|
||||
vol := vols[0]
|
||||
newSizeInBytes := uint64(volutil.RoundUpToGiB(newSize) * volutil.GIB)
|
||||
if vol.Spec.Size >= newSizeInBytes {
|
||||
glog.Infof("Portworx volume: %s already at size: %d greater than or equal to new "+
|
||||
"requested size: %d. Skipping resize.", vol.Spec.Size, newSizeInBytes)
|
||||
return nil
|
||||
}
|
||||
|
||||
vol.Spec.Size = newSizeInBytes
|
||||
err = driver.Set(spec.Name(), vol.Locator, vol.Spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check if the volume's size actually got updated
|
||||
vols, err = driver.Inspect([]string{spec.Name()})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(vols) != 1 {
|
||||
return fmt.Errorf("failed to inspect resized Portworx volume: %s. Found: %d volumes", spec.Name(), len(vols))
|
||||
}
|
||||
|
||||
updatedVol := vols[0]
|
||||
if updatedVol.Spec.Size < vol.Spec.Size {
|
||||
return fmt.Errorf("Portworx volume: %s doesn't match expected size after resize. expected:%v actual:%v",
|
||||
spec.Name(), vol.Spec.Size, updatedVol.Spec.Size)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func isClientValid(client *osdclient.Client) (bool, error) {
|
||||
if client == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
_, err := client.Versions(osdapi.OsdVolumePath)
|
||||
if err != nil {
|
||||
glog.Errorf("portworx client failed driver versions check. Err: %v", err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func createDriverClient(hostname string) (*osdclient.Client, error) {
|
||||
client, err := volumeclient.NewDriverClient("http://"+hostname+":"+osdMgmtPort,
|
||||
pxdDriverName, osdDriverVersion, pxDriverName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if isValid, err := isClientValid(client); isValid {
|
||||
return client, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// getPortworxDriver() returns a Portworx volume driver which can be used for volume operations
|
||||
// localOnly: If true, the returned driver will be connected to Portworx API server on volume host.
|
||||
// If false, driver will be connected to API server on volume host or Portworx k8s service cluster IP
|
||||
// This flag is required to explicitly force certain operations (mount, unmount, detach, attach) to
|
||||
// go to the volume host instead of the k8s service which might route it to any host. This pertains to how
|
||||
// Portworx mounts and attaches a volume to the running container. The node getting these requests needs to
|
||||
// see the pod container mounts (specifically /var/lib/kubelet/pods/<pod_id>)
|
||||
// Operations like create and delete volume don't need to be restricted to local volume host since
|
||||
// any node in the Portworx cluster can co-ordinate the create/delete request and forward the operations to
|
||||
// the Portworx node that will own/owns the data.
|
||||
func (util *PortworxVolumeUtil) getPortworxDriver(volumeHost volume.VolumeHost, localOnly bool) (volumeapi.VolumeDriver, error) {
|
||||
var err error
|
||||
if localOnly {
|
||||
util.portworxClient, err = createDriverClient(volumeHost.GetHostName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
glog.V(4).Infof("Using portworx local service at: %v as api endpoint", volumeHost.GetHostName())
|
||||
return volumeclient.VolumeDriver(util.portworxClient), nil
|
||||
}
|
||||
}
|
||||
|
||||
// check if existing saved client is valid
|
||||
if isValid, _ := isClientValid(util.portworxClient); isValid {
|
||||
return volumeclient.VolumeDriver(util.portworxClient), nil
|
||||
}
|
||||
|
||||
// create new client
|
||||
util.portworxClient, err = createDriverClient(volumeHost.GetHostName()) // for backward compatibility
|
||||
if err != nil || util.portworxClient == nil {
|
||||
// Create client from portworx service
|
||||
kubeClient := volumeHost.GetKubeClient()
|
||||
if kubeClient == nil {
|
||||
glog.Error("Failed to get kubeclient when creating portworx client")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
opts := metav1.GetOptions{}
|
||||
svc, err := kubeClient.CoreV1().Services(api.NamespaceSystem).Get(pxServiceName, opts)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to get service. Err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if svc == nil {
|
||||
glog.Errorf("Service: %v not found. Consult Portworx docs to deploy it.", pxServiceName)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
util.portworxClient, err = createDriverClient(svc.Spec.ClusterIP)
|
||||
if err != nil || util.portworxClient == nil {
|
||||
glog.Errorf("Failed to connect to portworx service. Err: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
glog.Infof("Using portworx cluster service at: %v as api endpoint", svc.Spec.ClusterIP)
|
||||
} else {
|
||||
glog.Infof("Using portworx service at: %v as api endpoint", volumeHost.GetHostName())
|
||||
}
|
||||
|
||||
return volumeclient.VolumeDriver(util.portworxClient), nil
|
||||
}
|
||||
Reference in New Issue
Block a user