mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 02:33:34 +00:00
cleanup: remove thick provisioning code
This commit removes the thick provisioning code as thick provisioning is deprecated in cephcsi 3.5.0. fixes: #2795 Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
committed by
mergify[bot]
parent
4ee4fdfebd
commit
28fef9b379
@ -167,13 +167,6 @@ func (rv *rbdVolume) createCloneFromImage(ctx context.Context, parentVol *rbdVol
|
||||
}
|
||||
}
|
||||
|
||||
if rv.ThickProvision {
|
||||
err = rv.setThickProvisioned()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed mark %q thick-provisioned: %w", rv, err)
|
||||
}
|
||||
}
|
||||
|
||||
err = j.StoreImageID(ctx, rv.JournalPool, rv.ReservedID, rv.ImageID)
|
||||
if err != nil {
|
||||
log.ErrorLog(ctx, "failed to store volume %s: %v", rv, err)
|
||||
@ -236,39 +229,27 @@ func (rv *rbdVolume) doSnapClone(ctx context.Context, parentVol *rbdVolume) erro
|
||||
}
|
||||
}()
|
||||
|
||||
if rv.ThickProvision {
|
||||
err = tempClone.DeepCopy(&rv.rbdImage)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to deep copy %q into %q: %w", parentVol, rv, err)
|
||||
}
|
||||
} else {
|
||||
// flatten clone
|
||||
errFlatten = tempClone.flattenRbdImage(ctx, false, rbdHardMaxCloneDepth, rbdSoftMaxCloneDepth)
|
||||
if errFlatten != nil {
|
||||
return errFlatten
|
||||
}
|
||||
// flatten clone
|
||||
errFlatten = tempClone.flattenRbdImage(ctx, false, rbdHardMaxCloneDepth, rbdSoftMaxCloneDepth)
|
||||
if errFlatten != nil {
|
||||
return errFlatten
|
||||
}
|
||||
|
||||
// create snap of temp clone from temporary cloned image
|
||||
// create final clone
|
||||
// delete snap of temp clone
|
||||
errClone = createRBDClone(ctx, tempClone, rv, cloneSnap)
|
||||
if errClone != nil {
|
||||
// set errFlatten error to cleanup temporary snapshot and temporary clone
|
||||
errFlatten = errors.New("failed to create user requested cloned image")
|
||||
// create snap of temp clone from temporary cloned image
|
||||
// create final clone
|
||||
// delete snap of temp clone
|
||||
errClone = createRBDClone(ctx, tempClone, rv, cloneSnap)
|
||||
if errClone != nil {
|
||||
// set errFlatten error to cleanup temporary snapshot and temporary clone
|
||||
errFlatten = errors.New("failed to create user requested cloned image")
|
||||
|
||||
return errClone
|
||||
}
|
||||
return errClone
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rv *rbdVolume) flattenCloneImage(ctx context.Context) error {
|
||||
if rv.ThickProvision {
|
||||
// thick-provisioned images do not need flattening
|
||||
return nil
|
||||
}
|
||||
|
||||
tempClone := rv.generateTempClone()
|
||||
// reducing the limit for cloned images to make sure the limit is in range,
|
||||
// If the intermediate clone reaches the depth we may need to return ABORT
|
||||
|
@ -19,8 +19,6 @@ package rbd
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
csicommon "github.com/ceph/ceph-csi/internal/csi-common"
|
||||
"github.com/ceph/ceph-csi/internal/util"
|
||||
@ -132,8 +130,6 @@ func (cs *ControllerServer) parseVolCreateRequest(
|
||||
return nil, status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
rbdVol.ThickProvision = isThickProvisionRequest(req.GetParameters())
|
||||
|
||||
rbdVol.RequestName = req.GetName()
|
||||
|
||||
// Volume Size - Default is 1 GiB
|
||||
@ -211,11 +207,6 @@ func checkValidCreateVolumeRequest(rbdVol, parentVol *rbdVolume, rbdSnap *rbdSna
|
||||
return status.Errorf(codes.InvalidArgument, "cannot restore from snapshot %s: %s", rbdSnap, err.Error())
|
||||
}
|
||||
|
||||
err = rbdSnap.isCompatibleThickProvision(rbdVol)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.InvalidArgument, "cannot restore from snapshot %s: %s", rbdSnap, err.Error())
|
||||
}
|
||||
|
||||
err = rbdSnap.isCompabitableClone(&rbdVol.rbdImage)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.InvalidArgument, "cannot restore from snapshot %s: %s", rbdSnap, err.Error())
|
||||
@ -227,11 +218,6 @@ func checkValidCreateVolumeRequest(rbdVol, parentVol *rbdVolume, rbdSnap *rbdSna
|
||||
return status.Errorf(codes.InvalidArgument, "cannot clone from volume %s: %s", parentVol, err.Error())
|
||||
}
|
||||
|
||||
err = parentVol.isCompatibleThickProvision(rbdVol)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.InvalidArgument, "cannot clone from volume %s: %s", parentVol, err.Error())
|
||||
}
|
||||
|
||||
err = parentVol.isCompabitableClone(&rbdVol.rbdImage)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.InvalidArgument, "cannot clone from volume %s: %s", parentVol, err.Error())
|
||||
@ -287,7 +273,7 @@ func (cs *ControllerServer) CreateVolume(
|
||||
if err != nil {
|
||||
return nil, getGRPCErrorForCreateVolume(err)
|
||||
} else if found {
|
||||
return cs.repairExistingVolume(ctx, req, cr, rbdVol, parentVol, rbdSnap)
|
||||
return cs.repairExistingVolume(ctx, req, cr, rbdVol, rbdSnap)
|
||||
}
|
||||
|
||||
err = checkValidCreateVolumeRequest(rbdVol, parentVol, rbdSnap)
|
||||
@ -352,50 +338,12 @@ func flattenParentImage(ctx context.Context, rbdVol *rbdVolume, cr *util.Credent
|
||||
// that the state is corrected to what was requested. It is needed to call this
|
||||
// when the process of creating a volume was interrupted.
|
||||
func (cs *ControllerServer) repairExistingVolume(ctx context.Context, req *csi.CreateVolumeRequest,
|
||||
cr *util.Credentials, rbdVol, parentVol *rbdVolume, rbdSnap *rbdSnapshot) (*csi.CreateVolumeResponse, error) {
|
||||
cr *util.Credentials, rbdVol *rbdVolume, rbdSnap *rbdSnapshot) (*csi.CreateVolumeResponse, error) {
|
||||
vcs := req.GetVolumeContentSource()
|
||||
|
||||
switch {
|
||||
// normal CreateVolume without VolumeContentSource
|
||||
case vcs == nil:
|
||||
// continue/restart allocating the volume in case it
|
||||
// should be thick-provisioned
|
||||
if isThickProvisionRequest(req.GetParameters()) {
|
||||
err := rbdVol.RepairThickProvision()
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
}
|
||||
// rbdVol is a restore from snapshot, rbdSnap is passed
|
||||
case vcs.GetSnapshot() != nil:
|
||||
// When restoring of a thick-provisioned volume was happening,
|
||||
// the image should be marked as thick-provisioned, unless it
|
||||
// was aborted in flight. In order to restart the
|
||||
// thick-restoring, delete the volume and let the caller retry
|
||||
// from the start.
|
||||
if isThickProvisionRequest(req.GetParameters()) {
|
||||
thick, err := rbdVol.isThickProvisioned()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(
|
||||
codes.Aborted,
|
||||
"failed to verify thick-provisioned volume %q: %s",
|
||||
rbdVol,
|
||||
err)
|
||||
} else if !thick {
|
||||
err = rbdVol.deleteImage(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Aborted, "failed to remove partially cloned volume %q: %s", rbdVol, err)
|
||||
}
|
||||
err = undoVolReservation(ctx, rbdVol, cr)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Aborted, "failed to remove volume %q from journal: %s", rbdVol, err)
|
||||
}
|
||||
|
||||
return nil, status.Errorf(
|
||||
codes.Aborted,
|
||||
"restoring thick-provisioned volume %q has been interrupted, please retry", rbdVol)
|
||||
}
|
||||
}
|
||||
// restore from snapshot implies rbdSnap != nil
|
||||
// check if image depth is reached limit and requires flatten
|
||||
err := checkFlatten(ctx, rbdVol, cr)
|
||||
@ -418,23 +366,6 @@ func (cs *ControllerServer) repairExistingVolume(ctx context.Context, req *csi.C
|
||||
|
||||
// rbdVol is a clone from parentVol
|
||||
case vcs.GetVolume() != nil:
|
||||
// When cloning into a thick-provisioned volume was happening,
|
||||
// the image should be marked as thick-provisioned, unless it
|
||||
// was aborted in flight. In order to restart the
|
||||
// thick-cloning, delete the volume and undo the reservation in
|
||||
// the journal to let the caller retry from the start.
|
||||
if isThickProvisionRequest(req.GetParameters()) {
|
||||
thick, err := rbdVol.isThickProvisioned()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(
|
||||
codes.Internal,
|
||||
"failed to verify thick-provisioned volume %q: %s",
|
||||
rbdVol,
|
||||
err)
|
||||
} else if !thick {
|
||||
return nil, cleanupThickClone(ctx, parentVol, rbdVol, rbdSnap, cr)
|
||||
}
|
||||
}
|
||||
// expand the image if the requested size is greater than the current size
|
||||
err := rbdVol.expand()
|
||||
if err != nil {
|
||||
@ -447,26 +378,6 @@ func (cs *ControllerServer) repairExistingVolume(ctx context.Context, req *csi.C
|
||||
return buildCreateVolumeResponse(req, rbdVol), nil
|
||||
}
|
||||
|
||||
// cleanupThickClone will delete the snapshot and volume and undo the reservation.
|
||||
func cleanupThickClone(ctx context.Context,
|
||||
rbdVol,
|
||||
parentVol *rbdVolume,
|
||||
rbdSnap *rbdSnapshot,
|
||||
cr *util.Credentials) error {
|
||||
err := cleanUpSnapshot(ctx, parentVol, rbdSnap, rbdVol)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "failed to remove partially cloned volume %q: %s", rbdVol, err)
|
||||
}
|
||||
err = undoVolReservation(ctx, rbdVol, cr)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "failed to remove volume %q from journal: %s", rbdVol, err)
|
||||
}
|
||||
|
||||
return status.Errorf(
|
||||
codes.Internal,
|
||||
"cloning thick-provisioned volume %q has been interrupted, please retry", rbdVol)
|
||||
}
|
||||
|
||||
// check snapshots on the rbd image, as we have limit from krbd that an image
|
||||
// cannot have more than 510 snapshot at a given point of time. If the
|
||||
// snapshots are more than the `maxSnapshotsOnImage` Add a task to flatten all
|
||||
@ -474,11 +385,6 @@ func cleanupThickClone(ctx context.Context,
|
||||
// are more than the `minSnapshotOnImage` Add a task to flatten all the
|
||||
// temporary cloned images.
|
||||
func flattenTemporaryClonedImages(ctx context.Context, rbdVol *rbdVolume, cr *util.Credentials) error {
|
||||
if rbdVol.ThickProvision {
|
||||
// thick-provisioned images do not need flattening
|
||||
return nil
|
||||
}
|
||||
|
||||
snaps, err := rbdVol.listSnapshots()
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrImageNotFound) {
|
||||
@ -592,27 +498,12 @@ func (cs *ControllerServer) createVolumeFromSnapshot(
|
||||
// as we are operating on single cluster reuse the connection
|
||||
parentVol.conn = rbdVol.conn.Copy()
|
||||
|
||||
if rbdVol.ThickProvision {
|
||||
err = parentVol.DeepCopy(&rbdVol.rbdImage)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "failed to deep copy %q into %q: %v", parentVol, rbdVol, err)
|
||||
}
|
||||
err = rbdVol.setThickProvisioned()
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "failed to mark %q thick-provisioned: %s", rbdVol, err)
|
||||
}
|
||||
err = parentVol.copyEncryptionConfig(&rbdVol.rbdImage, true)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, err.Error())
|
||||
}
|
||||
} else {
|
||||
// create clone image and delete snapshot
|
||||
err = rbdVol.cloneRbdImageFromSnapshot(ctx, rbdSnap, parentVol)
|
||||
if err != nil {
|
||||
log.ErrorLog(ctx, "failed to clone rbd image %s from snapshot %s: %v", rbdVol, rbdSnap, err)
|
||||
// create clone image and delete snapshot
|
||||
err = rbdVol.cloneRbdImageFromSnapshot(ctx, rbdSnap, parentVol)
|
||||
if err != nil {
|
||||
log.ErrorLog(ctx, "failed to clone rbd image %s from snapshot %s: %v", rbdVol, rbdSnap, err)
|
||||
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
log.DebugLog(ctx, "create volume %s from snapshot %s", rbdVol, rbdSnap)
|
||||
@ -1136,31 +1027,6 @@ func cloneFromSnapshot(
|
||||
}
|
||||
}
|
||||
|
||||
// The clone image created during CreateSnapshot has to be marked as thick.
|
||||
// As snapshot and volume both are independent we cannot depend on the
|
||||
// parent volume of the clone to check thick provision during CreateVolume
|
||||
// from snapshot operation because the parent volume can be deleted anytime
|
||||
// after snapshot is created.
|
||||
// TODO: copy thick provision config
|
||||
thick, err := rbdVol.isThickProvisioned()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed checking thick-provisioning of %q: %s", rbdVol, err)
|
||||
}
|
||||
|
||||
if thick {
|
||||
// check the thick metadata is already set on the clone image.
|
||||
thick, err = vol.isThickProvisioned()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed checking thick-provisioning of %q: %s", vol, err)
|
||||
}
|
||||
if !thick {
|
||||
err = vol.setThickProvisioned()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed mark %q thick-provisioned: %s", vol, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = vol.flattenRbdImage(ctx, false, rbdHardMaxCloneDepth, rbdSoftMaxCloneDepth)
|
||||
if errors.Is(err, ErrFlattenInProgress) {
|
||||
// if flattening is in progress, return error and do not cleanup
|
||||
@ -1258,30 +1124,13 @@ func (cs *ControllerServer) doSnapshotClone(
|
||||
}
|
||||
}
|
||||
|
||||
// The clone image created during CreateSnapshot has to be marked as thick.
|
||||
// As snapshot and volume both are independent we cannot depend on the
|
||||
// parent volume of the clone to check thick provision during CreateVolume
|
||||
// from snapshot operation because the parent volume can be deleted anytime
|
||||
// after snapshot is created.
|
||||
thick, err := parentVol.isThickProvisioned()
|
||||
err = cloneRbd.createSnapshot(ctx, rbdSnap)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed checking thick-provisioning of %q: %w", parentVol, err)
|
||||
}
|
||||
// update rbd image name for logging
|
||||
rbdSnap.RbdImageName = cloneRbd.RbdImageName
|
||||
log.ErrorLog(ctx, "failed to create snapshot %s: %v", rbdSnap, err)
|
||||
|
||||
if thick {
|
||||
err = cloneRbd.setThickProvisioned()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed mark %q thick-provisioned: %w", cloneRbd, err)
|
||||
}
|
||||
} else {
|
||||
err = cloneRbd.createSnapshot(ctx, rbdSnap)
|
||||
if err != nil {
|
||||
// update rbd image name for logging
|
||||
rbdSnap.RbdImageName = cloneRbd.RbdImageName
|
||||
log.ErrorLog(ctx, "failed to create snapshot %s: %v", rbdSnap, err)
|
||||
|
||||
return cloneRbd, err
|
||||
}
|
||||
return cloneRbd, err
|
||||
}
|
||||
|
||||
err = cloneRbd.getImageID()
|
||||
@ -1542,31 +1391,3 @@ func (cs *ControllerServer) ControllerExpandVolume(
|
||||
NodeExpansionRequired: nodeExpansion,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// logThickProvisioningDeprecation makes sure the deprecation warning about
|
||||
// thick-provisining is logged only once.
|
||||
var logThickProvisioningDeprecation = true
|
||||
|
||||
// isThickProvisionRequest returns true in case the request contains the
|
||||
// `thickProvision` option set to `true`.
|
||||
func isThickProvisionRequest(parameters map[string]string) bool {
|
||||
tp := "thickProvision"
|
||||
|
||||
thick, ok := parameters[tp]
|
||||
if !ok || thick == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
thickBool, err := strconv.ParseBool(thick)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if logThickProvisioningDeprecation {
|
||||
log.WarningLogMsg("thick-provisioning is deprecated and will " +
|
||||
"be removed in a future release")
|
||||
logThickProvisioningDeprecation = false
|
||||
}
|
||||
|
||||
return thickBool
|
||||
}
|
||||
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 The Ceph-CSI Authors.
|
||||
|
||||
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 rbd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
)
|
||||
|
||||
func TestIsThickProvisionRequest(t *testing.T) {
|
||||
t.Parallel()
|
||||
req := &csi.CreateVolumeRequest{
|
||||
Name: "fake",
|
||||
Parameters: map[string]string{
|
||||
"unkownOption": "not-set",
|
||||
},
|
||||
}
|
||||
|
||||
// pass disabled/invalid values for "thickProvision" option
|
||||
if isThickProvisionRequest(req.GetParameters()) {
|
||||
t.Error("request is not for thick-provisioning")
|
||||
}
|
||||
|
||||
req.Parameters["thickProvision"] = ""
|
||||
if isThickProvisionRequest(req.GetParameters()) {
|
||||
t.Errorf("request is not for thick-provisioning: %s", req.Parameters["thickProvision"])
|
||||
}
|
||||
|
||||
req.Parameters["thickProvision"] = "false"
|
||||
if isThickProvisionRequest(req.GetParameters()) {
|
||||
t.Errorf("request is not for thick-provisioning: %s", req.Parameters["thickProvision"])
|
||||
}
|
||||
|
||||
req.Parameters["thickProvision"] = "off"
|
||||
if isThickProvisionRequest(req.GetParameters()) {
|
||||
t.Errorf("request is not for thick-provisioning: %s", req.Parameters["thickProvision"])
|
||||
}
|
||||
|
||||
req.Parameters["thickProvision"] = "no"
|
||||
if isThickProvisionRequest(req.GetParameters()) {
|
||||
t.Errorf("request is not for thick-provisioning: %s", req.Parameters["thickProvision"])
|
||||
}
|
||||
|
||||
req.Parameters["thickProvision"] = "**true**"
|
||||
if isThickProvisionRequest(req.GetParameters()) {
|
||||
t.Errorf("request is not for thick-provisioning: %s", req.Parameters["thickProvision"])
|
||||
}
|
||||
|
||||
// only "true" should enable thick provisioning
|
||||
req.Parameters["thickProvision"] = "true"
|
||||
if !isThickProvisionRequest(req.GetParameters()) {
|
||||
t.Errorf("request should be for thick-provisioning: %s", req.Parameters["thickProvision"])
|
||||
}
|
||||
}
|
@ -178,7 +178,6 @@ func populateRbdVol(
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
rv.ThickProvision = isThickProvisionRequest(req.GetVolumeContext())
|
||||
isStaticVol := parseBoolOption(ctx, req.GetVolumeContext(), staticVol, false)
|
||||
// get rbd image name from the volume journal
|
||||
// for static volumes, the image name is actually the volume ID itself
|
||||
|
@ -310,7 +310,7 @@ func attachRBDImage(ctx context.Context, volOptions *rbdVolume, device string, c
|
||||
return devicePath, err
|
||||
}
|
||||
|
||||
func appendNbdDeviceTypeAndOptions(cmdArgs []string, isThick bool, userOptions, cookie string) []string {
|
||||
func appendNbdDeviceTypeAndOptions(cmdArgs []string, userOptions, cookie string) []string {
|
||||
cmdArgs = append(cmdArgs, "--device-type", accessTypeNbd)
|
||||
|
||||
isUnmap := CheckSliceContains(cmdArgs, "unmap")
|
||||
@ -328,12 +328,6 @@ func appendNbdDeviceTypeAndOptions(cmdArgs []string, isThick bool, userOptions,
|
||||
if hasNBDCookieSupport {
|
||||
cmdArgs = append(cmdArgs, "--options", fmt.Sprintf("cookie=%s", cookie))
|
||||
}
|
||||
|
||||
if isThick {
|
||||
// When an image is thick-provisioned, any discard/unmap/trim
|
||||
// requests should not free extents.
|
||||
cmdArgs = append(cmdArgs, "--options", "notrim")
|
||||
}
|
||||
}
|
||||
|
||||
if userOptions != "" {
|
||||
@ -345,22 +339,11 @@ func appendNbdDeviceTypeAndOptions(cmdArgs []string, isThick bool, userOptions,
|
||||
return cmdArgs
|
||||
}
|
||||
|
||||
func appendKRbdDeviceTypeAndOptions(cmdArgs []string, isThick bool, userOptions string) []string {
|
||||
cmdArgs = append(cmdArgs, "--device-type", accessTypeKRbd)
|
||||
|
||||
isUnmap := CheckSliceContains(cmdArgs, "unmap")
|
||||
if !isUnmap {
|
||||
if isThick {
|
||||
// When an image is thick-provisioned, any discard/unmap/trim
|
||||
// requests should not free extents.
|
||||
cmdArgs = append(cmdArgs, "--options", "notrim")
|
||||
}
|
||||
}
|
||||
|
||||
func appendKRbdDeviceTypeAndOptions(cmdArgs []string, userOptions string) []string {
|
||||
// Enable mapping and unmapping images from a non-initial network
|
||||
// namespace (e.g. for Multus CNI). The network namespace must be
|
||||
// owned by the initial user namespace.
|
||||
cmdArgs = append(cmdArgs, "--options", "noudev")
|
||||
cmdArgs = append(cmdArgs, "--device-type", accessTypeKRbd, "--options", "noudev")
|
||||
|
||||
if userOptions != "" {
|
||||
// userOptions is appended after, possibly overriding the above
|
||||
@ -413,12 +396,6 @@ func createPath(ctx context.Context, volOpt *rbdVolume, device string, cr *util.
|
||||
isNbd = true
|
||||
}
|
||||
|
||||
// check if the image should stay thick-provisioned
|
||||
isThick, err := volOpt.isThickProvisioned()
|
||||
if err != nil {
|
||||
log.WarningLog(ctx, "failed to detect if image %q is thick-provisioned: %v", volOpt, err)
|
||||
}
|
||||
|
||||
if isNbd {
|
||||
mapArgs = append(mapArgs, "--log-file",
|
||||
getCephClientLogFileName(volOpt.VolID, volOpt.LogDir, "rbd-nbd"))
|
||||
@ -433,9 +410,9 @@ func createPath(ctx context.Context, volOpt *rbdVolume, device string, cr *util.
|
||||
} else {
|
||||
mapArgs = append(mapArgs, "map", imagePath)
|
||||
if isNbd {
|
||||
mapArgs = appendNbdDeviceTypeAndOptions(mapArgs, isThick, volOpt.MapOptions, volOpt.VolID)
|
||||
mapArgs = appendNbdDeviceTypeAndOptions(mapArgs, volOpt.MapOptions, volOpt.VolID)
|
||||
} else {
|
||||
mapArgs = appendKRbdDeviceTypeAndOptions(mapArgs, isThick, volOpt.MapOptions)
|
||||
mapArgs = appendKRbdDeviceTypeAndOptions(mapArgs, volOpt.MapOptions)
|
||||
}
|
||||
}
|
||||
|
||||
@ -543,9 +520,9 @@ func detachRBDImageOrDeviceSpec(
|
||||
|
||||
unmapArgs := []string{"unmap", dArgs.imageOrDeviceSpec}
|
||||
if dArgs.isNbd {
|
||||
unmapArgs = appendNbdDeviceTypeAndOptions(unmapArgs, false, dArgs.unmapOptions, dArgs.volumeID)
|
||||
unmapArgs = appendNbdDeviceTypeAndOptions(unmapArgs, dArgs.unmapOptions, dArgs.volumeID)
|
||||
} else {
|
||||
unmapArgs = appendKRbdDeviceTypeAndOptions(unmapArgs, false, dArgs.unmapOptions)
|
||||
unmapArgs = appendKRbdDeviceTypeAndOptions(unmapArgs, dArgs.unmapOptions)
|
||||
}
|
||||
|
||||
_, stderr, err := util.ExecCommand(ctx, rbd, unmapArgs...)
|
||||
|
@ -58,18 +58,6 @@ const (
|
||||
rbdTaskRemoveCmdInvalidString = "No handler found"
|
||||
rbdTaskRemoveCmdAccessDeniedMessage = "access denied:"
|
||||
|
||||
// image metadata key for thick-provisioning.
|
||||
// As image metadata key starting with '.rbd' will not be copied when we do
|
||||
// clone or mirroring, deprecating the old key for the same reason use
|
||||
// 'thickProvisionMetaKey' to set image metadata.
|
||||
deprecatedthickProvisionMetaKey = ".rbd.csi.ceph.com/thick-provisioned"
|
||||
thickProvisionMetaKey = "rbd.csi.ceph.com/thick-provisioned"
|
||||
|
||||
// these are the metadata set on the image to identify the image is
|
||||
// thick provisioned or thin provisioned.
|
||||
thickProvisionMetaData = "true"
|
||||
thinProvisionMetaData = "false"
|
||||
|
||||
// migration label key and value for parameters in volume context.
|
||||
intreeMigrationKey = "migration"
|
||||
intreeMigrationLabel = "true"
|
||||
@ -173,7 +161,6 @@ type rbdVolume struct {
|
||||
RequestedVolSize int64
|
||||
DisableInUseChecks bool
|
||||
readOnly bool
|
||||
ThickProvision bool
|
||||
}
|
||||
|
||||
// rbdSnapshot represents a CSI snapshot and its RBD snapshot specifics.
|
||||
@ -382,26 +369,6 @@ func createImage(ctx context.Context, pOpts *rbdVolume, cr *util.Credentials) er
|
||||
}
|
||||
}
|
||||
|
||||
if pOpts.ThickProvision {
|
||||
err = pOpts.allocate(0)
|
||||
if err != nil {
|
||||
// nolint:errcheck // deleteImage() will log errors in
|
||||
// case it fails, no need to log them here again
|
||||
_ = pOpts.deleteImage(ctx)
|
||||
|
||||
return fmt.Errorf("failed to thick provision image: %w", err)
|
||||
}
|
||||
|
||||
err = pOpts.setThickProvisioned()
|
||||
if err != nil {
|
||||
// nolint:errcheck // deleteImage() will log errors in
|
||||
// case it fails, no need to log them here again
|
||||
_ = pOpts.deleteImage(ctx)
|
||||
|
||||
return fmt.Errorf("failed to mark image as thick-provisioned: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -465,82 +432,6 @@ func (ri *rbdImage) open() (*librbd.Image, error) {
|
||||
return image, nil
|
||||
}
|
||||
|
||||
// allocate uses the stripe-period of the image to fully allocate (thick
|
||||
// provision) the image.
|
||||
func (ri *rbdImage) allocate(offset uint64) error {
|
||||
// We do not want to call discard, we really want to write zeros to get
|
||||
// the allocation. This sets the option for the re-used connection, and
|
||||
// all subsequent images that are opened. That is not a problem, as
|
||||
// this is the only place images get written.
|
||||
err := ri.conn.DisableDiscardOnZeroedWriteSame()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
image, err := ri.open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer image.Close()
|
||||
|
||||
st, err := image.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sc, err := image.GetStripeCount()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// blockSize is the stripe-period: size of the object-size multiplied
|
||||
// by the stripe-count
|
||||
blockSize := sc * (1 << st.Order)
|
||||
zeroBlock := make([]byte, blockSize)
|
||||
|
||||
// the actual size of the image as available in the pool, can be
|
||||
// marginally different from the requested image size
|
||||
size := st.Size - offset
|
||||
|
||||
// In case the remaining space on the volume is smaller than blockSize,
|
||||
// write a partial block with WriteAt() after this loop.
|
||||
for size > blockSize {
|
||||
writeSize := size
|
||||
// write a maximum of 1GB per WriteSame() call
|
||||
if size > helpers.GiB {
|
||||
writeSize = helpers.GiB
|
||||
}
|
||||
|
||||
// round down to the size of a zeroBlock
|
||||
if (writeSize % blockSize) != 0 {
|
||||
writeSize = (writeSize / blockSize) * blockSize
|
||||
}
|
||||
|
||||
_, err = image.WriteSame(offset, writeSize, zeroBlock,
|
||||
rados.OpFlagNone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to allocate %d/%d bytes at "+
|
||||
"offset %d: %w", writeSize, blockSize, offset, err)
|
||||
}
|
||||
|
||||
// write succeeded
|
||||
size -= writeSize
|
||||
offset += writeSize
|
||||
}
|
||||
|
||||
// write the last remaining bytes, in case the image size can not be
|
||||
// written with the optimal blockSize
|
||||
if size != 0 {
|
||||
_, err = image.WriteAt(zeroBlock[:size], int64(offset))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to allocate %d bytes at "+
|
||||
"offset %d: %w", size, offset, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isInUse checks if there is a watcher on the image. It returns true if there
|
||||
// is a watcher on the image, otherwise returns false.
|
||||
func (ri *rbdImage) isInUse() (bool, error) {
|
||||
@ -1710,40 +1601,10 @@ func (ri *rbdImage) resize(newSize int64) error {
|
||||
}
|
||||
defer image.Close()
|
||||
|
||||
thick, err := ri.isThickProvisioned()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// offset is used to track from where on the expansion is done, so that
|
||||
// the extents can be allocated in case the image is thick-provisioned
|
||||
var offset uint64
|
||||
if thick {
|
||||
st, statErr := image.Stat()
|
||||
if statErr != nil {
|
||||
return statErr
|
||||
}
|
||||
|
||||
offset = st.Size
|
||||
}
|
||||
|
||||
err = image.Resize(uint64(util.RoundOffVolSize(newSize) * helpers.MiB))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if thick {
|
||||
err = ri.allocate(offset)
|
||||
if err != nil {
|
||||
resizeErr := image.Resize(offset)
|
||||
if resizeErr != nil {
|
||||
err = fmt.Errorf("failed to shrink image (%v) after failed allocation: %w", resizeErr, err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// update Volsize of rbdVolume object to newSize.
|
||||
ri.VolSize = newSize
|
||||
|
||||
@ -1820,71 +1681,6 @@ func (ri *rbdImage) MigrateMetadata(oldKey, newKey, defaultValue string) (string
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// setThickProvisioned records in the image metadata that it has been
|
||||
// thick-provisioned.
|
||||
func (ri *rbdImage) setThickProvisioned() error {
|
||||
err := ri.SetMetadata(thickProvisionMetaKey, thickProvisionMetaData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set metadata %q for %q: %w", thickProvisionMetaKey, ri, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isThickProvisioned checks in the image metadata if the image has been marked
|
||||
// as thick-provisioned. This can be used while expanding the image, so that
|
||||
// the expansion can be allocated too.
|
||||
func (ri *rbdImage) isThickProvisioned() (bool, error) {
|
||||
value, err := ri.MigrateMetadata(deprecatedthickProvisionMetaKey, thickProvisionMetaKey, thinProvisionMetaData)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get metadata %q for %q: %w", thickProvisionMetaKey, ri, err)
|
||||
}
|
||||
|
||||
thick, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to convert %q=%q to a boolean: %w", thickProvisionMetaKey, value, err)
|
||||
}
|
||||
|
||||
return thick, nil
|
||||
}
|
||||
|
||||
// RepairThickProvision writes zero bytes to the volume so that it will be
|
||||
// completely allocated. In case the volume is already marked as
|
||||
// thick-provisioned, nothing will be done.
|
||||
func (ri *rbdImage) RepairThickProvision() error {
|
||||
// if the image has the thick-provisioned metadata, it has been fully
|
||||
// allocated
|
||||
done, err := ri.isThickProvisioned()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to repair thick-provisioning of %q: %w", ri, err)
|
||||
} else if done {
|
||||
return nil
|
||||
}
|
||||
|
||||
// in case there are watchers, assume allocating is still happening in
|
||||
// the background (by an other process?)
|
||||
background, err := ri.isInUse()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get users of %q: %w", ri, err)
|
||||
} else if background {
|
||||
return fmt.Errorf("not going to restart thick-provisioning of in-use image %q", ri)
|
||||
}
|
||||
|
||||
// TODO: can this be improved by starting at the offset where
|
||||
// allocating was aborted/restarted?
|
||||
err = ri.allocate(0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to continue thick-provisioning of %q: %w", ri, err)
|
||||
}
|
||||
|
||||
err = ri.setThickProvisioned()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to continue thick-provisioning of %q: %w", ri, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopy creates an independent image (dest) from the source image. This
|
||||
// process may take some time when the image is large.
|
||||
func (ri *rbdImage) DeepCopy(dest *rbdImage) error {
|
||||
@ -2004,50 +1800,6 @@ func (ri *rbdImage) isCompabitableClone(dst *rbdImage) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ri *rbdImage) isCompatibleThickProvision(dst *rbdVolume) error {
|
||||
thick, err := ri.isThickProvisioned()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch {
|
||||
case thick && !dst.ThickProvision:
|
||||
return fmt.Errorf("cannot create thin volume from thick volume %q", ri)
|
||||
|
||||
case !thick && dst.ThickProvision:
|
||||
return fmt.Errorf("cannot create thick volume from thin volume %q", ri)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FIXME: merge isCompatibleThickProvision of rbdSnapshot and rbdImage to a single
|
||||
// function.
|
||||
func (rs *rbdSnapshot) isCompatibleThickProvision(dst *rbdVolume) error {
|
||||
// During CreateSnapshot the rbd image will be created with the
|
||||
// snapshot name. Replacing RbdImageName with RbdSnapName so that we
|
||||
// can check if the image is thick provisioned
|
||||
vol := generateVolFromSnap(rs)
|
||||
err := vol.Connect(rs.conn.Creds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer vol.Destroy()
|
||||
|
||||
thick, err := vol.isThickProvisioned()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch {
|
||||
case thick && !dst.ThickProvision:
|
||||
return fmt.Errorf("cannot create thin volume from thick volume %q", vol)
|
||||
|
||||
case !thick && dst.ThickProvision:
|
||||
return fmt.Errorf("cannot create thick volume from thin volume %q", vol)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ri *rbdImage) addSnapshotScheduling(
|
||||
interval admin.Interval,
|
||||
startTime admin.StartTime) error {
|
||||
|
Reference in New Issue
Block a user