From 222c375f2bb9f413b49e989d703d5e11b337588c Mon Sep 17 00:00:00 2001 From: "v.oleynikov" Date: Wed, 19 Jun 2024 15:42:39 +0300 Subject: [PATCH] fix Signed-off-by: v.oleynikov --- images/csi-huawei/host_helper.go | 190 +++++++++++++++++++++++++++++++ images/csi-huawei/werf.inc.yaml | 1 + 2 files changed, 191 insertions(+) create mode 100644 images/csi-huawei/host_helper.go diff --git a/images/csi-huawei/host_helper.go b/images/csi-huawei/host_helper.go new file mode 100644 index 0000000..8cdd6e6 --- /dev/null +++ b/images/csi-huawei/host_helper.go @@ -0,0 +1,190 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2023. 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 host defines a set of useful methods, which can help Connector to operate host information +package host + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/sirupsen/logrus" + + corev1 "k8s.io/api/core/v1" + apiErrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "huawei-csi-driver/csi/app" + "huawei-csi-driver/proto" + "huawei-csi-driver/utils" + "huawei-csi-driver/utils/log" +) + +const ( + + // secret name for saving data + hostInfoSecretName = "huawei-csi-host-info" +) + +// NodeHostInfo defines the base information of node host +type NodeHostInfo struct { + // HostName the name of host + HostName string `json:"hostName"` + // IscsiInitiator the initiator of ISCSI protocol + IscsiInitiator string `json:"iscsiInitiator"` + // FCInitiators the initiator of FC protocol + FCInitiators []string `json:"fCInitiators"` + // RoCEInitiator the initiator of RoCE protocol + RoCEInitiator string `json:"roCEInitiator"` +} + +// NewNodeHostInfo instantiates this node host info. +// If the initiator query fails, the error will not be returned directly, +// because the current host may not have an initiator, which should be judged by the caller and handled accordingly +func NewNodeHostInfo(ctx context.Context) (*NodeHostInfo, error) { + hostName, err := utils.GetHostName(ctx) + if err != nil { + log.AddContext(ctx).Errorf("get host name error: [%v]", err) + return nil, err + } + + iscsiInitiator, err := proto.GetISCSIInitiator(ctx) + if err != nil { + log.AddContext(ctx).Infof("get ISCSI initiator error: [%v]", err) + } + + fcInitiators, err := proto.GetFCInitiator(ctx) + if err != nil { + log.AddContext(ctx).Infof("get FC initiator error: [%v]", err) + } + + roCEInitiator, err := proto.GetRoCEInitiator(ctx) + if err != nil { + log.AddContext(ctx).Infof("get RoCE initiator error: [%v]", err) + } + + return &NodeHostInfo{ + HostName: strings.Trim(hostName, " "), + IscsiInitiator: iscsiInitiator, + FCInitiators: fcInitiators, + RoCEInitiator: roCEInitiator, + }, nil +} + +// SaveNodeHostInfoToSecret save the current node host information to secret. +// secret namespace use the namespace of the current pod. +func SaveNodeHostInfoToSecret(ctx context.Context) error { + + k8sUtils := app.GetGlobalConfig().K8sUtils + hostInfoSecret, err := k8sUtils.GetSecret(ctx, hostInfoSecretName, app.GetGlobalConfig().Namespace) + if apiErrors.IsNotFound(err) { + logrus.Infof("1 %s", err) + hostInfoSecret = makeNodeHostInfoSecret() + hostInfoSecret, err = k8sUtils.CreateSecret(ctx, hostInfoSecret) + logrus.Infof("2 %s", err) + if err != nil && !apiErrors.IsAlreadyExists(err) { + errMsg := fmt.Sprintf("create host secret err: %s", err) + return errors.New(errMsg) + } + } else if err != nil { + errMsg := fmt.Sprintf("get secret err: %s", err) + logrus.Infof("3 %s", errMsg) + return errors.New(errMsg) + } + + hostInfo, err := NewNodeHostInfo(ctx) + logrus.Infof("4 %s", err) + if err != nil { + log.Errorf("create node host info fail ,error: [%v]", err) + return err + } + + newSecretData, err := json.Marshal(hostInfo) + logrus.Infof("5 %s", err) + if err != nil { + log.Errorf("json marshal error, hosname:[%v],err: [%v]", hostInfo.HostName, err) + return err + } + + for true { + hostInfoSecret, err = k8sUtils.GetSecret(ctx, hostInfoSecretName, app.GetGlobalConfig().Namespace) + logrus.Infof("6 %s", err) + if err != nil { + errMsg := fmt.Sprintf("get secret err: %s", err) + return errors.New(errMsg) + } + + if hostInfoSecret.StringData == nil { + hostInfoSecret.StringData = make(map[string]string) + } + hostInfoSecret.StringData[hostInfo.HostName] = string(newSecretData) + + hostInfoSecret, err = k8sUtils.UpdateSecret(ctx, hostInfoSecret) + logrus.Infof("7 %s", err) + if err != nil && apiErrors.IsConflict(err) { + time.Sleep(time.Second) + log.Infof("update secret is conflict,retrying") + continue + } else if err != nil { + errMsg := fmt.Sprintf("update secret err: %s", err) + return errors.New(errMsg) + } + break + } + return nil +} + +// GetNodeHostInfosFromSecret get the specified node host information from secret. +func GetNodeHostInfosFromSecret(ctx context.Context, hostName string) (*NodeHostInfo, error) { + k8sUtils := app.GetGlobalConfig().K8sUtils + secret, err := k8sUtils.GetSecret(ctx, hostInfoSecretName, app.GetGlobalConfig().Namespace) + if err != nil { + log.AddContext(ctx).Errorf("get secret data error: [%v]", err) + return nil, err + } + if secret.Data == nil { + return nil, errors.New("secret data is empty") + } + if secretData, ok := secret.Data[hostName]; ok { + hostNodeInfo := &NodeHostInfo{} + if err = json.Unmarshal(secretData, hostNodeInfo); err != nil { + errMsg := fmt.Sprintf("json unmarshal data error: %s", err) + return nil, errors.New(errMsg) + } + return hostNodeInfo, nil + } + return nil, nil +} + +// makeNodeHostInfoSecret make node host info secret +func makeNodeHostInfoSecret() *corev1.Secret { + return &corev1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "Secret", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: hostInfoSecretName, + Namespace: app.GetGlobalConfig().Namespace, + }, + StringData: map[string]string{}, + Type: corev1.SecretTypeOpaque, + } +} diff --git a/images/csi-huawei/werf.inc.yaml b/images/csi-huawei/werf.inc.yaml index beaa96a..991163d 100644 --- a/images/csi-huawei/werf.inc.yaml +++ b/images/csi-huawei/werf.inc.yaml @@ -23,6 +23,7 @@ shell: - export GOPROXY={{ env "GOPROXY" }} - git clone --depth 1 --branch {{ env "SOURCE_REPO_TAG" }} {{ env "SOURCE_REPO" }}/Huawei/eSDK_K8S_Plugin.git /esdb_k8s_plugin - mv /main.go /esdb_k8s_plugin/csi + - mv /host_helper.go /esdb_k8s_plugin/connector/host - cd /esdb_k8s_plugin - GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-s -w" -o /huaweicsi ./csi - GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-s -w" -o /storage-backend-controller ./cmd/storage-backend-controller