Update Unstage transaction to undo steps done in Stage

In unstage we now adhere to the transaction (or order of steps)
done in Stage. To enable this we stash the image meta data
into a local file on the staging path for use with unstage
request.

This helps in unmapping a stale map, in case the mount or
other steps in the transaction are complete.

Signed-off-by: ShyamsundarR <srangana@redhat.com>
This commit is contained in:
ShyamsundarR
2019-08-03 18:11:28 -04:00
committed by mergify[bot]
parent 44f7b1fe4b
commit 885ec7049d
4 changed files with 214 additions and 119 deletions

View File

@ -37,6 +37,13 @@ const (
accessTypeNbd = "nbd"
rbd = "rbd"
// Output strings returned during invocation of "rbd unmap --device-type... <imageSpec>" when
// image is not found to be mapped. Used to ignore errors when attempting to unmap such images.
// The %s format specifier should contain the <imageSpec> string
// NOTE: When using devicePath instead of imageSpec, the error strings are different
rbdUnmapCmdkRbdMissingMap = "rbd: %s: not a mapped image or snapshot"
rbdUnmapCmdNbdMissingMap = "rbd-nbd: %s is not mapped"
)
var hasNBD = false
@ -195,23 +202,18 @@ func createPath(volOpt *rbdVolume, cr *util.Credentials) (string, error) {
mapOptions := []string{
"--id", cr.ID,
"-m", volOpt.Monitors,
"--keyfile=" + cr.KeyFile}
// Construct map and unmap variants for the command
mapOptions = append(mapOptions, "map", imagePath)
unmapOptions := []string{"unmap", imagePath}
"--keyfile=" + cr.KeyFile,
"map", imagePath,
}
// Choose access protocol
useNBD := false
accessType := accessTypeKRbd
if volOpt.Mounter == rbdTonbd && hasNBD {
accessType = accessTypeNbd
useNBD = true
}
// Update options with device type selection
mapOptions = append(mapOptions, "--device-type", accessType)
unmapOptions = append(unmapOptions, "--device-type", accessType)
// Execute map
output, err := execCommand(rbd, mapOptions)
@ -248,20 +250,38 @@ func waitForrbdImage(backoff wait.Backoff, volOptions *rbdVolume, cr *util.Crede
}
func detachRBDDevice(devicePath string) error {
nbdType := false
if strings.HasPrefix(devicePath, "/dev/nbd") {
nbdType = true
}
return detachRBDImageOrDeviceSpec(devicePath, false, nbdType)
}
// detachRBDImageOrDeviceSpec detaches an rbd imageSpec or devicePath, with additional checking
// when imageSpec is used to decide if image is already unmapped
func detachRBDImageOrDeviceSpec(imageOrDeviceSpec string, isImageSpec, ndbType bool) error {
var err error
var output []byte
klog.V(3).Infof("rbd: unmap device %s", devicePath)
accessType := accessTypeKRbd
if strings.HasPrefix(devicePath, "/dev/nbd") {
if ndbType {
accessType = accessTypeNbd
}
options := []string{"unmap", "--device-type", accessType, devicePath}
options := []string{"unmap", "--device-type", accessType, imageOrDeviceSpec}
output, err = execCommand(rbd, options)
if err != nil {
return fmt.Errorf("rbd: unmap failed %v, rbd output: %s", err, string(output))
// Messages for krbd and nbd differ, hence checking either of them for missing mapping
// This is not applicable when a device path is passed in
if isImageSpec &&
(strings.Contains(string(output), fmt.Sprintf(rbdUnmapCmdkRbdMissingMap, imageOrDeviceSpec)) ||
strings.Contains(string(output), fmt.Sprintf(rbdUnmapCmdNbdMissingMap, imageOrDeviceSpec))) {
// Devices found not to be mapped are treated as a successful detach
klog.Infof("image or device spec (%s) not mapped", imageOrDeviceSpec)
return nil
}
return fmt.Errorf("rbd: unmap for spec (%s) failed (%v): (%s)", imageOrDeviceSpec, err, string(output))
}
return nil