Skip to content

Commit

Permalink
Merge pull request kubernetes#80911 from pivotal-k8s/vsphere-windows-…
Browse files Browse the repository at this point in the history
…volumes

Add support for vSphere volume mount/attach on Windows
  • Loading branch information
k8s-ci-robot authored Aug 28, 2019
2 parents 586d200 + c7c755a commit 77277d3
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 16 deletions.
3 changes: 3 additions & 0 deletions pkg/volume/vsphere_volume/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ go_library(
"vsphere_volume.go",
"vsphere_volume_block.go",
"vsphere_volume_util.go",
"vsphere_volume_util_linux.go",
"vsphere_volume_util_unsupported.go",
"vsphere_volume_util_windows.go",
],
importpath = "k8s.io/kubernetes/pkg/volume/vsphere_volume",
deps = [
Expand Down
10 changes: 8 additions & 2 deletions pkg/volume/vsphere_volume/attacher.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"
"time"

"k8s.io/api/core/v1"
Expand Down Expand Up @@ -207,12 +208,17 @@ func (plugin *vsphereVolumePlugin) GetDeviceMountRefs(deviceMountPath string) ([

// MountDevice mounts device to global mount point.
func (attacher *vsphereVMDKAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string) error {
klog.Info("vsphere MountDevice", devicePath, deviceMountPath)
mounter := attacher.host.GetMounter(vsphereVolumePluginName)
notMnt, err := mounter.IsLikelyNotMountPoint(deviceMountPath)
if err != nil {
if os.IsNotExist(err) {
if err := os.MkdirAll(deviceMountPath, 0750); err != nil {
klog.Errorf("Failed to create directory at %#v. err: %s", deviceMountPath, err)
dir := deviceMountPath
if runtime.GOOS == "windows" {
dir = filepath.Dir(deviceMountPath)
}
if err := os.MkdirAll(dir, 0750); err != nil {
klog.Errorf("Failed to create directory at %#v. err: %s", dir, err)
return err
}
notMnt = true
Expand Down
11 changes: 8 additions & 3 deletions pkg/volume/vsphere_volume/vsphere_volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"

"k8s.io/api/core/v1"
Expand Down Expand Up @@ -241,9 +242,13 @@ func (b *vsphereVolumeMounter) SetUpAt(dir string, mounterArgs volume.MounterArg
return nil
}

if err := os.MkdirAll(dir, 0750); err != nil {
klog.V(4).Infof("Could not create directory %s: %v", dir, err)
return err
if runtime.GOOS != "windows" {
// On Windows, Mount will create the parent of dir and mklink (create a symbolic link) at dir later, so don't create a
// directory at dir now. Otherwise mklink will error: "Cannot create a file when that file already exists".
if err := os.MkdirAll(dir, 0750); err != nil {
klog.Errorf("Could not create directory %s: %v", dir, err)
return err
}
}

options := []string{"bind"}
Expand Down
11 changes: 0 additions & 11 deletions pkg/volume/vsphere_volume/vsphere_volume_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
cloudprovider "k8s.io/cloud-provider"
volumehelpers "k8s.io/cloud-provider/volume/helpers"
"k8s.io/klog"
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
volumeutil "k8s.io/kubernetes/pkg/volume/util"
"k8s.io/legacy-cloud-providers/vsphere"
Expand Down Expand Up @@ -77,16 +76,6 @@ type VolumeSpec struct {
Labels map[string]string
}

func verifyDevicePath(path string) (string, error) {
if pathExists, err := mount.PathExists(path); err != nil {
return "", fmt.Errorf("Error checking if path exists: %v", err)
} else if pathExists {
return path, nil
}

return "", nil
}

// CreateVolume creates a vSphere volume.
func (util *VsphereDiskUtil) CreateVolume(v *vsphereVolumeProvisioner, selectedNode *v1.Node, selectedZone []string) (volSpec *VolumeSpec, err error) {
var fstype string
Expand Down
35 changes: 35 additions & 0 deletions pkg/volume/vsphere_volume/vsphere_volume_util_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// +build linux

/*
Copyright 2019 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 vsphere_volume

import (
"fmt"

"k8s.io/kubernetes/pkg/util/mount"
)

func verifyDevicePath(path string) (string, error) {
if pathExists, err := mount.PathExists(path); err != nil {
return "", fmt.Errorf("Error checking if path exists: %v", err)
} else if pathExists {
return path, nil
}

return "", nil
}
25 changes: 25 additions & 0 deletions pkg/volume/vsphere_volume/vsphere_volume_util_unsupported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// +build !linux,!windows

/*
Copyright 2019 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 vsphere_volume

import "errors"

func verifyDevicePath(path string) (string, error) {
return "", errors.New("unsupported")
}
63 changes: 63 additions & 0 deletions pkg/volume/vsphere_volume/vsphere_volume_util_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// +build windows

/*
Copyright 2019 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 vsphere_volume

import (
"encoding/json"
"fmt"
"os/exec"
"strings"

"k8s.io/klog"
)

type diskInfoResult struct {
Number json.Number
SerialNumber string
}

func verifyDevicePath(path string) (string, error) {
if !strings.Contains(path, diskByIDPath) {
// If this volume has already been mounted then
// its devicePath will have already been converted to a disk number
klog.V(4).Infof("Found vSphere disk attached with disk number %v", path)
return path, nil
}
cmd := exec.Command("powershell", "/c", "Get-Disk | Select Number, SerialNumber | ConvertTo-JSON")
output, err := cmd.Output()
if err != nil {
klog.Errorf("Get-Disk failed, error: %v, output: %q", err, string(output))
return "", err
}

var results []diskInfoResult
if err = json.Unmarshal(output, &results); err != nil {
klog.Errorf("Failed to unmarshal Get-Disk json, output: %q", string(output))
return "", err
}
serialNumber := strings.TrimPrefix(path, diskByIDPath+diskSCSIPrefix)
for _, v := range results {
if v.SerialNumber == serialNumber {
klog.V(4).Infof("Found vSphere disk attached with serial %v", serialNumber)
return v.Number.String(), nil
}
}

return "", fmt.Errorf("unable to find vSphere disk with serial %v", serialNumber)
}

0 comments on commit 77277d3

Please sign in to comment.