go-ceph/rbd/snapshot.go

194 lines
4.9 KiB
Go
Raw Normal View History

package rbd
// #cgo LDFLAGS: -lrbd
// #include <stdlib.h>
// #include <rbd/librbd.h>
import "C"
import (
"unsafe"
ts "github.com/ceph/go-ceph/internal/timespec"
)
// Snapshot represents a snapshot on a particular rbd image.
type Snapshot struct {
image *Image
name string
}
// CreateSnapshot returns a new Snapshot objects after creating
// a snapshot of the rbd image.
//
// Implements:
//
// int rbd_snap_create(rbd_image_t image, const char *snapname);
func (image *Image) CreateSnapshot(snapname string) (*Snapshot, error) {
if err := image.validate(imageIsOpen); err != nil {
return nil, err
}
cSnapName := C.CString(snapname)
defer C.free(unsafe.Pointer(cSnapName))
ret := C.rbd_snap_create(image.image, cSnapName)
if ret < 0 {
return nil, getError(ret)
}
return &Snapshot{
image: image,
name: snapname,
}, nil
}
// validate the attributes listed in the req bitmask, and return an error in
// case the attribute is not set
// Calls snapshot.image.validate(req) to validate the image attributes.
func (snapshot *Snapshot) validate(req uint32) error {
if hasBit(req, snapshotNeedsName) && snapshot.name == "" {
return ErrSnapshotNoName
} else if snapshot.image != nil {
return snapshot.image.validate(req)
}
return nil
}
// GetSnapshot constructs a snapshot object for the image given
// the snap name. It does not validate that this snapshot exists.
func (image *Image) GetSnapshot(snapname string) *Snapshot {
return &Snapshot{
image: image,
name: snapname,
}
}
// Remove the snapshot from the connected rbd image.
//
// Implements:
//
// int rbd_snap_remove(rbd_image_t image, const char *snapname);
func (snapshot *Snapshot) Remove() error {
if err := snapshot.validate(snapshotNeedsName | imageIsOpen); err != nil {
return err
}
cSnapName := C.CString(snapshot.name)
defer C.free(unsafe.Pointer(cSnapName))
return getError(C.rbd_snap_remove(snapshot.image.image, cSnapName))
}
// Rollback the image to the snapshot.
//
// Implements:
//
// int rbd_snap_rollback(rbd_image_t image, const char *snapname);
func (snapshot *Snapshot) Rollback() error {
if err := snapshot.validate(snapshotNeedsName | imageIsOpen); err != nil {
return err
}
cSnapName := C.CString(snapshot.name)
defer C.free(unsafe.Pointer(cSnapName))
return getError(C.rbd_snap_rollback(snapshot.image.image, cSnapName))
}
// Protect a snapshot from unwanted deletion.
//
// Implements:
//
// int rbd_snap_protect(rbd_image_t image, const char *snap_name);
func (snapshot *Snapshot) Protect() error {
if err := snapshot.validate(snapshotNeedsName | imageIsOpen); err != nil {
return err
}
cSnapName := C.CString(snapshot.name)
defer C.free(unsafe.Pointer(cSnapName))
return getError(C.rbd_snap_protect(snapshot.image.image, cSnapName))
}
// Unprotect stops protecting the snapshot.
//
// Implements:
//
// int rbd_snap_unprotect(rbd_image_t image, const char *snap_name);
func (snapshot *Snapshot) Unprotect() error {
if err := snapshot.validate(snapshotNeedsName | imageIsOpen); err != nil {
return err
}
cSnapName := C.CString(snapshot.name)
defer C.free(unsafe.Pointer(cSnapName))
return getError(C.rbd_snap_unprotect(snapshot.image.image, cSnapName))
}
// IsProtected returns true if the snapshot is currently protected.
//
// Implements:
//
// int rbd_snap_is_protected(rbd_image_t image, const char *snap_name,
// int *is_protected);
func (snapshot *Snapshot) IsProtected() (bool, error) {
if err := snapshot.validate(snapshotNeedsName | imageIsOpen); err != nil {
return false, err
}
var cIsProtected C.int
cSnapName := C.CString(snapshot.name)
defer C.free(unsafe.Pointer(cSnapName))
ret := C.rbd_snap_is_protected(snapshot.image.image, cSnapName,
&cIsProtected)
if ret < 0 {
return false, getError(ret)
}
return cIsProtected != 0, nil
}
// Set updates the rbd image (not the Snapshot) such that the snapshot is the
// source of readable data.
//
// Deprecated: use the SetSnapshot method of the Image type instead
//
// Implements:
//
// int rbd_snap_set(rbd_image_t image, const char *snapname);
func (snapshot *Snapshot) Set() error {
if err := snapshot.validate(snapshotNeedsName | imageIsOpen); err != nil {
return err
}
return snapshot.image.SetSnapshot(snapshot.name)
}
// GetSnapTimestamp returns the timestamp of a snapshot for an image.
// For a non-existing snap ID, GetSnapTimestamp() may trigger an assertion
// and crash in the ceph library.
// Check https://tracker.ceph.com/issues/47287 for details.
//
// Implements:
//
// int rbd_snap_get_timestamp(rbd_image_t image, uint64_t snap_id, struct timespec *timestamp)
func (image *Image) GetSnapTimestamp(snapID uint64) (Timespec, error) {
if err := image.validate(imageIsOpen); err != nil {
return Timespec{}, err
}
var cts C.struct_timespec
ret := C.rbd_snap_get_timestamp(image.image, C.uint64_t(snapID), &cts)
if ret < 0 {
return Timespec{}, getError(ret)
}
return Timespec(ts.CStructToTimespec(ts.CTimespecPtr(&cts))), nil
}