mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-11-17 20:00:23 +00:00
Fix gometalinter issues
Signed-off-by: Madhu Rajanna <mrajanna@redhat.com>
This commit is contained in:
parent
7a0c233c27
commit
ca2e475296
@ -39,15 +39,13 @@ const cephKeyring = `[client.{{.UserID}}]
|
|||||||
key = {{.Key}}
|
key = {{.Key}}
|
||||||
`
|
`
|
||||||
|
|
||||||
// gosec
|
const cephSecret = `{{.Key}}` // #nosec
|
||||||
const cephSecret = `{{.Key}}`
|
|
||||||
|
|
||||||
// gosec
|
|
||||||
const (
|
const (
|
||||||
cephConfigRoot = "/etc/ceph"
|
cephConfigRoot = "/etc/ceph"
|
||||||
cephConfigFileNameFmt = "ceph.share.%s.conf"
|
cephConfigFileNameFmt = "ceph.share.%s.conf"
|
||||||
cephKeyringFileNameFmt = "ceph.share.%s.client.%s.keyring"
|
cephKeyringFileNameFmt = "ceph.share.%s.client.%s.keyring"
|
||||||
cephSecretFileNameFmt = "ceph.share.%s.client.%s.secret"
|
cephSecretFileNameFmt = "ceph.share.%s.client.%s.secret" // #nosec
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -78,7 +76,7 @@ type cephConfigData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func writeCephTemplate(fileName string, m os.FileMode, t *template.Template, data interface{}) error {
|
func writeCephTemplate(fileName string, m os.FileMode, t *template.Template, data interface{}) error {
|
||||||
// gosec
|
// #nosec
|
||||||
if err := os.MkdirAll(cephConfigRoot, 0755); err != nil {
|
if err := os.MkdirAll(cephConfigRoot, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func makeVolumeID(volName string) volumeID {
|
|||||||
func execCommand(command string, args ...string) ([]byte, error) {
|
func execCommand(command string, args ...string) ([]byte, error) {
|
||||||
glog.V(4).Infof("cephfs: EXEC %s %s", command, args)
|
glog.V(4).Infof("cephfs: EXEC %s %s", command, args)
|
||||||
|
|
||||||
cmd := exec.Command(command, args...)
|
cmd := exec.Command(command, args...) // #nosec
|
||||||
return cmd.CombinedOutput()
|
return cmd.CombinedOutput()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,9 @@ var (
|
|||||||
// Load available ceph mounters installed on system into availableMounters
|
// Load available ceph mounters installed on system into availableMounters
|
||||||
// Called from driver.go's Run()
|
// Called from driver.go's Run()
|
||||||
func loadAvailableMounters() error {
|
func loadAvailableMounters() error {
|
||||||
|
// #nosec
|
||||||
fuseMounterProbe := exec.Command("ceph-fuse", "--version")
|
fuseMounterProbe := exec.Command("ceph-fuse", "--version")
|
||||||
|
// #nosec
|
||||||
kernelMounterProbe := exec.Command("mount.ceph")
|
kernelMounterProbe := exec.Command("mount.ceph")
|
||||||
|
|
||||||
if fuseMounterProbe.Run() == nil {
|
if fuseMounterProbe.Run() == nil {
|
||||||
|
@ -132,8 +132,8 @@ func newVolumeOptions(volOptions, secret map[string]string) (*volumeOptions, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This field is optional, don't check for its presence
|
// This field is optional, don't check for its presence
|
||||||
// nolint: errcheck
|
// nolint
|
||||||
// (skip errcheck as this is optional)
|
// (skip errcheck and gosec as this is optional)
|
||||||
extractOption(&opts.Mounter, "mounter", volOptions)
|
extractOption(&opts.Mounter, "mounter", volOptions)
|
||||||
|
|
||||||
if err = opts.validate(); err != nil {
|
if err = opts.validate(); err != nil {
|
||||||
|
@ -55,14 +55,14 @@ var (
|
|||||||
// info from metadata store
|
// info from metadata store
|
||||||
func (cs *ControllerServer) LoadExDataFromMetadataStore() error {
|
func (cs *ControllerServer) LoadExDataFromMetadataStore() error {
|
||||||
vol := &rbdVolume{}
|
vol := &rbdVolume{}
|
||||||
// nolint: errcheck
|
// nolint
|
||||||
cs.MetadataStore.ForAll("csi-rbd-vol-", vol, func(identifier string) error {
|
cs.MetadataStore.ForAll("csi-rbd-vol-", vol, func(identifier string) error {
|
||||||
rbdVolumes[identifier] = vol
|
rbdVolumes[identifier] = vol
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
snap := &rbdSnapshot{}
|
snap := &rbdSnapshot{}
|
||||||
// nolint: errcheck
|
// nolint
|
||||||
cs.MetadataStore.ForAll("csi-rbd-(.*)-snap-", snap, func(identifier string) error {
|
cs.MetadataStore.ForAll("csi-rbd-(.*)-snap-", snap, func(identifier string) error {
|
||||||
rbdSnapshots[identifier] = snap
|
rbdSnapshots[identifier] = snap
|
||||||
return nil
|
return nil
|
||||||
@ -104,10 +104,10 @@ func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
|
|||||||
// check for the requested capacity and already allocated capacity
|
// check for the requested capacity and already allocated capacity
|
||||||
if exVol, err := getRBDVolumeByName(req.GetName()); err == nil {
|
if exVol, err := getRBDVolumeByName(req.GetName()); err == nil {
|
||||||
// Since err is nil, it means the volume with the same name already exists
|
// Since err is nil, it means the volume with the same name already exists
|
||||||
// need to check if the size of exisiting volume is the same as in new
|
// need to check if the size of existing volume is the same as in new
|
||||||
// request
|
// request
|
||||||
if exVol.VolSize >= req.GetCapacityRange().GetRequiredBytes() {
|
if exVol.VolSize >= req.GetCapacityRange().GetRequiredBytes() {
|
||||||
// exisiting volume is compatible with new request and should be reused.
|
// existing volume is compatible with new request and should be reused.
|
||||||
// TODO (sbezverk) Do I need to make sure that RBD volume still exists?
|
// TODO (sbezverk) Do I need to make sure that RBD volume still exists?
|
||||||
return &csi.CreateVolumeResponse{
|
return &csi.CreateVolumeResponse{
|
||||||
Volume: &csi.Volume{
|
Volume: &csi.Volume{
|
||||||
@ -145,22 +145,9 @@ func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
|
|||||||
volSizeGB := int(volSizeBytes / 1024 / 1024 / 1024)
|
volSizeGB := int(volSizeBytes / 1024 / 1024 / 1024)
|
||||||
|
|
||||||
// Check if there is already RBD image with requested name
|
// Check if there is already RBD image with requested name
|
||||||
found, _, _ := rbdStatus(rbdVol, rbdVol.UserID, req.GetSecrets())
|
err = cs.checkrbdStatus(rbdVol, req, volSizeGB)
|
||||||
if !found {
|
if err != nil {
|
||||||
// if VolumeContentSource is not nil, this request is for snapshot
|
return nil, err
|
||||||
if req.VolumeContentSource != nil {
|
|
||||||
if err = cs.checkSnapshot(req, rbdVol); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = createRBDImage(rbdVol, volSizeGB, rbdVol.AdminID, req.GetSecrets())
|
|
||||||
if err != nil {
|
|
||||||
glog.Warningf("failed to create volume: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.V(4).Infof("create volume %s", volName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if createErr := cs.MetadataStore.Create(volumeID, rbdVol); createErr != nil {
|
if createErr := cs.MetadataStore.Create(volumeID, rbdVol); createErr != nil {
|
||||||
glog.Warningf("failed to store volume metadata with error: %v", err)
|
glog.Warningf("failed to store volume metadata with error: %v", err)
|
||||||
@ -181,6 +168,28 @@ func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cs *ControllerServer) checkrbdStatus(rbdVol *rbdVolume, req *csi.CreateVolumeRequest, volSizeGB int) error {
|
||||||
|
var err error
|
||||||
|
// Check if there is already RBD image with requested name
|
||||||
|
found, _, _ := rbdStatus(rbdVol, rbdVol.UserID, req.GetSecrets()) // #nosec
|
||||||
|
if !found {
|
||||||
|
// if VolumeContentSource is not nil, this request is for snapshot
|
||||||
|
if req.VolumeContentSource != nil {
|
||||||
|
if err = cs.checkSnapshot(req, rbdVol); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = createRBDImage(rbdVol, volSizeGB, rbdVol.AdminID, req.GetSecrets())
|
||||||
|
if err != nil {
|
||||||
|
glog.Warningf("failed to create volume: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(4).Infof("create volume %s", rbdVol.VolName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
func (cs *ControllerServer) checkSnapshot(req *csi.CreateVolumeRequest, rbdVol *rbdVolume) error {
|
func (cs *ControllerServer) checkSnapshot(req *csi.CreateVolumeRequest, rbdVol *rbdVolume) error {
|
||||||
snapshot := req.VolumeContentSource.GetSnapshot()
|
snapshot := req.VolumeContentSource.GetSnapshot()
|
||||||
if snapshot == nil {
|
if snapshot == nil {
|
||||||
@ -275,19 +284,10 @@ func (cs *ControllerServer) ControllerPublishVolume(ctx context.Context, req *cs
|
|||||||
// CreateSnapshot creates the snapshot in backend and stores metadata
|
// CreateSnapshot creates the snapshot in backend and stores metadata
|
||||||
// in store
|
// in store
|
||||||
func (cs *ControllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateSnapshotRequest) (*csi.CreateSnapshotResponse, error) {
|
func (cs *ControllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateSnapshotRequest) (*csi.CreateSnapshotResponse, error) {
|
||||||
if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT); err != nil {
|
|
||||||
glog.Warningf("invalid create snapshot req: %v", req)
|
if err := cs.validateSnapshotReq(req); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check sanity of request Snapshot Name, Source Volume Id
|
|
||||||
if len(req.Name) == 0 {
|
|
||||||
return nil, status.Error(codes.InvalidArgument, "Snapshot Name cannot be empty")
|
|
||||||
}
|
|
||||||
if len(req.SourceVolumeId) == 0 {
|
|
||||||
return nil, status.Error(codes.InvalidArgument, "Source Volume ID cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
snapshotNameMutex.LockKey(req.GetName())
|
snapshotNameMutex.LockKey(req.GetName())
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -338,54 +338,16 @@ func (cs *ControllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS
|
|||||||
rbdSnap.SourceVolumeID = req.GetSourceVolumeId()
|
rbdSnap.SourceVolumeID = req.GetSourceVolumeId()
|
||||||
rbdSnap.SizeBytes = rbdVolume.VolSize
|
rbdSnap.SizeBytes = rbdVolume.VolSize
|
||||||
|
|
||||||
err = createSnapshot(rbdSnap, rbdSnap.AdminID, req.GetSecrets())
|
err = cs.doSnapshot(rbdSnap, req.GetSecrets())
|
||||||
// if we already have the snapshot, return the snapshot
|
// if we already have the snapshot, return the snapshot
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
return nil, err
|
||||||
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
|
||||||
if status.ExitStatus() == int(syscall.EEXIST) {
|
|
||||||
glog.Warningf("Snapshot with the same name: %s, we return this.", req.GetName())
|
|
||||||
} else {
|
|
||||||
glog.Warningf("failed to create snapshot: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
glog.Warningf("failed to create snapshot: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
glog.Warningf("failed to create snapshot: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
glog.V(4).Infof("create snapshot %s", snapName)
|
|
||||||
err = protectSnapshot(rbdSnap, rbdSnap.AdminID, req.GetSecrets())
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
err = deleteSnapshot(rbdSnap, rbdSnap.AdminID, req.GetSecrets())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("snapshot is created but failed to protect and delete snapshot: %v", err)
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("Snapshot is created but failed to protect snapshot")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rbdSnap.CreatedAt = ptypes.TimestampNow().GetSeconds()
|
rbdSnap.CreatedAt = ptypes.TimestampNow().GetSeconds()
|
||||||
|
|
||||||
if createErr := cs.MetadataStore.Create(snapshotID, rbdSnap); createErr != nil {
|
if err = cs.storeSnapMetadata(rbdSnap, req.GetSecrets()); err != nil {
|
||||||
|
return nil, err
|
||||||
glog.Warningf("rbd: failed to store snapInfo with error: %v", err)
|
|
||||||
// Unprotect snapshot
|
|
||||||
err = unprotectSnapshot(rbdSnap, rbdSnap.AdminID, req.GetSecrets())
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, "This Snapshot should be removed but failed to unprotect snapshot: %s/%s with error: %v", rbdSnap.Pool, rbdSnap.SnapName, err)
|
|
||||||
}
|
|
||||||
// Deleting snapshot
|
|
||||||
glog.V(4).Infof("deleting Snaphot %s", rbdSnap.SnapName)
|
|
||||||
if err = deleteSnapshot(rbdSnap, rbdSnap.AdminID, req.GetSecrets()); err != nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, "This Snapshot should be removed but failed to delete snapshot: %s/%s with error: %v", rbdSnap.Pool, rbdSnap.SnapName, err)
|
|
||||||
}
|
|
||||||
return nil, createErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rbdSnapshots[snapshotID] = rbdSnap
|
rbdSnapshots[snapshotID] = rbdSnap
|
||||||
@ -402,6 +364,75 @@ func (cs *ControllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cs *ControllerServer) storeSnapMetadata(rbdSnap *rbdSnapshot, secret map[string]string) error {
|
||||||
|
errCreate := cs.MetadataStore.Create(rbdSnap.SnapID, rbdSnap)
|
||||||
|
if errCreate != nil {
|
||||||
|
glog.Warningf("rbd: failed to store snapInfo with error: %v", errCreate)
|
||||||
|
// Unprotect snapshot
|
||||||
|
err := unprotectSnapshot(rbdSnap, rbdSnap.AdminID, secret)
|
||||||
|
if err != nil {
|
||||||
|
return status.Errorf(codes.Unknown, "This Snapshot should be removed but failed to unprotect snapshot: %s/%s with error: %v", rbdSnap.Pool, rbdSnap.SnapName, err)
|
||||||
|
}
|
||||||
|
// Deleting snapshot
|
||||||
|
glog.V(4).Infof("deleting Snaphot %s", rbdSnap.SnapName)
|
||||||
|
if err = deleteSnapshot(rbdSnap, rbdSnap.AdminID, secret); err != nil {
|
||||||
|
return status.Errorf(codes.Unknown, "This Snapshot should be removed but failed to delete snapshot: %s/%s with error: %v", rbdSnap.Pool, rbdSnap.SnapName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errCreate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *ControllerServer) validateSnapshotReq(req *csi.CreateSnapshotRequest) error {
|
||||||
|
if err := cs.Driver.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT); err != nil {
|
||||||
|
glog.Warningf("invalid create snapshot req: %v", req)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check sanity of request Snapshot Name, Source Volume Id
|
||||||
|
if len(req.Name) == 0 {
|
||||||
|
return status.Error(codes.InvalidArgument, "Snapshot Name cannot be empty")
|
||||||
|
}
|
||||||
|
if len(req.SourceVolumeId) == 0 {
|
||||||
|
return status.Error(codes.InvalidArgument, "Source Volume ID cannot be empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *ControllerServer) doSnapshot(rbdSnap *rbdSnapshot, secret map[string]string) error {
|
||||||
|
err := createSnapshot(rbdSnap, rbdSnap.AdminID, secret)
|
||||||
|
// if we already have the snapshot, return the snapshot
|
||||||
|
if err != nil {
|
||||||
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||||
|
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
||||||
|
if status.ExitStatus() == int(syscall.EEXIST) {
|
||||||
|
glog.Warningf("Snapshot with the same name: %s, we return this.", rbdSnap.SnapName)
|
||||||
|
} else {
|
||||||
|
glog.Warningf("failed to create snapshot: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
glog.Warningf("failed to create snapshot: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
glog.Warningf("failed to create snapshot: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
glog.V(4).Infof("create snapshot %s", rbdSnap.SnapName)
|
||||||
|
err = protectSnapshot(rbdSnap, rbdSnap.AdminID, secret)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err = deleteSnapshot(rbdSnap, rbdSnap.AdminID, secret)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("snapshot is created but failed to protect and delete snapshot: %v", err)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Snapshot is created but failed to protect snapshot")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteSnapshot deletes the snapshot in backend and removes the
|
// DeleteSnapshot deletes the snapshot in backend and removes the
|
||||||
//snapshot metadata from store
|
//snapshot metadata from store
|
||||||
func (cs *ControllerServer) DeleteSnapshot(ctx context.Context, req *csi.DeleteSnapshotRequest) (*csi.DeleteSnapshotResponse, error) {
|
func (cs *ControllerServer) DeleteSnapshot(ctx context.Context, req *csi.DeleteSnapshotRequest) (*csi.DeleteSnapshotResponse, error) {
|
||||||
|
@ -67,47 +67,16 @@ func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var volName string
|
volName, err := ns.getVolumeName(req)
|
||||||
isBlock := req.GetVolumeCapability().GetBlock() != nil
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
if isBlock {
|
|
||||||
// Get volName from targetPath
|
|
||||||
s := strings.Split(targetPath, "/")
|
|
||||||
volName = s[len(s)-1]
|
|
||||||
} else {
|
|
||||||
// Get volName from targetPath
|
|
||||||
if !strings.HasSuffix(targetPath, "/mount") {
|
|
||||||
return nil, fmt.Errorf("rbd: malformed the value of target path: %s", targetPath)
|
|
||||||
}
|
|
||||||
s := strings.Split(strings.TrimSuffix(targetPath, "/mount"), "/")
|
|
||||||
volName = s[len(s)-1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isBlock := req.GetVolumeCapability().GetBlock() != nil
|
||||||
// Check if that target path exists properly
|
// Check if that target path exists properly
|
||||||
notMnt, err := ns.mounter.IsNotMountPoint(targetPath)
|
notMnt, err := ns.createTargetPath(targetPath, isBlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
return nil, err
|
||||||
if isBlock {
|
|
||||||
// create an empty file
|
|
||||||
targetPathFile, e := os.OpenFile(targetPath, os.O_CREATE|os.O_RDWR, 0750)
|
|
||||||
if e != nil {
|
|
||||||
glog.V(4).Infof("Failed to create targetPath:%s with error: %v", targetPath, err)
|
|
||||||
return nil, status.Error(codes.Internal, e.Error())
|
|
||||||
}
|
|
||||||
if err = targetPathFile.Close(); err != nil {
|
|
||||||
glog.V(4).Infof("Failed to close targetPath:%s with error: %v", targetPath, err)
|
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Create a directory
|
|
||||||
if err = os.MkdirAll(targetPath, 0750); err != nil {
|
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
notMnt = true
|
|
||||||
} else {
|
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !notMnt {
|
if !notMnt {
|
||||||
@ -125,11 +94,41 @@ func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
|
|||||||
}
|
}
|
||||||
glog.V(4).Infof("rbd image: %s/%s was successfully mapped at %s\n", req.GetVolumeId(), volOptions.Pool, devicePath)
|
glog.V(4).Infof("rbd image: %s/%s was successfully mapped at %s\n", req.GetVolumeId(), volOptions.Pool, devicePath)
|
||||||
|
|
||||||
|
// Publish Path
|
||||||
|
err = ns.mountVolume(req, devicePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &csi.NodePublishVolumeResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NodeServer) getVolumeName(req *csi.NodePublishVolumeRequest) (string, error) {
|
||||||
|
var volName string
|
||||||
|
isBlock := req.GetVolumeCapability().GetBlock() != nil
|
||||||
|
targetPath := req.GetTargetPath()
|
||||||
|
if isBlock {
|
||||||
|
// Get volName from targetPath
|
||||||
|
s := strings.Split(targetPath, "/")
|
||||||
|
volName = s[len(s)-1]
|
||||||
|
} else {
|
||||||
|
// Get volName from targetPath
|
||||||
|
if !strings.HasSuffix(targetPath, "/mount") {
|
||||||
|
return "", fmt.Errorf("rbd: malformed the value of target path: %s", targetPath)
|
||||||
|
}
|
||||||
|
s := strings.Split(strings.TrimSuffix(targetPath, "/mount"), "/")
|
||||||
|
volName = s[len(s)-1]
|
||||||
|
}
|
||||||
|
return volName, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NodeServer) mountVolume(req *csi.NodePublishVolumeRequest, devicePath string) error {
|
||||||
// Publish Path
|
// Publish Path
|
||||||
fsType := req.GetVolumeCapability().GetMount().GetFsType()
|
fsType := req.GetVolumeCapability().GetMount().GetFsType()
|
||||||
readOnly := req.GetReadonly()
|
readOnly := req.GetReadonly()
|
||||||
attrib := req.GetVolumeContext()
|
attrib := req.GetVolumeContext()
|
||||||
mountFlags := req.GetVolumeCapability().GetMount().GetMountFlags()
|
mountFlags := req.GetVolumeCapability().GetMount().GetMountFlags()
|
||||||
|
isBlock := req.GetVolumeCapability().GetBlock() != nil
|
||||||
|
targetPath := req.GetTargetPath()
|
||||||
|
|
||||||
glog.V(4).Infof("target %v\nisBlock %v\nfstype %v\ndevice %v\nreadonly %v\nattributes %v\n mountflags %v\n",
|
glog.V(4).Infof("target %v\nisBlock %v\nfstype %v\ndevice %v\nreadonly %v\nattributes %v\n mountflags %v\n",
|
||||||
targetPath, isBlock, fsType, devicePath, readOnly, attrib, mountFlags)
|
targetPath, isBlock, fsType, devicePath, readOnly, attrib, mountFlags)
|
||||||
@ -138,7 +137,7 @@ func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
|
|||||||
if isBlock {
|
if isBlock {
|
||||||
options := []string{"bind"}
|
options := []string{"bind"}
|
||||||
if err := diskMounter.Mount(devicePath, targetPath, fsType, options); err != nil {
|
if err := diskMounter.Mount(devicePath, targetPath, fsType, options); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
options := []string{}
|
options := []string{}
|
||||||
@ -147,11 +146,42 @@ func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := diskMounter.FormatAndMount(devicePath, targetPath, fsType, options); err != nil {
|
if err := diskMounter.FormatAndMount(devicePath, targetPath, fsType, options); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NodeServer) createTargetPath(targetPath string, isBlock bool) (bool, error) {
|
||||||
|
// Check if that target path exists properly
|
||||||
|
notMnt, err := ns.mounter.IsNotMountPoint(targetPath)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
if isBlock {
|
||||||
|
// create an empty file
|
||||||
|
// #nosec
|
||||||
|
targetPathFile, e := os.OpenFile(targetPath, os.O_CREATE|os.O_RDWR, 0750)
|
||||||
|
if e != nil {
|
||||||
|
glog.V(4).Infof("Failed to create targetPath:%s with error: %v", targetPath, err)
|
||||||
|
return notMnt, status.Error(codes.Internal, e.Error())
|
||||||
|
}
|
||||||
|
if err = targetPathFile.Close(); err != nil {
|
||||||
|
glog.V(4).Infof("Failed to close targetPath:%s with error: %v", targetPath, err)
|
||||||
|
return notMnt, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Create a directory
|
||||||
|
if err = os.MkdirAll(targetPath, 0750); err != nil {
|
||||||
|
return notMnt, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notMnt = true
|
||||||
|
} else {
|
||||||
|
return false, status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return notMnt, err
|
||||||
|
|
||||||
return &csi.NodePublishVolumeResponse{}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeUnpublishVolume unmounts the volume from the target path
|
// NodeUnpublishVolume unmounts the volume from the target path
|
||||||
@ -230,6 +260,7 @@ func (ns *NodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
func resolveBindMountedBlockDevice(mountPath string) (string, error) {
|
func resolveBindMountedBlockDevice(mountPath string) (string, error) {
|
||||||
|
// #nosec
|
||||||
cmd := exec.Command("findmnt", "-n", "-o", "SOURCE", "--first-only", "--target", mountPath)
|
cmd := exec.Command("findmnt", "-n", "-o", "SOURCE", "--first-only", "--target", mountPath)
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -244,7 +275,7 @@ func parseFindMntResolveSource(out string) (string, error) {
|
|||||||
// cut trailing newline
|
// cut trailing newline
|
||||||
out = strings.TrimSuffix(out, "\n")
|
out = strings.TrimSuffix(out, "\n")
|
||||||
// Check if out is a mounted device
|
// Check if out is a mounted device
|
||||||
reMnt := regexp.MustCompile("^(/[^/]+(?:/[^/]*)*)$")
|
reMnt := regexp.MustCompile(`^(/[^/]+(?:/[^/]*)*)$`)
|
||||||
if match := reMnt.FindStringSubmatch(out); match != nil {
|
if match := reMnt.FindStringSubmatch(out); match != nil {
|
||||||
return match[1], nil
|
return match[1], nil
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ func getRbdDevFromImageAndPool(pool string, image string) (string, bool) {
|
|||||||
name := f.Name()
|
name := f.Name()
|
||||||
// First match pool, then match name.
|
// First match pool, then match name.
|
||||||
poolFile := path.Join(sysPath, name, "pool")
|
poolFile := path.Join(sysPath, name, "pool")
|
||||||
|
// #nosec
|
||||||
poolBytes, err := ioutil.ReadFile(poolFile)
|
poolBytes, err := ioutil.ReadFile(poolFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(4).Infof("error reading %s: %v", poolFile, err)
|
glog.V(4).Infof("error reading %s: %v", poolFile, err)
|
||||||
@ -71,6 +72,7 @@ func getRbdDevFromImageAndPool(pool string, image string) (string, bool) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
imgFile := path.Join(sysPath, name, "name")
|
imgFile := path.Join(sysPath, name, "name")
|
||||||
|
// #nosec
|
||||||
imgBytes, err := ioutil.ReadFile(imgFile)
|
imgBytes, err := ioutil.ReadFile(imgFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(4).Infof("error reading %s: %v", imgFile, err)
|
glog.V(4).Infof("error reading %s: %v", imgFile, err)
|
||||||
@ -140,12 +142,14 @@ func getNbdDevFromImageAndPool(pool string, image string) (string, bool) {
|
|||||||
glog.V(4).Infof("error reading nbd info directory %s: %v", nbdPath, err)
|
glog.V(4).Infof("error reading nbd info directory %s: %v", nbdPath, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// #nosec
|
||||||
pidBytes, err := ioutil.ReadFile(path.Join(nbdPath, "pid"))
|
pidBytes, err := ioutil.ReadFile(path.Join(nbdPath, "pid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(5).Infof("did not find valid pid file in dir %s: %v", nbdPath, err)
|
glog.V(5).Infof("did not find valid pid file in dir %s: %v", nbdPath, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cmdlineFileName := path.Join(hostRootFS, "/proc", strings.TrimSpace(string(pidBytes)), "cmdline")
|
cmdlineFileName := path.Join(hostRootFS, "/proc", strings.TrimSpace(string(pidBytes)), "cmdline")
|
||||||
|
// #nosec
|
||||||
rawCmdline, err := ioutil.ReadFile(cmdlineFileName)
|
rawCmdline, err := ioutil.ReadFile(cmdlineFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(4).Infof("failed to read cmdline file %s: %v", cmdlineFileName, err)
|
glog.V(4).Infof("failed to read cmdline file %s: %v", cmdlineFileName, err)
|
||||||
@ -246,22 +250,11 @@ func attachRBDImage(volOptions *rbdVolume, userID string, credentials map[string
|
|||||||
Factor: rbdImageWatcherFactor,
|
Factor: rbdImageWatcherFactor,
|
||||||
Steps: rbdImageWatcherSteps,
|
Steps: rbdImageWatcherSteps,
|
||||||
}
|
}
|
||||||
err := wait.ExponentialBackoff(backoff, func() (bool, error) {
|
err := waitForrbdImage(backoff, volOptions, userID, credentials)
|
||||||
used, rbdOutput, err := rbdStatus(volOptions, userID, credentials)
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("fail to check rbd image status with: (%v), rbd output: (%s)", err, rbdOutput)
|
|
||||||
}
|
|
||||||
return !used, nil
|
|
||||||
})
|
|
||||||
// return error if rbd image has not become available for the specified timeout
|
|
||||||
if err == wait.ErrWaitTimeout {
|
|
||||||
return "", fmt.Errorf("rbd image %s is still being used", imagePath)
|
|
||||||
}
|
|
||||||
// return error if any other errors were encountered during wating for the image to become available
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
mon, err := getMon(volOptions, credentials)
|
mon, err := getMon(volOptions, credentials)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -287,6 +280,25 @@ func attachRBDImage(volOptions *rbdVolume, userID string, credentials map[string
|
|||||||
return devicePath, nil
|
return devicePath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func waitForrbdImage(backoff wait.Backoff, volOptions *rbdVolume, userID string, credentials map[string]string) error {
|
||||||
|
image := volOptions.VolName
|
||||||
|
imagePath := fmt.Sprintf("%s/%s", volOptions.Pool, image)
|
||||||
|
|
||||||
|
err := wait.ExponentialBackoff(backoff, func() (bool, error) {
|
||||||
|
used, rbdOutput, err := rbdStatus(volOptions, userID, credentials)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("fail to check rbd image status with: (%v), rbd output: (%s)", err, rbdOutput)
|
||||||
|
}
|
||||||
|
return !used, nil
|
||||||
|
})
|
||||||
|
// return error if rbd image has not become available for the specified timeout
|
||||||
|
if err == wait.ErrWaitTimeout {
|
||||||
|
return fmt.Errorf("rbd image %s is still being used", imagePath)
|
||||||
|
}
|
||||||
|
// return error if any other errors were encountered during waiting for the image to become available
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func detachRBDDevice(devicePath string) error {
|
func detachRBDDevice(devicePath string) error {
|
||||||
var err error
|
var err error
|
||||||
var output []byte
|
var output []byte
|
||||||
|
@ -145,7 +145,7 @@ func createRBDImage(pOpts *rbdVolume, volSz int, adminID string, credentials map
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rbdStatus checks if there is watcher on the image.
|
// rbdStatus checks if there is watcher on the image.
|
||||||
// It returns true if there is a watcher onthe image, otherwise returns false.
|
// It returns true if there is a watcher on the image, otherwise returns false.
|
||||||
func rbdStatus(pOpts *rbdVolume, userID string, credentials map[string]string) (bool, string, error) {
|
func rbdStatus(pOpts *rbdVolume, userID string, credentials map[string]string) (bool, string, error) {
|
||||||
var output string
|
var output string
|
||||||
var cmd []byte
|
var cmd []byte
|
||||||
@ -221,6 +221,7 @@ func deleteRBDImage(pOpts *rbdVolume, adminID string, credentials map[string]str
|
|||||||
}
|
}
|
||||||
|
|
||||||
func execCommand(command string, args []string) ([]byte, error) {
|
func execCommand(command string, args []string) ([]byte, error) {
|
||||||
|
// #nosec
|
||||||
cmd := exec.Command(command, args...)
|
cmd := exec.Command(command, args...)
|
||||||
return cmd.CombinedOutput()
|
return cmd.CombinedOutput()
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ var cacheDir = "controller"
|
|||||||
func (nc *NodeCache) EnsureCacheDirectory(cacheDir string) error {
|
func (nc *NodeCache) EnsureCacheDirectory(cacheDir string) error {
|
||||||
fullPath := path.Join(nc.BasePath, cacheDir)
|
fullPath := path.Join(nc.BasePath, cacheDir)
|
||||||
if _, err := os.Stat(fullPath); os.IsNotExist(err) {
|
if _, err := os.Stat(fullPath); os.IsNotExist(err) {
|
||||||
|
// #nosec
|
||||||
if err := os.Mkdir(fullPath, 0755); err != nil {
|
if err := os.Mkdir(fullPath, 0755); err != nil {
|
||||||
return errors.Wrapf(err, "node-cache: failed to create %s folder with error: %v", fullPath, err)
|
return errors.Wrapf(err, "node-cache: failed to create %s folder with error: %v", fullPath, err)
|
||||||
}
|
}
|
||||||
@ -66,6 +67,7 @@ func (nc *NodeCache) ForAll(pattern string, destObj interface{}, f ForAllFunc) e
|
|||||||
if !strings.HasSuffix(file.Name(), ".json") {
|
if !strings.HasSuffix(file.Name(), ".json") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// #nosec
|
||||||
fp, err := os.Open(path.Join(nc.BasePath, cacheDir, file.Name()))
|
fp, err := os.Open(path.Join(nc.BasePath, cacheDir, file.Name()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Infof("node-cache: open file: %s err %v", file.Name(), err)
|
glog.Infof("node-cache: open file: %s err %v", file.Name(), err)
|
||||||
@ -111,6 +113,7 @@ func (nc *NodeCache) Create(identifier string, data interface{}) error {
|
|||||||
// Get retrieves the metadata from cache directory with identifier name
|
// Get retrieves the metadata from cache directory with identifier name
|
||||||
func (nc *NodeCache) Get(identifier string, data interface{}) error {
|
func (nc *NodeCache) Get(identifier string, data interface{}) error {
|
||||||
file := path.Join(nc.BasePath, cacheDir, identifier+".json")
|
file := path.Join(nc.BasePath, cacheDir, identifier+".json")
|
||||||
|
// #nosec
|
||||||
fp, err := os.Open(file)
|
fp, err := os.Open(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "node-cache: open error for %s", file)
|
return errors.Wrapf(err, "node-cache: open error for %s", file)
|
||||||
|
Loading…
Reference in New Issue
Block a user