rbd: Add new methods to generate spec strings

Refactor lots of string concatenation using the Stringer
implementation for each type.

Signed-off-by: Mehdy Khoshnoody <mehdy.khoshnoody@gmail.com>
This commit is contained in:
Mehdy Khoshnoody 2020-05-28 23:09:44 +04:30 committed by mergify[bot]
parent ed30fa19d4
commit c0361c47d6
4 changed files with 96 additions and 111 deletions

View File

@ -231,10 +231,10 @@ func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
err = rbdVol.ensureEncryptionMetadataSet(rbdImageRequiresEncryption) err = rbdVol.ensureEncryptionMetadataSet(rbdImageRequiresEncryption)
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "failed to save encryption status, deleting image %s: %s"), klog.Errorf(util.Log(ctx, "failed to save encryption status, deleting image %s: %s"),
rbdVol.RbdImageName, err) rbdVol, err)
if deleteErr := deleteImage(ctx, rbdVol, cr); deleteErr != nil { if deleteErr := deleteImage(ctx, rbdVol, cr); deleteErr != nil {
klog.Errorf(util.Log(ctx, "failed to delete rbd image: %s/%s with error: %v"), klog.Errorf(util.Log(ctx, "failed to delete rbd image: %s with error: %v"),
rbdVol.Pool, rbdVol.RbdImageName, deleteErr) rbdVol, deleteErr)
return nil, deleteErr return nil, deleteErr
} }
return nil, err return nil, err
@ -452,8 +452,8 @@ func (cs *ControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
// Deleting rbd image // Deleting rbd image
klog.V(4).Infof(util.Log(ctx, "deleting image %s"), rbdVol.RbdImageName) klog.V(4).Infof(util.Log(ctx, "deleting image %s"), rbdVol.RbdImageName)
if err = deleteImage(ctx, rbdVol, cr); err != nil { if err = deleteImage(ctx, rbdVol, cr); err != nil {
klog.Errorf(util.Log(ctx, "failed to delete rbd image: %s/%s with error: %v"), klog.Errorf(util.Log(ctx, "failed to delete rbd image: %s with error: %v"),
rbdVol.Pool, rbdVol.RbdImageName, err) rbdVol, err)
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
@ -740,16 +740,15 @@ func (cs *ControllerServer) DeleteSnapshot(ctx context.Context, req *csi.DeleteS
err = unprotectSnapshot(ctx, rbdSnap, cr) err = unprotectSnapshot(ctx, rbdSnap, cr)
if err != nil { if err != nil {
return nil, status.Errorf(codes.FailedPrecondition, return nil, status.Errorf(codes.FailedPrecondition,
"failed to unprotect snapshot: %s/%s with error: %v", "failed to unprotect snapshot: %s with error: %v",
rbdSnap.Pool, rbdSnap.RbdSnapName, err) rbdSnap, err)
} }
// Deleting snapshot // Deleting snapshot
klog.V(4).Infof(util.Log(ctx, "deleting Snaphot %s"), rbdSnap.RbdSnapName) klog.V(4).Infof(util.Log(ctx, "deleting Snaphot %s"), rbdSnap)
if err := deleteSnapshot(ctx, rbdSnap, cr); err != nil { if err := deleteSnapshot(ctx, rbdSnap, cr); err != nil {
return nil, status.Errorf(codes.FailedPrecondition, return nil, status.Errorf(codes.FailedPrecondition,
"failed to delete snapshot: %s/%s with error: %v", "failed to delete snapshot: %s with error: %v", rbdSnap, err)
rbdSnap.Pool, rbdSnap.RbdSnapName, err)
} }
return &csi.DeleteSnapshotResponse{}, nil return &csi.DeleteSnapshotResponse{}, nil
@ -801,8 +800,8 @@ func (cs *ControllerServer) ControllerExpandVolume(ctx context.Context, req *csi
defer rbdVol.Destroy() defer rbdVol.Destroy()
if rbdVol.Encrypted { if rbdVol.Encrypted {
return nil, status.Errorf(codes.InvalidArgument, "encrypted volumes do not support resize (%s/%s)", return nil, status.Errorf(codes.InvalidArgument, "encrypted volumes do not support resize (%s)",
rbdVol.Pool, rbdVol.RbdImageName) rbdVol)
} }
// always round up the request size in bytes to the nearest MiB/GiB // always round up the request size in bytes to the nearest MiB/GiB
@ -811,12 +810,12 @@ func (cs *ControllerServer) ControllerExpandVolume(ctx context.Context, req *csi
// resize volume if required // resize volume if required
nodeExpansion := false nodeExpansion := false
if rbdVol.VolSize < volSize { if rbdVol.VolSize < volSize {
klog.V(4).Infof(util.Log(ctx, "rbd volume %s/%s size is %v,resizing to %v"), rbdVol.Pool, rbdVol.RbdImageName, rbdVol.VolSize, volSize) klog.V(4).Infof(util.Log(ctx, "rbd volume %s size is %v,resizing to %v"), rbdVol, rbdVol.VolSize, volSize)
rbdVol.VolSize = volSize rbdVol.VolSize = volSize
nodeExpansion = true nodeExpansion = true
err = resizeRBDImage(rbdVol, cr) err = resizeRBDImage(rbdVol, cr)
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "failed to resize rbd image: %s/%s with error: %v"), rbdVol.Pool, rbdVol.RbdImageName, err) klog.Errorf(util.Log(ctx, "failed to resize rbd image: %s with error: %v"), rbdVol, err)
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
} }

View File

@ -623,7 +623,7 @@ func (ns *NodeServer) NodeUnstageVolume(ctx context.Context, req *csi.NodeUnstag
} }
// Unmapping rbd device // Unmapping rbd device
imageSpec := imgInfo.Pool + "/" + imgInfo.ImageName imageSpec := imgInfo.String()
if err = detachRBDImageOrDeviceSpec(ctx, imageSpec, true, imgInfo.NbdAccess, imgInfo.Encrypted, req.GetVolumeId()); err != nil { if err = detachRBDImageOrDeviceSpec(ctx, imageSpec, true, imgInfo.NbdAccess, imgInfo.Encrypted, req.GetVolumeId()); err != nil {
klog.Errorf(util.Log(ctx, "error unmapping volume (%s) from staging path (%s): (%v)"), req.GetVolumeId(), stagingTargetPath, err) klog.Errorf(util.Log(ctx, "error unmapping volume (%s) from staging path (%s): (%v)"), req.GetVolumeId(), stagingTargetPath, err)
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
@ -730,7 +730,7 @@ func (ns *NodeServer) NodeGetCapabilities(ctx context.Context, req *csi.NodeGetC
} }
func (ns *NodeServer) processEncryptedDevice(ctx context.Context, volOptions *rbdVolume, devicePath string) (string, error) { func (ns *NodeServer) processEncryptedDevice(ctx context.Context, volOptions *rbdVolume, devicePath string) (string, error) {
imageSpec := volOptions.Pool + "/" + volOptions.RbdImageName imageSpec := volOptions.String()
encrypted, err := volOptions.checkRbdImageEncrypted(ctx) encrypted, err := volOptions.checkRbdImageEncrypted(ctx)
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "failed to get encryption status for rbd image %s: %v"), klog.Errorf(util.Log(ctx, "failed to get encryption status for rbd image %s: %v"),
@ -780,13 +780,13 @@ func (ns *NodeServer) processEncryptedDevice(ctx context.Context, volOptions *rb
func encryptDevice(ctx context.Context, rbdVol *rbdVolume, devicePath string) error { func encryptDevice(ctx context.Context, rbdVol *rbdVolume, devicePath string) error {
passphrase, err := util.GetCryptoPassphrase(ctx, rbdVol.VolID, rbdVol.KMS) passphrase, err := util.GetCryptoPassphrase(ctx, rbdVol.VolID, rbdVol.KMS)
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "failed to get crypto passphrase for %s/%s: %v"), klog.Errorf(util.Log(ctx, "failed to get crypto passphrase for %s: %v"),
rbdVol.Pool, rbdVol.RbdImageName, err) rbdVol, err)
return err return err
} }
if err = util.EncryptVolume(ctx, devicePath, passphrase); err != nil { if err = util.EncryptVolume(ctx, devicePath, passphrase); err != nil {
err = fmt.Errorf("failed to encrypt volume %s/%s: %v", rbdVol.Pool, rbdVol.RbdImageName, err) err = fmt.Errorf("failed to encrypt volume %s: %v", rbdVol, err)
klog.Errorf(util.Log(ctx, err.Error())) klog.Errorf(util.Log(ctx, err.Error()))
return err return err
} }
@ -803,8 +803,8 @@ func encryptDevice(ctx context.Context, rbdVol *rbdVolume, devicePath string) er
func openEncryptedDevice(ctx context.Context, volOptions *rbdVolume, devicePath string) (string, error) { func openEncryptedDevice(ctx context.Context, volOptions *rbdVolume, devicePath string) (string, error) {
passphrase, err := util.GetCryptoPassphrase(ctx, volOptions.VolID, volOptions.KMS) passphrase, err := util.GetCryptoPassphrase(ctx, volOptions.VolID, volOptions.KMS)
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "failed to get passphrase for encrypted device %s/%s: %v"), klog.Errorf(util.Log(ctx, "failed to get passphrase for encrypted device %s: %v"),
volOptions.Pool, volOptions.RbdImageName, err) volOptions, err)
return "", status.Error(codes.Internal, err.Error()) return "", status.Error(codes.Internal, err.Error())
} }
@ -820,8 +820,8 @@ func openEncryptedDevice(ctx context.Context, volOptions *rbdVolume, devicePath
} else { } else {
err = util.OpenEncryptedVolume(ctx, devicePath, mapperFile, passphrase) err = util.OpenEncryptedVolume(ctx, devicePath, mapperFile, passphrase)
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "failed to open device %s/%s: %v"), klog.Errorf(util.Log(ctx, "failed to open device %s: %v"),
volOptions.Pool, volOptions.RbdImageName, err) volOptions, err)
return devicePath, err return devicePath, err
} }
} }

