
Errors from staticcheck: pkg/volume/azure_dd/azure_common.go:68:2: var winDiskNumFormat is unused (U1000) pkg/volume/csi/csi_block.go:97:2: field volumeInfo is unused (U1000) pkg/volume/csi/csi_block_test.go:56:6: func prepareBlockUnmapperTest is unused (U1000) pkg/volume/csi/csi_client.go:108:2: const initialDuration is unused (U1000) pkg/volume/csi/csi_client.go:109:2: const factor is unused (U1000) pkg/volume/csi/csi_client.go:110:2: const steps is unused (U1000) pkg/volume/csi/csi_client_test.go:83:8: this value of err is never used (SA4006) pkg/volume/csi/csi_mounter.go:76:2: field options is unused (U1000) pkg/volume/csi/csi_mounter_test.go:454:13: this value of err is never used (SA4006) pkg/volume/csi/csi_plugin_test.go:766:16: this value of err is never used (SA4006) pkg/volume/csi/csi_plugin_test.go:861:13: this value of err is never used (SA4006) pkg/volume/csi/csi_plugin_test.go:1186:13: this value of err is never used (SA4006) pkg/volume/csi/csi_plugin_test.go:1249:13: this value of err is never used (SA4006) pkg/volume/csi/csi_test.go:305:5: the goroutine calls T.Fatalf, which must be called in the same goroutine as the test (SA2002) pkg/volume/flexvolume/probe_test.go:67:10: this value of err is never used (SA4006) pkg/volume/iscsi/iscsi_test.go:95:2: field attachCalled is unused (U1000) pkg/volume/iscsi/iscsi_test.go:96:2: field detachCalled is unused (U1000) pkg/volume/iscsi/iscsi_test.go:501:24: this value of err is never used (SA4006) pkg/volume/iscsi/iscsi_util_test.go:159:2: this value of exist is never used (SA4006) pkg/volume/local/local.go:351:57: argument devicePath is overwritten before first use (SA4009) pkg/volume/plugins_test.go:119:2: this value of plug is never used (SA4006) pkg/volume/plugins_test.go:125:2: this value of plug is never used (SA4006) pkg/volume/quobyte/quobyte.go:474:23: this result of append is never used, except maybe in other appends (SA4010) pkg/volume/quobyte/quobyte.go:477:23: this result of append is never used, except maybe in other appends (SA4010) pkg/volume/quobyte/quobyte.go:480:23: this result of append is never used, except maybe in other appends (SA4010) pkg/volume/rbd/rbd.go:886:2: field adminSecret is unused (U1000) pkg/volume/rbd/rbd.go:887:2: field adminID is unused (U1000) pkg/volume/rbd/rbd.go:888:2: field imageFormat is unused (U1000) pkg/volume/rbd/rbd.go:889:2: field imageFeatures is unused (U1000) pkg/volume/storageos/storageos.go:302:2: field secretName is unused (U1000) pkg/volume/storageos/storageos_util_test.go:43:2: field apiAddr is unused (U1000) pkg/volume/storageos/storageos_util_test.go:44:2: field apiUser is unused (U1000) pkg/volume/storageos/storageos_util_test.go:45:2: field apiPass is unused (U1000) pkg/volume/storageos/storageos_util_test.go:46:2: field apiVersion is unused (U1000) pkg/volume/util/atomic_writer_test.go:756:49: argument err is overwritten before first use (SA4009) pkg/volume/util/fsquota/common/quota_linux_common.go:37:2: const acct is unused (U1000) pkg/volume/util/fsquota/common/quota_linux_common.go:38:2: const enforcing is unused (U1000) pkg/volume/util/fsquota/project.go:168:31: identical expressions on the left and right side of the '==' operator (SA4000) pkg/volume/util/fsquota/quota_linux.go:306:50: argument poduid is overwritten before first use (SA4009) pkg/volume/util/fsquota/quota_linux_test.go:558:16: this value of err is never used (SA4006) pkg/volume/util/subpath/subpath_linux.go:232:81: argument err is overwritten before first use (SA4009) pkg/volume/util/subpath/subpath_linux_test.go:579:73: argument err is overwritten before first use (SA4009)
220 lines
6.7 KiB
Go
220 lines
6.7 KiB
Go
// +build !providerless
|
|
|
|
/*
|
|
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 azure_dd
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
libstrings "strings"
|
|
|
|
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
|
|
|
v1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
"k8s.io/apimachinery/pkg/util/sets"
|
|
api "k8s.io/kubernetes/pkg/apis/core"
|
|
"k8s.io/kubernetes/pkg/volume"
|
|
"k8s.io/kubernetes/pkg/volume/util"
|
|
"k8s.io/legacy-cloud-providers/azure"
|
|
utilstrings "k8s.io/utils/strings"
|
|
)
|
|
|
|
const (
|
|
defaultStorageAccountType = compute.StandardSSDLRS
|
|
defaultAzureDiskKind = v1.AzureManagedDisk
|
|
defaultAzureDataDiskCachingMode = v1.AzureDataDiskCachingReadOnly
|
|
)
|
|
|
|
type dataDisk struct {
|
|
volume.MetricsProvider
|
|
volumeName string
|
|
diskName string
|
|
podUID types.UID
|
|
plugin *azureDataDiskPlugin
|
|
}
|
|
|
|
var (
|
|
supportedCachingModes = sets.NewString(
|
|
string(api.AzureDataDiskCachingNone),
|
|
string(api.AzureDataDiskCachingReadOnly),
|
|
string(api.AzureDataDiskCachingReadWrite))
|
|
|
|
supportedDiskKinds = sets.NewString(
|
|
string(api.AzureSharedBlobDisk),
|
|
string(api.AzureDedicatedBlobDisk),
|
|
string(api.AzureManagedDisk))
|
|
|
|
// only for Windows node
|
|
winDiskNumRE = regexp.MustCompile(`/dev/disk(.+)`)
|
|
)
|
|
|
|
func getPath(uid types.UID, volName string, host volume.VolumeHost) string {
|
|
return host.GetPodVolumeDir(uid, utilstrings.EscapeQualifiedName(azureDataDiskPluginName), volName)
|
|
}
|
|
|
|
// creates a unique path for disks (even if they share the same *.vhd name)
|
|
func makeGlobalPDPath(host volume.VolumeHost, diskURI string, isManaged bool) (string, error) {
|
|
diskURI = libstrings.ToLower(diskURI) // always lower uri because users may enter it in caps.
|
|
uniqueDiskNameTemplate := "%s%s"
|
|
hashedDiskURI := azure.MakeCRC32(diskURI)
|
|
prefix := "b"
|
|
if isManaged {
|
|
prefix = "m"
|
|
}
|
|
// "{m for managed b for blob}{hashed diskURI or DiskId depending on disk kind }"
|
|
diskName := fmt.Sprintf(uniqueDiskNameTemplate, prefix, hashedDiskURI)
|
|
pdPath := filepath.Join(host.GetPluginDir(azureDataDiskPluginName), util.MountsInGlobalPDPath, diskName)
|
|
|
|
return pdPath, nil
|
|
}
|
|
|
|
func makeDataDisk(volumeName string, podUID types.UID, diskName string, host volume.VolumeHost, plugin *azureDataDiskPlugin) *dataDisk {
|
|
var metricProvider volume.MetricsProvider
|
|
if podUID != "" {
|
|
metricProvider = volume.NewMetricsStatFS(getPath(podUID, volumeName, host))
|
|
}
|
|
|
|
return &dataDisk{
|
|
MetricsProvider: metricProvider,
|
|
volumeName: volumeName,
|
|
diskName: diskName,
|
|
podUID: podUID,
|
|
plugin: plugin,
|
|
}
|
|
}
|
|
|
|
func getVolumeSource(spec *volume.Spec) (volumeSource *v1.AzureDiskVolumeSource, readOnly bool, err error) {
|
|
if spec.Volume != nil && spec.Volume.AzureDisk != nil {
|
|
return spec.Volume.AzureDisk, spec.Volume.AzureDisk.ReadOnly != nil && *spec.Volume.AzureDisk.ReadOnly, nil
|
|
}
|
|
|
|
if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.AzureDisk != nil {
|
|
return spec.PersistentVolume.Spec.AzureDisk, spec.ReadOnly, nil
|
|
}
|
|
|
|
return nil, false, fmt.Errorf("azureDisk - Spec does not reference an Azure disk volume type")
|
|
}
|
|
|
|
func normalizeKind(kind string) (v1.AzureDataDiskKind, error) {
|
|
if kind == "" {
|
|
return defaultAzureDiskKind, nil
|
|
}
|
|
|
|
if !supportedDiskKinds.Has(kind) {
|
|
return "", fmt.Errorf("azureDisk - %s is not supported disk kind. Supported values are %s", kind, supportedDiskKinds.List())
|
|
}
|
|
|
|
return v1.AzureDataDiskKind(kind), nil
|
|
}
|
|
|
|
func normalizeStorageAccountType(storageAccountType string) (compute.DiskStorageAccountTypes, error) {
|
|
if storageAccountType == "" {
|
|
return defaultStorageAccountType, nil
|
|
}
|
|
|
|
sku := compute.DiskStorageAccountTypes(storageAccountType)
|
|
supportedSkuNames := compute.PossibleDiskStorageAccountTypesValues()
|
|
for _, s := range supportedSkuNames {
|
|
if sku == s {
|
|
return sku, nil
|
|
}
|
|
}
|
|
|
|
return "", fmt.Errorf("azureDisk - %s is not supported sku/storageaccounttype. Supported values are %s", storageAccountType, supportedSkuNames)
|
|
}
|
|
|
|
func normalizeCachingMode(cachingMode v1.AzureDataDiskCachingMode) (v1.AzureDataDiskCachingMode, error) {
|
|
if cachingMode == "" {
|
|
return defaultAzureDataDiskCachingMode, nil
|
|
}
|
|
|
|
if !supportedCachingModes.Has(string(cachingMode)) {
|
|
return "", fmt.Errorf("azureDisk - %s is not supported cachingmode. Supported values are %s", cachingMode, supportedCachingModes.List())
|
|
}
|
|
|
|
return cachingMode, nil
|
|
}
|
|
|
|
type ioHandler interface {
|
|
ReadDir(dirname string) ([]os.FileInfo, error)
|
|
WriteFile(filename string, data []byte, perm os.FileMode) error
|
|
Readlink(name string) (string, error)
|
|
ReadFile(filename string) ([]byte, error)
|
|
}
|
|
|
|
//TODO: check if priming the iscsi interface is actually needed
|
|
|
|
type osIOHandler struct{}
|
|
|
|
func (handler *osIOHandler) ReadDir(dirname string) ([]os.FileInfo, error) {
|
|
return ioutil.ReadDir(dirname)
|
|
}
|
|
|
|
func (handler *osIOHandler) WriteFile(filename string, data []byte, perm os.FileMode) error {
|
|
return ioutil.WriteFile(filename, data, perm)
|
|
}
|
|
|
|
func (handler *osIOHandler) Readlink(name string) (string, error) {
|
|
return os.Readlink(name)
|
|
}
|
|
|
|
func (handler *osIOHandler) ReadFile(filename string) ([]byte, error) {
|
|
return ioutil.ReadFile(filename)
|
|
}
|
|
|
|
func getDiskController(host volume.VolumeHost) (DiskController, error) {
|
|
cloudProvider := host.GetCloudProvider()
|
|
az, ok := cloudProvider.(*azure.Cloud)
|
|
|
|
if !ok || az == nil {
|
|
return nil, fmt.Errorf("AzureDisk - failed to get Azure Cloud Provider. GetCloudProvider returned %v instead", cloudProvider)
|
|
}
|
|
return az, nil
|
|
}
|
|
|
|
func getCloud(host volume.VolumeHost) (*azure.Cloud, error) {
|
|
cloudProvider := host.GetCloudProvider()
|
|
az, ok := cloudProvider.(*azure.Cloud)
|
|
|
|
if !ok || az == nil {
|
|
return nil, fmt.Errorf("AzureDisk - failed to get Azure Cloud Provider. GetCloudProvider returned %v instead", cloudProvider)
|
|
}
|
|
return az, nil
|
|
}
|
|
|
|
func strFirstLetterToUpper(str string) string {
|
|
if len(str) < 2 {
|
|
return str
|
|
}
|
|
return libstrings.ToUpper(string(str[0])) + str[1:]
|
|
}
|
|
|
|
// getDiskNum : extract the disk num from a device path,
|
|
// deviceInfo format could be like this: e.g. /dev/disk2
|
|
func getDiskNum(deviceInfo string) (string, error) {
|
|
matches := winDiskNumRE.FindStringSubmatch(deviceInfo)
|
|
if len(matches) == 2 {
|
|
return matches[1], nil
|
|
}
|
|
return "", fmt.Errorf("cannot parse deviceInfo: %s, correct format: /dev/disk?", deviceInfo)
|
|
}
|