Skip to content

Commit

Permalink
Implement a pre-init phase to sae node specific MDM lists.
Browse files Browse the repository at this point in the history
  • Loading branch information
donatwork committed Dec 9, 2024
1 parent 9f67ab8 commit 165178e
Show file tree
Hide file tree
Showing 8 changed files with 735 additions and 12 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ require (
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.etcd.io/etcd/api/v3 v3.5.17 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
Expand Down
12 changes: 12 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ func main() {
service.DriverConfigParamsFile = *driverConfigParamsfile
service.KubeConfig = *kubeconfig

// Run the service as a pre-init step.
if os.Getenv(gocsi.EnvVarMode) == "MDM-Info" {
fmt.Fprintf(os.Stdout, "PowerFlex Container Storage Interface (CSI) Plugin starting in pre-init mode.")
svc := service.NewPreInitService()
err := svc.PreInit()
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "failed to complete pre-init: %v", err)
os.Exit(1)
}
os.Exit(0)
}

run := func(ctx context.Context) {
gocsi.Run(ctx, service.Name, "A PowerFlex Container Storage Interface (CSI) Plugin",
usage, provider.New())
Expand Down
4 changes: 1 addition & 3 deletions service/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -828,9 +828,7 @@ func (s *service) createVolumeFromSnapshot(req *csi.CreateVolumeRequest,
snapID := getVolumeIDFromCsiVolumeID(snapshotSource.SnapshotId)
srcVol, err := s.getVolByID(snapID, systemID)
if err != nil {
if err != nil {
return nil, status.Errorf(codes.NotFound, "Snapshot not found: %s, error: %s", snapshotSource.SnapshotId, err.Error())
}
return nil, status.Errorf(codes.NotFound, "Snapshot not found: %s, error: %s", snapshotSource.SnapshotId, err.Error())
}
// Validate the size is the same.
if int64(srcVol.SizeInKb) != sizeInKbytes {
Expand Down
7 changes: 7 additions & 0 deletions service/features/array-config/simple-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
- username: "user"
password: "pass"
systemID: "systemid"
endpoint: "https://192.168.1.12"
skipCertificateValidation: true
isDefault: true
mdm: "192.168.1.10,192.168.1.11"
166 changes: 166 additions & 0 deletions service/preinit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved.
//
// 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 service

import (
"fmt"
"io/fs"
"os"
"strings"

"golang.org/x/net/context"
)

const (
defaultNodeMdmsFile = "/data/node_mdms.txt"
)

type PreInitService interface {
PreInit() error
}

func NewPreInitService() PreInitService {
return &service{}
}

type ArrayConfigurationProvider interface {
GetArrayConfiguration() ([]*ArrayConnectionData, error)
}

type FileWriterProvider interface {
WriteFile(filename string, data []byte, perm os.FileMode) error
}

type DefaultArrayConfigurationProvider struct{}

func (s *DefaultArrayConfigurationProvider) GetArrayConfiguration() ([]*ArrayConnectionData, error) {
arrayConfig, err := getArrayConfig(nil)
if err != nil {
return nil, err
}

connectionData := make([]*ArrayConnectionData, 0)
for _, v := range arrayConfig {
connectionData = append(connectionData, v)
}

return connectionData, nil
}

type DefaultFileWriterProvider struct{}

func (s *DefaultFileWriterProvider) WriteFile(filename string, data []byte, perm os.FileMode) error {
return os.WriteFile(filename, data, perm)
}

var (
arrayConfigurationProviderImpl ArrayConfigurationProvider = &DefaultArrayConfigurationProvider{}
fileWriterProviderImpl FileWriterProvider = &DefaultFileWriterProvider{}
nodeMdmsFile = defaultNodeMdmsFile
)

func (s *service) PreInit() error {
Log.Infof("PreInit running")

arrayConfig, err := arrayConfigurationProviderImpl.GetArrayConfiguration()
if err != nil {
return err
}

labelKey, err := getLabelKey(arrayConfig)
if err != nil {
return err
}

var mdmData string

if labelKey == "" {
Log.Debug("No zone key found, will configure all MDMs")
sb := strings.Builder{}
for _, connectionData := range arrayConfig {
if connectionData.Mdm != "" {
if sb.Len() > 0 {
sb.WriteString(",")
}
sb.WriteString(connectionData.Mdm)
}
}
mdmData = sb.String()
} else {
Log.Infof("Zone key detected, will configure MDMs for this node, key: %s", labelKey)
nodeLabels, err := s.GetNodeLabels(context.Background())
if err != nil {
return err
}
zone := nodeLabels[labelKey]

if zone == "" {
return fmt.Errorf("No zone found, cannot configure this node")
}

Log.Infof("Zone found, will configure MDMs for this node, zone: %s", zone)
mdmData, err = getMdmList(arrayConfig, labelKey, zone)
if err != nil {
return err
}
}

Log.Infof("Saving MDM list to %s, MDM=%s", nodeMdmsFile, mdmData)
err = fileWriterProviderImpl.WriteFile(nodeMdmsFile, []byte(fmt.Sprintf("MDM=%s\n", mdmData)), fs.FileMode(0o444))
return err
}

// Returns a string with the comma separated list of MDM addresses given a
// key and zone. The ordering of the MDM addresses is not guaranteed. An error is
// returned if either the key or zone are empty.
func getMdmList(connectionData []*ArrayConnectionData, key, zone string) (string, error) {
if key == "" {
return "", fmt.Errorf("key is empty")
}
if zone == "" {
return "", fmt.Errorf("zone is empty")
}

sb := &strings.Builder{}
for _, connectionData := range connectionData {
if connectionData.Mdm != "" && connectionData.Zone.LabelKey == key && connectionData.Zone.Name == zone {
if sb.Len() > 0 {
sb.WriteString(",")
}
sb.WriteString(connectionData.Mdm)
}
}

return sb.String(), nil
}

// Returns the label key for the given set of array configurations.
// It is expected that the value for labelKey is the same for all arrays.
// An empty string is returned if the labelKey is not present in all arrays.
// An error is returned if the key cannot be determined.
func getLabelKey(connectionData []*ArrayConnectionData) (string, error) {
if len(connectionData) == 0 {
return "", fmt.Errorf("array connection data is empty")
}

labelKey := connectionData[0].Zone.LabelKey

for _, v := range connectionData {
if v.Zone.LabelKey != labelKey {
return "", fmt.Errorf("zone label key is not the same for all arrays")
}
}

return labelKey, nil
}
Loading

0 comments on commit 165178e

Please sign in to comment.