Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #40 from jsafrane/merge-master
Bug 1959546: Update to current master
  • Loading branch information
openshift-merge-robot committed May 26, 2021
2 parents 077d6be + 0f115ef commit 8f7c124
Show file tree
Hide file tree
Showing 391 changed files with 172,124 additions and 1,925 deletions.
8 changes: 0 additions & 8 deletions README.md
Expand Up @@ -11,11 +11,3 @@ This operator is deployed automatically in OpenShift clusters when it runs on vS
```sh
$ ./vsphere-problem-detector start -v 5 --kubeconfig=$KUBECONFIG --namespace=openshift-cluster-storage-operator
```


## WIP

This is work-in-progress operator.

Until proper `VSphereProblemDetector` CRD is introduced in openshift/api, `ClusterCSIDriver` CR with name `csi.ovirt.org` is used!
Results of checks are rendered as `clustercsidriver.Status.Conditions` instead of proper fields.
3 changes: 1 addition & 2 deletions go.mod
Expand Up @@ -20,14 +20,13 @@ require (
github.com/spf13/cobra v1.0.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.6.1 // indirect
github.com/vmware/govmomi v0.20.3
github.com/vmware/govmomi v0.23.1
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.16.0 // indirect
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 // indirect
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd // indirect
golang.org/x/text v0.3.4 // indirect
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Expand Up @@ -93,6 +93,7 @@ github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-xdr v0.0.0-20161123171359-e6a2ba005892/go.mod h1:CTDl0pzVzE5DEzZhPfvhY/9sPFMQIxaJ9VAMs9AagrE=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
Expand Down Expand Up @@ -247,6 +248,7 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v0.0.0-20170306145142-6a5e28554805/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
Expand Down Expand Up @@ -460,6 +462,9 @@ github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJ
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vmware/govmomi v0.20.3 h1:gpw/0Ku+6RgF3jsi7fnCLmlcikBHfKBCUcu1qgc16OU=
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
github.com/vmware/govmomi v0.23.1 h1:vU09hxnNR/I7e+4zCJvW+5vHu5dO64Aoe2Lw7Yi/KRg=
github.com/vmware/govmomi v0.23.1/go.mod h1:Y+Wq4lst78L85Ge/F8+ORXIWiKYqaro1vhAulACy9Lc=
github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728/go.mod h1:x9oS4Wk2s2u4tS29nEaDLdzvuHdB19CvSGJjPgkZJNk=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
Expand Down
118 changes: 108 additions & 10 deletions pkg/check/datastore.go
Expand Up @@ -6,17 +6,27 @@ import (
"os/exec"
"strings"

"github.com/vmware/govmomi/property"

configv1 "github.com/openshift/api/config/v1"
"github.com/vmware/govmomi/pbm"
"github.com/vmware/govmomi/pbm/types"
"github.com/vmware/govmomi/view"
"github.com/vmware/govmomi/vim25/mo"
vim "github.com/vmware/govmomi/vim25/types"
"k8s.io/klog/v2"
)

const (
dsParameter = "datastore"
storagePolicyParameter = "storagepolicyname"
// Maximum length of <cluster-id>-dynamic-pvc-<uuid> for volume names.
// Kubernetes uses 90, https://github.com/kubernetes/kubernetes/blob/93d288e2a47fa6d497b50d37c8b3a04e91da4228/pkg/volume/vsphere_volume/vsphere_volume_util.go#L100
// Using 63 to work around https://bugzilla.redhat.com/show_bug.cgi?id=1926943
maxVolumeName = 63
dataCenterType = "Datacenter"
DatastoreInfoProperty = "info"
SummaryProperty = "summary"
)

// CheckStorageClasses tests that datastore name in all StorageClasses in the cluster is short enough.
Expand All @@ -33,7 +43,7 @@ func CheckStorageClasses(ctx *CheckContext) error {

var errs []error
for i := range scs {
sc := &scs[i]
sc := scs[i]
if sc.Provisioner != "kubernetes.io/vsphere-volume" {
klog.V(4).Infof("Skipping storage class %s: not a vSphere class", sc.Name)
continue
Expand All @@ -42,7 +52,7 @@ func CheckStorageClasses(ctx *CheckContext) error {
for k, v := range sc.Parameters {
switch strings.ToLower(k) {
case dsParameter:
if err := checkDataStore(v, infra); err != nil {
if err := checkDataStore(ctx, v, infra); err != nil {
klog.V(2).Infof("CheckStorageClasses: %s: %s", sc.Name, err)
errs = append(errs, fmt.Errorf("StorageClass %s: %s", sc.Name, err))
}
Expand All @@ -67,7 +77,7 @@ func CheckPVs(ctx *CheckContext) error {
return err
}
for i := range pvs {
pv := &pvs[i]
pv := pvs[i]
if pv.Spec.VsphereVolume == nil {
continue
}
Expand All @@ -90,7 +100,7 @@ func CheckDefaultDatastore(ctx *CheckContext) error {
}

dsName := ctx.VMConfig.Workspace.DefaultDatastore
if err := checkDataStore(dsName, infra); err != nil {
if err := checkDataStore(ctx, dsName, infra); err != nil {
return fmt.Errorf("defaultDatastore %q in vSphere configuration: %s", dsName, err)
}
return nil
Expand Down Expand Up @@ -119,7 +129,7 @@ func checkStoragePolicy(ctx *CheckContext, policyName string, infrastructure *co

var errs []error
for _, dataStore := range dataStores {
err := checkDataStore(dataStore, infrastructure)
err := checkDataStore(ctx, dataStore, infrastructure)
if err != nil {
errs = append(errs, fmt.Errorf("storage policy %s: %s", policyName, err))
}
Expand Down Expand Up @@ -226,13 +236,84 @@ func getPolicy(ctx *CheckContext, name string) ([]types.BasePbmProfile, error) {
return c.RetrieveContent(tctx, []types.PbmProfileId{{UniqueId: name}})
}

func checkDataStore(dsName string, infrastructure *configv1.Infrastructure) error {
func checkDataStore(ctx *CheckContext, dsName string, infrastructure *configv1.Infrastructure) error {
clusterID := infrastructure.Status.InfrastructureName
volumeName := fmt.Sprintf("[%s] 00000000-0000-0000-0000-000000000000/%s-dynamic-pvc-00000000-0000-0000-0000-000000000000.vmdk", dsName, clusterID)
klog.V(4).Infof("Checking data store %q with potential volume Name %s", dsName, volumeName)
if err := checkVolumeName(volumeName); err != nil {
volumeName := generateVolumeName(clusterID, "pvc-00000000-0000-0000-0000-000000000000", maxVolumeName)
fullVolumeName := fmt.Sprintf("[%s] 00000000-0000-0000-0000-000000000000/%s.vmdk", dsName, volumeName)
klog.V(4).Infof("Checking data store %q with potential volume Name %s", dsName, fullVolumeName)
if err := checkVolumeName(fullVolumeName); err != nil {
return fmt.Errorf("datastore %s: %s", dsName, err)
}
if err := checkForDatastoreCluster(ctx, dsName); err != nil {
return err
}
return nil
}

func checkForDatastoreCluster(ctx *CheckContext, dataStoreName string) error {
matchingDC, err := getDatacenter(ctx, ctx.VMConfig.Workspace.Datacenter)
if err != nil {
klog.Errorf("error getting datacenter %s: %v", ctx.VMConfig.Workspace.Datacenter, err)
return err
}
ds, err := getDataStoreByName(ctx, dataStoreName, matchingDC)
if err != nil {
klog.Errorf("error getting datastore %s: %v", dataStoreName, err)
return err
}

var dsMo mo.Datastore
pc := property.DefaultCollector(matchingDC.Client())
properties := []string{DatastoreInfoProperty, SummaryProperty}
tctx, cancel := context.WithTimeout(ctx.Context, *Timeout)
defer cancel()
err = pc.RetrieveOne(tctx, ds.Reference(), properties, &dsMo)
if err != nil {
klog.Errorf("error getting properties of datastore %s: %v", dataStoreName, err)
return nil
}

// list datastore cluster
m := view.NewManager(ctx.VMClient)
kind := []string{"StoragePod"}
tctx, cancel = context.WithTimeout(ctx.Context, *Timeout)
defer cancel()
v, err := m.CreateContainerView(tctx, ctx.VMClient.ServiceContent.RootFolder, kind, true)
if err != nil {
klog.Errorf("error listing datastore cluster: %+v", err)
return nil
}
defer func() {
v.Destroy(tctx)
}()

var content []mo.StoragePod
tctx, cancel = context.WithTimeout(ctx.Context, *Timeout)
defer cancel()
err = v.Retrieve(tctx, kind, []string{SummaryProperty, "childEntity"}, &content)
if err != nil {
klog.Errorf("error retrieving datastore cluster properties: %+v", err)
// it is possible that we do not actually have permission to fetch datastore clusters
// in which case rather than throwing an error - we will silently return nil, so as
// we don't trigger unnecessary alerts.
return nil
}

for _, ds := range content {
for _, child := range ds.Folder.ChildEntity {
tDS, err := getDatastore(ctx, child)
if err != nil {
// we may not have permissions to fetch unrelated datastores in OCP
// and hence we are going to ignore the error.
klog.Errorf("fetching datastore %s failed: %v", child.String(), err)
continue
}
if tDS.Summary.Url == dsMo.Summary.Url {
return fmt.Errorf("datastore %s is part of %s datastore cluster", tDS.Summary.Name, ds.Summary.Name)
}
}
}
klog.V(4).Infof("Checked datastore %s for SRDS - no problems found", dataStoreName)
return nil
}

Expand All @@ -242,7 +323,7 @@ func checkVolumeName(name string) error {
if err != nil {
return fmt.Errorf("error running systemd-escape: %s", err)
}
if len(path) >= 255 {
if len(escapedPath) >= 255 {
return fmt.Errorf("datastore name is too long: escaped volume path %q must be under 255 characters, got %d", escapedPath, len(escapedPath))
}
return nil
Expand All @@ -257,3 +338,20 @@ func systemdEscape(path string) (string, error) {
escapedPath := strings.TrimSpace(string(out))
return escapedPath, nil
}

// Copied from https://github.com/kubernetes/kubernetes/blob/93d288e2a47fa6d497b50d37c8b3a04e91da4228/pkg/volume/util/util.go#L230
// GenerateVolumeName returns a PV name with clusterName prefix. The function
// should be used to generate a name of GCE PD or Cinder volume. It basically
// adds "<clusterName>-dynamic-" before the PV name, making sure the resulting
// string fits given length and cuts "dynamic" if not.
func generateVolumeName(clusterName, pvName string, maxLength int) string {
prefix := clusterName + "-dynamic"
pvLen := len(pvName)

// cut the "<clusterName>-dynamic" to fit full pvName into maxLength
// +1 for the '-' dash
if pvLen+1+len(prefix) > maxLength {
prefix = prefix[:maxLength-pvLen-1]
}
return prefix + "-" + pvName
}

0 comments on commit 8f7c124

Please sign in to comment.