2018-01-09 18:59:50 +00:00
/ *
2019-04-03 08:46:15 +00:00
Copyright 2018 The Ceph - CSI Authors .
2018-01-09 18:59:50 +00:00
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 (
"fmt"
"os/exec"
"strings"
"time"
2018-03-06 22:33:57 +00:00
2018-10-09 10:08:56 +00:00
"github.com/pkg/errors"
2018-07-20 08:46:44 +00:00
"k8s.io/apimachinery/pkg/util/sets"
2019-02-04 13:05:07 +00:00
"k8s.io/klog"
2018-03-06 22:33:57 +00:00
"k8s.io/kubernetes/pkg/util/keymutex"
2018-01-09 18:59:50 +00:00
)
const (
imageWatcherStr = "watcher="
rbdImageFormat2 = "2"
// The following three values are used for 30 seconds timeout
// while waiting for RBD Watcher to expire.
rbdImageWatcherInitDelay = 1 * time . Second
rbdImageWatcherFactor = 1.4
rbdImageWatcherSteps = 10
2018-09-18 14:09:12 +00:00
rbdDefaultMounter = "rbd"
2018-01-09 18:59:50 +00:00
)
2018-03-06 22:33:57 +00:00
type rbdVolume struct {
2018-09-21 14:38:50 +00:00
VolName string ` json:"volName" `
VolID string ` json:"volID" `
Monitors string ` json:"monitors" `
MonValueFromSecret string ` json:"monValueFromSecret" `
Pool string ` json:"pool" `
ImageFormat string ` json:"imageFormat" `
ImageFeatures string ` json:"imageFeatures" `
VolSize int64 ` json:"volSize" `
2019-01-17 05:46:32 +00:00
AdminID string ` json:"adminId" `
UserID string ` json:"userId" `
2018-09-21 14:38:50 +00:00
Mounter string ` json:"mounter" `
2019-03-14 00:18:04 +00:00
DisableInUseChecks bool ` json:"disableInUseChecks" `
2019-03-12 15:57:36 +00:00
ClusterID string ` json:"clusterId" `
2018-01-09 18:59:50 +00:00
}
2018-08-08 05:42:17 +00:00
type rbdSnapshot struct {
2018-09-21 14:38:50 +00:00
SourceVolumeID string ` json:"sourceVolumeID" `
VolName string ` json:"volName" `
SnapName string ` json:"snapName" `
SnapID string ` json:"sanpID" `
Monitors string ` json:"monitors" `
MonValueFromSecret string ` json:"monValueFromSecret" `
Pool string ` json:"pool" `
CreatedAt int64 ` json:"createdAt" `
SizeBytes int64 ` json:"sizeBytes" `
2019-01-17 05:46:32 +00:00
AdminID string ` json:"adminId" `
UserID string ` json:"userId" `
2019-03-12 15:57:36 +00:00
ClusterID string ` json:"clusterId" `
2018-08-08 05:42:17 +00:00
}
2018-07-20 08:46:44 +00:00
var (
2018-10-17 12:52:45 +00:00
// serializes operations based on "<rbd pool>/<rbd image>" as key
2019-01-15 16:20:41 +00:00
attachdetachMutex = keymutex . NewHashed ( 0 )
2018-10-17 12:52:45 +00:00
// serializes operations based on "volume name" as key
2019-01-15 16:20:41 +00:00
volumeNameMutex = keymutex . NewHashed ( 0 )
2018-10-17 12:52:45 +00:00
// serializes operations based on "volume id" as key
2019-01-15 16:20:41 +00:00
volumeIDMutex = keymutex . NewHashed ( 0 )
2018-10-17 12:52:45 +00:00
// serializes operations based on "snapshot name" as key
2019-01-15 16:20:41 +00:00
snapshotNameMutex = keymutex . NewHashed ( 0 )
2018-10-17 12:52:45 +00:00
// serializes operations based on "snapshot id" as key
2019-01-15 16:20:41 +00:00
snapshotIDMutex = keymutex . NewHashed ( 0 )
2018-10-17 12:52:45 +00:00
// serializes operations based on "mount target path" as key
2019-01-15 16:20:41 +00:00
targetPathMutex = keymutex . NewHashed ( 0 )
2018-10-17 12:52:45 +00:00
2018-07-20 08:46:44 +00:00
supportedFeatures = sets . NewString ( "layering" )
)
2018-01-09 18:59:50 +00:00
2019-03-13 13:46:56 +00:00
func getRBDKey ( clusterid , id string , credentials map [ string ] string ) ( string , error ) {
var (
ok bool
err error
key string
)
2019-03-07 21:03:33 +00:00
2019-03-02 17:29:52 +00:00
if key , ok = credentials [ id ] ; ! ok {
2019-03-12 15:57:36 +00:00
if clusterid != "" {
key , err = confStore . KeyForUser ( clusterid , id )
2019-03-02 17:29:52 +00:00
if err != nil {
2019-03-12 15:57:36 +00:00
return "" , fmt . Errorf ( "RBD key for ID: %s not found in config store of clusterID (%s)" , id , clusterid )
2019-03-02 17:29:52 +00:00
}
} else {
return "" , fmt . Errorf ( "RBD key for ID: %s not found" , id )
}
2018-03-06 22:33:57 +00:00
}
2019-03-02 17:29:52 +00:00
return key , nil
2018-03-06 22:33:57 +00:00
}
2018-09-21 14:38:50 +00:00
func getMon ( pOpts * rbdVolume , credentials map [ string ] string ) ( string , error ) {
mon := pOpts . Monitors
if len ( mon ) == 0 {
// if mons are set in secret, retrieve them
if len ( pOpts . MonValueFromSecret ) == 0 {
// yet another sanity check
2019-01-16 13:17:29 +00:00
return "" , errors . New ( "either monitors or monValueFromSecret must be set" )
2018-09-21 14:38:50 +00:00
}
2019-01-16 13:03:38 +00:00
val , ok := credentials [ pOpts . MonValueFromSecret ]
if ! ok {
2018-09-21 14:38:50 +00:00
return "" , fmt . Errorf ( "mon data %s is not set in secret" , pOpts . MonValueFromSecret )
}
2019-01-16 13:03:38 +00:00
mon = val
2018-09-21 14:38:50 +00:00
}
return mon , nil
}
2018-01-09 18:59:50 +00:00
// CreateImage creates a new ceph image with provision and volume options.
2019-01-17 05:46:32 +00:00
func createRBDImage ( pOpts * rbdVolume , volSz int , adminID string , credentials map [ string ] string ) error {
2018-01-09 18:59:50 +00:00
var output [ ] byte
2018-09-21 14:38:50 +00:00
mon , err := getMon ( pOpts , credentials )
if err != nil {
return err
}
2018-01-16 01:52:28 +00:00
image := pOpts . VolName
2019-03-01 12:08:17 +00:00
volSzMiB := fmt . Sprintf ( "%dM" , volSz )
2018-01-09 18:59:50 +00:00
2019-03-12 15:57:36 +00:00
key , err := getRBDKey ( pOpts . ClusterID , adminID , credentials )
2018-03-06 22:33:57 +00:00
if err != nil {
return err
}
2018-01-09 18:59:50 +00:00
if pOpts . ImageFormat == rbdImageFormat2 {
2019-03-01 12:08:17 +00:00
klog . V ( 4 ) . Infof ( "rbd: create %s size %s format %s (features: %s) using mon %s, pool %s " , image , volSzMiB , pOpts . ImageFormat , pOpts . ImageFeatures , mon , pOpts . Pool )
2018-01-09 18:59:50 +00:00
} else {
2019-03-01 12:08:17 +00:00
klog . V ( 4 ) . Infof ( "rbd: create %s size %s format %s using mon %s, pool %s" , image , volSzMiB , pOpts . ImageFormat , mon , pOpts . Pool )
2018-01-09 18:59:50 +00:00
}
2019-03-01 12:08:17 +00:00
args := [ ] string { "create" , image , "--size" , volSzMiB , "--pool" , pOpts . Pool , "--id" , adminID , "-m" , mon , "--key=" + key , "--image-format" , pOpts . ImageFormat }
2018-01-09 18:59:50 +00:00
if pOpts . ImageFormat == rbdImageFormat2 {
2018-07-20 08:46:44 +00:00
args = append ( args , "--image-feature" , pOpts . ImageFeatures )
2018-01-09 18:59:50 +00:00
}
output , err = execCommand ( "rbd" , args )
if err != nil {
2018-10-09 10:08:56 +00:00
return errors . Wrapf ( err , "failed to create rbd image, command output: %s" , string ( output ) )
2018-01-09 18:59:50 +00:00
}
return nil
}
// rbdStatus checks if there is watcher on the image.
2019-01-28 19:55:10 +00:00
// It returns true if there is a watcher on the image, otherwise returns false.
2019-01-17 05:46:32 +00:00
func rbdStatus ( pOpts * rbdVolume , userID string , credentials map [ string ] string ) ( bool , string , error ) {
2018-01-09 18:59:50 +00:00
var output string
var cmd [ ] byte
2018-03-06 22:33:57 +00:00
image := pOpts . VolName
2018-01-09 18:59:50 +00:00
// If we don't have admin id/secret (e.g. attaching), fallback to user id/secret.
2018-08-09 13:07:00 +00:00
2019-03-12 15:57:36 +00:00
key , err := getRBDKey ( pOpts . ClusterID , userID , credentials )
2018-03-06 22:33:57 +00:00
if err != nil {
return false , "" , err
2018-01-09 18:59:50 +00:00
}
2018-09-21 14:38:50 +00:00
mon , err := getMon ( pOpts , credentials )
if err != nil {
return false , "" , err
}
2019-02-08 07:07:03 +00:00
klog . V ( 4 ) . Infof ( "rbd: status %s using mon %s, pool %s" , image , mon , pOpts . Pool )
2019-01-17 05:46:32 +00:00
args := [ ] string { "status" , image , "--pool" , pOpts . Pool , "-m" , mon , "--id" , userID , "--key=" + key }
2018-01-09 18:59:50 +00:00
cmd , err = execCommand ( "rbd" , args )
output = string ( cmd )
if err , ok := err . ( * exec . Error ) ; ok {
if err . Err == exec . ErrNotFound {
2019-02-04 13:05:07 +00:00
klog . Errorf ( "rbd cmd not found" )
2018-01-09 18:59:50 +00:00
// fail fast if command not found
return false , output , err
}
}
// If command never succeed, returns its last error.
if err != nil {
return false , output , err
}
if strings . Contains ( output , imageWatcherStr ) {
2019-02-04 13:05:07 +00:00
klog . V ( 4 ) . Infof ( "rbd: watchers on %s: %s" , image , output )
2018-01-09 18:59:50 +00:00
return true , output , nil
}
2019-02-04 13:05:07 +00:00
klog . Warningf ( "rbd: no watchers on %s" , image )
2019-01-16 13:03:38 +00:00
return false , output , nil
2018-01-09 18:59:50 +00:00
}
// DeleteImage deletes a ceph image with provision and volume options.
2019-01-17 05:46:32 +00:00
func deleteRBDImage ( pOpts * rbdVolume , adminID string , credentials map [ string ] string ) error {
2018-01-09 18:59:50 +00:00
var output [ ] byte
2018-03-06 22:33:57 +00:00
image := pOpts . VolName
2019-01-17 05:46:32 +00:00
found , _ , err := rbdStatus ( pOpts , adminID , credentials )
2018-01-09 18:59:50 +00:00
if err != nil {
return err
}
if found {
2019-02-04 13:05:07 +00:00
klog . Info ( "rbd is still being used " , image )
2018-01-09 18:59:50 +00:00
return fmt . Errorf ( "rbd %s is still being used" , image )
}
2019-03-12 15:57:36 +00:00
key , err := getRBDKey ( pOpts . ClusterID , adminID , credentials )
2018-03-06 22:33:57 +00:00
if err != nil {
return err
2018-01-09 18:59:50 +00:00
}
2018-09-21 14:38:50 +00:00
mon , err := getMon ( pOpts , credentials )
if err != nil {
return err
}
2018-01-09 18:59:50 +00:00
2019-02-08 07:07:03 +00:00
klog . V ( 4 ) . Infof ( "rbd: rm %s using mon %s, pool %s" , image , mon , pOpts . Pool )
2019-01-17 05:46:32 +00:00
args := [ ] string { "rm" , image , "--pool" , pOpts . Pool , "--id" , adminID , "-m" , mon , "--key=" + key }
2018-01-09 18:59:50 +00:00
output , err = execCommand ( "rbd" , args )
if err == nil {
return nil
}
2019-02-04 13:05:07 +00:00
klog . Errorf ( "failed to delete rbd image: %v, command output: %s" , err , string ( output ) )
2018-01-09 18:59:50 +00:00
return err
}
func execCommand ( command string , args [ ] string ) ( [ ] byte , error ) {
2019-01-28 19:55:10 +00:00
// #nosec
2018-01-09 18:59:50 +00:00
cmd := exec . Command ( command , args ... )
return cmd . CombinedOutput ( )
}
2019-03-12 15:57:36 +00:00
func getMonsAndClusterID ( options map [ string ] string ) ( monitors , clusterID , monInSecret string , err error ) {
2019-03-02 17:29:52 +00:00
var ok bool
monitors , ok = options [ "monitors" ]
if ! ok {
// if mons are not set in options, check if they are set in secret
if monInSecret , ok = options [ "monValueFromSecret" ] ; ! ok {
2019-03-12 15:57:36 +00:00
// if mons are not in secret, check if we have a cluster-id
if clusterID , ok = options [ "clusterID" ] ; ! ok {
2019-03-07 21:03:33 +00:00
err = errors . New ( "either monitors or monValueFromSecret or clusterID must be set" )
return
2019-03-02 17:29:52 +00:00
}
2019-03-07 21:03:33 +00:00
2019-03-12 15:57:36 +00:00
if monitors , err = confStore . Mons ( clusterID ) ; err != nil {
2019-03-02 17:29:52 +00:00
klog . Errorf ( "failed getting mons (%s)" , err )
2019-03-12 15:57:36 +00:00
err = fmt . Errorf ( "failed to fetch monitor list using clusterID (%s)" , clusterID )
2019-03-07 21:03:33 +00:00
return
2019-03-02 17:29:52 +00:00
}
}
}
return
}
2019-03-12 15:57:36 +00:00
func getIDs ( options map [ string ] string , clusterID string ) ( adminID , userID string , err error ) {
2019-03-02 17:29:52 +00:00
var ok bool
adminID , ok = options [ "adminid" ]
2019-03-07 21:03:33 +00:00
switch {
case ok :
2019-03-12 15:57:36 +00:00
case clusterID != "" :
if adminID , err = confStore . AdminID ( clusterID ) ; err != nil {
2019-03-13 13:46:56 +00:00
klog . Errorf ( "failed getting adminID (%s)" , err )
return "" , "" , fmt . Errorf ( "failed to fetch adminID for clusterID (%s)" , clusterID )
2019-03-02 17:29:52 +00:00
}
2019-03-07 21:03:33 +00:00
default :
adminID = rbdDefaultAdminID
2019-03-02 17:29:52 +00:00
}
userID , ok = options [ "userid" ]
2019-03-07 21:03:33 +00:00
switch {
case ok :
2019-03-12 15:57:36 +00:00
case clusterID != "" :
if userID , err = confStore . UserID ( clusterID ) ; err != nil {
2019-03-13 13:46:56 +00:00
klog . Errorf ( "failed getting userID (%s)" , err )
return "" , "" , fmt . Errorf ( "failed to fetch userID using clusterID (%s)" , clusterID )
2019-03-02 17:29:52 +00:00
}
2019-03-07 21:03:33 +00:00
default :
userID = rbdDefaultUserID
2019-03-02 17:29:52 +00:00
}
2019-03-07 21:03:33 +00:00
return adminID , userID , err
2019-03-02 17:29:52 +00:00
}
2019-03-14 00:18:04 +00:00
func getRBDVolumeOptions ( volOptions map [ string ] string , disableInUseChecks bool ) ( * rbdVolume , error ) {
2019-03-13 13:46:56 +00:00
var (
ok bool
err error
)
2019-03-02 17:29:52 +00:00
2018-03-06 22:33:57 +00:00
rbdVol := & rbdVolume { }
rbdVol . Pool , ok = volOptions [ "pool" ]
2018-01-09 18:59:50 +00:00
if ! ok {
2019-03-07 12:56:47 +00:00
return nil , errors . New ( "missing required parameter pool" )
2018-01-09 18:59:50 +00:00
}
2019-03-02 17:29:52 +00:00
2019-03-12 15:57:36 +00:00
rbdVol . Monitors , rbdVol . ClusterID , rbdVol . MonValueFromSecret , err = getMonsAndClusterID ( volOptions )
2019-03-02 17:29:52 +00:00
if err != nil {
return nil , err
2018-01-09 18:59:50 +00:00
}
2019-03-02 17:29:52 +00:00
2018-03-06 22:33:57 +00:00
rbdVol . ImageFormat , ok = volOptions [ "imageFormat" ]
2018-01-18 19:13:08 +00:00
if ! ok {
2018-07-20 08:46:44 +00:00
rbdVol . ImageFormat = rbdImageFormat2
}
2019-03-02 17:29:52 +00:00
2018-07-20 08:46:44 +00:00
if rbdVol . ImageFormat == rbdImageFormat2 {
// if no image features is provided, it results in empty string
// which disable all RBD image format 2 features as we expected
2019-01-17 06:49:35 +00:00
imageFeatures , found := volOptions [ "imageFeatures" ]
if found {
2018-07-20 08:46:44 +00:00
arr := strings . Split ( imageFeatures , "," )
for _ , f := range arr {
if ! supportedFeatures . Has ( f ) {
return nil , fmt . Errorf ( "invalid feature %q for volume csi-rbdplugin, supported features are: %v" , f , supportedFeatures )
}
}
rbdVol . ImageFeatures = imageFeatures
}
2018-01-09 18:59:50 +00:00
}
2019-03-14 00:18:04 +00:00
klog . V ( 3 ) . Infof ( "setting disableInUseChecks on rbd volume to: %v" , disableInUseChecks )
rbdVol . DisableInUseChecks = disableInUseChecks
2019-03-02 17:29:52 +00:00
err = getCredsFromVol ( rbdVol , volOptions )
if err != nil {
return nil , err
}
2019-01-29 05:49:16 +00:00
return rbdVol , nil
}
2019-03-02 17:29:52 +00:00
func getCredsFromVol ( rbdVol * rbdVolume , volOptions map [ string ] string ) error {
2019-03-13 13:46:56 +00:00
var (
ok bool
err error
)
2019-03-02 17:29:52 +00:00
2019-03-12 15:57:36 +00:00
rbdVol . AdminID , rbdVol . UserID , err = getIDs ( volOptions , rbdVol . ClusterID )
2019-03-02 17:29:52 +00:00
if err != nil {
return err
2018-08-09 13:07:00 +00:00
}
2019-03-02 17:29:52 +00:00
2018-09-18 14:09:12 +00:00
rbdVol . Mounter , ok = volOptions [ "mounter" ]
if ! ok {
rbdVol . Mounter = rbdDefaultMounter
}
2019-03-02 17:29:52 +00:00
2019-03-13 13:46:56 +00:00
return err
2018-01-09 18:59:50 +00:00
}
2019-03-02 17:29:52 +00:00
2018-08-08 05:42:17 +00:00
func getRBDSnapshotOptions ( snapOptions map [ string ] string ) ( * rbdSnapshot , error ) {
2019-03-13 13:46:56 +00:00
var (
ok bool
err error
)
2019-03-02 17:29:52 +00:00
2018-08-08 05:42:17 +00:00
rbdSnap := & rbdSnapshot { }
rbdSnap . Pool , ok = snapOptions [ "pool" ]
if ! ok {
2019-03-07 12:56:47 +00:00
return nil , errors . New ( "missing required parameter pool" )
2018-08-08 05:42:17 +00:00
}
2019-03-02 17:29:52 +00:00
2019-03-12 15:57:36 +00:00
rbdSnap . Monitors , rbdSnap . ClusterID , rbdSnap . MonValueFromSecret , err = getMonsAndClusterID ( snapOptions )
2019-03-02 17:29:52 +00:00
if err != nil {
return nil , err
2018-08-09 13:07:00 +00:00
}
2018-08-08 05:42:17 +00:00
2019-03-12 15:57:36 +00:00
rbdSnap . AdminID , rbdSnap . UserID , err = getIDs ( snapOptions , rbdSnap . ClusterID )
2019-03-02 17:29:52 +00:00
if err != nil {
return nil , err
}
2018-08-08 05:42:17 +00:00
return rbdSnap , nil
}
2018-08-09 13:07:13 +00:00
func hasSnapshotFeature ( imageFeatures string ) bool {
arr := strings . Split ( imageFeatures , "," )
for _ , f := range arr {
if f == "layering" {
return true
}
}
return false
}
2018-08-09 13:06:51 +00:00
func getRBDVolumeByID ( volumeID string ) ( * rbdVolume , error ) {
2018-03-06 22:33:57 +00:00
if rbdVol , ok := rbdVolumes [ volumeID ] ; ok {
return rbdVol , nil
}
2018-08-09 13:06:51 +00:00
return nil , fmt . Errorf ( "volume id %s does not exit in the volumes list" , volumeID )
2018-03-06 22:33:57 +00:00
}
2018-08-09 13:06:51 +00:00
func getRBDVolumeByName ( volName string ) ( * rbdVolume , error ) {
2018-03-06 22:33:57 +00:00
for _ , rbdVol := range rbdVolumes {
if rbdVol . VolName == volName {
return rbdVol , nil
}
}
2018-08-09 13:06:51 +00:00
return nil , fmt . Errorf ( "volume name %s does not exit in the volumes list" , volName )
2018-03-06 22:33:57 +00:00
}
2018-08-08 05:42:17 +00:00
2018-08-09 13:06:51 +00:00
func getRBDSnapshotByName ( snapName string ) ( * rbdSnapshot , error ) {
2018-08-08 05:42:17 +00:00
for _ , rbdSnap := range rbdSnapshots {
if rbdSnap . SnapName == snapName {
return rbdSnap , nil
}
}
2018-08-09 13:06:51 +00:00
return nil , fmt . Errorf ( "snapshot name %s does not exit in the snapshots list" , snapName )
2018-08-08 05:42:17 +00:00
}
2018-09-21 14:38:50 +00:00
func getSnapMon ( pOpts * rbdSnapshot , credentials map [ string ] string ) ( string , error ) {
mon := pOpts . Monitors
if len ( mon ) == 0 {
// if mons are set in secret, retrieve them
if len ( pOpts . MonValueFromSecret ) == 0 {
// yet another sanity check
2019-01-16 13:17:29 +00:00
return "" , errors . New ( "either monitors or monValueFromSecret must be set" )
2018-09-21 14:38:50 +00:00
}
2019-01-16 13:03:38 +00:00
val , ok := credentials [ pOpts . MonValueFromSecret ]
if ! ok {
2018-09-21 14:38:50 +00:00
return "" , fmt . Errorf ( "mon data %s is not set in secret" , pOpts . MonValueFromSecret )
}
2019-01-16 13:03:38 +00:00
mon = val
2018-09-21 14:38:50 +00:00
}
return mon , nil
}
2019-01-17 05:46:32 +00:00
func protectSnapshot ( pOpts * rbdSnapshot , adminID string , credentials map [ string ] string ) error {
2018-08-08 05:42:17 +00:00
var output [ ] byte
image := pOpts . VolName
snapID := pOpts . SnapID
2019-03-12 15:57:36 +00:00
key , err := getRBDKey ( pOpts . ClusterID , adminID , credentials )
2018-08-08 05:42:17 +00:00
if err != nil {
return err
}
2018-09-21 14:38:50 +00:00
mon , err := getSnapMon ( pOpts , credentials )
if err != nil {
return err
}
2019-02-08 07:07:03 +00:00
klog . V ( 4 ) . Infof ( "rbd: snap protect %s using mon %s, pool %s " , image , mon , pOpts . Pool )
2019-01-17 05:46:32 +00:00
args := [ ] string { "snap" , "protect" , "--pool" , pOpts . Pool , "--snap" , snapID , image , "--id" , adminID , "-m" , mon , "--key=" + key }
2018-08-08 05:42:17 +00:00
output , err = execCommand ( "rbd" , args )
if err != nil {
2018-10-09 10:08:56 +00:00
return errors . Wrapf ( err , "failed to protect snapshot, command output: %s" , string ( output ) )
2018-08-08 05:42:17 +00:00
}
return nil
}
2019-02-18 08:22:52 +00:00
func extractStoredVolOpt ( r * rbdVolume ) map [ string ] string {
volOptions := make ( map [ string ] string )
volOptions [ "pool" ] = r . Pool
if len ( r . Monitors ) > 0 {
volOptions [ "monitors" ] = r . Monitors
}
if len ( r . MonValueFromSecret ) > 0 {
volOptions [ "monValueFromSecret" ] = r . MonValueFromSecret
}
volOptions [ "imageFormat" ] = r . ImageFormat
if len ( r . ImageFeatures ) > 0 {
volOptions [ "imageFeatures" ] = r . ImageFeatures
}
if len ( r . AdminID ) > 0 {
2019-02-26 11:09:39 +00:00
volOptions [ "adminId" ] = r . AdminID
2019-02-18 08:22:52 +00:00
}
if len ( r . UserID ) > 0 {
2019-02-26 11:09:39 +00:00
volOptions [ "userId" ] = r . UserID
2019-02-18 08:22:52 +00:00
}
if len ( r . Mounter ) > 0 {
volOptions [ "mounter" ] = r . Mounter
}
return volOptions
}
2019-01-17 05:46:32 +00:00
func createSnapshot ( pOpts * rbdSnapshot , adminID string , credentials map [ string ] string ) error {
2018-08-08 05:42:17 +00:00
var output [ ] byte
2018-09-21 14:38:50 +00:00
mon , err := getSnapMon ( pOpts , credentials )
if err != nil {
return err
}
2018-08-08 05:42:17 +00:00
image := pOpts . VolName
snapID := pOpts . SnapID
2019-03-12 15:57:36 +00:00
key , err := getRBDKey ( pOpts . ClusterID , adminID , credentials )
2018-08-08 05:42:17 +00:00
if err != nil {
return err
}
2019-02-08 07:07:03 +00:00
klog . V ( 4 ) . Infof ( "rbd: snap create %s using mon %s, pool %s" , image , mon , pOpts . Pool )
2019-01-17 05:46:32 +00:00
args := [ ] string { "snap" , "create" , "--pool" , pOpts . Pool , "--snap" , snapID , image , "--id" , adminID , "-m" , mon , "--key=" + key }
2018-08-08 05:42:17 +00:00
output , err = execCommand ( "rbd" , args )
if err != nil {
2018-10-09 10:08:56 +00:00
return errors . Wrapf ( err , "failed to create snapshot, command output: %s" , string ( output ) )
2018-08-08 05:42:17 +00:00
}
return nil
}
2019-01-17 05:46:32 +00:00
func unprotectSnapshot ( pOpts * rbdSnapshot , adminID string , credentials map [ string ] string ) error {
2018-08-08 05:42:17 +00:00
var output [ ] byte
2018-09-21 14:38:50 +00:00
mon , err := getSnapMon ( pOpts , credentials )
if err != nil {
return err
}
2018-08-08 05:42:17 +00:00
image := pOpts . VolName
snapID := pOpts . SnapID
2019-03-12 15:57:36 +00:00
key , err := getRBDKey ( pOpts . ClusterID , adminID , credentials )
2018-08-08 05:42:17 +00:00
if err != nil {
return err
}
2019-02-08 07:07:03 +00:00
klog . V ( 4 ) . Infof ( "rbd: snap unprotect %s using mon %s, pool %s" , image , mon , pOpts . Pool )
2019-01-17 05:46:32 +00:00
args := [ ] string { "snap" , "unprotect" , "--pool" , pOpts . Pool , "--snap" , snapID , image , "--id" , adminID , "-m" , mon , "--key=" + key }
2018-08-08 05:42:17 +00:00
output , err = execCommand ( "rbd" , args )
if err != nil {
2018-10-09 10:08:56 +00:00
return errors . Wrapf ( err , "failed to unprotect snapshot, command output: %s" , string ( output ) )
2018-08-08 05:42:17 +00:00
}
return nil
}
2019-01-17 05:46:32 +00:00
func deleteSnapshot ( pOpts * rbdSnapshot , adminID string , credentials map [ string ] string ) error {
2018-08-08 05:42:17 +00:00
var output [ ] byte
2018-09-21 14:38:50 +00:00
mon , err := getSnapMon ( pOpts , credentials )
if err != nil {
return err
}
2018-08-08 05:42:17 +00:00
image := pOpts . VolName
snapID := pOpts . SnapID
2019-03-12 15:57:36 +00:00
key , err := getRBDKey ( pOpts . ClusterID , adminID , credentials )
2018-08-08 05:42:17 +00:00
if err != nil {
return err
}
2019-02-08 07:07:03 +00:00
klog . V ( 4 ) . Infof ( "rbd: snap rm %s using mon %s, pool %s" , image , mon , pOpts . Pool )
2019-01-17 05:46:32 +00:00
args := [ ] string { "snap" , "rm" , "--pool" , pOpts . Pool , "--snap" , snapID , image , "--id" , adminID , "-m" , mon , "--key=" + key }
2018-08-08 05:42:17 +00:00
output , err = execCommand ( "rbd" , args )
if err != nil {
2018-10-09 10:08:56 +00:00
return errors . Wrapf ( err , "failed to delete snapshot, command output: %s" , string ( output ) )
2018-08-08 05:42:17 +00:00
}
return nil
}
2019-01-17 05:46:32 +00:00
func restoreSnapshot ( pVolOpts * rbdVolume , pSnapOpts * rbdSnapshot , adminID string , credentials map [ string ] string ) error {
2018-08-08 05:42:17 +00:00
var output [ ] byte
2018-09-21 14:38:50 +00:00
mon , err := getMon ( pVolOpts , credentials )
if err != nil {
return err
}
2018-08-08 05:42:17 +00:00
image := pVolOpts . VolName
snapID := pSnapOpts . SnapID
2019-03-12 15:57:36 +00:00
key , err := getRBDKey ( pVolOpts . ClusterID , adminID , credentials )
2018-08-08 05:42:17 +00:00
if err != nil {
return err
}
2019-02-08 07:07:03 +00:00
klog . V ( 4 ) . Infof ( "rbd: clone %s using mon %s, pool %s" , image , mon , pVolOpts . Pool )
2019-01-17 05:46:32 +00:00
args := [ ] string { "clone" , pSnapOpts . Pool + "/" + pSnapOpts . VolName + "@" + snapID , pVolOpts . Pool + "/" + image , "--id" , adminID , "-m" , mon , "--key=" + key }
2018-08-08 05:42:17 +00:00
output , err = execCommand ( "rbd" , args )
if err != nil {
2018-10-09 10:08:56 +00:00
return errors . Wrapf ( err , "failed to restore snapshot, command output: %s" , string ( output ) )
2018-08-08 05:42:17 +00:00
}
return nil
}