diff --git a/README.md b/README.md index 9b3daca5..35af8906 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,15 @@ Huawei Container Storage Interface (CSI) Driver is used to provision LUN, recycle LUN, and provide a series of disaster recovery functions of storages for Kubernetes Containers. +--- +**NOTE:** + +Users are informed that versions earlier than 2.2.RC4 are **NOT AVAILABLE FOR DOWNLOAD**. Versions earlier than 2.2.RC4 have the following problem: After a node on the Kubernetes platform is powered off unexpectedly, residual drive letters occur.After the node is powered on, the residual drive letters will cause disk scanning exceptions, which may affect service running. + +This has been fixed with V2.2.13. + +--- + ## Compatibility Matrix | Features | 1.13|1.14|1.15|1.16|1.17|1.18|1.19| |---|---|---|---|---|---|---|---| diff --git a/RELEASE.md b/RELEASE.md index d3f1841d..bf0a2bd1 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -56,6 +56,7 @@ | |OceanStor F V3/V3 V300R003/V300R006| + ## Version mappings among CSI, Huawei Distributed storage, and Kubernetes | Kubernetes |Huawei Distributed storage| |---|---| diff --git a/src/connector/iscsi/iscsi_helper.go b/src/connector/iscsi/iscsi_helper.go index 2b2c684e..589e077d 100644 --- a/src/connector/iscsi/iscsi_helper.go +++ b/src/connector/iscsi/iscsi_helper.go @@ -101,8 +101,9 @@ func parseISCSIInfo(connectionProperties map[string]interface{}) (*connectorInfo } func runISCSIAdmin(tgtPortal, targetIQN string, iSCSICommand string, checkExitCode []string) error { - iSCSICmd := fmt.Sprintf("iscsiadm -m node -T %s -p %s %s", targetIQN, tgtPortal, iSCSICommand) - output, err := utils.ExecShellCmdFilterLog(iSCSICmd) + iSCSICmd := fmt.Sprintf("-m node -T %s -p %s %s", targetIQN, tgtPortal, iSCSICommand) + splitCmd := strings.Split(iSCSICmd, " ") + output, err := utils.ExecCmdIscsiFilterLog("/sbin/iscsiadm", splitCmd) if err != nil { if err.Error() == "timeout" { return err @@ -119,9 +120,11 @@ func runISCSIAdmin(tgtPortal, targetIQN string, iSCSICommand string, checkExitCo return nil } -func runISCSIBare(iSCSICommand string, checkExitCode []string) (string, error) { - iSCSICmd := fmt.Sprintf("iscsiadm %s", iSCSICommand) - output, err := utils.ExecShellCmdFilterLog(iSCSICmd) +func runISCSIBare(args string, checkExitCode []string) (string, error) { + //iSCSICmd := fmt.Sprintf("/sbin/iscsiadm %s", iSCSICommand) + iSCSICmd := "/sbin/iscsiadm" + splitArgs := strings.Split(args, " ") + output, err := utils.ExecCmdIscsiFilterLog(iSCSICmd, splitArgs) if err != nil { if err.Error() == "timeout" { return "", err diff --git a/src/connector/nfs/nfs_helper.go b/src/connector/nfs/nfs_helper.go index 9e8ff2fe..f39562da 100644 --- a/src/connector/nfs/nfs_helper.go +++ b/src/connector/nfs/nfs_helper.go @@ -192,7 +192,12 @@ func getFSType(sourcePath string) (string, error) { return "", err } - for _, out := range strings.Split(output, "\n") { + linesBlkid := strings.Split(output, "\n") + if len(linesBlkid) <= 1 { + return "", nil + } + + for _, out := range linesBlkid { fsInfo := strings.Split(out, "=") if len(fsInfo) == 2 && fsInfo[0] == "ID_FS_TYPE" { return fsInfo[1], nil diff --git a/src/proto/proto.go b/src/proto/proto.go index 1906a534..09add8a1 100644 --- a/src/proto/proto.go +++ b/src/proto/proto.go @@ -3,6 +3,7 @@ package proto import ( "errors" "fmt" + "io/ioutil" "net" "strings" "utils" @@ -10,19 +11,35 @@ import ( ) func GetISCSIInitiator() (string, error) { - output, err := utils.ExecShellCmd("awk 'BEGIN{FS=\"=\";ORS=\"\"}/^InitiatorName=/{print $2}' /etc/iscsi/initiatorname.iscsi") + + initiatornameBuf, err := ioutil.ReadFile("/etc/iscsi/initiatorname.iscsi") + + var initiatorname string; if err != nil { - if strings.Contains(output, "cannot open file") { - msg := "No ISCSI initiator exist" - log.Errorln(msg) - return "", errors.New(msg) - } + msg := "Error reading file /etc/iscsi/initiatorname.iscsi" + log.Errorln(msg) + return "", errors.New(msg) + } - log.Errorf("Get ISCSI initiator error: %v", output) - return "", err + + for _, line := range strings.Split(string(initiatornameBuf), "\n") { + if strings.TrimSpace(line) != "" && strings.HasPrefix(line,"InitiatorName=") { + splitValue := strings.Split(line, "=") + if len(splitValue) == 2 { + initiatorname = string(splitValue[1]) + return initiatorname, nil + } else { + msg := "bad content for file /etc/iscsi/initiatorname.iscsi" + log.Errorln(msg) + return "", errors.New(msg) + } + break + } } - return output, nil + msg := "initiatorname not found" + log.Errorln(msg) + return "", errors.New(msg) } func GetFCInitiator() ([]string, error) { diff --git a/src/utils/utils.go b/src/utils/utils.go index 265fe361..1bf65c47 100644 --- a/src/utils/utils.go +++ b/src/utils/utils.go @@ -18,6 +18,7 @@ package utils import ( "errors" "fmt" + "io/ioutil" "math/rand" "os" "os/exec" @@ -116,6 +117,48 @@ func ExecShellCmdFilterLog(format string, args ...interface{}) (string, error) { } } +// ExecCmdIscsiFilterLog execs the command and filters the result log +func ExecCmdIscsiFilterLog(format string, args []string) (string, error) { + var output string + var err error + done := make(chan string) + defer close(done) + + go func() { + output, err = execIscsiCmd(format, done, true, args) + }() + + select { + case do := <-done: + log.Debugf("Run iscsi cmd done %s.", do) + return output, err + case <-time.After(time.Duration(30) * time.Second): + return "", errors.New("timeout") + } +} + +func execIscsiCmd(command string, ch chan string, logFilter bool, args []string) (string, error) { + + //log.Infof("Gonna run iscsi cmd \"%s\".",cmd) + + defer func() { + ch <- fmt.Sprintf("Iscsi cmd \"%s\" done", command) + }() + + iscsiCmd := exec.Command(command, args...) + time.AfterFunc(30*time.Second, func() { _ = iscsiCmd.Process.Kill() }) + output, err := iscsiCmd.CombinedOutput() + if err != nil { + log.Warningf("Run iscsi cmd \"%s\" error: %s.", command, err) + return string(output), err + } + + if !logFilter { + log.Infof("Iscsi cmd \"%s\" result:\n%s", command, output) + } + return string(output), nil +} + func execShellCmd(format string, ch chan string, logFilter bool, args ...interface{}) (string, error) { cmd := fmt.Sprintf(format, args...) log.Infof("Gonna run shell cmd \"%s\".", MaskSensitiveInfo(cmd)) @@ -124,8 +167,10 @@ func execShellCmd(format string, ch chan string, logFilter bool, args ...interfa ch <- fmt.Sprintf("Shell cmd \"%s\" done", MaskSensitiveInfo(cmd)) }() - execCmd := []string{"-i/proc/1/ns/ipc", "-m/proc/1/ns/mnt", "-n/proc/1/ns/net", "/bin/sh", "-c", cmd} - shCmd := exec.Command("nsenter", execCmd...) + //execCmd := []string{"-i/proc/1/ns/ipc", "-m/proc/1/ns/mnt", "-n/proc/1/ns/net", "/bin/sh", "-c", cmd} + //shCmd := exec.Command("nsenter", execCmd...) + execCmd := []string{"-c", cmd} + shCmd := exec.Command("/bin/sh", execCmd...) time.AfterFunc(30*time.Second, func() { _ = shCmd.Process.Kill() }) output, err := shCmd.CombinedOutput() if err != nil { @@ -186,12 +231,13 @@ func GetFSSharePath(name string) string { } func GetHostName() (string, error) { - hostname, err := ExecShellCmd("hostname | xargs echo -n") + hostnameBuf, err := ioutil.ReadFile("/etc/hostname") if err != nil { return "", err } + hostname := strings.Split(string(hostnameBuf), "\n")[0] - return hostname, nil + return string(hostname), nil } func GetPathTail(device string) string {