View File

@ -202,8 +202,7 @@ func attachRBDImage(ctx context.Context, volOptions *rbdVolume, cr *util.Credent
func createPath(ctx context.Context, volOpt *rbdVolume, cr *util.Credentials) (string, error) { func createPath(ctx context.Context, volOpt *rbdVolume, cr *util.Credentials) (string, error) {
isNbd := false isNbd := false
image := volOpt.RbdImageName imagePath := volOpt.String()
imagePath := fmt.Sprintf("%s/%s", volOpt.Pool, image)
klog.V(5).Infof(util.Log(ctx, "rbd: map mon %s"), volOpt.Monitors) klog.V(5).Infof(util.Log(ctx, "rbd: map mon %s"), volOpt.Monitors)
@ -244,8 +243,7 @@ func createPath(ctx context.Context, volOpt *rbdVolume, cr *util.Credentials) (s
} }
func waitForrbdImage(ctx context.Context, backoff wait.Backoff, volOptions *rbdVolume, cr *util.Credentials) error { func waitForrbdImage(ctx context.Context, backoff wait.Backoff, volOptions *rbdVolume, cr *util.Credentials) error {
image := volOptions.RbdImageName imagePath := volOptions.String()
imagePath := fmt.Sprintf("%s/%s", volOptions.Pool, image)
err := wait.ExponentialBackoff(backoff, func() (bool, error) { err := wait.ExponentialBackoff(backoff, func() (bool, error) {
used, rbdOutput, err := rbdStatus(ctx, volOptions, cr) used, rbdOutput, err := rbdStatus(ctx, volOptions, cr)

View File

@ -156,21 +156,36 @@ func (rv *rbdVolume) Destroy() {
} }
} }
// String returns the image-spec (pool/image) format of the image
func (rv *rbdVolume) String() string {
return fmt.Sprintf("%s/%s", rv.Pool, rv.RbdImageName)
}
// String returns the snap-spec (pool/image@snap) format of the snapshot
func (rs *rbdSnapshot) String() string {
return fmt.Sprintf("%s/%s@%s", rs.Pool, rs.RbdImageName, rs.RbdSnapName)
}
// imageSpec returns the image-spec (pool/image) format of the snapshot
func (rs *rbdSnapshot) imageSpec() string {
return fmt.Sprintf("%s/%s", rs.Pool, rs.RbdImageName)
}
// createImage creates a new ceph image with provision and volume options. // createImage creates a new ceph image with provision and volume options.
func createImage(ctx context.Context, pOpts *rbdVolume, cr *util.Credentials) error { func createImage(ctx context.Context, pOpts *rbdVolume, cr *util.Credentials) error {
volSzMiB := fmt.Sprintf("%dM", util.RoundOffVolSize(pOpts.VolSize)) volSzMiB := fmt.Sprintf("%dM", util.RoundOffVolSize(pOpts.VolSize))
options := librbd.NewRbdImageOptions() options := librbd.NewRbdImageOptions()
logMsg := "rbd: create %s size %s (features: %s) using mon %s, pool %s " logMsg := "rbd: create %s size %s (features: %s) using mon %s"
if pOpts.DataPool != "" { if pOpts.DataPool != "" {
logMsg += fmt.Sprintf("data pool %s", pOpts.DataPool) logMsg += fmt.Sprintf(", data pool %s", pOpts.DataPool)
err := options.SetString(librbd.RbdImageOptionDataPool, pOpts.DataPool) err := options.SetString(librbd.RbdImageOptionDataPool, pOpts.DataPool)
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to set data pool") return errors.Wrapf(err, "failed to set data pool")
} }
} }
klog.V(4).Infof(util.Log(ctx, logMsg), klog.V(4).Infof(util.Log(ctx, logMsg),
pOpts.RbdImageName, volSzMiB, pOpts.ImageFeatures, pOpts.Monitors, pOpts.Pool) pOpts, volSzMiB, pOpts.ImageFeatures, pOpts.Monitors)
if pOpts.ImageFeatures != "" { if pOpts.ImageFeatures != "" {
features := imageFeaturesToUint64(ctx, pOpts.ImageFeatures) features := imageFeaturesToUint64(ctx, pOpts.ImageFeatures)
@ -227,10 +242,8 @@ func rbdStatus(ctx context.Context, pOpts *rbdVolume, cr *util.Credentials) (boo
var output string var output string
var cmd []byte var cmd []byte
image := pOpts.RbdImageName klog.V(4).Infof(util.Log(ctx, "rbd: status %s using mon %s"), pOpts, pOpts.Monitors)
args := []string{"status", pOpts.String(), "-m", pOpts.Monitors, "--id", cr.ID, "--keyfile=" + cr.KeyFile}
klog.V(4).Infof(util.Log(ctx, "rbd: status %s using mon %s, pool %s"), image, pOpts.Monitors, pOpts.Pool)
args := []string{"status", image, "--pool", pOpts.Pool, "-m", pOpts.Monitors, "--id", cr.ID, "--keyfile=" + cr.KeyFile}
cmd, err := execCommand("rbd", args) cmd, err := execCommand("rbd", args)
output = string(cmd) output = string(cmd)
@ -248,10 +261,10 @@ func rbdStatus(ctx context.Context, pOpts *rbdVolume, cr *util.Credentials) (boo
} }
if strings.Contains(output, imageWatcherStr) { if strings.Contains(output, imageWatcherStr) {
klog.V(4).Infof(util.Log(ctx, "rbd: watchers on %s: %s"), image, output) klog.V(4).Infof(util.Log(ctx, "rbd: watchers on %s: %s"), pOpts, output)
return true, output, nil return true, output, nil
} }
klog.Warningf(util.Log(ctx, "rbd: no watchers on %s"), image) klog.Warningf(util.Log(ctx, "rbd: no watchers on %s"), pOpts)
return false, output, nil return false, output, nil
} }
@ -261,7 +274,7 @@ func rbdManagerTaskDeleteImage(ctx context.Context, pOpts *rbdVolume, cr *util.C
var output []byte var output []byte
args := []string{"rbd", "task", "add", "remove", args := []string{"rbd", "task", "add", "remove",
pOpts.Pool + "/" + pOpts.RbdImageName, pOpts.String(),
"--id", cr.ID, "--id", cr.ID,
"--keyfile=" + cr.KeyFile, "--keyfile=" + cr.KeyFile,
"-m", pOpts.Monitors, "-m", pOpts.Monitors,
@ -294,16 +307,16 @@ func deleteImage(ctx context.Context, pOpts *rbdVolume, cr *util.Credentials) er
return err return err
} }
if found { if found {
klog.Errorf(util.Log(ctx, "rbd is still being used "), image) klog.Errorf(util.Log(ctx, "rbd %s is still being used"), pOpts)
return fmt.Errorf("rbd %s is still being used", image) return fmt.Errorf("rbd %s is still being used", pOpts)
} }
klog.V(4).Infof(util.Log(ctx, "rbd: rm %s using mon %s, pool %s"), image, pOpts.Monitors, pOpts.Pool) klog.V(4).Infof(util.Log(ctx, "rbd: rm %s using mon %s"), pOpts, pOpts.Monitors)
// attempt to use Ceph manager based deletion support if available // attempt to use Ceph manager based deletion support if available
rbdCephMgrSupported, err := rbdManagerTaskDeleteImage(ctx, pOpts, cr) rbdCephMgrSupported, err := rbdManagerTaskDeleteImage(ctx, pOpts, cr)
if rbdCephMgrSupported && err != nil { if rbdCephMgrSupported && err != nil {
klog.Errorf(util.Log(ctx, "failed to add task to delete rbd image: %s/%s, %v"), pOpts.Pool, image, err) klog.Errorf(util.Log(ctx, "failed to add task to delete rbd image: %s, %v"), pOpts, err)
return err return err
} }
@ -318,7 +331,7 @@ func deleteImage(ctx context.Context, pOpts *rbdVolume, cr *util.Credentials) er
rbdImage := librbd.GetImage(ioctx, image) rbdImage := librbd.GetImage(ioctx, image)
err = rbdImage.Remove() err = rbdImage.Remove()
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "failed to delete rbd image: %s/%s, error: %v"), pOpts.Pool, image, err) klog.Errorf(util.Log(ctx, "failed to delete rbd image: %s, error: %v"), pOpts, err)
} }
} }
@ -328,8 +341,7 @@ func deleteImage(ctx context.Context, pOpts *rbdVolume, cr *util.Credentials) er
// updateSnapWithImageInfo updates provided rbdSnapshot with information from on-disk data // updateSnapWithImageInfo updates provided rbdSnapshot with information from on-disk data
// regarding the same // regarding the same
func updateSnapWithImageInfo(ctx context.Context, rbdSnap *rbdSnapshot, cr *util.Credentials) error { func updateSnapWithImageInfo(ctx context.Context, rbdSnap *rbdSnapshot, cr *util.Credentials) error {
snapInfo, err := getSnapInfo(ctx, rbdSnap.Monitors, cr, rbdSnap.Pool, snapInfo, err := rbdSnap.getSnapInfo(ctx, rbdSnap.Monitors, cr)
rbdSnap.RbdImageName, rbdSnap.RbdSnapName)
if err != nil { if err != nil {
return err return err
} }
@ -349,7 +361,7 @@ func updateSnapWithImageInfo(ctx context.Context, rbdSnap *rbdSnapshot, cr *util
// updateVolWithImageInfo updates provided rbdVolume with information from on-disk data // updateVolWithImageInfo updates provided rbdVolume with information from on-disk data
// regarding the same // regarding the same
func updateVolWithImageInfo(ctx context.Context, rbdVol *rbdVolume, cr *util.Credentials) error { func updateVolWithImageInfo(ctx context.Context, rbdVol *rbdVolume, cr *util.Credentials) error {
imageInfo, err := getImageInfo(ctx, rbdVol.Monitors, cr, rbdVol.Pool, rbdVol.RbdImageName) imageInfo, err := rbdVol.getImageInfo(ctx, rbdVol.Monitors, cr)
if err != nil { if err != nil {
return err return err
} }
@ -702,12 +714,8 @@ func imageFeaturesToUint64(ctx context.Context, imageFeatures string) uint64 {
func protectSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credentials) error { func protectSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credentials) error {
var output []byte var output []byte
image := pOpts.RbdImageName klog.V(4).Infof(util.Log(ctx, "rbd: snap protect %s using mon %s"), pOpts, pOpts.Monitors)
snapName := pOpts.RbdSnapName args := []string{"snap", "protect", pOpts.String(), "--id", cr.ID, "-m", pOpts.Monitors, "--keyfile=" + cr.KeyFile}
klog.V(4).Infof(util.Log(ctx, "rbd: snap protect %s using mon %s, pool %s "), image, pOpts.Monitors, pOpts.Pool)
args := []string{"snap", "protect", "--pool", pOpts.Pool, "--snap", snapName, image, "--id",
cr.ID, "-m", pOpts.Monitors, "--keyfile=" + cr.KeyFile}
output, err := execCommand("rbd", args) output, err := execCommand("rbd", args)
@ -721,12 +729,8 @@ func protectSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credentia
func createSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credentials) error { func createSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credentials) error {
var output []byte var output []byte
image := pOpts.RbdImageName klog.V(4).Infof(util.Log(ctx, "rbd: snap create %s using mon %s"), pOpts, pOpts.Monitors)
snapName := pOpts.RbdSnapName args := []string{"snap", "create", pOpts.String(), "--id", cr.ID, "-m", pOpts.Monitors, "--keyfile=" + cr.KeyFile}
klog.V(4).Infof(util.Log(ctx, "rbd: snap create %s using mon %s, pool %s"), image, pOpts.Monitors, pOpts.Pool)
args := []string{"snap", "create", "--pool", pOpts.Pool, "--snap", snapName, image,
"--id", cr.ID, "-m", pOpts.Monitors, "--keyfile=" + cr.KeyFile}
output, err := execCommand("rbd", args) output, err := execCommand("rbd", args)
@ -740,12 +744,8 @@ func createSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credential
func unprotectSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credentials) error { func unprotectSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credentials) error {
var output []byte var output []byte
image := pOpts.RbdImageName klog.V(4).Infof(util.Log(ctx, "rbd: snap unprotect %s using mon %s"), pOpts, pOpts.Monitors)
snapName := pOpts.RbdSnapName args := []string{"snap", "unprotect", pOpts.String(), "--id", cr.ID, "-m", pOpts.Monitors, "--keyfile=" + cr.KeyFile}
klog.V(4).Infof(util.Log(ctx, "rbd: snap unprotect %s using mon %s, pool %s"), image, pOpts.Monitors, pOpts.Pool)
args := []string{"snap", "unprotect", "--pool", pOpts.Pool, "--snap", snapName, image, "--id",
cr.ID, "-m", pOpts.Monitors, "--keyfile=" + cr.KeyFile}
output, err := execCommand("rbd", args) output, err := execCommand("rbd", args)
@ -759,12 +759,8 @@ func unprotectSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credent
func deleteSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credentials) error { func deleteSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credentials) error {
var output []byte var output []byte
image := pOpts.RbdImageName klog.V(4).Infof(util.Log(ctx, "rbd: snap rm %s using mon %s"), pOpts, pOpts.Monitors)
snapName := pOpts.RbdSnapName args := []string{"snap", "rm", pOpts.String(), "--id", cr.ID, "-m", pOpts.Monitors, "--keyfile=" + cr.KeyFile}
klog.V(4).Infof(util.Log(ctx, "rbd: snap rm %s using mon %s, pool %s"), image, pOpts.Monitors, pOpts.Pool)
args := []string{"snap", "rm", "--pool", pOpts.Pool, "--snap", snapName, image, "--id",
cr.ID, "-m", pOpts.Monitors, "--keyfile=" + cr.KeyFile}
output, err := execCommand("rbd", args) output, err := execCommand("rbd", args)
@ -773,22 +769,20 @@ func deleteSnapshot(ctx context.Context, pOpts *rbdSnapshot, cr *util.Credential
} }
if err := undoSnapReservation(ctx, pOpts, cr); err != nil { if err := undoSnapReservation(ctx, pOpts, cr); err != nil {
klog.Errorf(util.Log(ctx, "failed to remove reservation for snapname (%s) with backing snap (%s) on image (%s) (%s)"), klog.Errorf(util.Log(ctx, "failed to remove reservation for snapname (%s) with backing snap (%s): %s"),
pOpts.RequestName, pOpts.RbdSnapName, pOpts.RbdImageName, err) pOpts.RequestName, pOpts, err)
} }
return nil return nil
} }
// nolint: interfacer
func restoreSnapshot(ctx context.Context, pVolOpts *rbdVolume, pSnapOpts *rbdSnapshot, cr *util.Credentials) error { func restoreSnapshot(ctx context.Context, pVolOpts *rbdVolume, pSnapOpts *rbdSnapshot, cr *util.Credentials) error {
var output []byte var output []byte
image := pVolOpts.RbdImageName klog.V(4).Infof(util.Log(ctx, "rbd: clone %s using mon %s"), pVolOpts, pVolOpts.Monitors)
snapName := pSnapOpts.RbdSnapName args := []string{"clone", pSnapOpts.String(), pVolOpts.String(),
"--id", cr.ID, "-m", pVolOpts.Monitors, "--keyfile=" + cr.KeyFile}
klog.V(4).Infof(util.Log(ctx, "rbd: clone %s using mon %s, pool %s"), image, pVolOpts.Monitors, pVolOpts.Pool)
args := []string{"clone", pSnapOpts.Pool + "/" + pSnapOpts.RbdImageName + "@" + snapName,
pVolOpts.Pool + "/" + image, "--id", cr.ID, "-m", pVolOpts.Monitors, "--keyfile=" + cr.KeyFile}
output, err := execCommand("rbd", args) output, err := execCommand("rbd", args)
@ -802,10 +796,7 @@ func restoreSnapshot(ctx context.Context, pVolOpts *rbdVolume, pSnapOpts *rbdSna
// getSnapshotMetadata fetches on-disk metadata about the snapshot and populates the passed in // getSnapshotMetadata fetches on-disk metadata about the snapshot and populates the passed in
// rbdSnapshot structure // rbdSnapshot structure
func getSnapshotMetadata(ctx context.Context, pSnapOpts *rbdSnapshot, cr *util.Credentials) error { func getSnapshotMetadata(ctx context.Context, pSnapOpts *rbdSnapshot, cr *util.Credentials) error {
imageName := pSnapOpts.RbdImageName snapInfo, err := pSnapOpts.getSnapInfo(ctx, pSnapOpts.Monitors, cr)
snapName := pSnapOpts.RbdSnapName
snapInfo, err := getSnapInfo(ctx, pSnapOpts.Monitors, cr, pSnapOpts.Pool, imageName, snapName)
if err != nil { if err != nil {
return err return err
} }
@ -835,7 +826,7 @@ type imageInfo struct {
// getImageInfo queries rbd about the given image and returns its metadata, and returns // getImageInfo queries rbd about the given image and returns its metadata, and returns
// ErrImageNotFound if provided image is not found // ErrImageNotFound if provided image is not found
func getImageInfo(ctx context.Context, monitors string, cr *util.Credentials, poolName, imageName string) (imageInfo, error) { func (rv *rbdVolume) getImageInfo(ctx context.Context, monitors string, cr *util.Credentials) (imageInfo, error) {
// rbd --format=json info [image-spec | snap-spec] // rbd --format=json info [image-spec | snap-spec]
var imgInfo imageInfo var imgInfo imageInfo
@ -847,22 +838,20 @@ func getImageInfo(ctx context.Context, monitors string, cr *util.Credentials, po
"--keyfile="+cr.KeyFile, "--keyfile="+cr.KeyFile,
"-c", util.CephConfigPath, "-c", util.CephConfigPath,
"--format="+"json", "--format="+"json",
"info", poolName+"/"+imageName) "info", rv.String())
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "failed getting information for image (%s): (%s)"), poolName+"/"+imageName, err) klog.Errorf(util.Log(ctx, "failed getting information for image (%s): (%s)"), rv, err)
if strings.Contains(string(stderr), "rbd: error opening image "+imageName+ if strings.Contains(string(stderr), "rbd: error opening image "+rv.RbdImageName+
": (2) No such file or directory") { ": (2) No such file or directory") {
return imgInfo, ErrImageNotFound{imageName, err} return imgInfo, ErrImageNotFound{rv.String(), err}
} }
return imgInfo, err return imgInfo, err
} }
err = json.Unmarshal(stdout, &imgInfo) err = json.Unmarshal(stdout, &imgInfo)
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "failed to parse JSON output of image info (%s): (%s)"), klog.Errorf(util.Log(ctx, "failed to parse JSON output of image info (%s): (%s)"), rv, err)
poolName+"/"+imageName, err) return imgInfo, fmt.Errorf("unmarshal failed: %+v. raw buffer response: %s", err, string(stdout))
return imgInfo, fmt.Errorf("unmarshal failed: %+v. raw buffer response: %s",
err, string(stdout))
} }
return imgInfo, nil return imgInfo, nil
@ -881,7 +870,7 @@ getSnapInfo queries rbd about the snapshots of the given image and returns its m
returns ErrImageNotFound if provided image is not found, and ErrSnapNotFound if provided snap returns ErrImageNotFound if provided image is not found, and ErrSnapNotFound if provided snap
is not found in the images snapshot list is not found in the images snapshot list
*/ */
func getSnapInfo(ctx context.Context, monitors string, cr *util.Credentials, poolName, imageName, snapName string) (snapInfo, error) { func (rs *rbdSnapshot) getSnapInfo(ctx context.Context, monitors string, cr *util.Credentials) (snapInfo, error) {
// rbd --format=json snap ls [image-spec] // rbd --format=json snap ls [image-spec]
var ( var (
@ -896,33 +885,30 @@ func getSnapInfo(ctx context.Context, monitors string, cr *util.Credentials, poo
"--keyfile="+cr.KeyFile, "--keyfile="+cr.KeyFile,
"-c", util.CephConfigPath, "-c", util.CephConfigPath,
"--format="+"json", "--format="+"json",
"snap", "ls", poolName+"/"+imageName) "snap", "ls", rs.imageSpec())
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "failed getting snap (%s) information from image (%s): (%s)"), klog.Errorf(util.Log(ctx, "failed getting snap (%s) information from image (%s): (%s)"),
snapName, poolName+"/"+imageName, err) rs.RbdSnapName, rs.imageSpec(), err)
if strings.Contains(string(stderr), "rbd: error opening image "+imageName+ if strings.Contains(string(stderr), "rbd: error opening image "+rs.RbdImageName+
": (2) No such file or directory") { ": (2) No such file or directory") {
return snpInfo, ErrImageNotFound{imageName, err} return snpInfo, ErrImageNotFound{rs.imageSpec(), err}
} }
return snpInfo, err return snpInfo, err
} }
err = json.Unmarshal(stdout, &snaps) err = json.Unmarshal(stdout, &snaps)
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "failed to parse JSON output of image snap list (%s): (%s)"), klog.Errorf(util.Log(ctx, "failed to parse JSON output of image snap list (%s): (%s)"), rs.imageSpec(), err)
poolName+"/"+imageName, err) return snpInfo, fmt.Errorf("unmarshal failed: %+v. raw buffer response: %s", err, string(stdout))
return snpInfo, fmt.Errorf("unmarshal failed: %+v. raw buffer response: %s",
err, string(stdout))
} }
for _, snap := range snaps { for _, snap := range snaps {
if snap.Name == snapName { if snap.Name == rs.RbdSnapName {
return snap, nil return snap, nil
} }
} }
return snpInfo, ErrSnapNotFound{snapName, fmt.Errorf("snap (%s) for image (%s) not found", return snpInfo, ErrSnapNotFound{rs.String(), fmt.Errorf("snap (%s) not found", rs)}
snapName, poolName+"/"+imageName)}
} }
// rbdImageMetadataStash strongly typed JSON spec for stashed RBD image metadata // rbdImageMetadataStash strongly typed JSON spec for stashed RBD image metadata
@ -937,6 +923,11 @@ type rbdImageMetadataStash struct {
// file name in which image metadata is stashed // file name in which image metadata is stashed
const stashFileName = "image-meta.json" const stashFileName = "image-meta.json"
// spec returns the image-spec (pool/image) format of the image
func (ri *rbdImageMetadataStash) String() string {
return fmt.Sprintf("%s/%s", ri.Pool, ri.ImageName)
}
// stashRBDImageMetadata stashes required fields into the stashFileName at the passed in path, in // stashRBDImageMetadata stashes required fields into the stashFileName at the passed in path, in
// JSON format // JSON format
func stashRBDImageMetadata(volOptions *rbdVolume, path string) error { func stashRBDImageMetadata(volOptions *rbdVolume, path string) error {
@ -954,15 +945,13 @@ func stashRBDImageMetadata(volOptions *rbdVolume, path string) error {
encodedBytes, err := json.Marshal(imgMeta) encodedBytes, err := json.Marshal(imgMeta)
if err != nil { if err != nil {
return fmt.Errorf("failed to marshall JSON image metadata for image (%s) in pool (%s): (%v)", return fmt.Errorf("failed to marshall JSON image metadata for image (%s): (%v)", volOptions, err)
volOptions.RbdImageName, volOptions.Pool, err)
} }
fPath := filepath.Join(path, stashFileName) fPath := filepath.Join(path, stashFileName)
err = ioutil.WriteFile(fPath, encodedBytes, 0600) err = ioutil.WriteFile(fPath, encodedBytes, 0600)
if err != nil { if err != nil {
return fmt.Errorf("failed to stash JSON image metadata for image (%s) in pool (%s) at path (%s): (%v)", return fmt.Errorf("failed to stash JSON image metadata for image (%s) at path (%s): (%v)", volOptions, fPath, err)
volOptions.RbdImageName, volOptions.Pool, fPath, err)
} }
return nil return nil
@ -1005,10 +994,9 @@ func resizeRBDImage(rbdVol *rbdVolume, cr *util.Credentials) error {
var output []byte var output []byte
mon := rbdVol.Monitors mon := rbdVol.Monitors
image := rbdVol.RbdImageName
volSzMiB := fmt.Sprintf("%dM", util.RoundOffVolSize(rbdVol.VolSize)) volSzMiB := fmt.Sprintf("%dM", util.RoundOffVolSize(rbdVol.VolSize))
args := []string{"resize", image, "--size", volSzMiB, "--pool", rbdVol.Pool, "--id", cr.ID, "-m", mon, "--keyfile=" + cr.KeyFile} args := []string{"resize", rbdVol.String(), "--size", volSzMiB, "--id", cr.ID, "-m", mon, "--keyfile=" + cr.KeyFile}
output, err := execCommand("rbd", args) output, err := execCommand("rbd", args)
if err != nil { if err != nil {
@ -1042,19 +1030,19 @@ func (rv *rbdVolume) SetMetadata(key, value string) error {
func (rv *rbdVolume) checkRbdImageEncrypted(ctx context.Context) (string, error) { func (rv *rbdVolume) checkRbdImageEncrypted(ctx context.Context) (string, error) {
value, err := rv.GetMetadata(encryptionMetaKey) value, err := rv.GetMetadata(encryptionMetaKey)
if err != nil { if err != nil {
klog.Errorf(util.Log(ctx, "checking image %s encrypted state metadata failed: %s"), rv.RbdImageName, err) klog.Errorf(util.Log(ctx, "checking image %s encrypted state metadata failed: %s"), rv, err)
return "", err return "", err
} }
encrypted := strings.TrimSpace(value) encrypted := strings.TrimSpace(value)
klog.V(4).Infof(util.Log(ctx, "image %s encrypted state metadata reports %q"), rv.RbdImageName, encrypted) klog.V(4).Infof(util.Log(ctx, "image %s encrypted state metadata reports %q"), rv, encrypted)
return encrypted, nil return encrypted, nil
} }
func (rv *rbdVolume) ensureEncryptionMetadataSet(status string) error { func (rv *rbdVolume) ensureEncryptionMetadataSet(status string) error {
err := rv.SetMetadata(encryptionMetaKey, status) err := rv.SetMetadata(encryptionMetaKey, status)
if err != nil { if err != nil {
return fmt.Errorf("failed to save encryption status for %s: %v", rv.RbdImageName, err) return fmt.Errorf("failed to save encryption status for %s: %v", rv, err)
} }
return nil return nil