/
group_snap.go
223 lines (192 loc) · 6.92 KB
/
group_snap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
package rbd
/*
#cgo LDFLAGS: -lrbd
#include <errno.h>
#include <stdlib.h>
#include <rbd/librbd.h>
extern int snapRollbackCallback(uint64_t, uint64_t, uintptr_t);
// inline wrapper to cast uintptr_t to void*
static inline int wrap_rbd_group_snap_rollback_with_progress(
rados_ioctx_t group_p, const char *group_name,
const char *snap_name, uintptr_t arg) {
return rbd_group_snap_rollback_with_progress(
group_p, group_name, snap_name, (librbd_progress_fn_t)snapRollbackCallback, (void*)arg);
};
*/
import "C"
import (
"unsafe"
"github.com/ceph/go-ceph/internal/callbacks"
"github.com/ceph/go-ceph/internal/retry"
"github.com/ceph/go-ceph/rados"
)
// GroupSnapCreate will create a group snapshot.
//
// Implements:
// int rbd_group_snap_create(rados_ioctx_t group_p,
// const char *group_name,
// const char *snap_name);
func GroupSnapCreate(ioctx *rados.IOContext, group, snap string) error {
cGroupName := C.CString(group)
defer C.free(unsafe.Pointer(cGroupName))
cSnapName := C.CString(snap)
defer C.free(unsafe.Pointer(cSnapName))
ret := C.rbd_group_snap_create(cephIoctx(ioctx), cGroupName, cSnapName)
return getError(ret)
}
// GroupSnapRemove removes an existing group snapshot.
//
// Implements:
// int rbd_group_snap_remove(rados_ioctx_t group_p,
// const char *group_name,
// const char *snap_name);
func GroupSnapRemove(ioctx *rados.IOContext, group, snap string) error {
cGroupName := C.CString(group)
defer C.free(unsafe.Pointer(cGroupName))
cSnapName := C.CString(snap)
defer C.free(unsafe.Pointer(cSnapName))
ret := C.rbd_group_snap_remove(cephIoctx(ioctx), cGroupName, cSnapName)
return getError(ret)
}
// GroupSnapRename will rename an existing group snapshot.
//
// Implements:
// int rbd_group_snap_rename(rados_ioctx_t group_p,
// const char *group_name,
// const char *old_snap_name,
// const char *new_snap_name);
func GroupSnapRename(ioctx *rados.IOContext, group, src, dest string) error {
cGroupName := C.CString(group)
defer C.free(unsafe.Pointer(cGroupName))
cOldSnapName := C.CString(src)
defer C.free(unsafe.Pointer(cOldSnapName))
cNewSnapName := C.CString(dest)
defer C.free(unsafe.Pointer(cNewSnapName))
ret := C.rbd_group_snap_rename(
cephIoctx(ioctx), cGroupName, cOldSnapName, cNewSnapName)
return getError(ret)
}
// GroupSnapState represents the state of a group snapshot in GroupSnapInfo.
type GroupSnapState int
const (
// GroupSnapStateIncomplete is equivalent to RBD_GROUP_SNAP_STATE_INCOMPLETE.
GroupSnapStateIncomplete = GroupSnapState(C.RBD_GROUP_SNAP_STATE_INCOMPLETE)
// GroupSnapStateComplete is equivalent to RBD_GROUP_SNAP_STATE_COMPLETE.
GroupSnapStateComplete = GroupSnapState(C.RBD_GROUP_SNAP_STATE_COMPLETE)
)
// GroupSnapInfo values are returned by GroupSnapList, representing the
// snapshots that are part of an rbd group.
type GroupSnapInfo struct {
Name string
State GroupSnapState
}
// GroupSnapList returns a slice of snapshots in a group.
//
// Implements:
// int rbd_group_snap_list(rados_ioctx_t group_p,
// const char *group_name,
// rbd_group_snap_info_t *snaps,
// size_t group_snap_info_size,
// size_t *num_entries);
func GroupSnapList(ioctx *rados.IOContext, group string) ([]GroupSnapInfo, error) {
cGroupName := C.CString(group)
defer C.free(unsafe.Pointer(cGroupName))
var (
cSnaps []C.rbd_group_snap_info_t
cSize C.size_t
err error
)
retry.WithSizes(1024, 262144, func(size int) retry.Hint {
cSize = C.size_t(size)
cSnaps = make([]C.rbd_group_snap_info_t, cSize)
ret := C.rbd_group_snap_list(
cephIoctx(ioctx),
cGroupName,
(*C.rbd_group_snap_info_t)(unsafe.Pointer(&cSnaps[0])),
C.sizeof_rbd_group_snap_info_t,
&cSize)
err = getErrorIfNegative(ret)
return retry.Size(int(cSize)).If(err == errRange)
})
if err != nil {
return nil, err
}
snaps := make([]GroupSnapInfo, cSize)
for i := range snaps {
snaps[i].Name = C.GoString(cSnaps[i].name)
snaps[i].State = GroupSnapState(cSnaps[i].state)
}
// free C memory allocated by C.rbd_group_snap_list call
ret := C.rbd_group_snap_list_cleanup(
(*C.rbd_group_snap_info_t)(unsafe.Pointer(&cSnaps[0])),
C.sizeof_rbd_group_snap_info_t,
cSize)
return snaps, getError(ret)
}
// GroupSnapRollback will roll back the images in the group to that of the
// given snapshot.
//
// Implements:
// int rbd_group_snap_rollback(rados_ioctx_t group_p,
// const char *group_name,
// const char *snap_name);
func GroupSnapRollback(ioctx *rados.IOContext, group, snap string) error {
cGroupName := C.CString(group)
defer C.free(unsafe.Pointer(cGroupName))
cSnapName := C.CString(snap)
defer C.free(unsafe.Pointer(cSnapName))
ret := C.rbd_group_snap_rollback(cephIoctx(ioctx), cGroupName, cSnapName)
return getError(ret)
}
// GroupSnapRollbackCallback defines the function signature needed for the
// GroupSnapRollbackWithProgress callback.
//
// This callback will be called by GroupSnapRollbackWithProgress when it
// wishes to report progress rolling back a group snapshot.
type GroupSnapRollbackCallback func(uint64, uint64, interface{}) int
var groupSnapRollbackCallbacks = callbacks.New()
// GroupSnapRollbackWithProgress will roll back the images in the group
// to that of given snapshot. The given progress callback will be called
// to report on the progress of the snapshot rollback.
//
// Implements:
// int rbd_group_snap_rollback_with_progress(rados_ioctx_t group_p,
// const char *group_name,
// const char *snap_name,
// librbd_progress_fn_t cb,
// void *cbdata);
func GroupSnapRollbackWithProgress(
ioctx *rados.IOContext, group, snap string,
cb GroupSnapRollbackCallback, data interface{}) error {
// the provided callback must be a real function
if cb == nil {
return rbdError(C.EINVAL)
}
cGroupName := C.CString(group)
defer C.free(unsafe.Pointer(cGroupName))
cSnapName := C.CString(snap)
defer C.free(unsafe.Pointer(cSnapName))
ctx := gsnapRollbackCallbackCtx{
callback: cb,
data: data,
}
cbIndex := groupSnapRollbackCallbacks.Add(ctx)
defer diffIterateCallbacks.Remove(cbIndex)
ret := C.wrap_rbd_group_snap_rollback_with_progress(
cephIoctx(ioctx),
cGroupName,
cSnapName,
C.uintptr_t(cbIndex))
return getError(ret)
}
type gsnapRollbackCallbackCtx struct {
callback GroupSnapRollbackCallback
data interface{}
}
//export snapRollbackCallback
func snapRollbackCallback(
offset, total C.uint64_t, index uintptr) C.int {
v := groupSnapRollbackCallbacks.Lookup(index)
ctx := v.(gsnapRollbackCallbackCtx)
return C.int(ctx.callback(uint64(offset), uint64(total), ctx.data))
}