From 4b45309cd7af5f2ec1c506d3e6d31971b8141e2d Mon Sep 17 00:00:00 2001 From: Kshitija Kakde Date: Tue, 27 Jun 2023 14:40:27 +0530 Subject: [PATCH] controller unpublish changes added --- service/controller.go | 43 ++++++++++++--- service/service.go | 122 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 150 insertions(+), 15 deletions(-) diff --git a/service/controller.go b/service/controller.go index d6de358f..d69b54e7 100644 --- a/service/controller.go +++ b/service/controller.go @@ -1265,6 +1265,42 @@ func (s *service) ControllerUnpublishVolume( "checkVolumesMap for id: %s failed : %s", csiVolID, err.Error()) } + nodeID := req.GetNodeId() + if nodeID == "" { + return nil, status.Error(codes.InvalidArgument, + "Node ID is required") + } + + adminClient := s.adminClients[systemID] + + isNFS := strings.Contains(csiVolID, "/") + + if isNFS { + fsID := getFilesystemIDFromCsiVolumeID(csiVolID) + fs, err := s.getFilesystemByID(fsID, systemID) + if err != nil { + if strings.EqualFold(err.Error(), sioGatewayFileSystemNotFound) || strings.Contains(err.Error(), "must be a hexadecimal number") { + return nil, status.Error(codes.NotFound, + "volume not found") + } + return nil, status.Errorf(codes.Internal, + "failure checking volume status before controller publish: %s", + err.Error()) + } + + sdcIP, err := s.getSDCIP(nodeID, systemID) + if err != nil { + return nil, status.Errorf(codes.NotFound, err.Error()) + } + + //unexport for NFS + err = s.unexportFilesystem(ctx, req, adminClient, fs, req.GetVolumeId(), sdcIP, nodeID) + if err != nil { + return nil, err + } + + return &csi.ControllerUnpublishVolumeResponse{}, nil + } volID := getVolumeIDFromCsiVolumeID(csiVolID) vol, err := s.getVolByID(volID, systemID) @@ -1279,12 +1315,6 @@ func (s *service) ControllerUnpublishVolume( err.Error()) } - nodeID := req.GetNodeId() - if nodeID == "" { - return nil, status.Error(codes.InvalidArgument, - "Node ID is required") - } - sdcID, err := s.getSDCID(nodeID, systemID) if err != nil { return nil, status.Errorf(codes.NotFound, err.Error()) @@ -1303,7 +1333,6 @@ func (s *service) ControllerUnpublishVolume( Log.Debug("volume already unpublished") return &csi.ControllerUnpublishVolumeResponse{}, nil } - adminClient := s.adminClients[systemID] targetVolume := goscaleio.NewVolume(adminClient) targetVolume.Volume = vol diff --git a/service/service.go b/service/service.go index f9952e98..d73f3349 100644 --- a/service/service.go +++ b/service/service.go @@ -22,6 +22,7 @@ import ( "os" "path/filepath" "runtime" + "sort" "strconv" "strings" "sync" @@ -969,9 +970,114 @@ func (s *service) getSystemIDFromCsiVolumeID(csiVolID string) string { return "" } +func Contains(slice []string, element string) bool { + for _, a := range slice { + if a == element { + return true + } + } + return false +} + +func (s *service) unexportFilesystem(ctx context.Context, req *csi.ControllerUnpublishVolumeRequest, client *goscaleio.Client, fs *siotypes.FileSystem, volumeContextID, nodeIP, nodeID string) error { + + var nfsExportName string + nfsExportName = NFSExportNamePrefix + fs.Name + + nfsExportExists := false + var nfsExportID string + deleteExport := true + // Check if nfs export exists for the File system + nfsExportList, err := client.GetNFSExport() + + if err != nil { + return err + } + + for _, nfsExport := range nfsExportList { + if nfsExport.FileSystemID == fs.ID { + nfsExportExists = true + if nfsExport.Name != nfsExportName { + //This means that share was created manually on array, hence don't delete via driver + deleteExport = false + nfsExportName = nfsExport.Name + } + nfsExportID = nfsExport.ID + nfsExportName = nfsExport.Name + } + } + + if !nfsExportExists { + Log.Infof("NFS Share: %s not found on array.", nfsExportName) + return nil + } + + // remove host access from NFS Export + nfsExportResp, err := client.GetNFSExportByIDName(nfsExportID, "") + + if err != nil { + return status.Errorf(codes.NotFound, "Could not find NFS Export: %s", err) + } + + fmt.Printf("%#v\n", nfsExportResp) + + var modifyParam *siotypes.NFSExportModify = &siotypes.NFSExportModify{} + + sort.Strings(nfsExportResp.ReadOnlyHosts) + index := sort.SearchStrings(nfsExportResp.ReadOnlyHosts, nodeIP) + if len(nfsExportResp.ReadOnlyHosts) > 0 { + if index >= 0 { + modifyParam.RemoveReadOnlyHosts = []string{nodeIP + "/255.255.255.255"} // we can't remove without netmask + Log.Debug("Going to remove IP from ROHosts: ", modifyParam.RemoveReadOnlyHosts[0]) + } + } + + sort.Strings(nfsExportResp.ReadOnlyRootHosts) + index = sort.SearchStrings(nfsExportResp.ReadOnlyRootHosts, nodeIP) + if len(nfsExportResp.ReadOnlyRootHosts) > 0 { + if index >= 0 { + modifyParam.RemoveReadOnlyRootHosts = []string{nodeIP + "/255.255.255.255"} // we can't remove without netmask + Log.Debug("Going to remove IP from RORootHosts: ", modifyParam.RemoveReadOnlyRootHosts[0]) + } + } + + if Contains(nfsExportResp.ReadWriteHosts, nodeIP+"/255.255.255.255") { + modifyParam.RemoveReadWriteHosts = []string{nodeIP + "/255.255.255.255"} // we can't remove without netmask + Log.Debug("Going to remove IP from RWHosts: ", modifyParam.RemoveReadWriteHosts[0]) + } + + if Contains(nfsExportResp.ReadWriteRootHosts, nodeIP+"/255.255.255.255") { + modifyParam.RemoveReadWriteRootHosts = []string{nodeIP + "/255.255.255.255"} // we can't remove without netmask + Log.Debug("Going to remove IP from RWRootHosts: ", modifyParam.RemoveReadWriteRootHosts[0]) + } + + err = client.ModifyNFSExport(modifyParam, nfsExportID) + + if err != nil { + return status.Errorf(codes.NotFound, "Allocating host %s access to NFS Export failed. Error: %v", nodeID, err) + + } + Log.Debugf("Host: %s access is removed from NFS Share: %s", nodeID, nfsExportID) + + if deleteExport { + err = client.DeleteNFSExport(nfsExportID) + + if err != nil { + return status.Errorf(codes.NotFound, "delete NFS Export failed. Error:%v", err) + } + + Log.Printf("NFS export %s deleted successfully", nfsExportID) + } + + Log.Debugf("ControllerUnpublishVolume successful for volid: [%s]", volumeContextID) + + return nil + +} + // exportFilesystem - Method to export filesystem with idempotency func (s *service) exportFilesystem(ctx context.Context, req *csi.ControllerPublishVolumeRequest, client *goscaleio.Client, fs *siotypes.FileSystem, nodeIP, nodeID string, pContext map[string]string, am *csi.VolumeCapability_AccessMode) (*csi.ControllerPublishVolumeResponse, error) { - + hostUrl := nodeIP + "/" + "255.255.255.255" var nfsExportName string nfsExportName = NFSExportNamePrefix + fs.Name @@ -1027,7 +1133,7 @@ func (s *service) exportFilesystem(ctx context.Context, req *csi.ControllerPubli var readHostList, readWriteHostList []string for _, host := range readOnlyHosts { - if host == nodeIP { + if host == hostUrl { foundIncompatible = true break } @@ -1036,7 +1142,7 @@ func (s *service) exportFilesystem(ctx context.Context, req *csi.ControllerPubli otherHostsWithAccess += len(readWriteHosts) if !foundIncompatible { for _, host := range readWriteHosts { - if host == nodeIP { + if host == hostUrl { foundIncompatible = true break } @@ -1047,7 +1153,7 @@ func (s *service) exportFilesystem(ctx context.Context, req *csi.ControllerPubli if !foundIncompatible { for _, host := range readOnlyRootHosts { readHostList = append(readHostList, host) - if host == nodeIP { + if host == hostUrl { if am.Mode == csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY { foundIdempotent = true } else { @@ -1060,8 +1166,8 @@ func (s *service) exportFilesystem(ctx context.Context, req *csi.ControllerPubli if !foundIncompatible && !foundIdempotent { for _, host := range readWriteRootHosts { - readWriteHostList = append(readWriteHostList, nodeIP) - if host == nodeIP { + readWriteHostList = append(readWriteHostList, hostUrl) + if host == hostUrl { if am.Mode == csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY { foundIncompatible = true } else { @@ -1087,10 +1193,10 @@ func (s *service) exportFilesystem(ctx context.Context, req *csi.ControllerPubli } //Allocate host access to NFS Share with appropriate access mode if am.Mode == csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY { - readHostList = append(readHostList, nodeIP) + readHostList = append(readHostList, hostUrl) client.ModifyNFSExport(&siotypes.NFSExportModify{AddReadOnlyRootHosts: readHostList}, nfsExportID) } else { - readWriteHostList = append(readWriteHostList, nodeIP) + readWriteHostList = append(readWriteHostList, hostUrl) client.ModifyNFSExport(&siotypes.NFSExportModify{AddReadWriteRootHosts: readWriteHostList}, nfsExportID) }