mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 05:27:21 +00:00
Merge pull request #85153 from codenrhoden/mount-no-exec-int
Retire mount.Exec for k8s.io/utils/exec
This commit is contained in:
commit
565566f4b2
@ -46,6 +46,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
||||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -45,6 +45,8 @@ import (
|
|||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
|
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/metrics"
|
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/metrics"
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/populator"
|
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/populator"
|
||||||
@ -768,8 +770,8 @@ func (adc *attachDetachController) DeleteServiceAccountTokenFunc() func(types.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adc *attachDetachController) GetExec(pluginName string) mount.Exec {
|
func (adc *attachDetachController) GetExec(pluginName string) utilexec.Interface {
|
||||||
return mount.NewOSExec()
|
return utilexec.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adc *attachDetachController) addNodeToDswp(node *v1.Node, nodeName types.NodeName) {
|
func (adc *attachDetachController) addNodeToDswp(node *v1.Node, nodeName types.NodeName) {
|
||||||
|
@ -33,6 +33,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
||||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,6 +41,8 @@ import (
|
|||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
|
|
||||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/events"
|
"k8s.io/kubernetes/pkg/controller/volume/events"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
@ -380,8 +382,8 @@ func (expc *expandController) GetMounter(pluginName string) mount.Interface {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expc *expandController) GetExec(pluginName string) mount.Exec {
|
func (expc *expandController) GetExec(pluginName string) utilexec.Interface {
|
||||||
return mount.NewOSExec()
|
return utilexec.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (expc *expandController) GetHostName() string {
|
func (expc *expandController) GetHostName() string {
|
||||||
|
@ -56,6 +56,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/cloud-provider/volume/errors:go_default_library",
|
"//staging/src/k8s.io/cloud-provider/volume/errors:go_default_library",
|
||||||
"//staging/src/k8s.io/csi-translation-lib:go_default_library",
|
"//staging/src/k8s.io/csi-translation-lib:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ import (
|
|||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
vol "k8s.io/kubernetes/pkg/volume"
|
vol "k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/subpath"
|
"k8s.io/kubernetes/pkg/volume/util/subpath"
|
||||||
@ -116,8 +118,8 @@ func (ctrl *PersistentVolumeController) DeleteServiceAccountTokenFunc() func(typ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adc *PersistentVolumeController) GetExec(pluginName string) mount.Exec {
|
func (adc *PersistentVolumeController) GetExec(pluginName string) utilexec.Interface {
|
||||||
return mount.NewOSExec()
|
return utilexec.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctrl *PersistentVolumeController) GetNodeLabels() (map[string]string, error) {
|
func (ctrl *PersistentVolumeController) GetNodeLabels() (map[string]string, error) {
|
||||||
|
@ -34,6 +34,8 @@ import (
|
|||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/configmap"
|
"k8s.io/kubernetes/pkg/kubelet/configmap"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/secret"
|
"k8s.io/kubernetes/pkg/kubelet/secret"
|
||||||
@ -86,7 +88,7 @@ func NewInitializedVolumePluginMgr(
|
|||||||
informerFactory: informerFactory,
|
informerFactory: informerFactory,
|
||||||
csiDriverLister: csiDriverLister,
|
csiDriverLister: csiDriverLister,
|
||||||
csiDriversSynced: csiDriversSynced,
|
csiDriversSynced: csiDriversSynced,
|
||||||
exec: mount.NewOSExec(),
|
exec: utilexec.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := kvh.volumePluginMgr.InitPlugins(plugins, prober, kvh); err != nil {
|
if err := kvh.volumePluginMgr.InitPlugins(plugins, prober, kvh); err != nil {
|
||||||
@ -115,7 +117,7 @@ type kubeletVolumeHost struct {
|
|||||||
informerFactory informers.SharedInformerFactory
|
informerFactory informers.SharedInformerFactory
|
||||||
csiDriverLister storagelisters.CSIDriverLister
|
csiDriverLister storagelisters.CSIDriverLister
|
||||||
csiDriversSynced cache.InformerSynced
|
csiDriversSynced cache.InformerSynced
|
||||||
exec mount.Exec
|
exec utilexec.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kvh *kubeletVolumeHost) SetKubeletError(err error) {
|
func (kvh *kubeletVolumeHost) SetKubeletError(err error) {
|
||||||
@ -271,6 +273,6 @@ func (kvh *kubeletVolumeHost) GetEventRecorder() record.EventRecorder {
|
|||||||
return kvh.kubelet.recorder
|
return kvh.kubelet.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kvh *kubeletVolumeHost) GetExec(pluginName string) mount.Exec {
|
func (kvh *kubeletVolumeHost) GetExec(pluginName string) utilexec.Interface {
|
||||||
return kvh.exec
|
return kvh.exec
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ go_library(
|
|||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
"doc.go",
|
"doc.go",
|
||||||
"exec.go",
|
|
||||||
"fake_exec.go",
|
"fake_exec.go",
|
||||||
"fake_mounter.go",
|
"fake_mounter.go",
|
||||||
"mount.go",
|
"mount.go",
|
||||||
@ -75,6 +74,7 @@ go_test(
|
|||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||||
] + select({
|
] + select({
|
||||||
"@io_bazel_rules_go//go/platform:windows": [
|
"@io_bazel_rules_go//go/platform:windows": [
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
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 mount
|
|
||||||
|
|
||||||
import "k8s.io/utils/exec"
|
|
||||||
|
|
||||||
// NewOSExec returns a new Exec interface implementation based on exec()
|
|
||||||
func NewOSExec() *OSExec {
|
|
||||||
return &OSExec{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OSExec is an implementation of Exec interface that uses simple utils.Exec
|
|
||||||
type OSExec struct{}
|
|
||||||
|
|
||||||
var _ Exec = &OSExec{}
|
|
||||||
|
|
||||||
// Run exucutes the given cmd and arges and returns stdout and stderr as a
|
|
||||||
// combined byte stream
|
|
||||||
func (e *OSExec) Run(cmd string, args ...string) ([]byte, error) {
|
|
||||||
exe := exec.New()
|
|
||||||
return exe.Command(cmd, args...).CombinedOutput()
|
|
||||||
}
|
|
@ -23,6 +23,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -53,13 +55,6 @@ type Interface interface {
|
|||||||
GetMountRefs(pathname string) ([]string, error)
|
GetMountRefs(pathname string) ([]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec is an interface for executing commands on systems.
|
|
||||||
type Exec interface {
|
|
||||||
// Run executes a command and returns its stdout + stderr combined in one
|
|
||||||
// stream.
|
|
||||||
Run(cmd string, args ...string) ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compile-time check to ensure all Mounter implementations satisfy
|
// Compile-time check to ensure all Mounter implementations satisfy
|
||||||
// the mount interface.
|
// the mount interface.
|
||||||
var _ Interface = &Mounter{}
|
var _ Interface = &Mounter{}
|
||||||
@ -79,7 +74,7 @@ type MountPoint struct {
|
|||||||
// mounts it otherwise the device is formatted first then mounted.
|
// mounts it otherwise the device is formatted first then mounted.
|
||||||
type SafeFormatAndMount struct {
|
type SafeFormatAndMount struct {
|
||||||
Interface
|
Interface
|
||||||
Exec
|
Exec utilexec.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// FormatAndMount formats the given disk, if needed, and mounts it.
|
// FormatAndMount formats the given disk, if needed, and mounts it.
|
||||||
|
@ -273,7 +273,7 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||||||
// Run fsck on the disk to fix repairable issues, only do this for volumes requested as rw.
|
// Run fsck on the disk to fix repairable issues, only do this for volumes requested as rw.
|
||||||
klog.V(4).Infof("Checking for issues with fsck on disk: %s", source)
|
klog.V(4).Infof("Checking for issues with fsck on disk: %s", source)
|
||||||
args := []string{"-a", source}
|
args := []string{"-a", source}
|
||||||
out, err := mounter.Exec.Run("fsck", args...)
|
out, err := mounter.Exec.Command("fsck", args...).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ee, isExitError := err.(utilexec.ExitError)
|
ee, isExitError := err.(utilexec.ExitError)
|
||||||
switch {
|
switch {
|
||||||
@ -320,7 +320,7 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
klog.Infof("Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", source, fstype, args)
|
klog.Infof("Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", source, fstype, args)
|
||||||
_, err := mounter.Exec.Run("mkfs."+fstype, args...)
|
_, err := mounter.Exec.Command("mkfs."+fstype, args...).CombinedOutput()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// the disk has been formatted successfully try to mount it again.
|
// the disk has been formatted successfully try to mount it again.
|
||||||
klog.Infof("Disk successfully formatted (mkfs): %s - %s %s", fstype, source, target)
|
klog.Infof("Disk successfully formatted (mkfs): %s - %s %s", fstype, source, target)
|
||||||
@ -344,7 +344,7 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||||||
func (mounter *SafeFormatAndMount) GetDiskFormat(disk string) (string, error) {
|
func (mounter *SafeFormatAndMount) GetDiskFormat(disk string) (string, error) {
|
||||||
args := []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", disk}
|
args := []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", disk}
|
||||||
klog.V(4).Infof("Attempting to determine if disk %q is formatted using blkid with args: (%v)", disk, args)
|
klog.V(4).Infof("Attempting to determine if disk %q is formatted using blkid with args: (%v)", disk, args)
|
||||||
dataOut, err := mounter.Exec.Run("blkid", args...)
|
dataOut, err := mounter.Exec.Command("blkid", args...).CombinedOutput()
|
||||||
output := string(dataOut)
|
output := string(dataOut)
|
||||||
klog.V(4).Infof("Output: %q, err: %v", output, err)
|
klog.V(4).Infof("Output: %q, err: %v", output, err)
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
"k8s.io/utils/keymutex"
|
"k8s.io/utils/keymutex"
|
||||||
utilpath "k8s.io/utils/path"
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
@ -219,7 +220,7 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||||||
// format disk if it is unformatted(raw)
|
// format disk if it is unformatted(raw)
|
||||||
cmd := fmt.Sprintf("Get-Disk -Number %s | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru"+
|
cmd := fmt.Sprintf("Get-Disk -Number %s | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru"+
|
||||||
" | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false", source, fstype)
|
" | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false", source, fstype)
|
||||||
if output, err := mounter.Exec.Run("powershell", "/c", cmd); err != nil {
|
if output, err := mounter.Exec.Command("powershell", "/c", cmd).CombinedOutput(); err != nil {
|
||||||
return fmt.Errorf("diskMount: format disk failed, error: %v, output: %q", err, string(output))
|
return fmt.Errorf("diskMount: format disk failed, error: %v, output: %q", err, string(output))
|
||||||
}
|
}
|
||||||
klog.V(4).Infof("diskMount: Disk successfully formatted, disk: %q, fstype: %q", source, fstype)
|
klog.V(4).Infof("diskMount: Disk successfully formatted, disk: %q, fstype: %q", source, fstype)
|
||||||
@ -231,7 +232,7 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||||||
driverPath := driveLetter + ":"
|
driverPath := driveLetter + ":"
|
||||||
target = NormalizeWindowsPath(target)
|
target = NormalizeWindowsPath(target)
|
||||||
klog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, driverPath, target)
|
klog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, driverPath, target)
|
||||||
if output, err := mounter.Exec.Run("cmd", "/c", "mklink", "/D", target, driverPath); err != nil {
|
if output, err := mounter.Exec.Command("cmd", "/c", "mklink", "/D", target, driverPath).CombinedOutput(); err != nil {
|
||||||
klog.Errorf("mklink failed: %v, output: %q", err, string(output))
|
klog.Errorf("mklink failed: %v, output: %q", err, string(output))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -239,9 +240,9 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get drive letter according to windows disk number
|
// Get drive letter according to windows disk number
|
||||||
func getDriveLetterByDiskNumber(diskNum string, exec Exec) (string, error) {
|
func getDriveLetterByDiskNumber(diskNum string, exec utilexec.Interface) (string, error) {
|
||||||
cmd := fmt.Sprintf("(Get-Partition -DiskNumber %s).DriveLetter", diskNum)
|
cmd := fmt.Sprintf("(Get-Partition -DiskNumber %s).DriveLetter", diskNum)
|
||||||
output, err := exec.Run("powershell", "/c", cmd)
|
output, err := exec.Command("powershell", "/c", cmd).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("azureMount: Get Drive Letter failed: %v, output: %q", err, string(output))
|
return "", fmt.Errorf("azureMount: Get Drive Letter failed: %v, output: %q", err, string(output))
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"k8s.io/utils/exec/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeLink(link, target string) error {
|
func makeLink(link, target string) error {
|
||||||
@ -224,61 +224,61 @@ func TestIsLikelyNotMountPoint(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFormatAndMount(t *testing.T) {
|
func TestFormatAndMount(t *testing.T) {
|
||||||
fakeMounter := ErrorMounter{NewFakeMounter(nil), 0, nil}
|
|
||||||
execCallback := func(cmd string, args ...string) ([]byte, error) {
|
|
||||||
for j := range args {
|
|
||||||
if strings.Contains(args[j], "Get-Disk -Number") {
|
|
||||||
return []byte("0"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(args[j], "Get-Partition -DiskNumber") {
|
|
||||||
return []byte("0"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(args[j], "mklink") {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("Unexpected cmd %s, args %v", cmd, args)
|
|
||||||
}
|
|
||||||
fakeExec := NewFakeExec(execCallback)
|
|
||||||
|
|
||||||
mounter := SafeFormatAndMount{
|
|
||||||
Interface: &fakeMounter,
|
|
||||||
Exec: fakeExec,
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
device string
|
device string
|
||||||
target string
|
target string
|
||||||
fstype string
|
fstype string
|
||||||
|
execScripts []ExecArgs
|
||||||
mountOptions []string
|
mountOptions []string
|
||||||
expectError bool
|
expectError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"0",
|
device: "0",
|
||||||
"disk",
|
target: "disk",
|
||||||
"NTFS",
|
fstype: "NTFS",
|
||||||
[]string{},
|
execScripts: []ExecArgs{
|
||||||
false,
|
{"powershell", []string{"/c", "Get-Disk", "-Number"}, "0", nil},
|
||||||
|
{"powershell", []string{"/c", "Get-Partition", "-DiskNumber"}, "0", nil},
|
||||||
|
{"cmd", []string{"/c", "mklink", "/D"}, "", nil},
|
||||||
|
},
|
||||||
|
mountOptions: []string{},
|
||||||
|
expectError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"0",
|
device: "0",
|
||||||
"disk",
|
target: "disk",
|
||||||
"",
|
fstype: "",
|
||||||
[]string{},
|
execScripts: []ExecArgs{
|
||||||
false,
|
{"powershell", []string{"/c", "Get-Disk", "-Number"}, "0", nil},
|
||||||
|
{"powershell", []string{"/c", "Get-Partition", "-DiskNumber"}, "0", nil},
|
||||||
|
{"cmd", []string{"/c", "mklink", "/D"}, "", nil},
|
||||||
|
},
|
||||||
|
mountOptions: []string{},
|
||||||
|
expectError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"invalidDevice",
|
device: "invalidDevice",
|
||||||
"disk",
|
target: "disk",
|
||||||
"NTFS",
|
fstype: "NTFS",
|
||||||
[]string{},
|
mountOptions: []string{},
|
||||||
true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
fakeMounter := ErrorMounter{NewFakeMounter(nil), 0, nil}
|
||||||
|
fakeExec := &testingexec.FakeExec{}
|
||||||
|
for _, script := range test.execScripts {
|
||||||
|
fakeCmd := &testingexec.FakeCmd{}
|
||||||
|
cmdAction := makeFakeCmd(fakeCmd, script.command, script.args...)
|
||||||
|
outputAction := makeFakeOutput(script.output, script.err)
|
||||||
|
fakeCmd.CombinedOutputScript = append(fakeCmd.CombinedOutputScript, outputAction)
|
||||||
|
fakeExec.CommandScript = append(fakeExec.CommandScript, cmdAction)
|
||||||
|
}
|
||||||
|
mounter := SafeFormatAndMount{
|
||||||
|
Interface: &fakeMounter,
|
||||||
|
Exec: fakeExec,
|
||||||
|
}
|
||||||
base, err := ioutil.TempDir("", test.device)
|
base, err := ioutil.TempDir("", test.device)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatalf(err.Error())
|
||||||
|
@ -24,7 +24,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
fakeexec "k8s.io/utils/exec/testing"
|
"k8s.io/utils/exec"
|
||||||
|
"k8s.io/utils/exec/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ErrorMounter struct {
|
type ErrorMounter struct {
|
||||||
@ -82,7 +83,7 @@ func TestSafeFormatAndMount(t *testing.T) {
|
|||||||
description: "Test 'fsck' fails with exit status 4",
|
description: "Test 'fsck' fails with exit status 4",
|
||||||
fstype: "ext4",
|
fstype: "ext4",
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
{"fsck", []string{"-a", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 4}},
|
{"fsck", []string{"-a", "/dev/foo"}, "", &testingexec.FakeExitError{Status: 4}},
|
||||||
},
|
},
|
||||||
expectedError: fmt.Errorf("'fsck' found errors on device /dev/foo but could not correct them"),
|
expectedError: fmt.Errorf("'fsck' found errors on device /dev/foo but could not correct them"),
|
||||||
},
|
},
|
||||||
@ -90,14 +91,14 @@ func TestSafeFormatAndMount(t *testing.T) {
|
|||||||
description: "Test 'fsck' fails with exit status 1 (errors found and corrected)",
|
description: "Test 'fsck' fails with exit status 1 (errors found and corrected)",
|
||||||
fstype: "ext4",
|
fstype: "ext4",
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
{"fsck", []string{"-a", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 1}},
|
{"fsck", []string{"-a", "/dev/foo"}, "", &testingexec.FakeExitError{Status: 1}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Test 'fsck' fails with exit status other than 1 and 4 (likely unformatted device)",
|
description: "Test 'fsck' fails with exit status other than 1 and 4 (likely unformatted device)",
|
||||||
fstype: "ext4",
|
fstype: "ext4",
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
{"fsck", []string{"-a", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 8}},
|
{"fsck", []string{"-a", "/dev/foo"}, "", &testingexec.FakeExitError{Status: 8}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -116,7 +117,7 @@ func TestSafeFormatAndMount(t *testing.T) {
|
|||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
|
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &testingexec.FakeExitError{Status: 2}},
|
||||||
{"mkfs.ext4", []string{"-F", "-m0", "/dev/foo"}, "", fmt.Errorf("formatting failed")},
|
{"mkfs.ext4", []string{"-F", "-m0", "/dev/foo"}, "", fmt.Errorf("formatting failed")},
|
||||||
},
|
},
|
||||||
expectedError: fmt.Errorf("formatting failed"),
|
expectedError: fmt.Errorf("formatting failed"),
|
||||||
@ -127,7 +128,7 @@ func TestSafeFormatAndMount(t *testing.T) {
|
|||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), fmt.Errorf("Still cannot mount")},
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), fmt.Errorf("Still cannot mount")},
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
|
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &testingexec.FakeExitError{Status: 2}},
|
||||||
{"mkfs.ext4", []string{"-F", "-m0", "/dev/foo"}, "", nil},
|
{"mkfs.ext4", []string{"-F", "-m0", "/dev/foo"}, "", nil},
|
||||||
},
|
},
|
||||||
expectedError: fmt.Errorf("Still cannot mount"),
|
expectedError: fmt.Errorf("Still cannot mount"),
|
||||||
@ -138,7 +139,7 @@ func TestSafeFormatAndMount(t *testing.T) {
|
|||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
|
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &testingexec.FakeExitError{Status: 2}},
|
||||||
{"mkfs.ext4", []string{"-F", "-m0", "/dev/foo"}, "", nil},
|
{"mkfs.ext4", []string{"-F", "-m0", "/dev/foo"}, "", nil},
|
||||||
},
|
},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
@ -149,7 +150,7 @@ func TestSafeFormatAndMount(t *testing.T) {
|
|||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
|
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &testingexec.FakeExitError{Status: 2}},
|
||||||
{"mkfs.ext3", []string{"-F", "-m0", "/dev/foo"}, "", nil},
|
{"mkfs.ext3", []string{"-F", "-m0", "/dev/foo"}, "", nil},
|
||||||
},
|
},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
@ -160,7 +161,7 @@ func TestSafeFormatAndMount(t *testing.T) {
|
|||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
|
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &testingexec.FakeExitError{Status: 2}},
|
||||||
{"mkfs.xfs", []string{"/dev/foo"}, "", nil},
|
{"mkfs.xfs", []string{"/dev/foo"}, "", nil},
|
||||||
},
|
},
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
@ -181,7 +182,7 @@ func TestSafeFormatAndMount(t *testing.T) {
|
|||||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||||
execScripts: []ExecArgs{
|
execScripts: []ExecArgs{
|
||||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 4}},
|
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &testingexec.FakeExitError{Status: 4}},
|
||||||
{"mkfs.xfs", []string{"/dev/foo"}, "", nil},
|
{"mkfs.xfs", []string{"/dev/foo"}, "", nil},
|
||||||
},
|
},
|
||||||
expectedError: fmt.Errorf("exit 4"),
|
expectedError: fmt.Errorf("exit 4"),
|
||||||
@ -189,27 +190,15 @@ func TestSafeFormatAndMount(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
execCallCount := 0
|
|
||||||
execCallback := func(cmd string, args ...string) ([]byte, error) {
|
|
||||||
if len(test.execScripts) <= execCallCount {
|
|
||||||
t.Errorf("Unexpected command: %s %v", cmd, args)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
script := test.execScripts[execCallCount]
|
|
||||||
execCallCount++
|
|
||||||
if script.command != cmd {
|
|
||||||
t.Errorf("Unexpected command %s. Expecting %s", cmd, script.command)
|
|
||||||
}
|
|
||||||
for j := range args {
|
|
||||||
if args[j] != script.args[j] {
|
|
||||||
t.Errorf("Unexpected args %v. Expecting %v", args, script.args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []byte(script.output), script.err
|
|
||||||
}
|
|
||||||
|
|
||||||
fakeMounter := ErrorMounter{NewFakeMounter(nil), 0, test.mountErrs}
|
fakeMounter := ErrorMounter{NewFakeMounter(nil), 0, test.mountErrs}
|
||||||
fakeExec := NewFakeExec(execCallback)
|
fakeExec := &testingexec.FakeExec{ExactOrder: true}
|
||||||
|
for _, script := range test.execScripts {
|
||||||
|
fakeCmd := &testingexec.FakeCmd{}
|
||||||
|
cmdAction := makeFakeCmd(fakeCmd, script.command, script.args...)
|
||||||
|
outputAction := makeFakeOutput(script.output, script.err)
|
||||||
|
fakeCmd.CombinedOutputScript = append(fakeCmd.CombinedOutputScript, outputAction)
|
||||||
|
fakeExec.CommandScript = append(fakeExec.CommandScript, cmdAction)
|
||||||
|
}
|
||||||
mounter := SafeFormatAndMount{
|
mounter := SafeFormatAndMount{
|
||||||
Interface: &fakeMounter,
|
Interface: &fakeMounter,
|
||||||
Exec: fakeExec,
|
Exec: fakeExec,
|
||||||
@ -241,3 +230,19 @@ func TestSafeFormatAndMount(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeFakeCmd(fakeCmd *testingexec.FakeCmd, cmd string, args ...string) testingexec.FakeCommandAction {
|
||||||
|
c := cmd
|
||||||
|
a := args
|
||||||
|
return func(cmd string, args ...string) exec.Cmd {
|
||||||
|
command := testingexec.InitFakeCmd(fakeCmd, c, a...)
|
||||||
|
return command
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeFakeOutput(output string, err error) testingexec.FakeCombinedOutputAction {
|
||||||
|
o := output
|
||||||
|
return func() ([]byte, error) {
|
||||||
|
return []byte(o), err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -61,7 +61,7 @@ func (resizefs *ResizeFs) Resize(devicePath string, deviceMountPath string) (boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (resizefs *ResizeFs) extResize(devicePath string) (bool, error) {
|
func (resizefs *ResizeFs) extResize(devicePath string) (bool, error) {
|
||||||
output, err := resizefs.mounter.Exec.Run("resize2fs", devicePath)
|
output, err := resizefs.mounter.Exec.Command("resize2fs", devicePath).CombinedOutput()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
klog.V(2).Infof("Device %s resized successfully", devicePath)
|
klog.V(2).Infof("Device %s resized successfully", devicePath)
|
||||||
return true, nil
|
return true, nil
|
||||||
@ -74,7 +74,7 @@ func (resizefs *ResizeFs) extResize(devicePath string) (bool, error) {
|
|||||||
|
|
||||||
func (resizefs *ResizeFs) xfsResize(deviceMountPath string) (bool, error) {
|
func (resizefs *ResizeFs) xfsResize(deviceMountPath string) (bool, error) {
|
||||||
args := []string{"-d", deviceMountPath}
|
args := []string{"-d", deviceMountPath}
|
||||||
output, err := resizefs.mounter.Exec.Run("xfs_growfs", args...)
|
output, err := resizefs.mounter.Exec.Command("xfs_growfs", args...).CombinedOutput()
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
klog.V(2).Infof("Device %s resized successfully", deviceMountPath)
|
klog.V(2).Infof("Device %s resized successfully", deviceMountPath)
|
||||||
|
@ -40,6 +40,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
||||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ func (attacher *awsElasticBlockStoreAttacher) getDiskNumber(volumeID string) (st
|
|||||||
volumeID = split[len(split)-1]
|
volumeID = split[len(split)-1]
|
||||||
|
|
||||||
exec := attacher.host.GetExec(awsElasticBlockStorePluginName)
|
exec := attacher.host.GetExec(awsElasticBlockStorePluginName)
|
||||||
output, err := exec.Run(ebsnvmeID)
|
output, err := exec.Command(ebsnvmeID).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("error calling ebsnvme-id.exe: %v", err)
|
return "", fmt.Errorf("error calling ebsnvme-id.exe: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,45 @@ go_library(
|
|||||||
"//vendor/github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage:go_default_library",
|
"//vendor/github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
"//vendor/k8s.io/utils/strings:go_default_library",
|
"//vendor/k8s.io/utils/strings:go_default_library",
|
||||||
|
] + select({
|
||||||
|
"@io_bazel_rules_go//go/platform:android": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
],
|
],
|
||||||
|
"@io_bazel_rules_go//go/platform:darwin": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
],
|
||||||
|
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
],
|
||||||
|
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
],
|
||||||
|
"@io_bazel_rules_go//go/platform:ios": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
],
|
||||||
|
"@io_bazel_rules_go//go/platform:linux": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
],
|
||||||
|
"@io_bazel_rules_go//go/platform:nacl": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
],
|
||||||
|
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
],
|
||||||
|
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
],
|
||||||
|
"@io_bazel_rules_go//go/platform:plan9": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
],
|
||||||
|
"@io_bazel_rules_go//go/platform:solaris": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
],
|
||||||
|
"@io_bazel_rules_go//go/platform:windows": [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
@ -70,7 +108,6 @@ go_test(
|
|||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/util/mount:go_default_library",
|
|
||||||
"//pkg/volume:go_default_library",
|
"//pkg/volume:go_default_library",
|
||||||
"//pkg/volume/testing:go_default_library",
|
"//pkg/volume/testing:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
@ -79,5 +116,6 @@ go_test(
|
|||||||
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
||||||
"//vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute:go_default_library",
|
"//vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute:go_default_library",
|
||||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
libstrings "strings"
|
libstrings "strings"
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
utilexec "k8s.io/utils/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
// exclude those used by azure as resource and OS root in /dev/disk/azure
|
// exclude those used by azure as resource and OS root in /dev/disk/azure
|
||||||
@ -69,7 +69,7 @@ func getDiskLinkByDevName(io ioHandler, devLinkPath, devName string) (string, er
|
|||||||
return "", fmt.Errorf("read %s error: %v", devLinkPath, err)
|
return "", fmt.Errorf("read %s error: %v", devLinkPath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func scsiHostRescan(io ioHandler, exec mount.Exec) {
|
func scsiHostRescan(io ioHandler, exec utilexec.Interface) {
|
||||||
scsi_path := "/sys/class/scsi_host/"
|
scsi_path := "/sys/class/scsi_host/"
|
||||||
if dirs, err := io.ReadDir(scsi_path); err == nil {
|
if dirs, err := io.ReadDir(scsi_path); err == nil {
|
||||||
for _, f := range dirs {
|
for _, f := range dirs {
|
||||||
@ -84,7 +84,7 @@ func scsiHostRescan(io ioHandler, exec mount.Exec) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func findDiskByLun(lun int, io ioHandler, exec mount.Exec) (string, error) {
|
func findDiskByLun(lun int, io ioHandler, exec utilexec.Interface) (string, error) {
|
||||||
azureDisks := listAzureDiskPath(io)
|
azureDisks := listAzureDiskPath(io)
|
||||||
return findDiskByLunWithConstraint(lun, io, azureDisks)
|
return findDiskByLunWithConstraint(lun, io, azureDisks)
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,7 @@ import (
|
|||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"k8s.io/utils/exec"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type fakeFileInfo struct {
|
type fakeFileInfo struct {
|
||||||
@ -126,7 +125,7 @@ func TestIoHandler(t *testing.T) {
|
|||||||
if runtime.GOOS != "windows" && runtime.GOOS != "linux" {
|
if runtime.GOOS != "windows" && runtime.GOOS != "linux" {
|
||||||
t.Skipf("TestIoHandler not supported on GOOS=%s", runtime.GOOS)
|
t.Skipf("TestIoHandler not supported on GOOS=%s", runtime.GOOS)
|
||||||
}
|
}
|
||||||
disk, err := findDiskByLun(lun, &fakeIOHandler{}, mount.NewOSExec())
|
disk, err := findDiskByLun(lun, &fakeIOHandler{}, exec.New())
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("no data disk found: disk %v err %v", disk, err)
|
t.Errorf("no data disk found: disk %v err %v", disk, err)
|
||||||
|
@ -19,11 +19,11 @@ limitations under the License.
|
|||||||
|
|
||||||
package azure_dd
|
package azure_dd
|
||||||
|
|
||||||
import "k8s.io/kubernetes/pkg/util/mount"
|
import "k8s.io/utils/exec"
|
||||||
|
|
||||||
func scsiHostRescan(io ioHandler, exec mount.Exec) {
|
func scsiHostRescan(io ioHandler, exec exec.Interface) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func findDiskByLun(lun int, io ioHandler, exec mount.Exec) (string, error) {
|
func findDiskByLun(lun int, io ioHandler, exec exec.Interface) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
@ -26,22 +26,23 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
)
|
)
|
||||||
|
|
||||||
func scsiHostRescan(io ioHandler, exec mount.Exec) {
|
func scsiHostRescan(io ioHandler, exec utilexec.Interface) {
|
||||||
cmd := "Update-HostStorageCache"
|
cmd := "Update-HostStorageCache"
|
||||||
output, err := exec.Run("powershell", "/c", cmd)
|
output, err := exec.Command("powershell", "/c", cmd).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Update-HostStorageCache failed in scsiHostRescan, error: %v, output: %q", err, string(output))
|
klog.Errorf("Update-HostStorageCache failed in scsiHostRescan, error: %v, output: %q", err, string(output))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// search Windows disk number by LUN
|
// search Windows disk number by LUN
|
||||||
func findDiskByLun(lun int, iohandler ioHandler, exec mount.Exec) (string, error) {
|
func findDiskByLun(lun int, iohandler ioHandler, exec utilexec.Interface) (string, error) {
|
||||||
cmd := `Get-Disk | select number, location | ConvertTo-Json`
|
cmd := `Get-Disk | select number, location | ConvertTo-Json`
|
||||||
output, err := exec.Run("powershell", "/c", cmd)
|
output, err := exec.Command("powershell", "/c", cmd).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Get-Disk failed in findDiskByLun, error: %v, output: %q", err, string(output))
|
klog.Errorf("Get-Disk failed in findDiskByLun, error: %v, output: %q", err, string(output))
|
||||||
return "", err
|
return "", err
|
||||||
@ -98,7 +99,7 @@ func findDiskByLun(lun int, iohandler ioHandler, exec mount.Exec) (string, error
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatIfNotFormatted(disk string, fstype string, exec mount.Exec) {
|
func formatIfNotFormatted(disk string, fstype string, exec utilexec.Interface) {
|
||||||
if err := mount.ValidateDiskNumber(disk); err != nil {
|
if err := mount.ValidateDiskNumber(disk); err != nil {
|
||||||
klog.Errorf("azureDisk Mount: formatIfNotFormatted failed, err: %v\n", err)
|
klog.Errorf("azureDisk Mount: formatIfNotFormatted failed, err: %v\n", err)
|
||||||
return
|
return
|
||||||
@ -110,7 +111,7 @@ func formatIfNotFormatted(disk string, fstype string, exec mount.Exec) {
|
|||||||
}
|
}
|
||||||
cmd := fmt.Sprintf("Get-Disk -Number %s | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru", disk)
|
cmd := fmt.Sprintf("Get-Disk -Number %s | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru", disk)
|
||||||
cmd += fmt.Sprintf(" | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false", fstype)
|
cmd += fmt.Sprintf(" | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false", fstype)
|
||||||
output, err := exec.Run("powershell", "/c", cmd)
|
output, err := exec.Command("powershell", "/c", cmd).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("azureDisk Mount: Get-Disk failed, error: %v, output: %q", err, string(output))
|
klog.Errorf("azureDisk Mount: Get-Disk failed, error: %v, output: %q", err, string(output))
|
||||||
} else {
|
} else {
|
||||||
|
@ -331,7 +331,7 @@ func (cephfsVolume *cephfsMounter) checkFuseMount() bool {
|
|||||||
execute := cephfsVolume.plugin.host.GetExec(cephfsVolume.plugin.GetPluginName())
|
execute := cephfsVolume.plugin.host.GetExec(cephfsVolume.plugin.GetPluginName())
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "linux":
|
case "linux":
|
||||||
if _, err := execute.Run("/usr/bin/test", "-x", "/sbin/mount.fuse.ceph"); err == nil {
|
if _, err := execute.Command("/usr/bin/test", "-x", "/sbin/mount.fuse.ceph").CombinedOutput(); err == nil {
|
||||||
klog.V(4).Info("/sbin/mount.fuse.ceph exists, it should be fuse mount.")
|
klog.V(4).Info("/sbin/mount.fuse.ceph exists, it should be fuse mount.")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
"//vendor/k8s.io/utils/strings:go_default_library",
|
"//vendor/k8s.io/utils/strings:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -48,6 +49,7 @@ go_test(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
@ -114,7 +116,7 @@ func (plugin *fcPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.Volu
|
|||||||
return plugin.newMounterInternal(spec, pod.UID, &fcUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
return plugin.newMounterInternal(spec, pod.UID, &fcUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *fcPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec mount.Exec) (volume.Mounter, error) {
|
func (plugin *fcPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec utilexec.Interface) (volume.Mounter, error) {
|
||||||
// fc volumes used directly in a pod have a ReadOnly flag set by the pod author.
|
// fc volumes used directly in a pod have a ReadOnly flag set by the pod author.
|
||||||
// fc volumes used as a PersistentVolume gets the ReadOnly flag indirectly through the persistent-claim volume used to mount the PV
|
// fc volumes used as a PersistentVolume gets the ReadOnly flag indirectly through the persistent-claim volume used to mount the PV
|
||||||
fc, readOnly, err := getVolumeSource(spec)
|
fc, readOnly, err := getVolumeSource(spec)
|
||||||
@ -174,7 +176,7 @@ func (plugin *fcPlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, _ v
|
|||||||
return plugin.newBlockVolumeMapperInternal(spec, uid, &fcUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
return plugin.newBlockVolumeMapperInternal(spec, uid, &fcUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *fcPlugin) newBlockVolumeMapperInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec mount.Exec) (volume.BlockVolumeMapper, error) {
|
func (plugin *fcPlugin) newBlockVolumeMapperInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec utilexec.Interface) (volume.BlockVolumeMapper, error) {
|
||||||
fc, readOnly, err := getVolumeSource(spec)
|
fc, readOnly, err := getVolumeSource(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -29,6 +29,8 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
utiltesting "k8s.io/client-go/util/testing"
|
utiltesting "k8s.io/client-go/util/testing"
|
||||||
|
"k8s.io/utils/exec/testing"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
@ -164,7 +166,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) {
|
|||||||
fakeManager := newFakeDiskManager()
|
fakeManager := newFakeDiskManager()
|
||||||
defer fakeManager.Cleanup()
|
defer fakeManager.Cleanup()
|
||||||
fakeMounter := mount.NewFakeMounter(nil)
|
fakeMounter := mount.NewFakeMounter(nil)
|
||||||
fakeExec := mount.NewFakeExec(nil)
|
fakeExec := &testingexec.FakeExec{}
|
||||||
mounter, err := plug.(*fcPlugin).newMounterInternal(spec, types.UID("poduid"), fakeManager, fakeMounter, fakeExec)
|
mounter, err := plug.(*fcPlugin).newMounterInternal(spec, types.UID("poduid"), fakeManager, fakeMounter, fakeExec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to make a new Mounter: %v", err)
|
t.Errorf("Failed to make a new Mounter: %v", err)
|
||||||
@ -227,7 +229,7 @@ func doTestPluginNilMounter(t *testing.T, spec *volume.Spec) {
|
|||||||
fakeManager := newFakeDiskManager()
|
fakeManager := newFakeDiskManager()
|
||||||
defer fakeManager.Cleanup()
|
defer fakeManager.Cleanup()
|
||||||
fakeMounter := mount.NewFakeMounter(nil)
|
fakeMounter := mount.NewFakeMounter(nil)
|
||||||
fakeExec := mount.NewFakeExec(nil)
|
fakeExec := &testingexec.FakeExec{}
|
||||||
mounter, err := plug.(*fcPlugin).newMounterInternal(spec, types.UID("poduid"), fakeManager, fakeMounter, fakeExec)
|
mounter, err := plug.(*fcPlugin).newMounterInternal(spec, types.UID("poduid"), fakeManager, fakeMounter, fakeExec)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Error failed to make a new Mounter is expected: %v", err)
|
t.Errorf("Error failed to make a new Mounter is expected: %v", err)
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
|
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
"k8s.io/kubernetes/test/utils/harness"
|
"k8s.io/kubernetes/test/utils/harness"
|
||||||
"k8s.io/utils/exec"
|
"k8s.io/utils/exec"
|
||||||
fakeexec "k8s.io/utils/exec/testing"
|
"k8s.io/utils/exec/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testPlugin(h *harness.Harness) (*flexVolumeAttachablePlugin, string) {
|
func testPlugin(h *harness.Harness) (*flexVolumeAttachablePlugin, string) {
|
||||||
@ -39,7 +39,7 @@ func testPlugin(h *harness.Harness) (*flexVolumeAttachablePlugin, string) {
|
|||||||
}, rootDir
|
}, rootDir
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertDriverCall(t *harness.Harness, output fakeexec.FakeCombinedOutputAction, expectedCommand string, expectedArgs ...string) fakeexec.FakeCommandAction {
|
func assertDriverCall(t *harness.Harness, output testingexec.FakeCombinedOutputAction, expectedCommand string, expectedArgs ...string) testingexec.FakeCommandAction {
|
||||||
return func(cmd string, args ...string) exec.Cmd {
|
return func(cmd string, args ...string) exec.Cmd {
|
||||||
if cmd != "/plugin/test" {
|
if cmd != "/plugin/test" {
|
||||||
t.Errorf("Wrong executable called: got %v, expected %v", cmd, "/plugin/test")
|
t.Errorf("Wrong executable called: got %v, expected %v", cmd, "/plugin/test")
|
||||||
@ -51,20 +51,20 @@ func assertDriverCall(t *harness.Harness, output fakeexec.FakeCombinedOutputActi
|
|||||||
if !sameArgs(cmdArgs, expectedArgs) {
|
if !sameArgs(cmdArgs, expectedArgs) {
|
||||||
t.Errorf("Wrong args for %s: got %v, expected %v", args[0], cmdArgs, expectedArgs)
|
t.Errorf("Wrong args for %s: got %v, expected %v", args[0], cmdArgs, expectedArgs)
|
||||||
}
|
}
|
||||||
return &fakeexec.FakeCmd{
|
return &testingexec.FakeCmd{
|
||||||
Argv: args,
|
Argv: args,
|
||||||
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{output},
|
CombinedOutputScript: []testingexec.FakeCombinedOutputAction{output},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fakeRunner(fakeCommands ...fakeexec.FakeCommandAction) exec.Interface {
|
func fakeRunner(fakeCommands ...testingexec.FakeCommandAction) exec.Interface {
|
||||||
return &fakeexec.FakeExec{
|
return &testingexec.FakeExec{
|
||||||
CommandScript: fakeCommands,
|
CommandScript: fakeCommands,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fakeResultOutput(result interface{}) fakeexec.FakeCombinedOutputAction {
|
func fakeResultOutput(result interface{}) testingexec.FakeCombinedOutputAction {
|
||||||
return func() ([]byte, error) {
|
return func() ([]byte, error) {
|
||||||
bytes, err := json.Marshal(result)
|
bytes, err := json.Marshal(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -74,11 +74,11 @@ func fakeResultOutput(result interface{}) fakeexec.FakeCombinedOutputAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func successOutput() fakeexec.FakeCombinedOutputAction {
|
func successOutput() testingexec.FakeCombinedOutputAction {
|
||||||
return fakeResultOutput(&DriverStatus{StatusSuccess, "", "", "", true, nil, 0})
|
return fakeResultOutput(&DriverStatus{StatusSuccess, "", "", "", true, nil, 0})
|
||||||
}
|
}
|
||||||
|
|
||||||
func notSupportedOutput() fakeexec.FakeCombinedOutputAction {
|
func notSupportedOutput() testingexec.FakeCombinedOutputAction {
|
||||||
return fakeResultOutput(&DriverStatus{StatusNotSupported, "", "", "", false, nil, 0})
|
return fakeResultOutput(&DriverStatus{StatusNotSupported, "", "", "", false, nil, 0})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/kubernetes/test/utils/harness"
|
"k8s.io/kubernetes/test/utils/harness"
|
||||||
exec "k8s.io/utils/exec/testing"
|
"k8s.io/utils/exec/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInit(tt *testing.T) {
|
func TestInit(tt *testing.T) {
|
||||||
@ -34,7 +34,7 @@ func TestInit(tt *testing.T) {
|
|||||||
plugin.Init(plugin.host)
|
plugin.Init(plugin.host)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fakeVolumeNameOutput(name string) exec.FakeCombinedOutputAction {
|
func fakeVolumeNameOutput(name string) testingexec.FakeCombinedOutputAction {
|
||||||
return fakeResultOutput(&DriverStatus{
|
return fakeResultOutput(&DriverStatus{
|
||||||
Status: StatusSuccess,
|
Status: StatusSuccess,
|
||||||
VolumeName: name,
|
VolumeName: name,
|
||||||
|
@ -33,6 +33,8 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
@ -179,10 +181,10 @@ func (attacher *gcePersistentDiskAttacher) BulkVerifyVolumes(volumesByNode map[t
|
|||||||
}
|
}
|
||||||
|
|
||||||
// search Windows disk number by LUN
|
// search Windows disk number by LUN
|
||||||
func getDiskID(pdName string, exec mount.Exec) (string, error) {
|
func getDiskID(pdName string, exec utilexec.Interface) (string, error) {
|
||||||
// TODO: replace Get-GcePdName with native windows support of Get-Disk, see issue #74674
|
// TODO: replace Get-GcePdName with native windows support of Get-Disk, see issue #74674
|
||||||
cmd := `Get-GcePdName | select Name, DeviceId | ConvertTo-Json`
|
cmd := `Get-GcePdName | select Name, DeviceId | ConvertTo-Json`
|
||||||
output, err := exec.Run("powershell", "/c", cmd)
|
output, err := exec.Command("powershell", "/c", cmd).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Get-GcePdName failed, error: %v, output: %q", err, string(output))
|
klog.Errorf("Get-GcePdName failed, error: %v, output: %q", err, string(output))
|
||||||
err = errors.New(err.Error() + " " + string(output))
|
err = errors.New(err.Error() + " " + string(output))
|
||||||
|
@ -264,7 +264,7 @@ func (b *glusterfsMounter) CanMount() error {
|
|||||||
exe := b.plugin.host.GetExec(b.plugin.GetPluginName())
|
exe := b.plugin.host.GetExec(b.plugin.GetPluginName())
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "linux":
|
case "linux":
|
||||||
if _, err := exe.Run("test", "-x", gciLinuxGlusterMountBinaryPath); err != nil {
|
if _, err := exe.Command("test", "-x", gciLinuxGlusterMountBinaryPath).CombinedOutput(); err != nil {
|
||||||
return fmt.Errorf("required binary %s is missing", gciLinuxGlusterMountBinaryPath)
|
return fmt.Errorf("required binary %s is missing", gciLinuxGlusterMountBinaryPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ go_test(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
ioutil "k8s.io/kubernetes/pkg/volume/util"
|
ioutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
@ -110,7 +112,7 @@ func (plugin *iscsiPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.V
|
|||||||
return plugin.newMounterInternal(spec, pod.UID, &ISCSIUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()), secret)
|
return plugin.newMounterInternal(spec, pod.UID, &ISCSIUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()), secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *iscsiPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec mount.Exec, secret map[string]string) (volume.Mounter, error) {
|
func (plugin *iscsiPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec utilexec.Interface, secret map[string]string) (volume.Mounter, error) {
|
||||||
readOnly, fsType, err := getISCSIVolumeInfo(spec)
|
readOnly, fsType, err := getISCSIVolumeInfo(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -153,7 +155,7 @@ func (plugin *iscsiPlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod,
|
|||||||
return plugin.newBlockVolumeMapperInternal(spec, uid, &ISCSIUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()), secret)
|
return plugin.newBlockVolumeMapperInternal(spec, uid, &ISCSIUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()), secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *iscsiPlugin) newBlockVolumeMapperInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec mount.Exec, secret map[string]string) (volume.BlockVolumeMapper, error) {
|
func (plugin *iscsiPlugin) newBlockVolumeMapperInternal(spec *volume.Spec, podUID types.UID, manager diskManager, mounter mount.Interface, exec utilexec.Interface, secret map[string]string) (volume.BlockVolumeMapper, error) {
|
||||||
readOnly, _, err := getISCSIVolumeInfo(spec)
|
readOnly, _, err := getISCSIVolumeInfo(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -174,7 +176,7 @@ func (plugin *iscsiPlugin) NewUnmounter(volName string, podUID types.UID) (volum
|
|||||||
return plugin.newUnmounterInternal(volName, podUID, &ISCSIUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
return plugin.newUnmounterInternal(volName, podUID, &ISCSIUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *iscsiPlugin) newUnmounterInternal(volName string, podUID types.UID, manager diskManager, mounter mount.Interface, exec mount.Exec) (volume.Unmounter, error) {
|
func (plugin *iscsiPlugin) newUnmounterInternal(volName string, podUID types.UID, manager diskManager, mounter mount.Interface, exec utilexec.Interface) (volume.Unmounter, error) {
|
||||||
return &iscsiDiskUnmounter{
|
return &iscsiDiskUnmounter{
|
||||||
iscsiDisk: &iscsiDisk{
|
iscsiDisk: &iscsiDisk{
|
||||||
podUID: podUID,
|
podUID: podUID,
|
||||||
@ -194,7 +196,7 @@ func (plugin *iscsiPlugin) NewBlockVolumeUnmapper(volName string, podUID types.U
|
|||||||
return plugin.newUnmapperInternal(volName, podUID, &ISCSIUtil{}, plugin.host.GetExec(plugin.GetPluginName()))
|
return plugin.newUnmapperInternal(volName, podUID, &ISCSIUtil{}, plugin.host.GetExec(plugin.GetPluginName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *iscsiPlugin) newUnmapperInternal(volName string, podUID types.UID, manager diskManager, exec mount.Exec) (volume.BlockVolumeUnmapper, error) {
|
func (plugin *iscsiPlugin) newUnmapperInternal(volName string, podUID types.UID, manager diskManager, exec utilexec.Interface) (volume.BlockVolumeUnmapper, error) {
|
||||||
return &iscsiDiskUnmapper{
|
return &iscsiDiskUnmapper{
|
||||||
iscsiDisk: &iscsiDisk{
|
iscsiDisk: &iscsiDisk{
|
||||||
podUID: podUID,
|
podUID: podUID,
|
||||||
@ -318,7 +320,7 @@ type iscsiDiskMounter struct {
|
|||||||
fsType string
|
fsType string
|
||||||
volumeMode v1.PersistentVolumeMode
|
volumeMode v1.PersistentVolumeMode
|
||||||
mounter *mount.SafeFormatAndMount
|
mounter *mount.SafeFormatAndMount
|
||||||
exec mount.Exec
|
exec utilexec.Interface
|
||||||
deviceUtil ioutil.DeviceUtil
|
deviceUtil ioutil.DeviceUtil
|
||||||
mountOptions []string
|
mountOptions []string
|
||||||
}
|
}
|
||||||
@ -356,7 +358,7 @@ func (b *iscsiDiskMounter) SetUpAt(dir string, mounterArgs volume.MounterArgs) e
|
|||||||
type iscsiDiskUnmounter struct {
|
type iscsiDiskUnmounter struct {
|
||||||
*iscsiDisk
|
*iscsiDisk
|
||||||
mounter mount.Interface
|
mounter mount.Interface
|
||||||
exec mount.Exec
|
exec utilexec.Interface
|
||||||
deviceUtil ioutil.DeviceUtil
|
deviceUtil ioutil.DeviceUtil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,7 +378,7 @@ func (c *iscsiDiskUnmounter) TearDownAt(dir string) error {
|
|||||||
type iscsiDiskMapper struct {
|
type iscsiDiskMapper struct {
|
||||||
*iscsiDisk
|
*iscsiDisk
|
||||||
readOnly bool
|
readOnly bool
|
||||||
exec mount.Exec
|
exec utilexec.Interface
|
||||||
deviceUtil ioutil.DeviceUtil
|
deviceUtil ioutil.DeviceUtil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,7 +394,7 @@ func (b *iscsiDiskMapper) MapDevice(devicePath, globalMapPath, volumeMapPath, vo
|
|||||||
|
|
||||||
type iscsiDiskUnmapper struct {
|
type iscsiDiskUnmapper struct {
|
||||||
*iscsiDisk
|
*iscsiDisk
|
||||||
exec mount.Exec
|
exec utilexec.Interface
|
||||||
deviceUtil ioutil.DeviceUtil
|
deviceUtil ioutil.DeviceUtil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
utiltesting "k8s.io/client-go/util/testing"
|
utiltesting "k8s.io/client-go/util/testing"
|
||||||
|
"k8s.io/utils/exec/testing"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
@ -160,7 +162,7 @@ func doTestPlugin(t *testing.T, spec *volume.Spec) {
|
|||||||
fakeManager := NewFakeDiskManager()
|
fakeManager := NewFakeDiskManager()
|
||||||
defer fakeManager.Cleanup()
|
defer fakeManager.Cleanup()
|
||||||
fakeMounter := mount.NewFakeMounter(nil)
|
fakeMounter := mount.NewFakeMounter(nil)
|
||||||
fakeExec := mount.NewFakeExec(nil)
|
fakeExec := &testingexec.FakeExec{}
|
||||||
mounter, err := plug.(*iscsiPlugin).newMounterInternal(spec, types.UID("poduid"), fakeManager, fakeMounter, fakeExec, nil)
|
mounter, err := plug.(*iscsiPlugin).newMounterInternal(spec, types.UID("poduid"), fakeManager, fakeMounter, fakeExec, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to make a new Mounter: %v", err)
|
t.Errorf("Failed to make a new Mounter: %v", err)
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -96,7 +97,7 @@ func updateISCSIDiscoverydb(b iscsiDiskMounter, tp string) error {
|
|||||||
v := b.secret[k]
|
v := b.secret[k]
|
||||||
if len(v) > 0 {
|
if len(v) > 0 {
|
||||||
// explicitly not using execWithLog so secrets are not logged
|
// explicitly not using execWithLog so secrets are not logged
|
||||||
out, err := b.exec.Run("iscsiadm", "-m", "discoverydb", "-t", "sendtargets", "-p", tp, "-I", b.Iface, "-o", "update", "-n", k, "-v", v)
|
out, err := b.exec.Command("iscsiadm", "-m", "discoverydb", "-t", "sendtargets", "-p", tp, "-I", b.Iface, "-o", "update", "-n", k, "-v", v).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("iscsi: failed to update discoverydb key %q error: %v", k, string(out))
|
return fmt.Errorf("iscsi: failed to update discoverydb key %q error: %v", k, string(out))
|
||||||
}
|
}
|
||||||
@ -119,7 +120,7 @@ func updateISCSINode(b iscsiDiskMounter, tp string) error {
|
|||||||
v := b.secret[k]
|
v := b.secret[k]
|
||||||
if len(v) > 0 {
|
if len(v) > 0 {
|
||||||
// explicitly not using execWithLog so secrets are not logged
|
// explicitly not using execWithLog so secrets are not logged
|
||||||
out, err := b.exec.Run("iscsiadm", "-m", "node", "-p", tp, "-T", b.Iqn, "-I", b.Iface, "-o", "update", "-n", k, "-v", v)
|
out, err := b.exec.Command("iscsiadm", "-m", "node", "-p", tp, "-T", b.Iqn, "-I", b.Iface, "-o", "update", "-n", k, "-v", v).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("iscsi: failed to update node session key %q error: %v", k, string(out))
|
return fmt.Errorf("iscsi: failed to update node session key %q error: %v", k, string(out))
|
||||||
}
|
}
|
||||||
@ -561,7 +562,7 @@ func deleteDevices(c iscsiDiskUnmounter) error {
|
|||||||
}
|
}
|
||||||
// Flush any multipath device maps
|
// Flush any multipath device maps
|
||||||
for mpathDevice := range mpathDevices {
|
for mpathDevice := range mpathDevices {
|
||||||
_, err = c.exec.Run("multipath", "-f", mpathDevice)
|
_, err = c.exec.Command("multipath", "-f", mpathDevice).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Warningf("Warning: Failed to flush multipath device map: %s\nError: %v", mpathDevice, err)
|
klog.Warningf("Warning: Failed to flush multipath device map: %s\nError: %v", mpathDevice, err)
|
||||||
// Fall through -- keep deleting the block devices
|
// Fall through -- keep deleting the block devices
|
||||||
@ -722,7 +723,7 @@ func (util *ISCSIUtil) DetachBlockISCSIDisk(c iscsiDiskUnmapper, mapPath string)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (util *ISCSIUtil) detachISCSIDisk(exec mount.Exec, portals []string, iqn, iface, volName, initiatorName string, found bool) error {
|
func (util *ISCSIUtil) detachISCSIDisk(exec utilexec.Interface, portals []string, iqn, iface, volName, initiatorName string, found bool) error {
|
||||||
for _, portal := range portals {
|
for _, portal := range portals {
|
||||||
logoutArgs := []string{"-m", "node", "-p", portal, "-T", iqn, "--logout"}
|
logoutArgs := []string{"-m", "node", "-p", portal, "-T", iqn, "--logout"}
|
||||||
deleteArgs := []string{"-m", "node", "-p", portal, "-T", iqn, "-o", "delete"}
|
deleteArgs := []string{"-m", "node", "-p", portal, "-T", iqn, "-o", "delete"}
|
||||||
@ -731,7 +732,7 @@ func (util *ISCSIUtil) detachISCSIDisk(exec mount.Exec, portals []string, iqn, i
|
|||||||
deleteArgs = append(deleteArgs, []string{"-I", iface}...)
|
deleteArgs = append(deleteArgs, []string{"-I", iface}...)
|
||||||
}
|
}
|
||||||
klog.Infof("iscsi: log out target %s iqn %s iface %s", portal, iqn, iface)
|
klog.Infof("iscsi: log out target %s iqn %s iface %s", portal, iqn, iface)
|
||||||
out, err := exec.Run("iscsiadm", logoutArgs...)
|
out, err := exec.Command("iscsiadm", logoutArgs...).CombinedOutput()
|
||||||
err = ignoreExitCodes(err, exit_ISCSI_ERR_NO_OBJS_FOUND, exit_ISCSI_ERR_SESS_NOT_FOUND)
|
err = ignoreExitCodes(err, exit_ISCSI_ERR_NO_OBJS_FOUND, exit_ISCSI_ERR_SESS_NOT_FOUND)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("iscsi: failed to detach disk Error: %s", string(out))
|
klog.Errorf("iscsi: failed to detach disk Error: %s", string(out))
|
||||||
@ -739,7 +740,7 @@ func (util *ISCSIUtil) detachISCSIDisk(exec mount.Exec, portals []string, iqn, i
|
|||||||
}
|
}
|
||||||
// Delete the node record
|
// Delete the node record
|
||||||
klog.Infof("iscsi: delete node record target %s iqn %s", portal, iqn)
|
klog.Infof("iscsi: delete node record target %s iqn %s", portal, iqn)
|
||||||
out, err = exec.Run("iscsiadm", deleteArgs...)
|
out, err = exec.Command("iscsiadm", deleteArgs...).CombinedOutput()
|
||||||
err = ignoreExitCodes(err, exit_ISCSI_ERR_NO_OBJS_FOUND, exit_ISCSI_ERR_SESS_NOT_FOUND)
|
err = ignoreExitCodes(err, exit_ISCSI_ERR_NO_OBJS_FOUND, exit_ISCSI_ERR_SESS_NOT_FOUND)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("iscsi: failed to delete node record Error: %s", string(out))
|
klog.Errorf("iscsi: failed to delete node record Error: %s", string(out))
|
||||||
@ -750,7 +751,7 @@ func (util *ISCSIUtil) detachISCSIDisk(exec mount.Exec, portals []string, iqn, i
|
|||||||
// If the iface is not created via iscsi plugin, skip to delete
|
// If the iface is not created via iscsi plugin, skip to delete
|
||||||
if initiatorName != "" && found && iface == (portals[0]+":"+volName) {
|
if initiatorName != "" && found && iface == (portals[0]+":"+volName) {
|
||||||
deleteArgs := []string{"-m", "iface", "-I", iface, "-o", "delete"}
|
deleteArgs := []string{"-m", "iface", "-I", iface, "-o", "delete"}
|
||||||
out, err := exec.Run("iscsiadm", deleteArgs...)
|
out, err := exec.Command("iscsiadm", deleteArgs...).CombinedOutput()
|
||||||
err = ignoreExitCodes(err, exit_ISCSI_ERR_NO_OBJS_FOUND, exit_ISCSI_ERR_SESS_NOT_FOUND)
|
err = ignoreExitCodes(err, exit_ISCSI_ERR_NO_OBJS_FOUND, exit_ISCSI_ERR_SESS_NOT_FOUND)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("iscsi: failed to delete iface Error: %s", string(out))
|
klog.Errorf("iscsi: failed to delete iface Error: %s", string(out))
|
||||||
@ -884,9 +885,15 @@ func cloneIface(b iscsiDiskMounter) error {
|
|||||||
return lastErr
|
return lastErr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Get and sort keys to maintain a stable iteration order
|
||||||
|
var keys []string
|
||||||
|
for k := range params {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
// update new iface records
|
// update new iface records
|
||||||
for key, val := range params {
|
for _, key := range keys {
|
||||||
_, err = execWithLog(b, "iscsiadm", "-m", "iface", "-I", b.Iface, "-o", "update", "-n", key, "-v", val)
|
_, err = execWithLog(b, "iscsiadm", "-m", "iface", "-I", b.Iface, "-o", "update", "-n", key, "-v", params[key])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
execWithLog(b, "iscsiadm", "-m", "iface", "-I", b.Iface, "-o", "delete")
|
execWithLog(b, "iscsiadm", "-m", "iface", "-I", b.Iface, "-o", "delete")
|
||||||
lastErr = fmt.Errorf("iscsi: failed to update iface records: %s (%v). iface(%s) will be used", out, err, b.InitIface)
|
lastErr = fmt.Errorf("iscsi: failed to update iface records: %s (%v). iface(%s) will be used", out, err, b.InitIface)
|
||||||
@ -965,7 +972,7 @@ func ignoreExitCodes(err error, ignoredExitCodes ...int) error {
|
|||||||
|
|
||||||
func execWithLog(b iscsiDiskMounter, cmd string, args ...string) (string, error) {
|
func execWithLog(b iscsiDiskMounter, cmd string, args ...string) (string, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
out, err := b.exec.Run(cmd, args...)
|
out, err := b.exec.Command(cmd, args...).CombinedOutput()
|
||||||
if klog.V(5) {
|
if klog.V(5) {
|
||||||
d := time.Since(start)
|
d := time.Since(start)
|
||||||
klog.V(5).Infof("Executed %s %v in %v, err: %v", cmd, args, d, err)
|
klog.V(5).Infof("Executed %s %v in %v, err: %v", cmd, args, d, err)
|
||||||
|
@ -17,16 +17,20 @@ limitations under the License.
|
|||||||
package iscsi
|
package iscsi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/utils/exec/testing"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
|
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TestIface = "192.168.1.10:pv0001"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExtractDeviceAndPrefix(t *testing.T) {
|
func TestExtractDeviceAndPrefix(t *testing.T) {
|
||||||
@ -216,28 +220,28 @@ func TestParseIscsiadmShow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClonedIface(t *testing.T) {
|
func TestClonedIface(t *testing.T) {
|
||||||
cmdCount := 0
|
fakeExec := &testingexec.FakeExec{}
|
||||||
fakeExec := mount.NewFakeExec(func(cmd string, args ...string) ([]byte, error) {
|
scripts := []volumetest.CommandScript{
|
||||||
cmdCount++
|
{
|
||||||
if cmd != "iscsiadm" {
|
Cmd: "iscsiadm",
|
||||||
t.Errorf("iscsiadm command expected, got %q", cmd)
|
Args: []string{"-m", "iface", "-I", "", "-o", "show"},
|
||||||
|
Output: "iface.ipaddress = <empty>\niface.transport_name = tcp\niface.initiatorname = <empty>\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Cmd: "iscsiadm",
|
||||||
|
Args: []string{"-m", "iface", "-I", TestIface, "-o", "new"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Cmd: "iscsiadm",
|
||||||
|
Args: []string{"-m", "iface", "-I", TestIface, "-o", "update", "-n", "iface.initiatorname", "-v", ""},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Cmd: "iscsiadm",
|
||||||
|
Args: []string{"-m", "iface", "-I", TestIface, "-o", "update", "-n", "iface.transport_name", "-v", "tcp"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
switch cmdCount {
|
volumetest.ScriptCommands(fakeExec, scripts)
|
||||||
case 1:
|
fakeExec.ExactOrder = true
|
||||||
// iscsiadm -m iface -I <iface> -o show
|
|
||||||
return []byte("iface.ipaddress = <empty>\niface.transport_name = tcp\niface.initiatorname = <empty>\n"), nil
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
// iscsiadm -m iface -I <newIface> -o new
|
|
||||||
return []byte("New interface 192.168.1.10:pv0001 added"), nil
|
|
||||||
case 3:
|
|
||||||
// iscsiadm -m iface -I <newIface> -o update -n <key> -v <val>
|
|
||||||
return []byte(""), nil
|
|
||||||
case 4:
|
|
||||||
return []byte(""), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("Unexpected exec call nr %d: %s", cmdCount, cmd)
|
|
||||||
})
|
|
||||||
plugins := []volume.VolumePlugin{
|
plugins := []volume.VolumePlugin{
|
||||||
&iscsiPlugin{
|
&iscsiPlugin{
|
||||||
host: nil,
|
host: nil,
|
||||||
@ -246,27 +250,32 @@ func TestClonedIface(t *testing.T) {
|
|||||||
plugin := plugins[0]
|
plugin := plugins[0]
|
||||||
fakeMounter := iscsiDiskMounter{
|
fakeMounter := iscsiDiskMounter{
|
||||||
iscsiDisk: &iscsiDisk{
|
iscsiDisk: &iscsiDisk{
|
||||||
Iface: "192.168.1.10:pv0001",
|
Iface: TestIface,
|
||||||
plugin: plugin.(*iscsiPlugin)},
|
plugin: plugin.(*iscsiPlugin)},
|
||||||
exec: fakeExec,
|
exec: fakeExec,
|
||||||
}
|
}
|
||||||
cloneIface(fakeMounter)
|
err := cloneIface(fakeMounter)
|
||||||
if cmdCount != 4 {
|
if err != nil {
|
||||||
t.Errorf("expected 4 CombinedOutput() calls, got %d", cmdCount)
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if fakeExec.CommandCalls != len(scripts) {
|
||||||
|
t.Errorf("expected 4 CombinedOutput() calls, got %d", fakeExec.CommandCalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClonedIfaceShowError(t *testing.T) {
|
func TestClonedIfaceShowError(t *testing.T) {
|
||||||
cmdCount := 0
|
fakeExec := &testingexec.FakeExec{}
|
||||||
fakeExec := mount.NewFakeExec(func(cmd string, args ...string) ([]byte, error) {
|
scripts := []volumetest.CommandScript{
|
||||||
cmdCount++
|
{
|
||||||
if cmd != "iscsiadm" {
|
Cmd: "iscsiadm",
|
||||||
t.Errorf("iscsiadm command expected, got %q", cmd)
|
Args: []string{"-m", "iface", "-I", "", "-o", "show"},
|
||||||
|
Output: "test error",
|
||||||
|
ReturnCode: 1,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// iscsiadm -m iface -I <iface> -o show, return test error
|
volumetest.ScriptCommands(fakeExec, scripts)
|
||||||
return []byte(""), errors.New("test error")
|
fakeExec.ExactOrder = true
|
||||||
})
|
|
||||||
plugins := []volume.VolumePlugin{
|
plugins := []volume.VolumePlugin{
|
||||||
&iscsiPlugin{
|
&iscsiPlugin{
|
||||||
host: nil,
|
host: nil,
|
||||||
@ -275,43 +284,49 @@ func TestClonedIfaceShowError(t *testing.T) {
|
|||||||
plugin := plugins[0]
|
plugin := plugins[0]
|
||||||
fakeMounter := iscsiDiskMounter{
|
fakeMounter := iscsiDiskMounter{
|
||||||
iscsiDisk: &iscsiDisk{
|
iscsiDisk: &iscsiDisk{
|
||||||
Iface: "192.168.1.10:pv0001",
|
Iface: TestIface,
|
||||||
plugin: plugin.(*iscsiPlugin)},
|
plugin: plugin.(*iscsiPlugin)},
|
||||||
exec: fakeExec,
|
exec: fakeExec,
|
||||||
}
|
}
|
||||||
cloneIface(fakeMounter)
|
err := cloneIface(fakeMounter)
|
||||||
if cmdCount != 1 {
|
if err == nil {
|
||||||
t.Errorf("expected 1 CombinedOutput() calls, got %d", cmdCount)
|
t.Errorf("expect to receive error, nil received")
|
||||||
|
}
|
||||||
|
if fakeExec.CommandCalls != len(scripts) {
|
||||||
|
t.Errorf("expected 1 CombinedOutput() calls, got %d", fakeExec.CommandCalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClonedIfaceUpdateError(t *testing.T) {
|
func TestClonedIfaceUpdateError(t *testing.T) {
|
||||||
cmdCount := 0
|
fakeExec := &testingexec.FakeExec{}
|
||||||
fakeExec := mount.NewFakeExec(func(cmd string, args ...string) ([]byte, error) {
|
scripts := []volumetest.CommandScript{
|
||||||
cmdCount++
|
{
|
||||||
if cmd != "iscsiadm" {
|
Cmd: "iscsiadm",
|
||||||
t.Errorf("iscsiadm command expected, got %q", cmd)
|
Args: []string{"-m", "iface", "-I", "", "-o", "show"},
|
||||||
|
Output: "iface.ipaddress = <empty>\niface.transport_name = tcp\niface.initiatorname = <empty>\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Cmd: "iscsiadm",
|
||||||
|
Args: []string{"-m", "iface", "-I", TestIface, "-o", "new"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Cmd: "iscsiadm",
|
||||||
|
Args: []string{"-m", "iface", "-I", TestIface, "-o", "update", "-n", "iface.initiatorname", "-v", ""},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Cmd: "iscsiadm",
|
||||||
|
Args: []string{"-m", "iface", "-I", TestIface, "-o", "update", "-n", "iface.transport_name", "-v", "tcp"},
|
||||||
|
ReturnCode: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Cmd: "iscsiadm",
|
||||||
|
Args: []string{"-m", "iface", "-I", TestIface, "-o", "delete"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
switch cmdCount {
|
volumetest.ScriptCommands(fakeExec, scripts)
|
||||||
case 1:
|
fakeExec.ExactOrder = true
|
||||||
// iscsiadm -m iface -I <iface> -o show
|
|
||||||
return []byte("iface.ipaddress = <empty>\niface.transport_name = tcp\niface.initiatorname = <empty>\n"), nil
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
// iscsiadm -m iface -I <newIface> -o new
|
|
||||||
return []byte("New interface 192.168.1.10:pv0001 added"), nil
|
|
||||||
case 3:
|
|
||||||
// iscsiadm -m iface -I <newIface> -o update -n <key> -v <val>
|
|
||||||
return []byte(""), nil
|
|
||||||
case 4:
|
|
||||||
return []byte(""), errors.New("test error")
|
|
||||||
case 5:
|
|
||||||
// iscsiadm -m iface -I <newIface> -o delete
|
|
||||||
return []byte(""), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("Unexpected exec call nr %d: %s", cmdCount, cmd)
|
|
||||||
})
|
|
||||||
plugins := []volume.VolumePlugin{
|
plugins := []volume.VolumePlugin{
|
||||||
&iscsiPlugin{
|
&iscsiPlugin{
|
||||||
host: nil,
|
host: nil,
|
||||||
@ -320,13 +335,16 @@ func TestClonedIfaceUpdateError(t *testing.T) {
|
|||||||
plugin := plugins[0]
|
plugin := plugins[0]
|
||||||
fakeMounter := iscsiDiskMounter{
|
fakeMounter := iscsiDiskMounter{
|
||||||
iscsiDisk: &iscsiDisk{
|
iscsiDisk: &iscsiDisk{
|
||||||
Iface: "192.168.1.10:pv0001",
|
Iface: TestIface,
|
||||||
plugin: plugin.(*iscsiPlugin)},
|
plugin: plugin.(*iscsiPlugin)},
|
||||||
exec: fakeExec,
|
exec: fakeExec,
|
||||||
}
|
}
|
||||||
cloneIface(fakeMounter)
|
err := cloneIface(fakeMounter)
|
||||||
if cmdCount != 5 {
|
if err == nil {
|
||||||
t.Errorf("expected 5 CombinedOutput() calls, got %d", cmdCount)
|
t.Errorf("expect to receive error, nil received")
|
||||||
|
}
|
||||||
|
if fakeExec.CommandCalls != len(scripts) {
|
||||||
|
t.Errorf("expected 5 CombinedOutput() calls, got %d", fakeExec.CommandCalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -206,15 +206,15 @@ func (nfsMounter *nfsMounter) CanMount() error {
|
|||||||
exec := nfsMounter.plugin.host.GetExec(nfsMounter.plugin.GetPluginName())
|
exec := nfsMounter.plugin.host.GetExec(nfsMounter.plugin.GetPluginName())
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "linux":
|
case "linux":
|
||||||
if _, err := exec.Run("test", "-x", "/sbin/mount.nfs"); err != nil {
|
if _, err := exec.Command("test", "-x", "/sbin/mount.nfs").CombinedOutput(); err != nil {
|
||||||
return fmt.Errorf("Required binary /sbin/mount.nfs is missing")
|
return fmt.Errorf("Required binary /sbin/mount.nfs is missing")
|
||||||
}
|
}
|
||||||
if _, err := exec.Run("test", "-x", "/sbin/mount.nfs4"); err != nil {
|
if _, err := exec.Command("test", "-x", "/sbin/mount.nfs4").CombinedOutput(); err != nil {
|
||||||
return fmt.Errorf("Required binary /sbin/mount.nfs4 is missing")
|
return fmt.Errorf("Required binary /sbin/mount.nfs4 is missing")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case "darwin":
|
case "darwin":
|
||||||
if _, err := exec.Run("test", "-x", "/sbin/mount_nfs"); err != nil {
|
if _, err := exec.Command("test", "-x", "/sbin/mount_nfs").CombinedOutput(); err != nil {
|
||||||
return fmt.Errorf("Required binary /sbin/mount_nfs is missing")
|
return fmt.Errorf("Required binary /sbin/mount_nfs is missing")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,8 @@ import (
|
|||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
"k8s.io/utils/exec"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
||||||
@ -437,7 +439,7 @@ type VolumeHost interface {
|
|||||||
DeleteServiceAccountTokenFunc() func(podUID types.UID)
|
DeleteServiceAccountTokenFunc() func(podUID types.UID)
|
||||||
|
|
||||||
// Returns an interface that should be used to execute any utilities in volume plugins
|
// Returns an interface that should be used to execute any utilities in volume plugins
|
||||||
GetExec(pluginName string) mount.Exec
|
GetExec(pluginName string) exec.Interface
|
||||||
|
|
||||||
// Returns the labels on the node
|
// Returns the labels on the node
|
||||||
GetNodeLabels() (map[string]string, error)
|
GetNodeLabels() (map[string]string, error)
|
||||||
|
@ -102,7 +102,7 @@ func (plugin *quobytePlugin) CanSupport(spec *volume.Spec) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
exec := plugin.host.GetExec(plugin.GetPluginName())
|
exec := plugin.host.GetExec(plugin.GetPluginName())
|
||||||
if out, err := exec.Run("ls", "/sbin/mount.quobyte"); err == nil {
|
if out, err := exec.Command("ls", "/sbin/mount.quobyte").CombinedOutput(); err == nil {
|
||||||
klog.V(4).Infof("quobyte: can support: %s", string(out))
|
klog.V(4).Infof("quobyte: can support: %s", string(out))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
|
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
"//vendor/k8s.io/utils/path:go_default_library",
|
"//vendor/k8s.io/utils/path:go_default_library",
|
||||||
"//vendor/k8s.io/utils/strings:go_default_library",
|
"//vendor/k8s.io/utils/strings:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -38,6 +38,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
volutil "k8s.io/kubernetes/pkg/volume/util"
|
volutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
utilstrings "k8s.io/utils/strings"
|
utilstrings "k8s.io/utils/strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -502,7 +503,7 @@ func (plugin *rbdPlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, _
|
|||||||
return plugin.newBlockVolumeMapperInternal(spec, uid, &RBDUtil{}, secret, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
return plugin.newBlockVolumeMapperInternal(spec, uid, &RBDUtil{}, secret, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *rbdPlugin) newBlockVolumeMapperInternal(spec *volume.Spec, podUID types.UID, manager diskManager, secret string, mounter mount.Interface, exec mount.Exec) (volume.BlockVolumeMapper, error) {
|
func (plugin *rbdPlugin) newBlockVolumeMapperInternal(spec *volume.Spec, podUID types.UID, manager diskManager, secret string, mounter mount.Interface, exec utilexec.Interface) (volume.BlockVolumeMapper, error) {
|
||||||
mon, err := getVolumeSourceMonitors(spec)
|
mon, err := getVolumeSourceMonitors(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -770,7 +771,7 @@ type rbd struct {
|
|||||||
ReadOnly bool
|
ReadOnly bool
|
||||||
plugin *rbdPlugin
|
plugin *rbdPlugin
|
||||||
mounter *mount.SafeFormatAndMount
|
mounter *mount.SafeFormatAndMount
|
||||||
exec mount.Exec
|
exec utilexec.Interface
|
||||||
// Utility interface that provides API calls to the provider to attach/detach disks.
|
// Utility interface that provides API calls to the provider to attach/detach disks.
|
||||||
manager diskManager
|
manager diskManager
|
||||||
volume.MetricsProvider `json:"-"`
|
volume.MetricsProvider `json:"-"`
|
||||||
|
@ -32,7 +32,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/apimachinery/pkg/util/errors"
|
"k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
@ -42,6 +42,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/util/node"
|
"k8s.io/kubernetes/pkg/util/node"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volutil "k8s.io/kubernetes/pkg/volume/util"
|
volutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
utilpath "k8s.io/utils/path"
|
utilpath "k8s.io/utils/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -227,22 +228,22 @@ func execRbdMap(b rbdMounter, rbdCmd string, mon string) ([]byte, error) {
|
|||||||
// do not change this format - some tools like rbd-nbd are strict about it.
|
// do not change this format - some tools like rbd-nbd are strict about it.
|
||||||
imgPath := fmt.Sprintf("%s/%s", b.Pool, b.Image)
|
imgPath := fmt.Sprintf("%s/%s", b.Pool, b.Image)
|
||||||
if b.Secret != "" {
|
if b.Secret != "" {
|
||||||
return b.exec.Run(rbdCmd,
|
return b.exec.Command(rbdCmd,
|
||||||
"map", imgPath, "--id", b.Id, "-m", mon, "--key="+b.Secret)
|
"map", imgPath, "--id", b.Id, "-m", mon, "--key="+b.Secret).CombinedOutput()
|
||||||
} else {
|
} else {
|
||||||
return b.exec.Run(rbdCmd,
|
return b.exec.Command(rbdCmd,
|
||||||
"map", imgPath, "--id", b.Id, "-m", mon, "-k", b.Keyring)
|
"map", imgPath, "--id", b.Id, "-m", mon, "-k", b.Keyring).CombinedOutput()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if rbd-nbd tools are installed.
|
// Check if rbd-nbd tools are installed.
|
||||||
func checkRbdNbdTools(e mount.Exec) bool {
|
func checkRbdNbdTools(e utilexec.Interface) bool {
|
||||||
_, err := e.Run("modprobe", "nbd")
|
_, err := e.Command("modprobe", "nbd").CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.V(5).Infof("rbd-nbd: nbd modprobe failed with error %v", err)
|
klog.V(5).Infof("rbd-nbd: nbd modprobe failed with error %v", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if _, err := e.Run("rbd-nbd", "--version"); err != nil {
|
if _, err := e.Command("rbd-nbd", "--version").CombinedOutput(); err != nil {
|
||||||
klog.V(5).Infof("rbd-nbd: getting rbd-nbd version failed with error %v", err)
|
klog.V(5).Infof("rbd-nbd: getting rbd-nbd version failed with error %v", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -335,7 +336,7 @@ func (util *RBDUtil) rbdUnlock(b rbdMounter) error {
|
|||||||
// Get the locker name, something like "client.1234".
|
// Get the locker name, something like "client.1234".
|
||||||
args := []string{"lock", "list", b.Image, "--pool", b.Pool, "--id", b.Id, "-m", mon}
|
args := []string{"lock", "list", b.Image, "--pool", b.Pool, "--id", b.Id, "-m", mon}
|
||||||
args = append(args, secret_opt...)
|
args = append(args, secret_opt...)
|
||||||
cmd, err = b.exec.Run("rbd", args...)
|
cmd, err = b.exec.Command("rbd", args...).CombinedOutput()
|
||||||
output = string(cmd)
|
output = string(cmd)
|
||||||
klog.V(4).Infof("lock list output %q", output)
|
klog.V(4).Infof("lock list output %q", output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -353,7 +354,7 @@ func (util *RBDUtil) rbdUnlock(b rbdMounter) error {
|
|||||||
if len(locker) > 0 {
|
if len(locker) > 0 {
|
||||||
args := []string{"lock", "remove", b.Image, lock_id, locker, "--pool", b.Pool, "--id", b.Id, "-m", mon}
|
args := []string{"lock", "remove", b.Image, lock_id, locker, "--pool", b.Pool, "--id", b.Id, "-m", mon}
|
||||||
args = append(args, secret_opt...)
|
args = append(args, secret_opt...)
|
||||||
cmd, err = b.exec.Run("rbd", args...)
|
cmd, err = b.exec.Command("rbd", args...).CombinedOutput()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
klog.V(4).Infof("rbd: successfully remove lock (locker_id: %s) on image: %s/%s with id %s mon %s", lock_id, b.Pool, b.Image, b.Id, mon)
|
klog.V(4).Infof("rbd: successfully remove lock (locker_id: %s) on image: %s/%s with id %s mon %s", lock_id, b.Pool, b.Image, b.Id, mon)
|
||||||
} else {
|
} else {
|
||||||
@ -432,7 +433,7 @@ func (util *RBDUtil) AttachDisk(b rbdMounter) (string, error) {
|
|||||||
mon := util.kernelRBDMonitorsOpt(b.Mon)
|
mon := util.kernelRBDMonitorsOpt(b.Mon)
|
||||||
klog.V(1).Infof("rbd: map mon %s", mon)
|
klog.V(1).Infof("rbd: map mon %s", mon)
|
||||||
|
|
||||||
_, err := b.exec.Run("modprobe", "rbd")
|
_, err := b.exec.Command("modprobe", "rbd").CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Warningf("rbd: failed to load rbd kernel module:%v", err)
|
klog.Warningf("rbd: failed to load rbd kernel module:%v", err)
|
||||||
}
|
}
|
||||||
@ -483,7 +484,7 @@ func (util *RBDUtil) DetachDisk(plugin *rbdPlugin, deviceMountPath string, devic
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rbd unmap
|
// rbd unmap
|
||||||
output, err := exec.Run(rbdCmd, "unmap", device)
|
output, err := exec.Command(rbdCmd, "unmap", device).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rbdErrors(err, fmt.Errorf("rbd: failed to unmap device %s, error %v, rbd output: %v", device, err, output))
|
return rbdErrors(err, fmt.Errorf("rbd: failed to unmap device %s, error %v, rbd output: %v", device, err, output))
|
||||||
}
|
}
|
||||||
@ -542,7 +543,7 @@ func (util *RBDUtil) DetachBlockDisk(disk rbdDiskUnmapper, mapPath string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rbd unmap
|
// rbd unmap
|
||||||
output, err := exec.Run(rbdCmd, "unmap", device)
|
output, err := exec.Command(rbdCmd, "unmap", device).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rbdErrors(err, fmt.Errorf("rbd: failed to unmap device %s, error %v, rbd output: %s", device, err, string(output)))
|
return rbdErrors(err, fmt.Errorf("rbd: failed to unmap device %s, error %v, rbd output: %s", device, err, string(output)))
|
||||||
}
|
}
|
||||||
@ -601,7 +602,7 @@ func (util *RBDUtil) CreateImage(p *rbdVolumeProvisioner) (r *v1.RBDPersistentVo
|
|||||||
features := strings.Join(p.rbdMounter.imageFeatures, ",")
|
features := strings.Join(p.rbdMounter.imageFeatures, ",")
|
||||||
args = append(args, "--image-feature", features)
|
args = append(args, "--image-feature", features)
|
||||||
}
|
}
|
||||||
output, err = p.exec.Run("rbd", args...)
|
output, err = p.exec.Command("rbd", args...).CombinedOutput()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Warningf("failed to create rbd image, output %v", string(output))
|
klog.Warningf("failed to create rbd image, output %v", string(output))
|
||||||
@ -628,8 +629,8 @@ func (util *RBDUtil) DeleteImage(p *rbdVolumeDeleter) error {
|
|||||||
// rbd rm.
|
// rbd rm.
|
||||||
mon := util.kernelRBDMonitorsOpt(p.rbdMounter.Mon)
|
mon := util.kernelRBDMonitorsOpt(p.rbdMounter.Mon)
|
||||||
klog.V(4).Infof("rbd: rm %s using mon %s, pool %s id %s key %s", p.rbdMounter.Image, mon, p.rbdMounter.Pool, p.rbdMounter.adminId, p.rbdMounter.adminSecret)
|
klog.V(4).Infof("rbd: rm %s using mon %s, pool %s id %s key %s", p.rbdMounter.Image, mon, p.rbdMounter.Pool, p.rbdMounter.adminId, p.rbdMounter.adminSecret)
|
||||||
output, err = p.exec.Run("rbd",
|
output, err = p.exec.Command("rbd",
|
||||||
"rm", p.rbdMounter.Image, "--pool", p.rbdMounter.Pool, "--id", p.rbdMounter.adminId, "-m", mon, "--key="+p.rbdMounter.adminSecret)
|
"rm", p.rbdMounter.Image, "--pool", p.rbdMounter.Pool, "--id", p.rbdMounter.adminId, "-m", mon, "--key="+p.rbdMounter.adminSecret).CombinedOutput()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -660,8 +661,8 @@ func (util *RBDUtil) ExpandImage(rbdExpander *rbdVolumeExpander, oldSize resourc
|
|||||||
// rbd resize.
|
// rbd resize.
|
||||||
mon := util.kernelRBDMonitorsOpt(rbdExpander.rbdMounter.Mon)
|
mon := util.kernelRBDMonitorsOpt(rbdExpander.rbdMounter.Mon)
|
||||||
klog.V(4).Infof("rbd: resize %s using mon %s, pool %s id %s key %s", rbdExpander.rbdMounter.Image, mon, rbdExpander.rbdMounter.Pool, rbdExpander.rbdMounter.adminId, rbdExpander.rbdMounter.adminSecret)
|
klog.V(4).Infof("rbd: resize %s using mon %s, pool %s id %s key %s", rbdExpander.rbdMounter.Image, mon, rbdExpander.rbdMounter.Pool, rbdExpander.rbdMounter.adminId, rbdExpander.rbdMounter.adminSecret)
|
||||||
output, err = rbdExpander.exec.Run("rbd",
|
output, err = rbdExpander.exec.Command("rbd",
|
||||||
"resize", rbdExpander.rbdMounter.Image, "--size", newVolSz, "--pool", rbdExpander.rbdMounter.Pool, "--id", rbdExpander.rbdMounter.adminId, "-m", mon, "--key="+rbdExpander.rbdMounter.adminSecret)
|
"resize", rbdExpander.rbdMounter.Image, "--size", newVolSz, "--pool", rbdExpander.rbdMounter.Pool, "--id", rbdExpander.rbdMounter.adminId, "-m", mon, "--key="+rbdExpander.rbdMounter.adminSecret).CombinedOutput()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return newSizeQuant, nil
|
return newSizeQuant, nil
|
||||||
}
|
}
|
||||||
@ -702,8 +703,8 @@ func (util *RBDUtil) rbdInfo(b *rbdMounter) (int, error) {
|
|||||||
// rbd: error opening image 1234: (2) No such file or directory
|
// rbd: error opening image 1234: (2) No such file or directory
|
||||||
//
|
//
|
||||||
klog.V(4).Infof("rbd: info %s using mon %s, pool %s id %s key %s", b.Image, mon, b.Pool, id, secret)
|
klog.V(4).Infof("rbd: info %s using mon %s, pool %s id %s key %s", b.Image, mon, b.Pool, id, secret)
|
||||||
output, err = b.exec.Run("rbd",
|
output, err = b.exec.Command("rbd",
|
||||||
"info", b.Image, "--pool", b.Pool, "-m", mon, "--id", id, "--key="+secret, "-k=/dev/null", "--format=json")
|
"info", b.Image, "--pool", b.Pool, "-m", mon, "--id", id, "--key="+secret, "-k=/dev/null", "--format=json").CombinedOutput()
|
||||||
|
|
||||||
if err, ok := err.(*exec.Error); ok {
|
if err, ok := err.(*exec.Error); ok {
|
||||||
if err.Err == exec.ErrNotFound {
|
if err.Err == exec.ErrNotFound {
|
||||||
@ -765,8 +766,8 @@ func (util *RBDUtil) rbdStatus(b *rbdMounter) (bool, string, error) {
|
|||||||
// rbd: error opening image kubernetes-dynamic-pvc-<UUID>: (2) No such file or directory
|
// rbd: error opening image kubernetes-dynamic-pvc-<UUID>: (2) No such file or directory
|
||||||
//
|
//
|
||||||
klog.V(4).Infof("rbd: status %s using mon %s, pool %s id %s key %s", b.Image, mon, b.Pool, id, secret)
|
klog.V(4).Infof("rbd: status %s using mon %s, pool %s id %s key %s", b.Image, mon, b.Pool, id, secret)
|
||||||
cmd, err = b.exec.Run("rbd",
|
cmd, err = b.exec.Command("rbd",
|
||||||
"status", b.Image, "--pool", b.Pool, "-m", mon, "--id", id, "--key="+secret)
|
"status", b.Image, "--pool", b.Pool, "-m", mon, "--id", id, "--key="+secret).CombinedOutput()
|
||||||
output = string(cmd)
|
output = string(cmd)
|
||||||
|
|
||||||
if err, ok := err.(*exec.Error); ok {
|
if err, ok := err.(*exec.Error); ok {
|
||||||
|
@ -15,7 +15,6 @@ go_test(
|
|||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/util/mount:go_default_library",
|
|
||||||
"//pkg/volume:go_default_library",
|
"//pkg/volume:go_default_library",
|
||||||
"//pkg/volume/testing:go_default_library",
|
"//pkg/volume/testing:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
@ -26,6 +25,7 @@ go_test(
|
|||||||
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
||||||
"//vendor/github.com/thecodeteam/goscaleio/types/v1:go_default_library",
|
"//vendor/github.com/thecodeteam/goscaleio/types/v1:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,6 +52,7 @@ go_library(
|
|||||||
"//vendor/github.com/thecodeteam/goscaleio:go_default_library",
|
"//vendor/github.com/thecodeteam/goscaleio:go_default_library",
|
||||||
"//vendor/github.com/thecodeteam/goscaleio/types/v1:go_default_library",
|
"//vendor/github.com/thecodeteam/goscaleio/types/v1:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
"//vendor/k8s.io/utils/keymutex:go_default_library",
|
"//vendor/k8s.io/utils/keymutex:go_default_library",
|
||||||
"//vendor/k8s.io/utils/strings:go_default_library",
|
"//vendor/k8s.io/utils/strings:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
utilexec "k8s.io/utils/exec"
|
||||||
|
|
||||||
sio "github.com/thecodeteam/goscaleio"
|
sio "github.com/thecodeteam/goscaleio"
|
||||||
siotypes "github.com/thecodeteam/goscaleio/types/v1"
|
siotypes "github.com/thecodeteam/goscaleio/types/v1"
|
||||||
@ -78,10 +78,10 @@ type sioClient struct {
|
|||||||
inited bool
|
inited bool
|
||||||
diskRegex *regexp.Regexp
|
diskRegex *regexp.Regexp
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
exec mount.Exec
|
exec utilexec.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSioClient(gateway, username, password string, sslEnabled bool, exec mount.Exec) (*sioClient, error) {
|
func newSioClient(gateway, username, password string, sslEnabled bool, exec utilexec.Interface) (*sioClient, error) {
|
||||||
client := new(sioClient)
|
client := new(sioClient)
|
||||||
client.gateway = gateway
|
client.gateway = gateway
|
||||||
client.username = username
|
client.username = username
|
||||||
@ -321,7 +321,7 @@ func (c *sioClient) getGUID() (string, error) {
|
|||||||
if c.sdcGUID == "" {
|
if c.sdcGUID == "" {
|
||||||
klog.V(4).Info(log("sdc guid label not set, falling back to using drv_cfg"))
|
klog.V(4).Info(log("sdc guid label not set, falling back to using drv_cfg"))
|
||||||
cmd := c.getSdcCmd()
|
cmd := c.getSdcCmd()
|
||||||
output, err := c.exec.Run(cmd, "--query_guid")
|
output, err := c.exec.Command(cmd, "--query_guid").CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(log("drv_cfg --query_guid failed: %v", err))
|
klog.Error(log("drv_cfg --query_guid failed: %v", err))
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -20,9 +20,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
|
|
||||||
siotypes "github.com/thecodeteam/goscaleio/types/v1"
|
siotypes "github.com/thecodeteam/goscaleio/types/v1"
|
||||||
)
|
)
|
||||||
@ -30,10 +29,10 @@ import (
|
|||||||
type sioMgr struct {
|
type sioMgr struct {
|
||||||
client sioInterface
|
client sioInterface
|
||||||
configData map[string]string
|
configData map[string]string
|
||||||
exec mount.Exec
|
exec utilexec.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSioMgr(configs map[string]string, exec mount.Exec) (*sioMgr, error) {
|
func newSioMgr(configs map[string]string, exec utilexec.Interface) (*sioMgr, error) {
|
||||||
if configs == nil {
|
if configs == nil {
|
||||||
return nil, errors.New("missing configuration data")
|
return nil, errors.New("missing configuration data")
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
|
||||||
|
|
||||||
siotypes "github.com/thecodeteam/goscaleio/types/v1"
|
siotypes "github.com/thecodeteam/goscaleio/types/v1"
|
||||||
|
"k8s.io/utils/exec/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -44,7 +43,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func newTestMgr(t *testing.T) *sioMgr {
|
func newTestMgr(t *testing.T) *sioMgr {
|
||||||
mgr, err := newSioMgr(fakeConfig, mount.NewFakeExec(nil))
|
mgr, err := newSioMgr(fakeConfig, &testingexec.FakeExec{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -53,7 +52,7 @@ func newTestMgr(t *testing.T) *sioMgr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMgrNew(t *testing.T) {
|
func TestMgrNew(t *testing.T) {
|
||||||
mgr, err := newSioMgr(fakeConfig, mount.NewFakeExec(nil))
|
mgr, err := newSioMgr(fakeConfig, &testingexec.FakeExec{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ go_library(
|
|||||||
"//vendor/github.com/storageos/go-api:go_default_library",
|
"//vendor/github.com/storageos/go-api:go_default_library",
|
||||||
"//vendor/github.com/storageos/go-api/types:go_default_library",
|
"//vendor/github.com/storageos/go-api/types:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
"//vendor/k8s.io/utils/strings:go_default_library",
|
"//vendor/k8s.io/utils/strings:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -48,6 +49,7 @@ go_test(
|
|||||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
||||||
"//vendor/github.com/storageos/go-api/types:go_default_library",
|
"//vendor/github.com/storageos/go-api/types:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
utilstrings "k8s.io/utils/strings"
|
utilstrings "k8s.io/utils/strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -115,7 +116,7 @@ func (plugin *storageosPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volu
|
|||||||
return plugin.newMounterInternal(spec, pod, apiCfg, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
return plugin.newMounterInternal(spec, pod, apiCfg, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *storageosPlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod, apiCfg *storageosAPIConfig, manager storageosManager, mounter mount.Interface, exec mount.Exec) (volume.Mounter, error) {
|
func (plugin *storageosPlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod, apiCfg *storageosAPIConfig, manager storageosManager, mounter mount.Interface, exec utilexec.Interface) (volume.Mounter, error) {
|
||||||
|
|
||||||
volName, volNamespace, fsType, readOnly, err := getVolumeInfoFromSpec(spec)
|
volName, volNamespace, fsType, readOnly, err := getVolumeInfoFromSpec(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -147,7 +148,7 @@ func (plugin *storageosPlugin) NewUnmounter(pvName string, podUID types.UID) (vo
|
|||||||
return plugin.newUnmounterInternal(pvName, podUID, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
return plugin.newUnmounterInternal(pvName, podUID, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (plugin *storageosPlugin) newUnmounterInternal(pvName string, podUID types.UID, manager storageosManager, mounter mount.Interface, exec mount.Exec) (volume.Unmounter, error) {
|
func (plugin *storageosPlugin) newUnmounterInternal(pvName string, podUID types.UID, manager storageosManager, mounter mount.Interface, exec utilexec.Interface) (volume.Unmounter, error) {
|
||||||
|
|
||||||
// Parse volume namespace & name from mountpoint if mounted
|
// Parse volume namespace & name from mountpoint if mounted
|
||||||
volNamespace, volName, err := getVolumeInfo(pvName, podUID, plugin.host)
|
volNamespace, volName, err := getVolumeInfo(pvName, podUID, plugin.host)
|
||||||
@ -311,7 +312,7 @@ type storageos struct {
|
|||||||
apiCfg *storageosAPIConfig
|
apiCfg *storageosAPIConfig
|
||||||
manager storageosManager
|
manager storageosManager
|
||||||
mounter mount.Interface
|
mounter mount.Interface
|
||||||
exec mount.Exec
|
exec utilexec.Interface
|
||||||
plugin *storageosPlugin
|
plugin *storageosPlugin
|
||||||
volume.MetricsProvider
|
volume.MetricsProvider
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
|
"k8s.io/utils/exec/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCanSupport(t *testing.T) {
|
func TestCanSupport(t *testing.T) {
|
||||||
@ -194,7 +195,7 @@ func TestPlugin(t *testing.T) {
|
|||||||
t.Errorf("Couldn't get secret from %v/%v", pod.Namespace, secretName)
|
t.Errorf("Couldn't get secret from %v/%v", pod.Namespace, secretName)
|
||||||
}
|
}
|
||||||
|
|
||||||
mounter, err := plug.(*storageosPlugin).newMounterInternal(volume.NewSpecFromVolume(spec), pod, apiCfg, fakeManager, mount.NewFakeMounter(nil), mount.NewFakeExec(nil))
|
mounter, err := plug.(*storageosPlugin).newMounterInternal(volume.NewSpecFromVolume(spec), pod, apiCfg, fakeManager, mount.NewFakeMounter(nil), &testingexec.FakeExec{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to make a new Mounter: %v", err)
|
t.Fatalf("Failed to make a new Mounter: %v", err)
|
||||||
}
|
}
|
||||||
@ -231,7 +232,7 @@ func TestPlugin(t *testing.T) {
|
|||||||
|
|
||||||
// Test Unmounter
|
// Test Unmounter
|
||||||
fakeManager = &fakePDManager{}
|
fakeManager = &fakePDManager{}
|
||||||
unmounter, err := plug.(*storageosPlugin).newUnmounterInternal("vol1-pvname", types.UID("poduid"), fakeManager, mount.NewFakeMounter(nil), mount.NewFakeExec(nil))
|
unmounter, err := plug.(*storageosPlugin).newUnmounterInternal("vol1-pvname", types.UID("poduid"), fakeManager, mount.NewFakeMounter(nil), &testingexec.FakeExec{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to make a new Unmounter: %v", err)
|
t.Errorf("Failed to make a new Unmounter: %v", err)
|
||||||
}
|
}
|
||||||
@ -372,7 +373,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
|
|||||||
fakeManager := &fakePDManager{}
|
fakeManager := &fakePDManager{}
|
||||||
fakeConfig := &fakeConfig{}
|
fakeConfig := &fakeConfig{}
|
||||||
apiCfg := fakeConfig.GetAPIConfig()
|
apiCfg := fakeConfig.GetAPIConfig()
|
||||||
mounter, err := plug.(*storageosPlugin).newMounterInternal(spec, pod, apiCfg, fakeManager, mount.NewFakeMounter(nil), mount.NewFakeExec(nil))
|
mounter, err := plug.(*storageosPlugin).newMounterInternal(spec, pod, apiCfg, fakeManager, mount.NewFakeMounter(nil), &testingexec.FakeExec{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error creating a new internal mounter:%v", err)
|
t.Fatalf("error creating a new internal mounter:%v", err)
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,10 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
|
||||||
|
|
||||||
storageosapi "github.com/storageos/go-api"
|
storageosapi "github.com/storageos/go-api"
|
||||||
storageostypes "github.com/storageos/go-api/types"
|
storageostypes "github.com/storageos/go-api/types"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -331,7 +330,7 @@ func pathDeviceType(path string) (deviceType, error) {
|
|||||||
|
|
||||||
// attachFileDevice takes a path to a regular file and makes it available as an
|
// attachFileDevice takes a path to a regular file and makes it available as an
|
||||||
// attached block device.
|
// attached block device.
|
||||||
func attachFileDevice(path string, exec mount.Exec) (string, error) {
|
func attachFileDevice(path string, exec utilexec.Interface) (string, error) {
|
||||||
blockDevicePath, err := getLoopDevice(path, exec)
|
blockDevicePath, err := getLoopDevice(path, exec)
|
||||||
if err != nil && err.Error() != ErrDeviceNotFound {
|
if err != nil && err.Error() != ErrDeviceNotFound {
|
||||||
return "", err
|
return "", err
|
||||||
@ -349,7 +348,7 @@ func attachFileDevice(path string, exec mount.Exec) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the full path to the loop device associated with the given path.
|
// Returns the full path to the loop device associated with the given path.
|
||||||
func getLoopDevice(path string, exec mount.Exec) (string, error) {
|
func getLoopDevice(path string, exec utilexec.Interface) (string, error) {
|
||||||
_, err := os.Stat(path)
|
_, err := os.Stat(path)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return "", errors.New(ErrNotAvailable)
|
return "", errors.New(ErrNotAvailable)
|
||||||
@ -359,7 +358,7 @@ func getLoopDevice(path string, exec mount.Exec) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
args := []string{"-j", path}
|
args := []string{"-j", path}
|
||||||
out, err := exec.Run(losetupPath, args...)
|
out, err := exec.Command(losetupPath, args...).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.V(2).Infof("Failed device discover command for path %s: %v", path, err)
|
klog.V(2).Infof("Failed device discover command for path %s: %v", path, err)
|
||||||
return "", err
|
return "", err
|
||||||
@ -367,9 +366,9 @@ func getLoopDevice(path string, exec mount.Exec) (string, error) {
|
|||||||
return parseLosetupOutputForDevice(out)
|
return parseLosetupOutputForDevice(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeLoopDevice(path string, exec mount.Exec) (string, error) {
|
func makeLoopDevice(path string, exec utilexec.Interface) (string, error) {
|
||||||
args := []string{"-f", "-P", "--show", path}
|
args := []string{"-f", "-P", "--show", path}
|
||||||
out, err := exec.Run(losetupPath, args...)
|
out, err := exec.Command(losetupPath, args...).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.V(2).Infof("Failed device create command for path %s: %v", path, err)
|
klog.V(2).Infof("Failed device create command for path %s: %v", path, err)
|
||||||
return "", err
|
return "", err
|
||||||
@ -377,9 +376,9 @@ func makeLoopDevice(path string, exec mount.Exec) (string, error) {
|
|||||||
return parseLosetupOutputForDevice(out)
|
return parseLosetupOutputForDevice(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeLoopDevice(device string, exec mount.Exec) error {
|
func removeLoopDevice(device string, exec utilexec.Interface) error {
|
||||||
args := []string{"-d", device}
|
args := []string{"-d", device}
|
||||||
out, err := exec.Run(losetupPath, args...)
|
out, err := exec.Command(losetupPath, args...).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !strings.Contains(string(out), "No such device or address") {
|
if !strings.Contains(string(out), "No such device or address") {
|
||||||
return err
|
return err
|
||||||
|
@ -35,6 +35,8 @@ go_library(
|
|||||||
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
||||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||||
"//vendor/github.com/stretchr/testify/mock:go_default_library",
|
"//vendor/github.com/stretchr/testify/mock:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||||
"//vendor/k8s.io/utils/strings:go_default_library",
|
"//vendor/k8s.io/utils/strings:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -20,7 +20,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -41,6 +40,9 @@ import (
|
|||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
utiltesting "k8s.io/client-go/util/testing"
|
utiltesting "k8s.io/client-go/util/testing"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
|
"k8s.io/utils/exec"
|
||||||
|
"k8s.io/utils/exec/testing"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
. "k8s.io/kubernetes/pkg/volume"
|
. "k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
@ -73,7 +75,7 @@ type fakeVolumeHost struct {
|
|||||||
cloud cloudprovider.Interface
|
cloud cloudprovider.Interface
|
||||||
mounter mount.Interface
|
mounter mount.Interface
|
||||||
hostUtil hostutil.HostUtils
|
hostUtil hostutil.HostUtils
|
||||||
exec mount.Exec
|
exec *testingexec.FakeExec
|
||||||
nodeLabels map[string]string
|
nodeLabels map[string]string
|
||||||
nodeName string
|
nodeName string
|
||||||
subpather subpath.Interface
|
subpather subpath.Interface
|
||||||
@ -111,7 +113,7 @@ func newFakeVolumeHost(rootDir string, kubeClient clientset.Interface, plugins [
|
|||||||
host := &fakeVolumeHost{rootDir: rootDir, kubeClient: kubeClient, cloud: cloud}
|
host := &fakeVolumeHost{rootDir: rootDir, kubeClient: kubeClient, cloud: cloud}
|
||||||
host.mounter = mount.NewFakeMounter(nil)
|
host.mounter = mount.NewFakeMounter(nil)
|
||||||
host.hostUtil = hostutil.NewFakeHostUtil(pathToTypeMap)
|
host.hostUtil = hostutil.NewFakeHostUtil(pathToTypeMap)
|
||||||
host.exec = mount.NewFakeExec(nil)
|
host.exec = &testingexec.FakeExec{DisableScripts: true}
|
||||||
host.pluginMgr.InitPlugins(plugins, nil /* prober */, host)
|
host.pluginMgr.InitPlugins(plugins, nil /* prober */, host)
|
||||||
host.subpather = &subpath.FakeSubpath{}
|
host.subpather = &subpath.FakeSubpath{}
|
||||||
host.informerFactory = informers.NewSharedInformerFactory(kubeClient, time.Minute)
|
host.informerFactory = informers.NewSharedInformerFactory(kubeClient, time.Minute)
|
||||||
@ -213,7 +215,7 @@ func (f *fakeVolumeHost) GetSecretFunc() func(namespace, name string) (*v1.Secre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *fakeVolumeHost) GetExec(pluginName string) mount.Exec {
|
func (f *fakeVolumeHost) GetExec(pluginName string) exec.Interface {
|
||||||
return f.exec
|
return f.exec
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,6 +250,64 @@ func (f *fakeVolumeHost) GetEventRecorder() record.EventRecorder {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *fakeVolumeHost) ScriptCommands(scripts []CommandScript) {
|
||||||
|
ScriptCommands(f.exec, scripts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommandScript is used to pre-configure a command that will be executed and
|
||||||
|
// optionally set it's output (stdout and stderr combined) and return code.
|
||||||
|
type CommandScript struct {
|
||||||
|
// Cmd is the command to execute, e.g. "ls"
|
||||||
|
Cmd string
|
||||||
|
// Args is a slice of arguments to pass to the command, e.g. "-a"
|
||||||
|
Args []string
|
||||||
|
// Output is the combined stdout and stderr of the command to return
|
||||||
|
Output string
|
||||||
|
// ReturnCode is the exit code for the command. Setting this to non-zero will
|
||||||
|
// cause the command to return an error with this exit code set.
|
||||||
|
ReturnCode int
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScriptCommands configures fe, the FakeExec, to have a pre-configured list of
|
||||||
|
// commands to expect. Calling more commands using fe than those scripted will
|
||||||
|
// result in a panic. By default, the fe does not enforce command argument checking
|
||||||
|
// or order -- if you have given an Output to the command, the first command scripted
|
||||||
|
// will return its output on the first command call, even if the command called is
|
||||||
|
// different than the one scripted. This is mostly useful to make sure that the
|
||||||
|
// right number of commands were called. If you want to check the exact commands
|
||||||
|
// and arguments were called, set fe.ExectOrder to true.
|
||||||
|
func ScriptCommands(fe *testingexec.FakeExec, scripts []CommandScript) {
|
||||||
|
fe.DisableScripts = false
|
||||||
|
for _, script := range scripts {
|
||||||
|
fakeCmd := &testingexec.FakeCmd{}
|
||||||
|
cmdAction := makeFakeCmd(fakeCmd, script.Cmd, script.Args...)
|
||||||
|
outputAction := makeFakeOutput(script.Output, script.ReturnCode)
|
||||||
|
fakeCmd.CombinedOutputScript = append(fakeCmd.CombinedOutputScript, outputAction)
|
||||||
|
fe.CommandScript = append(fe.CommandScript, cmdAction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeFakeCmd(fakeCmd *testingexec.FakeCmd, cmd string, args ...string) testingexec.FakeCommandAction {
|
||||||
|
fc := fakeCmd
|
||||||
|
c := cmd
|
||||||
|
a := args
|
||||||
|
return func(cmd string, args ...string) exec.Cmd {
|
||||||
|
command := testingexec.InitFakeCmd(fc, c, a...)
|
||||||
|
return command
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeFakeOutput(output string, rc int) testingexec.FakeCombinedOutputAction {
|
||||||
|
o := output
|
||||||
|
var e error
|
||||||
|
if rc != 0 {
|
||||||
|
e = testingexec.FakeExitError{Status: rc}
|
||||||
|
}
|
||||||
|
return func() ([]byte, error) {
|
||||||
|
return []byte(o), e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ProbeVolumePlugins(config VolumeConfig) []VolumePlugin {
|
func ProbeVolumePlugins(config VolumeConfig) []VolumePlugin {
|
||||||
if _, ok := config.OtherAttributes["fake-property"]; ok {
|
if _, ok := config.OtherAttributes["fake-property"]; ok {
|
||||||
return []VolumePlugin{
|
return []VolumePlugin{
|
||||||
@ -1131,7 +1191,7 @@ func FindEmptyDirectoryUsageOnTmpfs() (*resource.Quantity, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
out, err := exec.Command("nice", "-n", "19", "du", "-x", "-s", "-B", "1", tmpDir).CombinedOutput()
|
out, err := exec.New().Command("nice", "-n", "19", "du", "-x", "-s", "-B", "1", tmpDir).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed command 'du' on %s with error %v", tmpDir, err)
|
return nil, fmt.Errorf("failed command 'du' on %s with error %v", tmpDir, err)
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/component-base/metrics:go_default_library",
|
"//staging/src/k8s.io/component-base/metrics:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",
|
"//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
"//vendor/k8s.io/utils/strings:go_default_library",
|
"//vendor/k8s.io/utils/strings:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -36,6 +36,7 @@ import (
|
|||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
@ -44,6 +45,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/types"
|
"k8s.io/kubernetes/pkg/volume/util/types"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
utilstrings "k8s.io/utils/strings"
|
utilstrings "k8s.io/utils/strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -585,11 +587,11 @@ func HasMountRefs(mountPath string, mountRefs []string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//WriteVolumeCache flush disk data given the spcified mount path
|
//WriteVolumeCache flush disk data given the spcified mount path
|
||||||
func WriteVolumeCache(deviceMountPath string, exec mount.Exec) error {
|
func WriteVolumeCache(deviceMountPath string, exec utilexec.Interface) error {
|
||||||
// If runtime os is windows, execute Write-VolumeCache powershell command on the disk
|
// If runtime os is windows, execute Write-VolumeCache powershell command on the disk
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
cmd := fmt.Sprintf("Get-Volume -FilePath %s | Write-Volumecache", deviceMountPath)
|
cmd := fmt.Sprintf("Get-Volume -FilePath %s | Write-Volumecache", deviceMountPath)
|
||||||
output, err := exec.Run("powershell", "/c", cmd)
|
output, err := exec.Command("powershell", "/c", cmd).CombinedOutput()
|
||||||
klog.Infof("command (%q) execeuted: %v, output: %q", cmd, err, string(output))
|
klog.Infof("command (%q) execeuted: %v, output: %q", cmd, err, string(output))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("command (%q) failed: %v, output: %q", cmd, err, string(output))
|
return fmt.Errorf("command (%q) failed: %v, output: %q", cmd, err, string(output))
|
||||||
|
Loading…
Reference in New Issue
Block a user