cleanup: Remove quobyte volume plugins from k8s codebase
This commit is contained in:
parent
83591a1196
commit
9c869b3dfc
32
LICENSES/vendor/github.com/quobyte/api/LICENSE
generated
vendored
32
LICENSES/vendor/github.com/quobyte/api/LICENSE
generated
vendored
@ -1,32 +0,0 @@
|
|||||||
= vendor/github.com/quobyte/api licensed under: =
|
|
||||||
|
|
||||||
|
|
||||||
Copyright (c) 2016, Quobyte Inc.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of quobyte-automation nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
= vendor/github.com/quobyte/api/LICENSE beacc5ea3bcda24bdcec545022dbb0b4
|
|
@ -40,7 +40,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/volume/iscsi"
|
"k8s.io/kubernetes/pkg/volume/iscsi"
|
||||||
"k8s.io/kubernetes/pkg/volume/local"
|
"k8s.io/kubernetes/pkg/volume/local"
|
||||||
"k8s.io/kubernetes/pkg/volume/nfs"
|
"k8s.io/kubernetes/pkg/volume/nfs"
|
||||||
"k8s.io/kubernetes/pkg/volume/quobyte"
|
|
||||||
"k8s.io/kubernetes/pkg/volume/storageos"
|
"k8s.io/kubernetes/pkg/volume/storageos"
|
||||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
|
|
||||||
@ -125,8 +124,7 @@ func ProbeControllerVolumePlugins(cloud cloudprovider.Interface, config persiste
|
|||||||
}
|
}
|
||||||
allPlugins = append(allPlugins, nfs.ProbeVolumePlugins(nfsConfig)...)
|
allPlugins = append(allPlugins, nfs.ProbeVolumePlugins(nfsConfig)...)
|
||||||
allPlugins = append(allPlugins, glusterfs.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, glusterfs.ProbeVolumePlugins()...)
|
||||||
// add rbd provisioner
|
|
||||||
allPlugins = append(allPlugins, quobyte.ProbeVolumePlugins()...)
|
|
||||||
var err error
|
var err error
|
||||||
allPlugins, err = appendExpandableLegacyProviderVolumes(allPlugins, utilfeature.DefaultFeatureGate)
|
allPlugins, err = appendExpandableLegacyProviderVolumes(allPlugins, utilfeature.DefaultFeatureGate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -38,7 +38,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/volume/local"
|
"k8s.io/kubernetes/pkg/volume/local"
|
||||||
"k8s.io/kubernetes/pkg/volume/nfs"
|
"k8s.io/kubernetes/pkg/volume/nfs"
|
||||||
"k8s.io/kubernetes/pkg/volume/projected"
|
"k8s.io/kubernetes/pkg/volume/projected"
|
||||||
"k8s.io/kubernetes/pkg/volume/quobyte"
|
|
||||||
"k8s.io/kubernetes/pkg/volume/secret"
|
"k8s.io/kubernetes/pkg/volume/secret"
|
||||||
"k8s.io/kubernetes/pkg/volume/storageos"
|
"k8s.io/kubernetes/pkg/volume/storageos"
|
||||||
|
|
||||||
@ -68,7 +67,6 @@ func ProbeVolumePlugins(featureGate featuregate.FeatureGate) ([]volume.VolumePlu
|
|||||||
allPlugins = append(allPlugins, secret.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, secret.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, iscsi.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, iscsi.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, glusterfs.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, glusterfs.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, quobyte.ProbeVolumePlugins()...)
|
|
||||||
allPlugins = append(allPlugins, cephfs.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, cephfs.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, downwardapi.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, downwardapi.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...)
|
||||||
|
2
go.mod
2
go.mod
@ -63,7 +63,6 @@ require (
|
|||||||
github.com/prometheus/client_golang v1.12.1
|
github.com/prometheus/client_golang v1.12.1
|
||||||
github.com/prometheus/client_model v0.2.0
|
github.com/prometheus/client_model v0.2.0
|
||||||
github.com/prometheus/common v0.32.1
|
github.com/prometheus/common v0.32.1
|
||||||
github.com/quobyte/api v0.1.8
|
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/spf13/cobra v1.4.0
|
github.com/spf13/cobra v1.4.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
@ -473,7 +472,6 @@ replace (
|
|||||||
github.com/prometheus/client_model => github.com/prometheus/client_model v0.2.0
|
github.com/prometheus/client_model => github.com/prometheus/client_model v0.2.0
|
||||||
github.com/prometheus/common => github.com/prometheus/common v0.32.1
|
github.com/prometheus/common => github.com/prometheus/common v0.32.1
|
||||||
github.com/prometheus/procfs => github.com/prometheus/procfs v0.7.3
|
github.com/prometheus/procfs => github.com/prometheus/procfs v0.7.3
|
||||||
github.com/quobyte/api => github.com/quobyte/api v0.1.8
|
|
||||||
github.com/remyoudompheng/bigfft => github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446
|
github.com/remyoudompheng/bigfft => github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446
|
||||||
github.com/robfig/cron/v3 => github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 => github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/rogpeppe/fastuuid => github.com/rogpeppe/fastuuid v1.2.0
|
github.com/rogpeppe/fastuuid => github.com/rogpeppe/fastuuid v1.2.0
|
||||||
|
2
go.sum
2
go.sum
@ -367,8 +367,6 @@ github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuI
|
|||||||
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
||||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
github.com/quobyte/api v0.1.8 h1:+sOX1gIlC/OaLipqVZWrHgly9Kh9Qo8OygeS0mWAg30=
|
|
||||||
github.com/quobyte/api v0.1.8/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI=
|
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
|
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
|
||||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||||
|
@ -53,7 +53,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/volume/nfs"
|
"k8s.io/kubernetes/pkg/volume/nfs"
|
||||||
"k8s.io/kubernetes/pkg/volume/portworx"
|
"k8s.io/kubernetes/pkg/volume/portworx"
|
||||||
"k8s.io/kubernetes/pkg/volume/projected"
|
"k8s.io/kubernetes/pkg/volume/projected"
|
||||||
"k8s.io/kubernetes/pkg/volume/quobyte"
|
|
||||||
"k8s.io/kubernetes/pkg/volume/rbd"
|
"k8s.io/kubernetes/pkg/volume/rbd"
|
||||||
"k8s.io/kubernetes/pkg/volume/secret"
|
"k8s.io/kubernetes/pkg/volume/secret"
|
||||||
"k8s.io/kubernetes/pkg/volume/storageos"
|
"k8s.io/kubernetes/pkg/volume/storageos"
|
||||||
@ -78,7 +77,6 @@ func volumePlugins() []volume.VolumePlugin {
|
|||||||
allPlugins = append(allPlugins, iscsi.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, iscsi.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, glusterfs.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, glusterfs.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, rbd.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, rbd.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, quobyte.ProbeVolumePlugins()...)
|
|
||||||
allPlugins = append(allPlugins, cephfs.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, cephfs.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, downwardapi.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, downwardapi.ProbeVolumePlugins()...)
|
||||||
allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...)
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
# See the OWNERS docs at https://go.k8s.io/owners
|
|
||||||
|
|
||||||
approvers:
|
|
||||||
- saad-ali
|
|
||||||
reviewers:
|
|
||||||
- saad-ali
|
|
||||||
- jsafrane
|
|
||||||
- jingxu97
|
|
||||||
- msau42
|
|
||||||
emeritus_approvers:
|
|
||||||
- rootfs
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 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 quobyte contains the internal representation of Quobyte
|
|
||||||
// volumes.
|
|
||||||
package quobyte
|
|
@ -1,513 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 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 quobyte
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
gostrings "strings"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"k8s.io/klog/v2"
|
|
||||||
"k8s.io/mount-utils"
|
|
||||||
utilstrings "k8s.io/utils/strings"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ProbeVolumePlugins is the primary entrypoint for volume plugins.
|
|
||||||
func ProbeVolumePlugins() []volume.VolumePlugin {
|
|
||||||
return []volume.VolumePlugin{&quobytePlugin{nil}}
|
|
||||||
}
|
|
||||||
|
|
||||||
type quobytePlugin struct {
|
|
||||||
host volume.VolumeHost
|
|
||||||
}
|
|
||||||
|
|
||||||
// This user is used to authenticate against the
|
|
||||||
// Quobyte API server and holds all information
|
|
||||||
type quobyteAPIConfig struct {
|
|
||||||
quobyteUser string
|
|
||||||
quobytePassword string `datapolicy:"password"`
|
|
||||||
quobyteAPIServer string
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ volume.VolumePlugin = &quobytePlugin{}
|
|
||||||
var _ volume.PersistentVolumePlugin = &quobytePlugin{}
|
|
||||||
var _ volume.DeletableVolumePlugin = &quobytePlugin{}
|
|
||||||
var _ volume.ProvisionableVolumePlugin = &quobytePlugin{}
|
|
||||||
var _ volume.Provisioner = &quobyteVolumeProvisioner{}
|
|
||||||
var _ volume.Deleter = &quobyteVolumeDeleter{}
|
|
||||||
|
|
||||||
const (
|
|
||||||
quobytePluginName = "kubernetes.io/quobyte"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) Init(host volume.VolumeHost) error {
|
|
||||||
if host == nil {
|
|
||||||
return errors.New("host must not be nil")
|
|
||||||
}
|
|
||||||
plugin.host = host
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) GetPluginName() string {
|
|
||||||
return quobytePluginName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) GetVolumeName(spec *volume.Spec) (string, error) {
|
|
||||||
volumeSource, _, err := getVolumeSource(spec)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"%v:%v",
|
|
||||||
volumeSource.Registry,
|
|
||||||
volumeSource.Volume), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) CanSupport(spec *volume.Spec) bool {
|
|
||||||
if (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Quobyte == nil) ||
|
|
||||||
(spec.Volume != nil && spec.Volume.Quobyte == nil) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// If Quobyte is already mounted we don't need to check if the binary is installed
|
|
||||||
if mounter, err := plugin.newMounterInternal(spec, nil, plugin.host.GetMounter(plugin.GetPluginName())); err == nil {
|
|
||||||
qm, _ := mounter.(*quobyteMounter)
|
|
||||||
pluginDir := plugin.host.GetPluginDir(utilstrings.EscapeQualifiedName(quobytePluginName))
|
|
||||||
if mounted, err := qm.pluginDirIsMounted(pluginDir); mounted && err == nil {
|
|
||||||
klog.V(4).Infof("quobyte: can support")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
klog.V(4).Infof("quobyte: Error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
exec := plugin.host.GetExec(plugin.GetPluginName())
|
|
||||||
if out, err := exec.Command("ls", "/sbin/mount.quobyte").CombinedOutput(); err == nil {
|
|
||||||
klog.V(4).Infof("quobyte: can support: %s", string(out))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) RequiresRemount(spec *volume.Spec) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) SupportsMountOption() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) SupportsBulkVolumeVerification() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) GetAccessModes() []v1.PersistentVolumeAccessMode {
|
|
||||||
return []v1.PersistentVolumeAccessMode{
|
|
||||||
v1.ReadWriteOnce,
|
|
||||||
v1.ReadOnlyMany,
|
|
||||||
v1.ReadWriteMany,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getVolumeSource(spec *volume.Spec) (*v1.QuobyteVolumeSource, bool, error) {
|
|
||||||
if spec.Volume != nil && spec.Volume.Quobyte != nil {
|
|
||||||
return spec.Volume.Quobyte, spec.Volume.Quobyte.ReadOnly, nil
|
|
||||||
} else if spec.PersistentVolume != nil &&
|
|
||||||
spec.PersistentVolume.Spec.Quobyte != nil {
|
|
||||||
return spec.PersistentVolume.Spec.Quobyte, spec.ReadOnly, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false, fmt.Errorf("Spec does not reference a Quobyte volume type")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) {
|
|
||||||
quobyteVolume := &v1.Volume{
|
|
||||||
Name: volumeName,
|
|
||||||
VolumeSource: v1.VolumeSource{
|
|
||||||
Quobyte: &v1.QuobyteVolumeSource{
|
|
||||||
Volume: volumeName,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return volume.NewSpecFromVolume(quobyteVolume), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) {
|
|
||||||
return plugin.newMounterInternal(spec, pod, plugin.host.GetMounter(plugin.GetPluginName()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod, mounter mount.Interface) (volume.Mounter, error) {
|
|
||||||
source, readOnly, err := getVolumeSource(spec)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &quobyteMounter{
|
|
||||||
quobyte: &quobyte{
|
|
||||||
volName: spec.Name(),
|
|
||||||
user: source.User,
|
|
||||||
group: source.Group,
|
|
||||||
mounter: mounter,
|
|
||||||
pod: pod,
|
|
||||||
volume: source.Volume,
|
|
||||||
plugin: plugin,
|
|
||||||
},
|
|
||||||
registry: source.Registry,
|
|
||||||
readOnly: readOnly,
|
|
||||||
mountOptions: util.MountOptionFromSpec(spec),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) {
|
|
||||||
return plugin.newUnmounterInternal(volName, podUID, plugin.host.GetMounter(plugin.GetPluginName()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) newUnmounterInternal(volName string, podUID types.UID, mounter mount.Interface) (volume.Unmounter, error) {
|
|
||||||
return &quobyteUnmounter{
|
|
||||||
&quobyte{
|
|
||||||
volName: volName,
|
|
||||||
mounter: mounter,
|
|
||||||
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: podUID}},
|
|
||||||
plugin: plugin,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quobyte volumes represent a bare host directory mount of an quobyte export.
|
|
||||||
type quobyte struct {
|
|
||||||
volName string
|
|
||||||
pod *v1.Pod
|
|
||||||
user string
|
|
||||||
group string
|
|
||||||
volume string
|
|
||||||
tenant string
|
|
||||||
config string
|
|
||||||
mounter mount.Interface
|
|
||||||
plugin *quobytePlugin
|
|
||||||
volume.MetricsNil
|
|
||||||
}
|
|
||||||
|
|
||||||
type quobyteMounter struct {
|
|
||||||
*quobyte
|
|
||||||
registry string
|
|
||||||
readOnly bool
|
|
||||||
mountOptions []string
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ volume.Mounter = &quobyteMounter{}
|
|
||||||
|
|
||||||
func (mounter *quobyteMounter) GetAttributes() volume.Attributes {
|
|
||||||
return volume.Attributes{
|
|
||||||
ReadOnly: mounter.readOnly,
|
|
||||||
Managed: false,
|
|
||||||
SELinuxRelabel: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetUp attaches the disk and bind mounts to the volume path.
|
|
||||||
func (mounter *quobyteMounter) SetUp(mounterArgs volume.MounterArgs) error {
|
|
||||||
pluginDir := mounter.plugin.host.GetPluginDir(utilstrings.EscapeQualifiedName(quobytePluginName))
|
|
||||||
return mounter.SetUpAt(pluginDir, mounterArgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mounter *quobyteMounter) SetUpAt(dir string, mounterArgs volume.MounterArgs) error {
|
|
||||||
// Check if Quobyte is already mounted on the host in the Plugin Dir
|
|
||||||
// if so we can use this mountpoint instead of creating a new one
|
|
||||||
// IsLikelyNotMountPoint wouldn't check the mount type
|
|
||||||
if mounted, err := mounter.pluginDirIsMounted(dir); err != nil {
|
|
||||||
return err
|
|
||||||
} else if mounted {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := os.MkdirAll(dir, 0750); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var options []string
|
|
||||||
options = append(options, "allow-usermapping-in-volumename")
|
|
||||||
if mounter.readOnly {
|
|
||||||
options = append(options, "ro")
|
|
||||||
}
|
|
||||||
|
|
||||||
//if a trailing slash is missing we add it here
|
|
||||||
mountOptions := util.JoinMountOptions(mounter.mountOptions, options)
|
|
||||||
if err := mounter.mounter.MountSensitiveWithoutSystemd(mounter.correctTraillingSlash(mounter.registry), dir, "quobyte", mountOptions, nil); err != nil {
|
|
||||||
return fmt.Errorf("quobyte: mount failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
klog.V(4).Infof("quobyte: mount set up: %s", dir)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPath returns the path to the user specific mount of a Quobyte volume
|
|
||||||
// Returns a path in the format ../user#group@volume
|
|
||||||
func (quobyteVolume *quobyte) GetPath() string {
|
|
||||||
user := quobyteVolume.user
|
|
||||||
if len(user) == 0 {
|
|
||||||
user = "root"
|
|
||||||
}
|
|
||||||
|
|
||||||
group := quobyteVolume.group
|
|
||||||
if len(group) == 0 {
|
|
||||||
group = "nfsnobody"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quobyte has only one mount in the PluginDir where all Volumes are mounted
|
|
||||||
// The Quobyte client does a fixed-user mapping
|
|
||||||
pluginDir := quobyteVolume.plugin.host.GetPluginDir(utilstrings.EscapeQualifiedName(quobytePluginName))
|
|
||||||
return filepath.Join(pluginDir, fmt.Sprintf("%s#%s@%s", user, group, quobyteVolume.volume))
|
|
||||||
}
|
|
||||||
|
|
||||||
type quobyteUnmounter struct {
|
|
||||||
*quobyte
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ volume.Unmounter = &quobyteUnmounter{}
|
|
||||||
|
|
||||||
func (unmounter *quobyteUnmounter) TearDown() error {
|
|
||||||
return unmounter.TearDownAt(unmounter.GetPath())
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't need to unmount on the host because only one mount exists
|
|
||||||
func (unmounter *quobyteUnmounter) TearDownAt(dir string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type quobyteVolumeDeleter struct {
|
|
||||||
*quobyteMounter
|
|
||||||
pv *v1.PersistentVolume
|
|
||||||
dialOptions *proxyutil.FilteredDialOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) NewDeleter(spec *volume.Spec) (volume.Deleter, error) {
|
|
||||||
if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Quobyte == nil {
|
|
||||||
return nil, fmt.Errorf("spec.PersistentVolume.Spec.Quobyte is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
return plugin.newDeleterInternal(spec)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) newDeleterInternal(spec *volume.Spec) (volume.Deleter, error) {
|
|
||||||
source, readOnly, err := getVolumeSource(spec)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if plugin.host == nil {
|
|
||||||
return nil, errors.New("host must not be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &quobyteVolumeDeleter{
|
|
||||||
quobyteMounter: &quobyteMounter{
|
|
||||||
quobyte: &quobyte{
|
|
||||||
volName: spec.Name(),
|
|
||||||
user: source.User,
|
|
||||||
group: source.Group,
|
|
||||||
volume: source.Volume,
|
|
||||||
plugin: plugin,
|
|
||||||
tenant: source.Tenant,
|
|
||||||
},
|
|
||||||
registry: source.Registry,
|
|
||||||
readOnly: readOnly,
|
|
||||||
},
|
|
||||||
pv: spec.PersistentVolume,
|
|
||||||
dialOptions: plugin.host.GetFilteredDialOptions(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) {
|
|
||||||
return plugin.newProvisionerInternal(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (plugin *quobytePlugin) newProvisionerInternal(options volume.VolumeOptions) (volume.Provisioner, error) {
|
|
||||||
if plugin.host == nil {
|
|
||||||
return nil, errors.New("host must not be nil")
|
|
||||||
}
|
|
||||||
return &quobyteVolumeProvisioner{
|
|
||||||
quobyteMounter: &quobyteMounter{
|
|
||||||
quobyte: &quobyte{
|
|
||||||
plugin: plugin,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
options: options,
|
|
||||||
dialOptions: plugin.host.GetFilteredDialOptions(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type quobyteVolumeProvisioner struct {
|
|
||||||
*quobyteMounter
|
|
||||||
options volume.VolumeOptions
|
|
||||||
dialOptions *proxyutil.FilteredDialOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (provisioner *quobyteVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) {
|
|
||||||
if !util.ContainsAllAccessModes(provisioner.plugin.GetAccessModes(), provisioner.options.PVC.Spec.AccessModes) {
|
|
||||||
return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", provisioner.options.PVC.Spec.AccessModes, provisioner.plugin.GetAccessModes())
|
|
||||||
}
|
|
||||||
|
|
||||||
if util.CheckPersistentVolumeClaimModeBlock(provisioner.options.PVC) {
|
|
||||||
return nil, fmt.Errorf("%s does not support block volume provisioning", provisioner.plugin.GetPluginName())
|
|
||||||
}
|
|
||||||
|
|
||||||
if provisioner.options.PVC.Spec.Selector != nil {
|
|
||||||
return nil, fmt.Errorf("claim Selector is not supported")
|
|
||||||
}
|
|
||||||
provisioner.config = "BASE"
|
|
||||||
provisioner.tenant = "DEFAULT"
|
|
||||||
createQuota := false
|
|
||||||
|
|
||||||
cfg, err := parseAPIConfig(provisioner.plugin, provisioner.options.Parameters)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for k, v := range provisioner.options.Parameters {
|
|
||||||
switch gostrings.ToLower(k) {
|
|
||||||
case "registry":
|
|
||||||
provisioner.registry = v
|
|
||||||
case "user":
|
|
||||||
provisioner.user = v
|
|
||||||
case "group":
|
|
||||||
provisioner.group = v
|
|
||||||
case "quobytetenant":
|
|
||||||
provisioner.tenant = v
|
|
||||||
case "quobyteconfig":
|
|
||||||
provisioner.config = v
|
|
||||||
case "createquota":
|
|
||||||
createQuota = gostrings.ToLower(v) == "true"
|
|
||||||
case "adminsecretname",
|
|
||||||
"adminsecretnamespace",
|
|
||||||
"quobyteapiserver":
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("invalid option %q for volume plugin %s", k, provisioner.plugin.GetPluginName())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !validateRegistry(provisioner.registry) {
|
|
||||||
return nil, fmt.Errorf("quobyte registry missing or malformed: must be a host:port pair or multiple pairs separated by commas")
|
|
||||||
}
|
|
||||||
|
|
||||||
// create random image name
|
|
||||||
provisioner.volume = fmt.Sprintf("kubernetes-dynamic-pvc-%s", uuid.New().String())
|
|
||||||
|
|
||||||
manager := &quobyteVolumeManager{
|
|
||||||
config: cfg,
|
|
||||||
dialOptions: provisioner.dialOptions,
|
|
||||||
}
|
|
||||||
|
|
||||||
vol, sizeGB, err := manager.createVolume(provisioner, createQuota)
|
|
||||||
if err != nil {
|
|
||||||
// don't log error details from client calls in events
|
|
||||||
klog.V(4).Infof("CreateVolume failed: %v", err)
|
|
||||||
return nil, errors.New("CreateVolume failed: see kube-controller-manager.log for details")
|
|
||||||
}
|
|
||||||
pv := new(v1.PersistentVolume)
|
|
||||||
metav1.SetMetaDataAnnotation(&pv.ObjectMeta, util.VolumeDynamicallyCreatedByKey, "quobyte-dynamic-provisioner")
|
|
||||||
pv.Spec.PersistentVolumeSource.Quobyte = vol
|
|
||||||
pv.Spec.PersistentVolumeReclaimPolicy = provisioner.options.PersistentVolumeReclaimPolicy
|
|
||||||
pv.Spec.AccessModes = provisioner.options.PVC.Spec.AccessModes
|
|
||||||
if len(pv.Spec.AccessModes) == 0 {
|
|
||||||
pv.Spec.AccessModes = provisioner.plugin.GetAccessModes()
|
|
||||||
}
|
|
||||||
pv.Spec.Capacity = v1.ResourceList{
|
|
||||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)),
|
|
||||||
}
|
|
||||||
pv.Spec.MountOptions = provisioner.options.MountOptions
|
|
||||||
pv.Spec.PersistentVolumeSource.Quobyte.Tenant = provisioner.tenant
|
|
||||||
return pv, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (deleter *quobyteVolumeDeleter) GetPath() string {
|
|
||||||
return deleter.quobyte.GetPath()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (deleter *quobyteVolumeDeleter) Delete() error {
|
|
||||||
class, err := util.GetClassForVolume(deleter.plugin.host.GetKubeClient(), deleter.pv)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg, err := parseAPIConfig(deleter.plugin, class.Parameters)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
manager := &quobyteVolumeManager{
|
|
||||||
config: cfg,
|
|
||||||
dialOptions: deleter.dialOptions,
|
|
||||||
}
|
|
||||||
err = manager.deleteVolume(deleter)
|
|
||||||
if err != nil {
|
|
||||||
// don't log error details from client calls in events
|
|
||||||
klog.V(4).Infof("DeleteVolume failed: %v", err)
|
|
||||||
return errors.New("DeleteVolume failed: see kube-controller-manager.log for details")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse API configuration (url, username and password) out of class.Parameters.
|
|
||||||
func parseAPIConfig(plugin *quobytePlugin, params map[string]string) (*quobyteAPIConfig, error) {
|
|
||||||
var apiServer, secretName string
|
|
||||||
secretNamespace := "default"
|
|
||||||
|
|
||||||
for k, v := range params {
|
|
||||||
switch gostrings.ToLower(k) {
|
|
||||||
case "adminsecretname":
|
|
||||||
secretName = v
|
|
||||||
case "adminsecretnamespace":
|
|
||||||
secretNamespace = v
|
|
||||||
case "quobyteapiserver":
|
|
||||||
apiServer = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(apiServer) == 0 {
|
|
||||||
return nil, fmt.Errorf("quobyte API server missing or malformed: must be a http(s)://host:port pair or multiple pairs separated by commas")
|
|
||||||
}
|
|
||||||
|
|
||||||
secretMap, err := util.GetSecretForPV(secretNamespace, secretName, quobytePluginName, plugin.host.GetKubeClient())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := &quobyteAPIConfig{
|
|
||||||
quobyteAPIServer: apiServer,
|
|
||||||
}
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
if cfg.quobyteUser, ok = secretMap["user"]; !ok {
|
|
||||||
return nil, fmt.Errorf("missing \"user\" in secret %s/%s", secretNamespace, secretName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg.quobytePassword, ok = secretMap["password"]; !ok {
|
|
||||||
return nil, fmt.Errorf("missing \"password\" in secret %s/%s", secretNamespace, secretName)
|
|
||||||
}
|
|
||||||
|
|
||||||
return cfg, nil
|
|
||||||
}
|
|
@ -1,197 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 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 quobyte
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"k8s.io/mount-utils"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
|
||||||
utiltesting "k8s.io/client-go/util/testing"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
|
||||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCanSupport(t *testing.T) {
|
|
||||||
tmpDir, err := utiltesting.MkTmpdir("quobyte_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error creating temp dir: %v", err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(tmpDir)
|
|
||||||
|
|
||||||
plugMgr := volume.VolumePluginMgr{}
|
|
||||||
plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
|
|
||||||
plug, err := plugMgr.FindPluginByName("kubernetes.io/quobyte")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Can't find the plugin by name")
|
|
||||||
}
|
|
||||||
if plug.GetPluginName() != "kubernetes.io/quobyte" {
|
|
||||||
t.Errorf("Wrong name: %s", plug.GetPluginName())
|
|
||||||
}
|
|
||||||
if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{}}}}) {
|
|
||||||
t.Errorf("Expected false")
|
|
||||||
}
|
|
||||||
if plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{}}}) {
|
|
||||||
t.Errorf("Expected false")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetAccessModes(t *testing.T) {
|
|
||||||
tmpDir, err := utiltesting.MkTmpdir("quobyte_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error creating temp dir: %v", err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(tmpDir)
|
|
||||||
|
|
||||||
plugMgr := volume.VolumePluginMgr{}
|
|
||||||
plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
|
|
||||||
|
|
||||||
plug, err := plugMgr.FindPersistentPluginByName("kubernetes.io/quobyte")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Can't find the plugin by name")
|
|
||||||
}
|
|
||||||
if !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteOnce) || !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadOnlyMany) || !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteMany) {
|
|
||||||
t.Errorf("Expected three AccessModeTypes: %s, %s, and %s", v1.ReadWriteOnce, v1.ReadOnlyMany, v1.ReadWriteMany)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func doTestPlugin(t *testing.T, spec *volume.Spec) {
|
|
||||||
tmpDir, err := utiltesting.MkTmpdir("quobyte_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error creating temp dir: %v", err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(tmpDir)
|
|
||||||
|
|
||||||
plugMgr := volume.VolumePluginMgr{}
|
|
||||||
plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil))
|
|
||||||
plug, err := plugMgr.FindPluginByName("kubernetes.io/quobyte")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Can't find the plugin by name")
|
|
||||||
}
|
|
||||||
|
|
||||||
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
|
|
||||||
mounter, err := plug.(*quobytePlugin).newMounterInternal(spec, pod, mount.NewFakeMounter(nil))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to make a new Mounter: %v", err)
|
|
||||||
}
|
|
||||||
if mounter == nil {
|
|
||||||
t.Fatal("Got a nil Mounter")
|
|
||||||
}
|
|
||||||
|
|
||||||
volumePath := mounter.GetPath()
|
|
||||||
if volumePath != filepath.Join(tmpDir, "plugins/kubernetes.io~quobyte/root#root@vol") {
|
|
||||||
t.Errorf("Got unexpected path: %s expected: %s", volumePath, fmt.Sprintf("%s/plugins/kubernetes.io~quobyte/root#root@vol", tmpDir))
|
|
||||||
}
|
|
||||||
if err := mounter.SetUp(volume.MounterArgs{}); err != nil {
|
|
||||||
t.Errorf("Expected success, got: %v", err)
|
|
||||||
}
|
|
||||||
unmounter, err := plug.(*quobytePlugin).newUnmounterInternal("vol", types.UID("poduid"), mount.NewFakeMounter(nil))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to make a new unmounter: %v", err)
|
|
||||||
}
|
|
||||||
if unmounter == nil {
|
|
||||||
t.Error("Got a nil unmounter")
|
|
||||||
}
|
|
||||||
if err := unmounter.TearDown(); err != nil {
|
|
||||||
t.Errorf("Expected success, got: %v", err)
|
|
||||||
}
|
|
||||||
// We don't need to check tear down, we don't unmount quobyte
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPluginVolume(t *testing.T) {
|
|
||||||
vol := &v1.Volume{
|
|
||||||
Name: "vol1",
|
|
||||||
VolumeSource: v1.VolumeSource{
|
|
||||||
Quobyte: &v1.QuobyteVolumeSource{Registry: "reg:7861", Volume: "vol", ReadOnly: false, User: "root", Group: "root"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
doTestPlugin(t, volume.NewSpecFromVolume(vol))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPluginPersistentVolume(t *testing.T) {
|
|
||||||
vol := &v1.PersistentVolume{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "vol1",
|
|
||||||
},
|
|
||||||
Spec: v1.PersistentVolumeSpec{
|
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
|
||||||
Quobyte: &v1.QuobyteVolumeSource{Registry: "reg:7861", Volume: "vol", ReadOnly: false, User: "root", Group: "root"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPersistentClaimReadOnlyFlag(t *testing.T) {
|
|
||||||
pv := &v1.PersistentVolume{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "pvA",
|
|
||||||
},
|
|
||||||
Spec: v1.PersistentVolumeSpec{
|
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
|
||||||
Quobyte: &v1.QuobyteVolumeSource{Registry: "reg:7861", Volume: "vol", ReadOnly: false, User: "root", Group: "root"},
|
|
||||||
},
|
|
||||||
ClaimRef: &v1.ObjectReference{
|
|
||||||
Name: "claimA",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
claim := &v1.PersistentVolumeClaim{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "claimA",
|
|
||||||
Namespace: "nsA",
|
|
||||||
},
|
|
||||||
Spec: v1.PersistentVolumeClaimSpec{
|
|
||||||
VolumeName: "pvA",
|
|
||||||
},
|
|
||||||
Status: v1.PersistentVolumeClaimStatus{
|
|
||||||
Phase: v1.ClaimBound,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDir, err := utiltesting.MkTmpdir("quobyte_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error creating temp dir: %v", err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(tmpDir)
|
|
||||||
|
|
||||||
client := fake.NewSimpleClientset(pv, claim)
|
|
||||||
plugMgr := volume.VolumePluginMgr{}
|
|
||||||
plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, client, nil))
|
|
||||||
plug, _ := plugMgr.FindPluginByName(quobytePluginName)
|
|
||||||
|
|
||||||
// readOnly bool is supplied by persistent-claim volume source when its mounter creates other volumes
|
|
||||||
spec := volume.NewSpecFromPersistentVolume(pv, true)
|
|
||||||
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
|
|
||||||
mounter, _ := plug.NewMounter(spec, pod, volume.VolumeOptions{})
|
|
||||||
if mounter == nil {
|
|
||||||
t.Fatalf("Got a nil Mounter")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !mounter.GetAttributes().ReadOnly {
|
|
||||||
t.Errorf("Expected true for mounter.IsReadOnly")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,132 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 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 quobyte
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
|
||||||
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
|
||||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
|
||||||
|
|
||||||
quobyteapi "github.com/quobyte/api"
|
|
||||||
"k8s.io/klog/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type quobyteVolumeManager struct {
|
|
||||||
config *quobyteAPIConfig
|
|
||||||
dialOptions *proxyutil.FilteredDialOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *quobyteVolumeManager) createVolume(provisioner *quobyteVolumeProvisioner, createQuota bool) (quobyte *v1.QuobyteVolumeSource, size int, err error) {
|
|
||||||
capacity := provisioner.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
|
|
||||||
volumeSize, err := volumehelpers.RoundUpToGiBInt(capacity)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
// Quobyte has the concept of Volumes which doesn't have a specific size (they can grow unlimited)
|
|
||||||
// to simulate a size constraint we set here a Quota for logical space
|
|
||||||
volumeRequest := &quobyteapi.CreateVolumeRequest{
|
|
||||||
Name: provisioner.volume,
|
|
||||||
RootUserID: provisioner.user,
|
|
||||||
RootGroupID: provisioner.group,
|
|
||||||
TenantID: provisioner.tenant,
|
|
||||||
ConfigurationName: provisioner.config,
|
|
||||||
}
|
|
||||||
|
|
||||||
quobyteClient := manager.createQuobyteClient()
|
|
||||||
volumeUUID, err := quobyteClient.CreateVolume(volumeRequest)
|
|
||||||
if err != nil {
|
|
||||||
return &v1.QuobyteVolumeSource{}, volumeSize, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set Quota for Volume with specified byte size
|
|
||||||
if createQuota {
|
|
||||||
err = quobyteClient.SetVolumeQuota(volumeUUID, uint64(capacity.Value()))
|
|
||||||
if err != nil {
|
|
||||||
return &v1.QuobyteVolumeSource{}, volumeSize, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
klog.V(4).Infof("Created Quobyte volume %s", provisioner.volume)
|
|
||||||
return &v1.QuobyteVolumeSource{
|
|
||||||
Registry: provisioner.registry,
|
|
||||||
Volume: provisioner.volume,
|
|
||||||
User: provisioner.user,
|
|
||||||
Group: provisioner.group,
|
|
||||||
}, volumeSize, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *quobyteVolumeManager) deleteVolume(deleter *quobyteVolumeDeleter) error {
|
|
||||||
return manager.createQuobyteClient().DeleteVolumeByName(deleter.volume, deleter.tenant)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (manager *quobyteVolumeManager) createQuobyteClient() *quobyteapi.QuobyteClient {
|
|
||||||
client := quobyteapi.NewQuobyteClient(
|
|
||||||
manager.config.quobyteAPIServer,
|
|
||||||
manager.config.quobyteUser,
|
|
||||||
manager.config.quobytePassword,
|
|
||||||
)
|
|
||||||
// quobyte client library @v0.1.7 uses a zero-value http.Client with a nil
|
|
||||||
// transport which is equivalent to using http.DefaultTransport.
|
|
||||||
rt := http.DefaultTransport.(*http.Transport).Clone()
|
|
||||||
rt.DialContext = proxyutil.NewFilteredDialContext(rt.DialContext, nil, manager.dialOptions)
|
|
||||||
client.SetTransport(rt)
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mounter *quobyteMounter) pluginDirIsMounted(pluginDir string) (bool, error) {
|
|
||||||
mounts, err := mounter.mounter.List()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, mountPoint := range mounts {
|
|
||||||
if strings.HasPrefix(mountPoint.Type, "quobyte") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if mountPoint.Path == pluginDir {
|
|
||||||
klog.V(4).Infof("quobyte: found mountpoint %s in /proc/mounts", mountPoint.Path)
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mounter *quobyteMounter) correctTraillingSlash(regStr string) string {
|
|
||||||
return filepath.Clean(regStr) + string(os.PathSeparator)
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateRegistry(registry string) bool {
|
|
||||||
if len(registry) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, hostPortPair := range strings.Split(registry, ",") {
|
|
||||||
if _, _, err := net.SplitHostPort(hostPortPair); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
28
vendor/github.com/quobyte/api/LICENSE
generated
vendored
28
vendor/github.com/quobyte/api/LICENSE
generated
vendored
@ -1,28 +0,0 @@
|
|||||||
|
|
||||||
Copyright (c) 2016, Quobyte Inc.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of quobyte-automation nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
40
vendor/github.com/quobyte/api/README.md
generated
vendored
40
vendor/github.com/quobyte/api/README.md
generated
vendored
@ -1,40 +0,0 @@
|
|||||||
# Quobyte API Clients
|
|
||||||
|
|
||||||
Get the quobyte api client
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go get github.com/quobyte/api
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
quobyte_api "github.com/quobyte/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
client := quobyte_api.NewQuobyteClient("http://apiserver:7860", "user", "password")
|
|
||||||
client.SetAPIRetryPolicy(quobyte_api.RetryInfinitely) // Default quobyte_api.RetryInteractive
|
|
||||||
req := &quobyte_api.CreateVolumeRequest{
|
|
||||||
Name: "MyVolume",
|
|
||||||
RootUserID: "root",
|
|
||||||
RootGroupID: "root",
|
|
||||||
ConfigurationName: "BASE",
|
|
||||||
Labels: []quobyte_api.Label{
|
|
||||||
{Name: "label1", Value: "value1"},
|
|
||||||
{Name: "label2", Value: "value2"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
volumeUUID, err := client.CreateVolume(req)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("%s", volumeUUID)
|
|
||||||
}
|
|
||||||
```
|
|
245
vendor/github.com/quobyte/api/quobyte.go
generated
vendored
245
vendor/github.com/quobyte/api/quobyte.go
generated
vendored
@ -1,245 +0,0 @@
|
|||||||
// Package quobyte represents a golang API for the Quobyte Storage System
|
|
||||||
package quobyte
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
)
|
|
||||||
|
|
||||||
// retry policy codes
|
|
||||||
const (
|
|
||||||
RetryNever string = "NEVER"
|
|
||||||
RetryInteractive string = "INTERACTIVE"
|
|
||||||
RetryInfinitely string = "INFINITELY"
|
|
||||||
RetryOncePerTarget string = "ONCE_PER_TARGET"
|
|
||||||
)
|
|
||||||
|
|
||||||
var UUIDValidator = regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
|
|
||||||
|
|
||||||
type QuobyteClient struct {
|
|
||||||
client *http.Client
|
|
||||||
url string
|
|
||||||
username string
|
|
||||||
password string
|
|
||||||
apiRetryPolicy string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *QuobyteClient) SetAPIRetryPolicy(retry string) {
|
|
||||||
client.apiRetryPolicy = retry
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *QuobyteClient) GetAPIRetryPolicy() string {
|
|
||||||
return client.apiRetryPolicy
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *QuobyteClient) SetTransport(t http.RoundTripper) {
|
|
||||||
client.client.Transport = t
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewQuobyteClient creates a new Quobyte API client
|
|
||||||
func NewQuobyteClient(url string, username string, password string) *QuobyteClient {
|
|
||||||
return &QuobyteClient{
|
|
||||||
client: &http.Client{},
|
|
||||||
url: url,
|
|
||||||
username: username,
|
|
||||||
password: password,
|
|
||||||
apiRetryPolicy: RetryInteractive,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateVolume creates a new Quobyte volume. Its root directory will be owned by given user and group
|
|
||||||
func (client QuobyteClient) CreateVolume(request *CreateVolumeRequest) (string, error) {
|
|
||||||
var response volumeUUID
|
|
||||||
tenantUUID, err := client.GetTenantUUID(request.TenantID)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
request.TenantID = tenantUUID
|
|
||||||
|
|
||||||
if err = client.sendRequest("createVolume", request, &response); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.VolumeUUID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetVolumeUUID resolves the volumeUUID for the given volume and tenant name.
|
|
||||||
// This method should be used when it is not clear if the given string is volume UUID or Name.
|
|
||||||
func (client QuobyteClient) GetVolumeUUID(volume, tenant string) (string, error) {
|
|
||||||
if len(volume) != 0 && !IsValidUUID(volume) {
|
|
||||||
tenantUUID, err := client.GetTenantUUID(tenant)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
volUUID, err := client.ResolveVolumeNameToUUID(volume, tenantUUID)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return volUUID, nil
|
|
||||||
}
|
|
||||||
return volume, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTenantUUID resolves the tenatnUUID for the given name
|
|
||||||
// This method should be used when it is not clear if the given string is Tenant UUID or Name.
|
|
||||||
func (client QuobyteClient) GetTenantUUID(tenant string) (string, error) {
|
|
||||||
if len(tenant) != 0 && !IsValidUUID(tenant) {
|
|
||||||
tenantUUID, err := client.ResolveTenantNameToUUID(tenant)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return tenantUUID, nil
|
|
||||||
}
|
|
||||||
return tenant, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveVolumeNameToUUID resolves a volume name to a UUID
|
|
||||||
func (client *QuobyteClient) ResolveVolumeNameToUUID(volumeName, tenant string) (string, error) {
|
|
||||||
request := &resolveVolumeNameRequest{
|
|
||||||
VolumeName: volumeName,
|
|
||||||
TenantDomain: tenant,
|
|
||||||
}
|
|
||||||
var response volumeUUID
|
|
||||||
if err := client.sendRequest("resolveVolumeName", request, &response); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.VolumeUUID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteVolumeByResolvingNamesToUUID deletes the volume by resolving the volume name and tenant name to
|
|
||||||
// respective UUID if required.
|
|
||||||
// This method should be used if the given volume, tenant information is name or UUID.
|
|
||||||
func (client *QuobyteClient) DeleteVolumeByResolvingNamesToUUID(volume, tenant string) error {
|
|
||||||
volumeUUID, err := client.GetVolumeUUID(volume, tenant)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return client.DeleteVolume(volumeUUID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteVolume deletes a Quobyte volume
|
|
||||||
func (client *QuobyteClient) DeleteVolume(UUID string) error {
|
|
||||||
return client.sendRequest(
|
|
||||||
"deleteVolume",
|
|
||||||
&volumeUUID{
|
|
||||||
VolumeUUID: UUID,
|
|
||||||
},
|
|
||||||
nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteVolumeByName deletes a volume by a given name
|
|
||||||
func (client *QuobyteClient) DeleteVolumeByName(volumeName, tenant string) error {
|
|
||||||
uuid, err := client.ResolveVolumeNameToUUID(volumeName, tenant)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return client.DeleteVolume(uuid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetClientList returns a list of all active clients
|
|
||||||
func (client *QuobyteClient) GetClientList(tenant string) (GetClientListResponse, error) {
|
|
||||||
request := &getClientListRequest{
|
|
||||||
TenantDomain: tenant,
|
|
||||||
}
|
|
||||||
|
|
||||||
var response GetClientListResponse
|
|
||||||
if err := client.sendRequest("getClientListRequest", request, &response); err != nil {
|
|
||||||
return response, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetVolumeQuota sets a Quota to the specified Volume
|
|
||||||
func (client *QuobyteClient) SetVolumeQuota(volumeUUID string, quotaSize uint64) error {
|
|
||||||
request := &setQuotaRequest{
|
|
||||||
Quotas: []*quota{
|
|
||||||
"a{
|
|
||||||
Consumer: []*consumingEntity{
|
|
||||||
&consumingEntity{
|
|
||||||
Type: "VOLUME",
|
|
||||||
Identifier: volumeUUID,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Limits: []*resource{
|
|
||||||
&resource{
|
|
||||||
Type: "LOGICAL_DISK_SPACE",
|
|
||||||
Value: quotaSize,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return client.sendRequest("setQuota", request, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTenant returns the Tenant configuration for all specified tenants
|
|
||||||
func (client *QuobyteClient) GetTenant(tenantIDs []string) (GetTenantResponse, error) {
|
|
||||||
request := &getTenantRequest{TenantIDs: tenantIDs}
|
|
||||||
|
|
||||||
var response GetTenantResponse
|
|
||||||
err := client.sendRequest("getTenant", request, &response)
|
|
||||||
if err != nil {
|
|
||||||
return response, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTenantMap returns a map that contains all tenant names and there ID's
|
|
||||||
func (client *QuobyteClient) GetTenantMap() (map[string]string, error) {
|
|
||||||
result := map[string]string{}
|
|
||||||
response, err := client.GetTenant([]string{})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tenant := range response.Tenants {
|
|
||||||
result[tenant.Name] = tenant.TenantID
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTenant creates a Tenant with the specified name
|
|
||||||
func (client *QuobyteClient) SetTenant(tenantName string) (string, error) {
|
|
||||||
request := &setTenantRequest{
|
|
||||||
&TenantDomainConfiguration{
|
|
||||||
Name: tenantName,
|
|
||||||
},
|
|
||||||
retryPolicy{client.GetAPIRetryPolicy()},
|
|
||||||
}
|
|
||||||
|
|
||||||
var response setTenantResponse
|
|
||||||
err := client.sendRequest("setTenant", request, &response)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.TenantID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValidUUID Validates the given uuid
|
|
||||||
func IsValidUUID(uuid string) bool {
|
|
||||||
return UUIDValidator.MatchString(uuid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveTenantNameToUUID Returns UUID for given name, error if not found.
|
|
||||||
func (client *QuobyteClient) ResolveTenantNameToUUID(name string) (string, error) {
|
|
||||||
request := &resolveTenantNameRequest{
|
|
||||||
TenantName: name,
|
|
||||||
}
|
|
||||||
|
|
||||||
var response resolveTenantNameResponse
|
|
||||||
err := client.sendRequest("resolveTenantName", request, &response)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return response.TenantID, nil
|
|
||||||
}
|
|
124
vendor/github.com/quobyte/api/rpc_client.go
generated
vendored
124
vendor/github.com/quobyte/api/rpc_client.go
generated
vendored
@ -1,124 +0,0 @@
|
|||||||
package quobyte
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"math/rand"
|
|
||||||
"net/http"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
emptyResponse string = "Empty result and no error occured"
|
|
||||||
)
|
|
||||||
|
|
||||||
type request struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Version string `json:"jsonrpc"`
|
|
||||||
Method string `json:"method"`
|
|
||||||
Params interface{} `json:"params"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type response struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Version string `json:"jsonrpc"`
|
|
||||||
Result *json.RawMessage `json:"result"`
|
|
||||||
Error *json.RawMessage `json:"error"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type rpcError struct {
|
|
||||||
Code int64 `json:"code"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err *rpcError) decodeErrorCode() string {
|
|
||||||
switch err.Code {
|
|
||||||
case -32600:
|
|
||||||
return "ERROR_CODE_INVALID_REQUEST"
|
|
||||||
case -32603:
|
|
||||||
return "ERROR_CODE_JSON_ENCODING_FAILED"
|
|
||||||
case -32601:
|
|
||||||
return "ERROR_CODE_METHOD_NOT_FOUND"
|
|
||||||
case -32700:
|
|
||||||
return "ERROR_CODE_PARSE_ERROR"
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeRequest(method string, params interface{}) ([]byte, error) {
|
|
||||||
return json.Marshal(&request{
|
|
||||||
// Generate random ID and convert it to a string
|
|
||||||
ID: strconv.FormatInt(rand.Int63(), 10),
|
|
||||||
Version: "2.0",
|
|
||||||
Method: method,
|
|
||||||
Params: params,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeResponse(ioReader io.Reader, reply interface{}) error {
|
|
||||||
var resp response
|
|
||||||
if err := json.NewDecoder(ioReader).Decode(&resp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Error != nil {
|
|
||||||
var rpcErr rpcError
|
|
||||||
if err := json.Unmarshal(*resp.Error, &rpcErr); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if rpcErr.Message != "" {
|
|
||||||
return errors.New(rpcErr.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
respError := rpcErr.decodeErrorCode()
|
|
||||||
if respError != "" {
|
|
||||||
return errors.New(respError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Result != nil && reply != nil {
|
|
||||||
return json.Unmarshal(*resp.Result, reply)
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors.New(emptyResponse)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client QuobyteClient) sendRequest(method string, request interface{}, response interface{}) error {
|
|
||||||
etype := reflect.ValueOf(request).Elem()
|
|
||||||
field := etype.FieldByName("RetryPolicy")
|
|
||||||
if field.IsValid() {
|
|
||||||
field.SetString(client.GetAPIRetryPolicy())
|
|
||||||
}
|
|
||||||
message, err := encodeRequest(method, request)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req, err := http.NewRequest("POST", client.url, bytes.NewBuffer(message))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
req.SetBasicAuth(client.username, client.password)
|
|
||||||
resp, err := client.client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
|
||||||
log.Printf("Warning: HTTP status code for request is %s\n",
|
|
||||||
strconv.Itoa(resp.StatusCode))
|
|
||||||
if resp.StatusCode == 401 {
|
|
||||||
return errors.New("Unable to authenticate with Quobyte API service")
|
|
||||||
}
|
|
||||||
return fmt.Errorf("JsonRPC failed with error code %d", resp.StatusCode)
|
|
||||||
}
|
|
||||||
return decodeResponse(resp.Body, &response)
|
|
||||||
}
|
|
109
vendor/github.com/quobyte/api/types.go
generated
vendored
109
vendor/github.com/quobyte/api/types.go
generated
vendored
@ -1,109 +0,0 @@
|
|||||||
package quobyte
|
|
||||||
|
|
||||||
type retryPolicy struct {
|
|
||||||
RetryPolicy string `json:"retry,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateVolumeRequest represents a CreateVolumeRequest
|
|
||||||
type CreateVolumeRequest struct {
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
RootUserID string `json:"root_user_id,omitempty"`
|
|
||||||
RootGroupID string `json:"root_group_id,omitempty"`
|
|
||||||
ReplicaDeviceIDS []uint64 `json:"replica_device_ids,string,omitempty"`
|
|
||||||
ConfigurationName string `json:"configuration_name,omitempty"`
|
|
||||||
Labels []Label `json:"label,omitempty"`
|
|
||||||
AccessMode uint32 `json:"access_mode,uint32,omitempty"`
|
|
||||||
TenantID string `json:"tenant_id,omitempty"`
|
|
||||||
retryPolicy
|
|
||||||
}
|
|
||||||
|
|
||||||
type Label struct {
|
|
||||||
Name string `json:"name,string,omitempty"`
|
|
||||||
Value string `json:"value,string,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type resolveVolumeNameRequest struct {
|
|
||||||
VolumeName string `json:"volume_name,omitempty"`
|
|
||||||
TenantDomain string `json:"tenant_domain,omitempty"`
|
|
||||||
retryPolicy
|
|
||||||
}
|
|
||||||
|
|
||||||
type resolveTenantNameRequest struct {
|
|
||||||
TenantName string `json:"tenant_name,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type resolveTenantNameResponse struct {
|
|
||||||
TenantID string `json:"tenant_id,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type volumeUUID struct {
|
|
||||||
VolumeUUID string `json:"volume_uuid,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type getClientListRequest struct {
|
|
||||||
TenantDomain string `json:"tenant_domain,omitempty"`
|
|
||||||
retryPolicy
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetClientListResponse struct {
|
|
||||||
Clients []Client `json:"client,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
MountedUserName string `json:"mount_user_name,omitempty"`
|
|
||||||
MountedVolumeUUID string `json:"mounted_volume_uuid,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type consumingEntity struct {
|
|
||||||
Type string `json:"type,omitempty"`
|
|
||||||
Identifier string `json:"identifier,omitempty"`
|
|
||||||
TenantID string `json:"tenant_id,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type resource struct {
|
|
||||||
Type string `json:"type,omitempty"`
|
|
||||||
Value uint64 `json:"value,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type quota struct {
|
|
||||||
ID string `json:"id,omitempty"`
|
|
||||||
Consumer []*consumingEntity `json:"consumer,omitempty"`
|
|
||||||
Limits []*resource `json:"limits,omitempty"`
|
|
||||||
Currentusage []*resource `json:"current_usage,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type setQuotaRequest struct {
|
|
||||||
Quotas []*quota `json:"quotas,omitempty"`
|
|
||||||
retryPolicy
|
|
||||||
}
|
|
||||||
|
|
||||||
type getTenantRequest struct {
|
|
||||||
TenantIDs []string `json:"tenant_id,omitempty"`
|
|
||||||
retryPolicy
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetTenantResponse struct {
|
|
||||||
Tenants []*TenantDomainConfiguration `json:"tenant,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TenantDomainConfiguration struct {
|
|
||||||
TenantID string `json:"tenant_id,omitempty"`
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
RestrictToNetwork []string `json:"restrict_to_network,omitempty"`
|
|
||||||
VolumeAccess []*TenantDomainConfigurationVolumeAccess `json:"volume_access,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TenantDomainConfigurationVolumeAccess struct {
|
|
||||||
VolumeUUID string `json:"volume_uuid,omitempty"`
|
|
||||||
RestrictToNetwork string `json:"restrict_to_network,omitempty"`
|
|
||||||
ReadOnly bool `json:"read_only,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type setTenantRequest struct {
|
|
||||||
Tenants *TenantDomainConfiguration `json:"tenant,omitempty"`
|
|
||||||
retryPolicy
|
|
||||||
}
|
|
||||||
|
|
||||||
type setTenantResponse struct {
|
|
||||||
TenantID string `json:"tenant_id,omitempty"`
|
|
||||||
}
|
|
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@ -734,9 +734,6 @@ github.com/prometheus/common/model
|
|||||||
github.com/prometheus/procfs
|
github.com/prometheus/procfs
|
||||||
github.com/prometheus/procfs/internal/fs
|
github.com/prometheus/procfs/internal/fs
|
||||||
github.com/prometheus/procfs/internal/util
|
github.com/prometheus/procfs/internal/util
|
||||||
# github.com/quobyte/api v0.1.8 => github.com/quobyte/api v0.1.8
|
|
||||||
## explicit
|
|
||||||
github.com/quobyte/api
|
|
||||||
# github.com/robfig/cron/v3 v3.0.1 => github.com/robfig/cron/v3 v3.0.1
|
# github.com/robfig/cron/v3 v3.0.1 => github.com/robfig/cron/v3 v3.0.1
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/robfig/cron/v3
|
github.com/robfig/cron/v3
|
||||||
@ -2763,7 +2760,6 @@ sigs.k8s.io/yaml
|
|||||||
# github.com/prometheus/client_model => github.com/prometheus/client_model v0.2.0
|
# github.com/prometheus/client_model => github.com/prometheus/client_model v0.2.0
|
||||||
# github.com/prometheus/common => github.com/prometheus/common v0.32.1
|
# github.com/prometheus/common => github.com/prometheus/common v0.32.1
|
||||||
# github.com/prometheus/procfs => github.com/prometheus/procfs v0.7.3
|
# github.com/prometheus/procfs => github.com/prometheus/procfs v0.7.3
|
||||||
# github.com/quobyte/api => github.com/quobyte/api v0.1.8
|
|
||||||
# github.com/remyoudompheng/bigfft => github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446
|
# github.com/remyoudompheng/bigfft => github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446
|
||||||
# github.com/robfig/cron/v3 => github.com/robfig/cron/v3 v3.0.1
|
# github.com/robfig/cron/v3 => github.com/robfig/cron/v3 v3.0.1
|
||||||
# github.com/rogpeppe/fastuuid => github.com/rogpeppe/fastuuid v1.2.0
|
# github.com/rogpeppe/fastuuid => github.com/rogpeppe/fastuuid v1.2.0
|
||||||
|
Loading…
Reference in New Issue
Block a user