mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-11-23 23:00:19 +00:00
rebase: update go-ceph to v0.10.0
This commit updates the go-ceph to latest release. More details about release at https://github.com/ceph/go-ceph/releases/tag/v0.10.0 Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
parent
65dc573302
commit
d4b1e09815
2
go.mod
2
go.mod
@ -4,7 +4,7 @@ go 1.13
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/aws/aws-sdk-go v1.38.8
|
github.com/aws/aws-sdk-go v1.38.8
|
||||||
github.com/ceph/go-ceph v0.8.0
|
github.com/ceph/go-ceph v0.10.0
|
||||||
github.com/container-storage-interface/spec v1.3.0
|
github.com/container-storage-interface/spec v1.3.0
|
||||||
github.com/csi-addons/replication-lib-utils v0.2.0
|
github.com/csi-addons/replication-lib-utils v0.2.0
|
||||||
github.com/csi-addons/spec v0.1.0
|
github.com/csi-addons/spec v0.1.0
|
||||||
|
4
go.sum
4
go.sum
@ -192,8 +192,8 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH
|
|||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f h1:gJzxrodnNd/CtPXjO3WYiakyNzHg3rtAi7rO74ejHYU=
|
github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f h1:gJzxrodnNd/CtPXjO3WYiakyNzHg3rtAi7rO74ejHYU=
|
||||||
github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f/go.mod h1:C0rtzmGXgN78pYR0tGJFhtHgkbAs0lIbHwkB81VxDQE=
|
github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f/go.mod h1:C0rtzmGXgN78pYR0tGJFhtHgkbAs0lIbHwkB81VxDQE=
|
||||||
github.com/ceph/go-ceph v0.8.0 h1:d+VP0eyconBl9RrvKVUq7S0npyK969ErLkCt5pg2fp0=
|
github.com/ceph/go-ceph v0.10.0 h1:c9Bvqdt2ccv7aSyNBFtN9fm4dwMyfj8IX2or15tb4ag=
|
||||||
github.com/ceph/go-ceph v0.8.0/go.mod h1:wd+keAOqrcsN//20VQnHBGtnBnY0KHl0PA024Ng8HfQ=
|
github.com/ceph/go-ceph v0.10.0/go.mod h1:mafFpf5Vg8Ai8Bd+FAMvKBHLmtdpTXdRP/TNq8XWegY=
|
||||||
github.com/cespare/prettybench v0.0.0-20150116022406-03b8cfe5406c/go.mod h1:Xe6ZsFhtM8HrDku0pxJ3/Lr51rwykrzgFwpmTzleatY=
|
github.com/cespare/prettybench v0.0.0-20150116022406-03b8cfe5406c/go.mod h1:Xe6ZsFhtM8HrDku0pxJ3/Lr51rwykrzgFwpmTzleatY=
|
||||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
|
8
vendor/github.com/ceph/go-ceph/cephfs/admin/clone.go
generated
vendored
8
vendor/github.com/ceph/go-ceph/cephfs/admin/clone.go
generated
vendored
@ -53,10 +53,10 @@ func (fsa *FSAdmin) CloneSubVolumeSnapshot(volume, group, subvolume, snapshot, n
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkCloneResponse(res response) error {
|
func checkCloneResponse(res response) error {
|
||||||
if strings.HasSuffix(res.status, notProtectedSuffix) {
|
if strings.HasSuffix(res.Status(), notProtectedSuffix) {
|
||||||
return NotProtectedError{response: res}
|
return NotProtectedError{response: res}
|
||||||
}
|
}
|
||||||
return res.noData().End()
|
return res.NoData().End()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloneState is used to define constant values used to determine the state of
|
// CloneState is used to define constant values used to determine the state of
|
||||||
@ -94,7 +94,7 @@ type cloneStatusWrapper struct {
|
|||||||
|
|
||||||
func parseCloneStatus(res response) (*CloneStatus, error) {
|
func parseCloneStatus(res response) (*CloneStatus, error) {
|
||||||
var status cloneStatusWrapper
|
var status cloneStatusWrapper
|
||||||
if err := res.noStatus().unmarshal(&status).End(); err != nil {
|
if err := res.NoStatus().Unmarshal(&status).End(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &status.Status, nil
|
return &status.Status, nil
|
||||||
@ -132,5 +132,5 @@ func (fsa *FSAdmin) CancelClone(volume, group, clone string) error {
|
|||||||
if group != NoGroup {
|
if group != NoGroup {
|
||||||
m["group_name"] = group
|
m["group_name"] = group
|
||||||
}
|
}
|
||||||
return fsa.marshalMgrCommand(m).noData().End()
|
return fsa.marshalMgrCommand(m).NoData().End()
|
||||||
}
|
}
|
||||||
|
36
vendor/github.com/ceph/go-ceph/cephfs/admin/fsadmin.go
generated
vendored
36
vendor/github.com/ceph/go-ceph/cephfs/admin/fsadmin.go
generated
vendored
@ -3,18 +3,16 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
ccom "github.com/ceph/go-ceph/common/commands"
|
||||||
|
"github.com/ceph/go-ceph/internal/commands"
|
||||||
"github.com/ceph/go-ceph/rados"
|
"github.com/ceph/go-ceph/rados"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RadosCommander provides an interface to execute JSON-formatted commands that
|
// RadosCommander provides an interface to execute JSON-formatted commands that
|
||||||
// allow the cephfs administrative functions to interact with the Ceph cluster.
|
// allow the cephfs administrative functions to interact with the Ceph cluster.
|
||||||
type RadosCommander interface {
|
type RadosCommander = ccom.RadosCommander
|
||||||
MgrCommand(buf [][]byte) ([]byte, string, error)
|
|
||||||
MonCommand(buf []byte) ([]byte, string, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FSAdmin is used to administrate CephFS within a ceph cluster.
|
// FSAdmin is used to administrate CephFS within a ceph cluster.
|
||||||
type FSAdmin struct {
|
type FSAdmin struct {
|
||||||
@ -60,39 +58,25 @@ func (fsa *FSAdmin) validate() error {
|
|||||||
// rawMgrCommand takes a byte buffer and sends it to the MGR as a command.
|
// rawMgrCommand takes a byte buffer and sends it to the MGR as a command.
|
||||||
// The buffer is expected to contain preformatted JSON.
|
// The buffer is expected to contain preformatted JSON.
|
||||||
func (fsa *FSAdmin) rawMgrCommand(buf []byte) response {
|
func (fsa *FSAdmin) rawMgrCommand(buf []byte) response {
|
||||||
if err := fsa.validate(); err != nil {
|
return commands.RawMgrCommand(fsa.conn, buf)
|
||||||
return response{err: err}
|
|
||||||
}
|
|
||||||
return newResponse(fsa.conn.MgrCommand([][]byte{buf}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// marshalMgrCommand takes an generic interface{} value, converts it to JSON and
|
// marshalMgrCommand takes an generic interface{} value, converts it to JSON and
|
||||||
// sends the json to the MGR as a command.
|
// sends the json to the MGR as a command.
|
||||||
func (fsa *FSAdmin) marshalMgrCommand(v interface{}) response {
|
func (fsa *FSAdmin) marshalMgrCommand(v interface{}) response {
|
||||||
b, err := json.Marshal(v)
|
return commands.MarshalMgrCommand(fsa.conn, v)
|
||||||
if err != nil {
|
|
||||||
return response{err: err}
|
|
||||||
}
|
|
||||||
return fsa.rawMgrCommand(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// rawMonCommand takes a byte buffer and sends it to the MON as a command.
|
// rawMonCommand takes a byte buffer and sends it to the MON as a command.
|
||||||
// The buffer is expected to contain preformatted JSON.
|
// The buffer is expected to contain preformatted JSON.
|
||||||
func (fsa *FSAdmin) rawMonCommand(buf []byte) response {
|
func (fsa *FSAdmin) rawMonCommand(buf []byte) response {
|
||||||
if err := fsa.validate(); err != nil {
|
return commands.RawMonCommand(fsa.conn, buf)
|
||||||
return response{err: err}
|
|
||||||
}
|
|
||||||
return newResponse(fsa.conn.MonCommand(buf))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// marshalMonCommand takes an generic interface{} value, converts it to JSON and
|
// marshalMonCommand takes an generic interface{} value, converts it to JSON and
|
||||||
// sends the json to the MGR as a command.
|
// sends the json to the MGR as a command.
|
||||||
func (fsa *FSAdmin) marshalMonCommand(v interface{}) response {
|
func (fsa *FSAdmin) marshalMonCommand(v interface{}) response {
|
||||||
b, err := json.Marshal(v)
|
return commands.MarshalMonCommand(fsa.conn, v)
|
||||||
if err != nil {
|
|
||||||
return response{err: err}
|
|
||||||
}
|
|
||||||
return fsa.rawMonCommand(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type listNamedResult struct {
|
type listNamedResult struct {
|
||||||
@ -101,7 +85,7 @@ type listNamedResult struct {
|
|||||||
|
|
||||||
func parseListNames(res response) ([]string, error) {
|
func parseListNames(res response) ([]string, error) {
|
||||||
var r []listNamedResult
|
var r []listNamedResult
|
||||||
if err := res.noStatus().unmarshal(&r).End(); err != nil {
|
if err := res.NoStatus().Unmarshal(&r).End(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
vl := make([]string, len(r))
|
vl := make([]string, len(r))
|
||||||
@ -114,10 +98,10 @@ func parseListNames(res response) ([]string, error) {
|
|||||||
// parsePathResponse returns a cleaned up path from requests that get a path
|
// parsePathResponse returns a cleaned up path from requests that get a path
|
||||||
// unless an error is encountered, then an error is returned.
|
// unless an error is encountered, then an error is returned.
|
||||||
func parsePathResponse(res response) (string, error) {
|
func parsePathResponse(res response) (string, error) {
|
||||||
if res2 := res.noStatus(); !res2.Ok() {
|
if res2 := res.NoStatus(); !res2.Ok() {
|
||||||
return "", res.End()
|
return "", res.End()
|
||||||
}
|
}
|
||||||
b := res.body
|
b := res.Body()
|
||||||
// if there's a trailing newline in the buffer strip it.
|
// if there's a trailing newline in the buffer strip it.
|
||||||
// ceph assumes a CLI wants the output of the buffer and there's
|
// ceph assumes a CLI wants the output of the buffer and there's
|
||||||
// no format=json mode available currently.
|
// no format=json mode available currently.
|
||||||
|
136
vendor/github.com/ceph/go-ceph/cephfs/admin/response.go
generated
vendored
136
vendor/github.com/ceph/go-ceph/cephfs/admin/response.go
generated
vendored
@ -3,140 +3,22 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"github.com/ceph/go-ceph/internal/commands"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrStatusNotEmpty may be returned if a call should not have a status
|
// ErrStatusNotEmpty is an alias for commands.ErrStatusNotEmpty
|
||||||
// string set but one is.
|
ErrStatusNotEmpty = commands.ErrStatusNotEmpty
|
||||||
ErrStatusNotEmpty = errors.New("response status not empty")
|
// ErrBodyNotEmpty is an alias for commands.ErrBodyNotEmpty
|
||||||
// ErrBodyNotEmpty may be returned if a call should have an empty body but
|
ErrBodyNotEmpty = commands.ErrBodyNotEmpty
|
||||||
// a body value is present.
|
|
||||||
ErrBodyNotEmpty = errors.New("response body not empty")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
type response = commands.Response
|
||||||
deprecatedSuffix = "call is deprecated and will be removed in a future release"
|
|
||||||
missingPrefix = "No handler found"
|
|
||||||
einval = -22
|
|
||||||
)
|
|
||||||
|
|
||||||
type cephError interface {
|
// NotImplementedError is an alias for commands.NotImplementedError.
|
||||||
ErrorCode() int
|
type NotImplementedError = commands.NotImplementedError
|
||||||
}
|
|
||||||
|
|
||||||
// NotImplementedError error values will be returned in the case that an API
|
|
||||||
// call is not available in the version of Ceph that is running in the target
|
|
||||||
// cluster.
|
|
||||||
type NotImplementedError struct {
|
|
||||||
response
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e NotImplementedError) Error() string {
|
|
||||||
return fmt.Sprintf("API call not implemented server-side: %s", e.status)
|
|
||||||
}
|
|
||||||
|
|
||||||
// response encapsulates the data returned by ceph and supports easy processing
|
|
||||||
// pipelines.
|
|
||||||
type response struct {
|
|
||||||
body []byte
|
|
||||||
status string
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ok returns true if the response contains no error.
|
|
||||||
func (r response) Ok() bool {
|
|
||||||
return r.err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (r response) Error() string {
|
|
||||||
if r.status == "" {
|
|
||||||
return r.err.Error()
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s: %q", r.err, r.status)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap returns the error this response contains.
|
|
||||||
func (r response) Unwrap() error {
|
|
||||||
return r.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status returns the status string value.
|
|
||||||
func (r response) Status() string {
|
|
||||||
return r.status
|
|
||||||
}
|
|
||||||
|
|
||||||
// End returns an error if the response contains an error or nil, indicating
|
|
||||||
// that response is no longer needed for processing.
|
|
||||||
func (r response) End() error {
|
|
||||||
if !r.Ok() {
|
|
||||||
if ce, ok := r.err.(cephError); ok {
|
|
||||||
if ce.ErrorCode() == einval && strings.HasPrefix(r.status, missingPrefix) {
|
|
||||||
return NotImplementedError{response: r}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// noStatus asserts that the input response has no status value.
|
|
||||||
func (r response) noStatus() response {
|
|
||||||
if !r.Ok() {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
if r.status != "" {
|
|
||||||
return response{r.body, r.status, ErrStatusNotEmpty}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// noBody asserts that the input response has no body value.
|
|
||||||
func (r response) noBody() response {
|
|
||||||
if !r.Ok() {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
if len(r.body) != 0 {
|
|
||||||
return response{r.body, r.status, ErrBodyNotEmpty}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// noData asserts that the input response has no status or body values.
|
|
||||||
func (r response) noData() response {
|
|
||||||
return r.noStatus().noBody()
|
|
||||||
}
|
|
||||||
|
|
||||||
// filterDeprecated removes deprecation warnings from the response status.
|
|
||||||
// Use it when checking the response from calls that may be deprecated in ceph
|
|
||||||
// if you want those calls to continue working if the warning is present.
|
|
||||||
func (r response) filterDeprecated() response {
|
|
||||||
if !r.Ok() {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(r.status, deprecatedSuffix) {
|
|
||||||
return response{r.body, "", r.err}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// unmarshal data from the response body into v.
|
|
||||||
func (r response) unmarshal(v interface{}) response {
|
|
||||||
if !r.Ok() {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(r.body, v); err != nil {
|
|
||||||
return response{body: r.body, err: err}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// newResponse returns a response.
|
// newResponse returns a response.
|
||||||
func newResponse(b []byte, s string, e error) response {
|
func newResponse(b []byte, s string, e error) response {
|
||||||
return response{b, s, e}
|
return commands.NewResponse(b, s, e)
|
||||||
}
|
}
|
||||||
|
18
vendor/github.com/ceph/go-ceph/cephfs/admin/subvolume.go
generated
vendored
18
vendor/github.com/ceph/go-ceph/cephfs/admin/subvolume.go
generated
vendored
@ -61,7 +61,7 @@ func (fsa *FSAdmin) CreateSubVolume(volume, group, name string, o *SubVolumeOpti
|
|||||||
o = &SubVolumeOptions{}
|
o = &SubVolumeOptions{}
|
||||||
}
|
}
|
||||||
f := o.toFields(volume, group, name)
|
f := o.toFields(volume, group, name)
|
||||||
return fsa.marshalMgrCommand(f).noData().End()
|
return fsa.marshalMgrCommand(f).NoData().End()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListSubVolumes returns a list of subvolumes belonging to the volume and
|
// ListSubVolumes returns a list of subvolumes belonging to the volume and
|
||||||
@ -117,7 +117,7 @@ func (fsa *FSAdmin) RemoveSubVolumeWithFlags(volume, group, name string, o SubVo
|
|||||||
if group != NoGroup {
|
if group != NoGroup {
|
||||||
m["group_name"] = group
|
m["group_name"] = group
|
||||||
}
|
}
|
||||||
return fsa.marshalMgrCommand(mergeFlags(m, o)).noData().End()
|
return fsa.marshalMgrCommand(mergeFlags(m, o)).NoData().End()
|
||||||
}
|
}
|
||||||
|
|
||||||
type subVolumeResizeFields struct {
|
type subVolumeResizeFields struct {
|
||||||
@ -159,7 +159,7 @@ func (fsa *FSAdmin) ResizeSubVolume(
|
|||||||
}
|
}
|
||||||
var result []*SubVolumeResizeResult
|
var result []*SubVolumeResizeResult
|
||||||
res := fsa.marshalMgrCommand(f)
|
res := fsa.marshalMgrCommand(f)
|
||||||
if err := res.noStatus().unmarshal(&result).End(); err != nil {
|
if err := res.NoStatus().Unmarshal(&result).End(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return result[0], nil
|
return result[0], nil
|
||||||
@ -248,7 +248,7 @@ type subVolumeInfoWrapper struct {
|
|||||||
|
|
||||||
func parseSubVolumeInfo(res response) (*SubVolumeInfo, error) {
|
func parseSubVolumeInfo(res response) (*SubVolumeInfo, error) {
|
||||||
var info subVolumeInfoWrapper
|
var info subVolumeInfoWrapper
|
||||||
if err := res.noStatus().unmarshal(&info).End(); err != nil {
|
if err := res.NoStatus().Unmarshal(&info).End(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if info.VBytesQuota != nil {
|
if info.VBytesQuota != nil {
|
||||||
@ -289,7 +289,7 @@ func (fsa *FSAdmin) CreateSubVolumeSnapshot(volume, group, source, name string)
|
|||||||
if group != NoGroup {
|
if group != NoGroup {
|
||||||
m["group_name"] = group
|
m["group_name"] = group
|
||||||
}
|
}
|
||||||
return fsa.marshalMgrCommand(m).noData().End()
|
return fsa.marshalMgrCommand(m).NoData().End()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveSubVolumeSnapshot removes the specified snapshot from the subvolume.
|
// RemoveSubVolumeSnapshot removes the specified snapshot from the subvolume.
|
||||||
@ -320,7 +320,7 @@ func (fsa *FSAdmin) rmSubVolumeSnapshot(volume, group, subvolume, name string, o
|
|||||||
if group != NoGroup {
|
if group != NoGroup {
|
||||||
m["group_name"] = group
|
m["group_name"] = group
|
||||||
}
|
}
|
||||||
return fsa.marshalMgrCommand(mergeFlags(m, o)).noData().End()
|
return fsa.marshalMgrCommand(mergeFlags(m, o)).NoData().End()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListSubVolumeSnapshots returns a listing of snapshots for a given subvolume.
|
// ListSubVolumeSnapshots returns a listing of snapshots for a given subvolume.
|
||||||
@ -351,7 +351,7 @@ type SubVolumeSnapshotInfo struct {
|
|||||||
|
|
||||||
func parseSubVolumeSnapshotInfo(res response) (*SubVolumeSnapshotInfo, error) {
|
func parseSubVolumeSnapshotInfo(res response) (*SubVolumeSnapshotInfo, error) {
|
||||||
var info SubVolumeSnapshotInfo
|
var info SubVolumeSnapshotInfo
|
||||||
if err := res.noStatus().unmarshal(&info).End(); err != nil {
|
if err := res.NoStatus().Unmarshal(&info).End(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &info, nil
|
return &info, nil
|
||||||
@ -390,7 +390,7 @@ func (fsa *FSAdmin) ProtectSubVolumeSnapshot(volume, group, subvolume, name stri
|
|||||||
if group != NoGroup {
|
if group != NoGroup {
|
||||||
m["group_name"] = group
|
m["group_name"] = group
|
||||||
}
|
}
|
||||||
return fsa.marshalMgrCommand(m).filterDeprecated().noData().End()
|
return fsa.marshalMgrCommand(m).FilterDeprecated().NoData().End()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnprotectSubVolumeSnapshot removes protection from the specified snapshot.
|
// UnprotectSubVolumeSnapshot removes protection from the specified snapshot.
|
||||||
@ -408,5 +408,5 @@ func (fsa *FSAdmin) UnprotectSubVolumeSnapshot(volume, group, subvolume, name st
|
|||||||
if group != NoGroup {
|
if group != NoGroup {
|
||||||
m["group_name"] = group
|
m["group_name"] = group
|
||||||
}
|
}
|
||||||
return fsa.marshalMgrCommand(m).filterDeprecated().noData().End()
|
return fsa.marshalMgrCommand(m).FilterDeprecated().NoData().End()
|
||||||
}
|
}
|
||||||
|
4
vendor/github.com/ceph/go-ceph/cephfs/admin/subvolumegroup.go
generated
vendored
4
vendor/github.com/ceph/go-ceph/cephfs/admin/subvolumegroup.go
generated
vendored
@ -48,7 +48,7 @@ func (fsa *FSAdmin) CreateSubVolumeGroup(volume, name string, o *SubVolumeGroupO
|
|||||||
o = &SubVolumeGroupOptions{}
|
o = &SubVolumeGroupOptions{}
|
||||||
}
|
}
|
||||||
res := fsa.marshalMgrCommand(o.toFields(volume, name))
|
res := fsa.marshalMgrCommand(o.toFields(volume, name))
|
||||||
return res.noData().End()
|
return res.NoData().End()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListSubVolumeGroups returns a list of subvolume groups belonging to the
|
// ListSubVolumeGroups returns a list of subvolume groups belonging to the
|
||||||
@ -86,7 +86,7 @@ func (fsa *FSAdmin) rmSubVolumeGroup(volume, name string, o commonRmFlags) error
|
|||||||
"group_name": name,
|
"group_name": name,
|
||||||
"format": "json",
|
"format": "json",
|
||||||
}, o))
|
}, o))
|
||||||
return res.noData().End()
|
return res.NoData().End()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubVolumeGroupPath returns the path to the subvolume from the root of the
|
// SubVolumeGroupPath returns the path to the subvolume from the root of the
|
||||||
|
20
vendor/github.com/ceph/go-ceph/cephfs/admin/volume.go
generated
vendored
20
vendor/github.com/ceph/go-ceph/cephfs/admin/volume.go
generated
vendored
@ -43,7 +43,7 @@ func (fsa *FSAdmin) ListFileSystems() ([]FSPoolInfo, error) {
|
|||||||
|
|
||||||
func parseFsList(res response) ([]FSPoolInfo, error) {
|
func parseFsList(res response) ([]FSPoolInfo, error) {
|
||||||
var listing []FSPoolInfo
|
var listing []FSPoolInfo
|
||||||
if err := res.noStatus().unmarshal(&listing).End(); err != nil {
|
if err := res.NoStatus().Unmarshal(&listing).End(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return listing, nil
|
return listing, nil
|
||||||
@ -78,13 +78,8 @@ func parseDumpToIdents(res response) ([]VolumeIdent, error) {
|
|||||||
if !res.Ok() {
|
if !res.Ok() {
|
||||||
return nil, res.End()
|
return nil, res.End()
|
||||||
}
|
}
|
||||||
if len(res.status) >= dumpOkLen && res.status[:dumpOkLen] == dumpOkPrefix {
|
|
||||||
// Unhelpfully, ceph drops a status string on success responses for this
|
|
||||||
// call. this hacks around that by ignoring its typical prefix
|
|
||||||
res.status = ""
|
|
||||||
}
|
|
||||||
var dump fsDump
|
var dump fsDump
|
||||||
if err := res.noStatus().unmarshal(&dump).End(); err != nil {
|
if err := res.FilterPrefix(dumpOkPrefix).NoStatus().Unmarshal(&dump).End(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// copy the dump json into the simpler enumeration list
|
// copy the dump json into the simpler enumeration list
|
||||||
@ -123,15 +118,16 @@ type VolumeStatus struct {
|
|||||||
|
|
||||||
func parseVolumeStatus(res response) (*VolumeStatus, error) {
|
func parseVolumeStatus(res response) (*VolumeStatus, error) {
|
||||||
var vs VolumeStatus
|
var vs VolumeStatus
|
||||||
res = res.noStatus()
|
res = res.NoStatus()
|
||||||
if !res.Ok() {
|
if !res.Ok() {
|
||||||
return nil, res.End()
|
return nil, res.End()
|
||||||
}
|
}
|
||||||
res = res.unmarshal(&vs)
|
res = res.Unmarshal(&vs)
|
||||||
if !res.Ok() {
|
if !res.Ok() {
|
||||||
if bytes.HasPrefix(res.body, []byte("ceph")) {
|
if bytes.HasPrefix(res.Body(), []byte("ceph")) {
|
||||||
res.status = invalidTextualResponse
|
return nil, NotImplementedError{
|
||||||
return nil, NotImplementedError{response: res}
|
Response: newResponse(res.Body(), invalidTextualResponse, res.Unwrap()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil, res.End()
|
return nil, res.End()
|
||||||
}
|
}
|
||||||
|
7
vendor/github.com/ceph/go-ceph/common/commands/doc.go
generated
vendored
Normal file
7
vendor/github.com/ceph/go-ceph/common/commands/doc.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
Package commands provides types and utility functions that are used for
|
||||||
|
interfacing with the JSON based command infrastructure in Ceph.
|
||||||
|
|
||||||
|
The *rados.Conn type implements many of the interfaces found in this package.
|
||||||
|
*/
|
||||||
|
package commands
|
20
vendor/github.com/ceph/go-ceph/common/commands/interfaces.go
generated
vendored
Normal file
20
vendor/github.com/ceph/go-ceph/common/commands/interfaces.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
// MgrCommander in an interface for the API needed to execute JSON formatted
|
||||||
|
// commands on the ceph mgr.
|
||||||
|
type MgrCommander interface {
|
||||||
|
MgrCommand(buf [][]byte) ([]byte, string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MonCommander is an interface for the API needed to execute JSON formatted
|
||||||
|
// commands on the ceph mon(s).
|
||||||
|
type MonCommander interface {
|
||||||
|
MonCommand(buf []byte) ([]byte, string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RadosCommander provides an interface for APIs needed to execute JSON
|
||||||
|
// formatted commands on the Ceph cluster.
|
||||||
|
type RadosCommander interface {
|
||||||
|
MgrCommander
|
||||||
|
MonCommander
|
||||||
|
}
|
53
vendor/github.com/ceph/go-ceph/internal/commands/commands.go
generated
vendored
Normal file
53
vendor/github.com/ceph/go-ceph/internal/commands/commands.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
ccom "github.com/ceph/go-ceph/common/commands"
|
||||||
|
"github.com/ceph/go-ceph/rados"
|
||||||
|
)
|
||||||
|
|
||||||
|
func validate(m interface{}) error {
|
||||||
|
if m == nil {
|
||||||
|
return rados.ErrNotConnected
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RawMgrCommand takes a byte buffer and sends it to the MGR as a command.
|
||||||
|
// The buffer is expected to contain preformatted JSON.
|
||||||
|
func RawMgrCommand(m ccom.MgrCommander, buf []byte) Response {
|
||||||
|
if err := validate(m); err != nil {
|
||||||
|
return Response{err: err}
|
||||||
|
}
|
||||||
|
return NewResponse(m.MgrCommand([][]byte{buf}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalMgrCommand takes an generic interface{} value, converts it to JSON
|
||||||
|
// and sends the json to the MGR as a command.
|
||||||
|
func MarshalMgrCommand(m ccom.MgrCommander, v interface{}) Response {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return Response{err: err}
|
||||||
|
}
|
||||||
|
return RawMgrCommand(m, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RawMonCommand takes a byte buffer and sends it to the MON as a command.
|
||||||
|
// The buffer is expected to contain preformatted JSON.
|
||||||
|
func RawMonCommand(m ccom.MonCommander, buf []byte) Response {
|
||||||
|
if err := validate(m); err != nil {
|
||||||
|
return Response{err: err}
|
||||||
|
}
|
||||||
|
return NewResponse(m.MonCommand(buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalMonCommand takes an generic interface{} value, converts it to JSON
|
||||||
|
// and sends the json to the MGR as a command.
|
||||||
|
func MarshalMonCommand(m ccom.MonCommander, v interface{}) Response {
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
return Response{err: err}
|
||||||
|
}
|
||||||
|
return RawMonCommand(m, b)
|
||||||
|
}
|
163
vendor/github.com/ceph/go-ceph/internal/commands/response.go
generated
vendored
Normal file
163
vendor/github.com/ceph/go-ceph/internal/commands/response.go
generated
vendored
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrStatusNotEmpty may be returned if a call should not have a status
|
||||||
|
// string set but one is.
|
||||||
|
ErrStatusNotEmpty = errors.New("response status not empty")
|
||||||
|
// ErrBodyNotEmpty may be returned if a call should have an empty body but
|
||||||
|
// a body value is present.
|
||||||
|
ErrBodyNotEmpty = errors.New("response body not empty")
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
deprecatedSuffix = "call is deprecated and will be removed in a future release"
|
||||||
|
missingPrefix = "No handler found"
|
||||||
|
einval = -22
|
||||||
|
)
|
||||||
|
|
||||||
|
type cephError interface {
|
||||||
|
ErrorCode() int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotImplementedError error values will be returned in the case that an API
|
||||||
|
// call is not available in the version of Ceph that is running in the target
|
||||||
|
// cluster.
|
||||||
|
type NotImplementedError struct {
|
||||||
|
Response
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e NotImplementedError) Error() string {
|
||||||
|
return fmt.Sprintf("API call not implemented server-side: %s", e.status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response encapsulates the data returned by ceph and supports easy processing
|
||||||
|
// pipelines.
|
||||||
|
type Response struct {
|
||||||
|
body []byte
|
||||||
|
status string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ok returns true if the response contains no error.
|
||||||
|
func (r Response) Ok() bool {
|
||||||
|
return r.err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (r Response) Error() string {
|
||||||
|
if r.status == "" {
|
||||||
|
return r.err.Error()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s: %q", r.err, r.status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap returns the error this response contains.
|
||||||
|
func (r Response) Unwrap() error {
|
||||||
|
return r.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status returns the status string value.
|
||||||
|
func (r Response) Status() string {
|
||||||
|
return r.status
|
||||||
|
}
|
||||||
|
|
||||||
|
// Body returns the response body as a raw byte-slice.
|
||||||
|
func (r Response) Body() []byte {
|
||||||
|
return r.body
|
||||||
|
}
|
||||||
|
|
||||||
|
// End returns an error if the response contains an error or nil, indicating
|
||||||
|
// that response is no longer needed for processing.
|
||||||
|
func (r Response) End() error {
|
||||||
|
if !r.Ok() {
|
||||||
|
if ce, ok := r.err.(cephError); ok {
|
||||||
|
if ce.ErrorCode() == einval && strings.HasPrefix(r.status, missingPrefix) {
|
||||||
|
return NotImplementedError{Response: r}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoStatus asserts that the input response has no status value.
|
||||||
|
func (r Response) NoStatus() Response {
|
||||||
|
if !r.Ok() {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
if r.status != "" {
|
||||||
|
return Response{r.body, r.status, ErrStatusNotEmpty}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoBody asserts that the input response has no body value.
|
||||||
|
func (r Response) NoBody() Response {
|
||||||
|
if !r.Ok() {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
if len(r.body) != 0 {
|
||||||
|
return Response{r.body, r.status, ErrBodyNotEmpty}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoData asserts that the input response has no status or body values.
|
||||||
|
func (r Response) NoData() Response {
|
||||||
|
return r.NoStatus().NoBody()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterPrefix sets the status value to an empty string if the status
|
||||||
|
// value contains the given prefix string.
|
||||||
|
func (r Response) FilterPrefix(p string) Response {
|
||||||
|
if !r.Ok() {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(r.status, p) {
|
||||||
|
return Response{r.body, "", r.err}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterSuffix sets the status value to an empty string if the status
|
||||||
|
// value contains the given suffix string.
|
||||||
|
func (r Response) FilterSuffix(s string) Response {
|
||||||
|
if !r.Ok() {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(r.status, s) {
|
||||||
|
return Response{r.body, "", r.err}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterDeprecated removes deprecation warnings from the response status.
|
||||||
|
// Use it when checking the response from calls that may be deprecated in ceph
|
||||||
|
// if you want those calls to continue working if the warning is present.
|
||||||
|
func (r Response) FilterDeprecated() Response {
|
||||||
|
return r.FilterSuffix(deprecatedSuffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal data from the response body into v.
|
||||||
|
func (r Response) Unmarshal(v interface{}) Response {
|
||||||
|
if !r.Ok() {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(r.body, v); err != nil {
|
||||||
|
return Response{body: r.body, err: err}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewResponse returns a response.
|
||||||
|
func NewResponse(b []byte, s string, e error) Response {
|
||||||
|
return Response{b, s, e}
|
||||||
|
}
|
53
vendor/github.com/ceph/go-ceph/internal/commands/trace.go
generated
vendored
Normal file
53
vendor/github.com/ceph/go-ceph/internal/commands/trace.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
ccom "github.com/ceph/go-ceph/common/commands"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewTraceCommander is a RadosCommander that wraps a given RadosCommander
|
||||||
|
// and when commands are executes prints debug level "traces" to the
|
||||||
|
// standard output.
|
||||||
|
func NewTraceCommander(c ccom.RadosCommander) ccom.RadosCommander {
|
||||||
|
return &tracingCommander{c}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tracingCommander serves two purposes: first, it allows one to trace the
|
||||||
|
// input and output json when running the tests. It can help with actually
|
||||||
|
// debugging the tests. Second, it demonstrates the rationale for using an
|
||||||
|
// interface in FSAdmin. You can layer any sort of debugging, error injection,
|
||||||
|
// or whatnot between the FSAdmin layer and the RADOS layer.
|
||||||
|
type tracingCommander struct {
|
||||||
|
conn ccom.RadosCommander
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tracingCommander) MgrCommand(buf [][]byte) ([]byte, string, error) {
|
||||||
|
fmt.Println("(MGR Command)")
|
||||||
|
for i := range buf {
|
||||||
|
fmt.Println("IN:", string(buf[i]))
|
||||||
|
}
|
||||||
|
r, s, err := t.conn.MgrCommand(buf)
|
||||||
|
fmt.Println("OUT(result):", string(r))
|
||||||
|
if s != "" {
|
||||||
|
fmt.Println("OUT(status):", s)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("OUT(error):", err.Error())
|
||||||
|
}
|
||||||
|
return r, s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tracingCommander) MonCommand(buf []byte) ([]byte, string, error) {
|
||||||
|
fmt.Println("(MON Command)")
|
||||||
|
fmt.Println("IN:", string(buf))
|
||||||
|
r, s, err := t.conn.MonCommand(buf)
|
||||||
|
fmt.Println("OUT(result):", string(r))
|
||||||
|
if s != "" {
|
||||||
|
fmt.Println("OUT(status):", s)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("OUT(error):", err.Error())
|
||||||
|
}
|
||||||
|
return r, s, err
|
||||||
|
}
|
3
vendor/github.com/ceph/go-ceph/internal/cutil/aliases.go
generated
vendored
3
vendor/github.com/ceph/go-ceph/internal/cutil/aliases.go
generated
vendored
@ -8,12 +8,13 @@ typedef void* voidptr;
|
|||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// MaxIdx is the maximum index on 32 bit systems
|
// MaxIdx is the maximum index on 32 bit systems
|
||||||
MaxIdx = 1<<31 - 1 // 2GB, max int32 value, should be safe
|
MaxIdx = math.MaxInt32 // 2GB, max int32 value, should be safe
|
||||||
|
|
||||||
// PtrSize is the size of a pointer
|
// PtrSize is the size of a pointer
|
||||||
PtrSize = C.sizeof_voidptr
|
PtrSize = C.sizeof_voidptr
|
||||||
|
76
vendor/github.com/ceph/go-ceph/internal/cutil/cslice.go
generated
vendored
Normal file
76
vendor/github.com/ceph/go-ceph/internal/cutil/cslice.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package cutil
|
||||||
|
|
||||||
|
// The following code needs some explanation:
|
||||||
|
// This creates slices on top of the C memory buffers allocated before in
|
||||||
|
// order to safely and comfortably use them as arrays. First the void pointer
|
||||||
|
// is cast to a pointer to an array of the type that will be stored in the
|
||||||
|
// array. Because the size of an array is a constant, but the real array size
|
||||||
|
// is dynamic, we just use the biggest possible index value MaxIdx, to make
|
||||||
|
// sure it's always big enough. (Nothing is allocated by casting, so the size
|
||||||
|
// can be arbitrarily big.) So, if the array should store items of myType, the
|
||||||
|
// cast would be (*[MaxIdx]myItem)(myCMemPtr).
|
||||||
|
// From that array pointer a slice is created with the [start:end:capacity]
|
||||||
|
// syntax. The capacity must be set explicitly here, because by default it
|
||||||
|
// would be set to the size of the original array, which is MaxIdx, which
|
||||||
|
// doesn't reflect reality in this case. This results in definitions like:
|
||||||
|
// cSlice := (*[MaxIdx]myItem)(myCMemPtr)[:numOfItems:numOfItems]
|
||||||
|
|
||||||
|
////////// CPtr //////////
|
||||||
|
|
||||||
|
// CPtrCSlice is a C allocated slice of C pointers.
|
||||||
|
type CPtrCSlice []CPtr
|
||||||
|
|
||||||
|
// NewCPtrCSlice returns a CPtrSlice.
|
||||||
|
// Similar to CString it must be freed with slice.Free()
|
||||||
|
func NewCPtrCSlice(size int) CPtrCSlice {
|
||||||
|
if size == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cMem := Malloc(SizeT(size) * PtrSize)
|
||||||
|
cSlice := (*[MaxIdx]CPtr)(cMem)[:size:size]
|
||||||
|
return cSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ptr returns a pointer to CPtrSlice
|
||||||
|
func (v *CPtrCSlice) Ptr() CPtr {
|
||||||
|
if len(*v) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return CPtr(&(*v)[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free frees a CPtrSlice
|
||||||
|
func (v *CPtrCSlice) Free() {
|
||||||
|
Free(v.Ptr())
|
||||||
|
*v = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
////////// SizeT //////////
|
||||||
|
|
||||||
|
// SizeTCSlice is a C allocated slice of C.size_t.
|
||||||
|
type SizeTCSlice []SizeT
|
||||||
|
|
||||||
|
// NewSizeTCSlice returns a SizeTCSlice.
|
||||||
|
// Similar to CString it must be freed with slice.Free()
|
||||||
|
func NewSizeTCSlice(size int) SizeTCSlice {
|
||||||
|
if size == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cMem := Malloc(SizeT(size) * SizeTSize)
|
||||||
|
cSlice := (*[MaxIdx]SizeT)(cMem)[:size:size]
|
||||||
|
return cSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ptr returns a pointer to SizeTCSlice
|
||||||
|
func (v *SizeTCSlice) Ptr() CPtr {
|
||||||
|
if len(*v) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return CPtr(&(*v)[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free frees a SizeTCSlice
|
||||||
|
func (v *SizeTCSlice) Free() {
|
||||||
|
Free(v.Ptr())
|
||||||
|
*v = nil
|
||||||
|
}
|
13
vendor/github.com/ceph/go-ceph/internal/cutil/ptrguard.go
generated
vendored
13
vendor/github.com/ceph/go-ceph/internal/cutil/ptrguard.go
generated
vendored
@ -57,6 +57,17 @@ func (v *PtrGuard) Release() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The uintptrPtr() helper function below assumes that uintptr has the same size
|
||||||
|
// as a pointer, although in theory it could be larger. Therefore we use this
|
||||||
|
// constant expression to assert size equality as a safeguard at compile time.
|
||||||
|
// How it works: the difference of both sizes is converted into an 8 bit value
|
||||||
|
// and left-bit-shifted by 8. This always creates an overflow error at compile
|
||||||
|
// time, if the difference of the sizes is not 0.
|
||||||
|
const _ = uint8(unsafe.Sizeof(uintptr(0))-PtrSize) << 8 // size assert
|
||||||
|
func uintptrPtr(p *CPtr) *uintptr {
|
||||||
|
return (*uintptr)(unsafe.Pointer(p))
|
||||||
|
}
|
||||||
|
|
||||||
//go:uintptrescapes
|
//go:uintptrescapes
|
||||||
|
|
||||||
// From https://golang.org/src/cmd/compile/internal/gc/lex.go:
|
// From https://golang.org/src/cmd/compile/internal/gc/lex.go:
|
||||||
@ -69,7 +80,7 @@ func (v *PtrGuard) Release() {
|
|||||||
// Also see https://golang.org/cmd/compile/#hdr-Compiler_Directives
|
// Also see https://golang.org/cmd/compile/#hdr-Compiler_Directives
|
||||||
|
|
||||||
func storeUntilRelease(v *PtrGuard, cPtr *CPtr, goPtr uintptr) {
|
func storeUntilRelease(v *PtrGuard, cPtr *CPtr, goPtr uintptr) {
|
||||||
uip := (*uintptr)(unsafe.Pointer(cPtr))
|
uip := uintptrPtr(cPtr)
|
||||||
*uip = goPtr // store Go pointer in C memory at c_ptr
|
*uip = goPtr // store Go pointer in C memory at c_ptr
|
||||||
v.stored.Unlock() // send "stored" signal to main thread -->(1)
|
v.stored.Unlock() // send "stored" signal to main thread -->(1)
|
||||||
v.release.Lock() // wait for "release" signal from main thread when
|
v.release.Lock() // wait for "release" signal from main thread when
|
||||||
|
29
vendor/github.com/ceph/go-ceph/rados/ioctx.go
generated
vendored
29
vendor/github.com/ceph/go-ceph/rados/ioctx.go
generated
vendored
@ -658,3 +658,32 @@ func (ioctx *IOContext) GetLastVersion() (uint64, error) {
|
|||||||
v := C.rados_get_last_version(ioctx.ioctx)
|
v := C.rados_get_last_version(ioctx.ioctx)
|
||||||
return uint64(v), nil
|
return uint64(v), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNamespace gets the namespace used for objects within this IO context.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rados_ioctx_get_namespace(rados_ioctx_t io, char *buf,
|
||||||
|
// unsigned maxlen);
|
||||||
|
func (ioctx *IOContext) GetNamespace() (string, error) {
|
||||||
|
if err := ioctx.validate(); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
buf []byte
|
||||||
|
ret C.int
|
||||||
|
)
|
||||||
|
retry.WithSizes(128, 8192, func(size int) retry.Hint {
|
||||||
|
buf = make([]byte, size)
|
||||||
|
ret = C.rados_ioctx_get_namespace(
|
||||||
|
ioctx.ioctx,
|
||||||
|
(*C.char)(unsafe.Pointer(&buf[0])),
|
||||||
|
C.unsigned(len(buf)))
|
||||||
|
err = getErrorIfNegative(ret)
|
||||||
|
return retry.DoubleSize.If(err == errRange)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(buf[:ret]), nil
|
||||||
|
}
|
||||||
|
49
vendor/github.com/ceph/go-ceph/rados/ioctx_nautilus.go
generated
vendored
49
vendor/github.com/ceph/go-ceph/rados/ioctx_nautilus.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// +build !luminous,!mimic
|
// +build nautilus
|
||||||
|
|
||||||
package rados
|
package rados
|
||||||
|
|
||||||
@ -7,37 +7,28 @@ package rados
|
|||||||
//
|
//
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
// SetPoolFullTry makes sure to send requests to the cluster despite
|
||||||
"unsafe"
|
// the cluster or pool being marked full; ops will either succeed(e.g., delete)
|
||||||
|
// or return EDQUOT or ENOSPC.
|
||||||
"github.com/ceph/go-ceph/internal/retry"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetNamespace gets the namespace used for objects within this IO context.
|
|
||||||
//
|
//
|
||||||
// Implements:
|
// Implements:
|
||||||
// int rados_ioctx_get_namespace(rados_ioctx_t io, char *buf,
|
// void rados_set_osdmap_full_try(rados_ioctx_t io);
|
||||||
// unsigned maxlen);
|
func (ioctx *IOContext) SetPoolFullTry() error {
|
||||||
func (ioctx *IOContext) GetNamespace() (string, error) {
|
|
||||||
if err := ioctx.validate(); err != nil {
|
if err := ioctx.validate(); err != nil {
|
||||||
return "", err
|
return err
|
||||||
}
|
}
|
||||||
var (
|
C.rados_set_osdmap_full_try(ioctx.ioctx)
|
||||||
err error
|
return nil
|
||||||
buf []byte
|
|
||||||
ret C.int
|
|
||||||
)
|
|
||||||
retry.WithSizes(128, 8192, func(size int) retry.Hint {
|
|
||||||
buf = make([]byte, size)
|
|
||||||
ret = C.rados_ioctx_get_namespace(
|
|
||||||
ioctx.ioctx,
|
|
||||||
(*C.char)(unsafe.Pointer(&buf[0])),
|
|
||||||
C.unsigned(len(buf)))
|
|
||||||
err = getErrorIfNegative(ret)
|
|
||||||
return retry.DoubleSize.If(err == errRange)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
return string(buf[:ret]), nil
|
|
||||||
|
// UnsetPoolFullTry unsets the flag set by SetPoolFullTry()
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// void rados_unset_osdmap_full_try(rados_ioctx_t io);
|
||||||
|
func (ioctx *IOContext) UnsetPoolFullTry() error {
|
||||||
|
if err := ioctx.validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
C.rados_unset_osdmap_full_try(ioctx.ioctx)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
37
vendor/github.com/ceph/go-ceph/rados/ioctx_octopus.go
generated
vendored
Normal file
37
vendor/github.com/ceph/go-ceph/rados/ioctx_octopus.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// +build !nautilus
|
||||||
|
|
||||||
|
package rados
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: -lrados
|
||||||
|
// #include <rados/librados.h>
|
||||||
|
//
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// Ceph octopus deprecates rados_set_osdmap_full_try() and implements rados_set_pool_full_try()
|
||||||
|
// Ceph octopus deprecates rados_unset_osdmap_full_try() and implements rados_unset_pool_full_try()
|
||||||
|
|
||||||
|
// SetPoolFullTry makes sure to send requests to the cluster despite
|
||||||
|
// the cluster or pool being marked full; ops will either succeed(e.g., delete)
|
||||||
|
// or return EDQUOT or ENOSPC.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// void rados_set_pool_full_try(rados_ioctx_t io);
|
||||||
|
func (ioctx *IOContext) SetPoolFullTry() error {
|
||||||
|
if err := ioctx.validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
C.rados_set_pool_full_try(ioctx.ioctx)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsetPoolFullTry unsets the flag set by SetPoolFullTry()
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// void rados_unset_pool_full_try(rados_ioctx_t io);
|
||||||
|
func (ioctx *IOContext) UnsetPoolFullTry() error {
|
||||||
|
if err := ioctx.validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
C.rados_unset_pool_full_try(ioctx.ioctx)
|
||||||
|
return nil
|
||||||
|
}
|
66
vendor/github.com/ceph/go-ceph/rados/omap.go
generated
vendored
66
vendor/github.com/ceph/go-ceph/rados/omap.go
generated
vendored
@ -4,20 +4,14 @@ package rados
|
|||||||
#cgo LDFLAGS: -lrados
|
#cgo LDFLAGS: -lrados
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <rados/librados.h>
|
#include <rados/librados.h>
|
||||||
|
|
||||||
typedef void* voidptr;
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
"github.com/ceph/go-ceph/internal/cutil"
|
||||||
ptrSize = C.sizeof_voidptr
|
|
||||||
sizeTSize = C.sizeof_size_t
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// setOmapStep is a write op step. It holds C memory used in the operation.
|
// setOmapStep is a write op step. It holds C memory used in the operation.
|
||||||
@ -26,50 +20,44 @@ type setOmapStep struct {
|
|||||||
withoutUpdate
|
withoutUpdate
|
||||||
|
|
||||||
// C arguments
|
// C arguments
|
||||||
cKeys **C.char
|
cKeys cutil.CPtrCSlice
|
||||||
cValues **C.char
|
cValues cutil.CPtrCSlice
|
||||||
cLengths *C.size_t
|
cLengths cutil.SizeTCSlice
|
||||||
cNum C.size_t
|
cNum C.size_t
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSetOmapStep(pairs map[string][]byte) *setOmapStep {
|
func newSetOmapStep(pairs map[string][]byte) *setOmapStep {
|
||||||
|
|
||||||
maplen := C.size_t(len(pairs))
|
maplen := len(pairs)
|
||||||
cKeys := C.malloc(maplen * ptrSize)
|
cKeys := cutil.NewCPtrCSlice(maplen)
|
||||||
cValues := C.malloc(maplen * ptrSize)
|
cValues := cutil.NewCPtrCSlice(maplen)
|
||||||
cLengths := C.malloc(maplen * sizeTSize)
|
cLengths := cutil.NewSizeTCSlice(maplen)
|
||||||
|
|
||||||
sos := &setOmapStep{
|
sos := &setOmapStep{
|
||||||
cKeys: (**C.char)(cKeys),
|
cKeys: cKeys,
|
||||||
cValues: (**C.char)(cValues),
|
cValues: cValues,
|
||||||
cLengths: (*C.size_t)(cLengths),
|
cLengths: cLengths,
|
||||||
cNum: C.size_t(len(pairs)),
|
cNum: C.size_t(maplen),
|
||||||
}
|
}
|
||||||
sos.add(cKeys)
|
|
||||||
sos.add(cValues)
|
|
||||||
sos.add(cLengths)
|
|
||||||
|
|
||||||
var i uintptr
|
var i uintptr
|
||||||
for key, value := range pairs {
|
for key, value := range pairs {
|
||||||
// key
|
// key
|
||||||
ck := C.CString(key)
|
ck := C.CString(key)
|
||||||
sos.add(unsafe.Pointer(ck))
|
sos.add(unsafe.Pointer(ck))
|
||||||
ckp := (**C.char)(unsafe.Pointer(uintptr(cKeys) + i*ptrSize))
|
cKeys[i] = cutil.CPtr(ck)
|
||||||
*ckp = ck
|
|
||||||
|
|
||||||
// value and its length
|
// value and its length
|
||||||
cvp := (**C.char)(unsafe.Pointer(uintptr(cValues) + i*ptrSize))
|
vlen := cutil.SizeT(len(value))
|
||||||
vlen := C.size_t(len(value))
|
|
||||||
if vlen > 0 {
|
if vlen > 0 {
|
||||||
cv := C.CBytes(value)
|
cv := C.CBytes(value)
|
||||||
sos.add(cv)
|
sos.add(cv)
|
||||||
*cvp = (*C.char)(cv)
|
cValues[i] = cutil.CPtr(cv)
|
||||||
} else {
|
} else {
|
||||||
*cvp = nil
|
cValues[i] = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
clp := (*C.size_t)(unsafe.Pointer(uintptr(cLengths) + i*ptrSize))
|
cLengths[i] = vlen
|
||||||
*clp = vlen
|
|
||||||
|
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
@ -79,9 +67,9 @@ func newSetOmapStep(pairs map[string][]byte) *setOmapStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sos *setOmapStep) free() {
|
func (sos *setOmapStep) free() {
|
||||||
sos.cKeys = nil
|
sos.cKeys.Free()
|
||||||
sos.cValues = nil
|
sos.cValues.Free()
|
||||||
sos.cLengths = nil
|
sos.cLengths.Free()
|
||||||
sos.withRefs.free()
|
sos.withRefs.free()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,23 +178,21 @@ type removeOmapKeysStep struct {
|
|||||||
withoutUpdate
|
withoutUpdate
|
||||||
|
|
||||||
// arguments:
|
// arguments:
|
||||||
cKeys **C.char
|
cKeys cutil.CPtrCSlice
|
||||||
cNum C.size_t
|
cNum C.size_t
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRemoveOmapKeysStep(keys []string) *removeOmapKeysStep {
|
func newRemoveOmapKeysStep(keys []string) *removeOmapKeysStep {
|
||||||
cKeys := C.malloc(C.size_t(len(keys)) * ptrSize)
|
cKeys := cutil.NewCPtrCSlice(len(keys))
|
||||||
roks := &removeOmapKeysStep{
|
roks := &removeOmapKeysStep{
|
||||||
cKeys: (**C.char)(cKeys),
|
cKeys: cKeys,
|
||||||
cNum: C.size_t(len(keys)),
|
cNum: C.size_t(len(keys)),
|
||||||
}
|
}
|
||||||
roks.add(cKeys)
|
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
ckp := (**C.char)(unsafe.Pointer(uintptr(cKeys) + uintptr(i)*ptrSize))
|
cKeys[i] = cutil.CPtr(C.CString(key))
|
||||||
*ckp = C.CString(key)
|
roks.add(unsafe.Pointer(cKeys[i]))
|
||||||
roks.add(unsafe.Pointer(*ckp))
|
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +201,7 @@ func newRemoveOmapKeysStep(keys []string) *removeOmapKeysStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (roks *removeOmapKeysStep) free() {
|
func (roks *removeOmapKeysStep) free() {
|
||||||
roks.cKeys = nil
|
roks.cKeys.Free()
|
||||||
roks.withRefs.free()
|
roks.withRefs.free()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
8
vendor/github.com/ceph/go-ceph/rados/write_op.go
generated
vendored
8
vendor/github.com/ceph/go-ceph/rados/write_op.go
generated
vendored
@ -96,9 +96,9 @@ func (w *WriteOp) SetOmap(pairs map[string][]byte) {
|
|||||||
w.steps = append(w.steps, sos)
|
w.steps = append(w.steps, sos)
|
||||||
C.rados_write_op_omap_set(
|
C.rados_write_op_omap_set(
|
||||||
w.op,
|
w.op,
|
||||||
sos.cKeys,
|
(**C.char)(sos.cKeys.Ptr()),
|
||||||
sos.cValues,
|
(**C.char)(sos.cValues.Ptr()),
|
||||||
sos.cLengths,
|
(*C.size_t)(sos.cLengths.Ptr()),
|
||||||
sos.cNum)
|
sos.cNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ func (w *WriteOp) RmOmapKeys(keys []string) {
|
|||||||
w.steps = append(w.steps, roks)
|
w.steps = append(w.steps, roks)
|
||||||
C.rados_write_op_omap_rm_keys(
|
C.rados_write_op_omap_rm_keys(
|
||||||
w.op,
|
w.op,
|
||||||
roks.cKeys,
|
(**C.char)(roks.cKeys.Ptr()),
|
||||||
roks.cNum)
|
roks.cNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
vendor/github.com/ceph/go-ceph/rbd/errors.go
generated
vendored
6
vendor/github.com/ceph/go-ceph/rbd/errors.go
generated
vendored
@ -71,6 +71,12 @@ var (
|
|||||||
// revive:enable:exported
|
// revive:enable:exported
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Public general error
|
||||||
|
const (
|
||||||
|
// ErrNotExist indicates a non-specific missing resource.
|
||||||
|
ErrNotExist = rbdError(-C.ENOENT)
|
||||||
|
)
|
||||||
|
|
||||||
// Private errors:
|
// Private errors:
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
499
vendor/github.com/ceph/go-ceph/rbd/mirror.go
generated
vendored
499
vendor/github.com/ceph/go-ceph/rbd/mirror.go
generated
vendored
@ -13,8 +13,10 @@ package rbd
|
|||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/ceph/go-ceph/internal/cutil"
|
||||||
"github.com/ceph/go-ceph/internal/retry"
|
"github.com/ceph/go-ceph/internal/retry"
|
||||||
"github.com/ceph/go-ceph/rados"
|
"github.com/ceph/go-ceph/rados"
|
||||||
)
|
)
|
||||||
@ -31,6 +33,20 @@ const (
|
|||||||
MirrorModePool = MirrorMode(C.RBD_MIRROR_MODE_POOL)
|
MirrorModePool = MirrorMode(C.RBD_MIRROR_MODE_POOL)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// String representation of MirrorMode.
|
||||||
|
func (m MirrorMode) String() string {
|
||||||
|
switch m {
|
||||||
|
case MirrorModeDisabled:
|
||||||
|
return "disabled"
|
||||||
|
case MirrorModeImage:
|
||||||
|
return "image"
|
||||||
|
case MirrorModePool:
|
||||||
|
return "pool"
|
||||||
|
default:
|
||||||
|
return "<unknown>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ImageMirrorMode is used to indicate the mirroring approach for an RBD image.
|
// ImageMirrorMode is used to indicate the mirroring approach for an RBD image.
|
||||||
type ImageMirrorMode int64
|
type ImageMirrorMode int64
|
||||||
|
|
||||||
@ -43,6 +59,46 @@ const (
|
|||||||
ImageMirrorModeSnapshot = ImageMirrorMode(C.RBD_MIRROR_IMAGE_MODE_SNAPSHOT)
|
ImageMirrorModeSnapshot = ImageMirrorMode(C.RBD_MIRROR_IMAGE_MODE_SNAPSHOT)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// String representation of ImageMirrorMode.
|
||||||
|
func (imm ImageMirrorMode) String() string {
|
||||||
|
switch imm {
|
||||||
|
case ImageMirrorModeJournal:
|
||||||
|
return "journal"
|
||||||
|
case ImageMirrorModeSnapshot:
|
||||||
|
return "snapshot"
|
||||||
|
default:
|
||||||
|
return "<unknown>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMirrorUUID returns a string naming the mirroring uuid for the pool
|
||||||
|
// associated with the ioctx.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_uuid_get(rados_ioctx_t io_ctx,
|
||||||
|
// char *uuid, size_t *max_len);
|
||||||
|
func GetMirrorUUID(ioctx *rados.IOContext) (string, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
buf []byte
|
||||||
|
cSize C.size_t
|
||||||
|
)
|
||||||
|
retry.WithSizes(1024, 1<<16, func(size int) retry.Hint {
|
||||||
|
cSize = C.size_t(size)
|
||||||
|
buf = make([]byte, cSize)
|
||||||
|
ret := C.rbd_mirror_uuid_get(
|
||||||
|
cephIoctx(ioctx),
|
||||||
|
(*C.char)(unsafe.Pointer(&buf[0])),
|
||||||
|
&cSize)
|
||||||
|
err = getErrorIfNegative(ret)
|
||||||
|
return retry.Size(int(cSize)).If(err == errRange)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(buf[:cSize]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetMirrorMode is used to enable or disable pool level mirroring with either
|
// SetMirrorMode is used to enable or disable pool level mirroring with either
|
||||||
// an automatic or per-image behavior.
|
// an automatic or per-image behavior.
|
||||||
//
|
//
|
||||||
@ -181,6 +237,20 @@ const (
|
|||||||
MirrorImageDisabled = MirrorImageState(C.RBD_MIRROR_IMAGE_DISABLED)
|
MirrorImageDisabled = MirrorImageState(C.RBD_MIRROR_IMAGE_DISABLED)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// String representation of MirrorImageState.
|
||||||
|
func (mis MirrorImageState) String() string {
|
||||||
|
switch mis {
|
||||||
|
case MirrorImageDisabling:
|
||||||
|
return "disabling"
|
||||||
|
case MirrorImageEnabled:
|
||||||
|
return "enabled"
|
||||||
|
case MirrorImageDisabled:
|
||||||
|
return "disabled"
|
||||||
|
default:
|
||||||
|
return "<unknown>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MirrorImageInfo represents the mirroring status information of a RBD image.
|
// MirrorImageInfo represents the mirroring status information of a RBD image.
|
||||||
type MirrorImageInfo struct {
|
type MirrorImageInfo struct {
|
||||||
GlobalID string
|
GlobalID string
|
||||||
@ -188,6 +258,14 @@ type MirrorImageInfo struct {
|
|||||||
Primary bool
|
Primary bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertMirrorImageInfo(cInfo *C.rbd_mirror_image_info_t) MirrorImageInfo {
|
||||||
|
return MirrorImageInfo{
|
||||||
|
GlobalID: C.GoString(cInfo.global_id),
|
||||||
|
State: MirrorImageState(cInfo.state),
|
||||||
|
Primary: bool(cInfo.primary),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetMirrorImageInfo fetches the mirroring status information of a RBD image.
|
// GetMirrorImageInfo fetches the mirroring status information of a RBD image.
|
||||||
//
|
//
|
||||||
// Implements:
|
// Implements:
|
||||||
@ -209,11 +287,7 @@ func (image *Image) GetMirrorImageInfo() (*MirrorImageInfo, error) {
|
|||||||
return nil, getError(ret)
|
return nil, getError(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
mii := MirrorImageInfo{
|
mii := convertMirrorImageInfo(&cInfo)
|
||||||
GlobalID: C.GoString(cInfo.global_id),
|
|
||||||
State: MirrorImageState(cInfo.state),
|
|
||||||
Primary: bool(cInfo.primary),
|
|
||||||
}
|
|
||||||
|
|
||||||
// free C memory allocated by C.rbd_mirror_image_get_info call
|
// free C memory allocated by C.rbd_mirror_image_get_info call
|
||||||
C.rbd_mirror_image_get_info_cleanup(&cInfo)
|
C.rbd_mirror_image_get_info_cleanup(&cInfo)
|
||||||
@ -233,3 +307,418 @@ func (image *Image) GetImageMirrorMode() (ImageMirrorMode, error) {
|
|||||||
ret := C.rbd_mirror_image_get_mode(image.image, &mode)
|
ret := C.rbd_mirror_image_get_mode(image.image, &mode)
|
||||||
return ImageMirrorMode(mode), getError(ret)
|
return ImageMirrorMode(mode), getError(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MirrorImageStatusState is used to indicate the state of a mirrored image
|
||||||
|
// within the site status info.
|
||||||
|
type MirrorImageStatusState int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MirrorImageStatusStateUnknown is equivalent to MIRROR_IMAGE_STATUS_STATE_UNKNOWN
|
||||||
|
MirrorImageStatusStateUnknown = MirrorImageStatusState(C.MIRROR_IMAGE_STATUS_STATE_UNKNOWN)
|
||||||
|
// MirrorImageStatusStateError is equivalent to MIRROR_IMAGE_STATUS_STATE_ERROR
|
||||||
|
MirrorImageStatusStateError = MirrorImageStatusState(C.MIRROR_IMAGE_STATUS_STATE_ERROR)
|
||||||
|
// MirrorImageStatusStateSyncing is equivalent to MIRROR_IMAGE_STATUS_STATE_SYNCING
|
||||||
|
MirrorImageStatusStateSyncing = MirrorImageStatusState(C.MIRROR_IMAGE_STATUS_STATE_SYNCING)
|
||||||
|
// MirrorImageStatusStateStartingReplay is equivalent to MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY
|
||||||
|
MirrorImageStatusStateStartingReplay = MirrorImageStatusState(C.MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY)
|
||||||
|
// MirrorImageStatusStateReplaying is equivalent to MIRROR_IMAGE_STATUS_STATE_REPLAYING
|
||||||
|
MirrorImageStatusStateReplaying = MirrorImageStatusState(C.MIRROR_IMAGE_STATUS_STATE_REPLAYING)
|
||||||
|
// MirrorImageStatusStateStoppingReplay is equivalent to MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY
|
||||||
|
MirrorImageStatusStateStoppingReplay = MirrorImageStatusState(C.MIRROR_IMAGE_STATUS_STATE_STOPPING_REPLAY)
|
||||||
|
// MirrorImageStatusStateStopped is equivalent to MIRROR_IMAGE_STATUS_STATE_STOPPED
|
||||||
|
MirrorImageStatusStateStopped = MirrorImageStatusState(C.MIRROR_IMAGE_STATUS_STATE_STOPPED)
|
||||||
|
)
|
||||||
|
|
||||||
|
// String represents the MirrorImageStatusState as a short string.
|
||||||
|
func (state MirrorImageStatusState) String() (s string) {
|
||||||
|
switch state {
|
||||||
|
case MirrorImageStatusStateUnknown:
|
||||||
|
s = "unknown"
|
||||||
|
case MirrorImageStatusStateError:
|
||||||
|
s = "error"
|
||||||
|
case MirrorImageStatusStateSyncing:
|
||||||
|
s = "syncing"
|
||||||
|
case MirrorImageStatusStateStartingReplay:
|
||||||
|
s = "starting_replay"
|
||||||
|
case MirrorImageStatusStateReplaying:
|
||||||
|
s = "replaying"
|
||||||
|
case MirrorImageStatusStateStoppingReplay:
|
||||||
|
s = "stopping_replay"
|
||||||
|
case MirrorImageStatusStateStopped:
|
||||||
|
s = "stopped"
|
||||||
|
default:
|
||||||
|
s = fmt.Sprintf("unknown(%d)", state)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// SiteMirrorImageStatus contains information pertaining to the status of
|
||||||
|
// a mirrored image within a site.
|
||||||
|
type SiteMirrorImageStatus struct {
|
||||||
|
MirrorUUID string
|
||||||
|
State MirrorImageStatusState
|
||||||
|
Description string
|
||||||
|
LastUpdate int64
|
||||||
|
Up bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalMirrorImageStatus contains information pertaining to the global
|
||||||
|
// status of a mirrored image. It contains general information as well
|
||||||
|
// as per-site information stored in the SiteStatuses slice.
|
||||||
|
type GlobalMirrorImageStatus struct {
|
||||||
|
Name string
|
||||||
|
Info MirrorImageInfo
|
||||||
|
SiteStatuses []SiteMirrorImageStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalStatus returns one SiteMirrorImageStatus item from the SiteStatuses
|
||||||
|
// slice that corresponds to the local site's status. If the local status
|
||||||
|
// is not found than the error ErrNotExist will be returned.
|
||||||
|
func (gmis GlobalMirrorImageStatus) LocalStatus() (SiteMirrorImageStatus, error) {
|
||||||
|
var (
|
||||||
|
ss SiteMirrorImageStatus
|
||||||
|
err error = ErrNotExist
|
||||||
|
)
|
||||||
|
for i := range gmis.SiteStatuses {
|
||||||
|
// I couldn't find it explicitly documented, but a site mirror uuid
|
||||||
|
// of an empty string indicates that this is the local site.
|
||||||
|
// This pattern occurs in both the pybind code and ceph c++.
|
||||||
|
if gmis.SiteStatuses[i].MirrorUUID == "" {
|
||||||
|
ss = gmis.SiteStatuses[i]
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ss, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type siteArray [cutil.MaxIdx]C.rbd_mirror_image_site_status_t
|
||||||
|
|
||||||
|
// GetGlobalMirrorStatus returns status information pertaining to the state
|
||||||
|
// of the images's mirroring.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_image_get_global_status(
|
||||||
|
// rbd_image_t image,
|
||||||
|
// rbd_mirror_image_global_status_t *mirror_image_global_status,
|
||||||
|
// size_t status_size);
|
||||||
|
func (image *Image) GetGlobalMirrorStatus() (GlobalMirrorImageStatus, error) {
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return GlobalMirrorImageStatus{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s := C.rbd_mirror_image_global_status_t{}
|
||||||
|
ret := C.rbd_mirror_image_get_global_status(
|
||||||
|
image.image,
|
||||||
|
&s,
|
||||||
|
C.sizeof_rbd_mirror_image_global_status_t)
|
||||||
|
if err := getError(ret); err != nil {
|
||||||
|
return GlobalMirrorImageStatus{}, err
|
||||||
|
}
|
||||||
|
defer C.rbd_mirror_image_global_status_cleanup(&s)
|
||||||
|
|
||||||
|
status := newGlobalMirrorImageStatus(&s)
|
||||||
|
return status, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGlobalMirrorImageStatus(
|
||||||
|
s *C.rbd_mirror_image_global_status_t) GlobalMirrorImageStatus {
|
||||||
|
|
||||||
|
status := GlobalMirrorImageStatus{
|
||||||
|
Name: C.GoString(s.name),
|
||||||
|
Info: convertMirrorImageInfo(&s.info),
|
||||||
|
SiteStatuses: make([]SiteMirrorImageStatus, s.site_statuses_count),
|
||||||
|
}
|
||||||
|
// use the "Sven Technique" to treat the C pointer as a go slice temporarily
|
||||||
|
sscs := (*siteArray)(unsafe.Pointer(s.site_statuses))[:s.site_statuses_count:s.site_statuses_count]
|
||||||
|
for i := C.uint32_t(0); i < s.site_statuses_count; i++ {
|
||||||
|
ss := sscs[i]
|
||||||
|
status.SiteStatuses[i] = SiteMirrorImageStatus{
|
||||||
|
MirrorUUID: C.GoString(ss.mirror_uuid),
|
||||||
|
State: MirrorImageStatusState(ss.state),
|
||||||
|
Description: C.GoString(ss.description),
|
||||||
|
LastUpdate: int64(ss.last_update),
|
||||||
|
Up: bool(ss.up),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMirrorSnapshot creates a snapshot for image propagation to mirrors.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_image_create_snapshot(rbd_image_t image,
|
||||||
|
// uint64_t *snap_id);
|
||||||
|
func (image *Image) CreateMirrorSnapshot() (uint64, error) {
|
||||||
|
var snapID C.uint64_t
|
||||||
|
ret := C.rbd_mirror_image_create_snapshot(
|
||||||
|
image.image,
|
||||||
|
&snapID)
|
||||||
|
return uint64(snapID), getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorImageStatusSummary returns a map of images statuses and the count
|
||||||
|
// of images with said status.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_image_status_summary(
|
||||||
|
// rados_ioctx_t io_ctx, rbd_mirror_image_status_state_t *states, int *counts,
|
||||||
|
// size_t *maxlen);
|
||||||
|
func MirrorImageStatusSummary(
|
||||||
|
ioctx *rados.IOContext) (map[MirrorImageStatusState]uint, error) {
|
||||||
|
// ideally, we already know the size of the arrays - they should be
|
||||||
|
// the size of all the values of the rbd_mirror_image_status_state_t
|
||||||
|
// enum. But the C api doesn't enforce this so we give a little
|
||||||
|
// wiggle room in case the server returns values outside the enum
|
||||||
|
// we know about. This is the only case I can think of that we'd
|
||||||
|
// be able to get -ERANGE.
|
||||||
|
var (
|
||||||
|
cioctx = cephIoctx(ioctx)
|
||||||
|
err error
|
||||||
|
cStates []C.rbd_mirror_image_status_state_t
|
||||||
|
cCounts []C.int
|
||||||
|
cSize C.size_t
|
||||||
|
)
|
||||||
|
retry.WithSizes(16, 1<<16, func(size int) retry.Hint {
|
||||||
|
cSize = C.size_t(size)
|
||||||
|
cStates = make([]C.rbd_mirror_image_status_state_t, cSize)
|
||||||
|
cCounts = make([]C.int, cSize)
|
||||||
|
ret := C.rbd_mirror_image_status_summary(
|
||||||
|
cioctx,
|
||||||
|
(*C.rbd_mirror_image_status_state_t)(&cStates[0]),
|
||||||
|
(*C.int)(&cCounts[0]),
|
||||||
|
&cSize)
|
||||||
|
err = getErrorIfNegative(ret)
|
||||||
|
return retry.Size(int(cSize)).If(err == errRange)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
m := map[MirrorImageStatusState]uint{}
|
||||||
|
for i := 0; i < int(cSize); i++ {
|
||||||
|
s := MirrorImageStatusState(cStates[i])
|
||||||
|
m[s] = uint(cCounts[i])
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMirrorSiteName sets the site name, used for rbd mirroring, for the ceph
|
||||||
|
// cluster associated with the provided rados connection.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_site_name_set(rados_t cluster,
|
||||||
|
// const char *name);
|
||||||
|
func SetMirrorSiteName(conn *rados.Conn, name string) error {
|
||||||
|
cName := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cName))
|
||||||
|
|
||||||
|
ret := C.rbd_mirror_site_name_set(
|
||||||
|
C.rados_t(conn.Cluster()),
|
||||||
|
cName)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMirrorSiteName gets the site name, used for rbd mirroring, for the ceph
|
||||||
|
// cluster associated with the provided rados connection.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_site_name_get(rados_t cluster,
|
||||||
|
// char *name, size_t *max_len);
|
||||||
|
func GetMirrorSiteName(conn *rados.Conn) (string, error) {
|
||||||
|
|
||||||
|
var (
|
||||||
|
cluster = C.rados_t(conn.Cluster())
|
||||||
|
err error
|
||||||
|
buf []byte
|
||||||
|
cSize C.size_t
|
||||||
|
)
|
||||||
|
retry.WithSizes(1024, 1<<16, func(size int) retry.Hint {
|
||||||
|
cSize = C.size_t(size)
|
||||||
|
buf = make([]byte, cSize)
|
||||||
|
ret := C.rbd_mirror_site_name_get(
|
||||||
|
cluster,
|
||||||
|
(*C.char)(unsafe.Pointer(&buf[0])),
|
||||||
|
&cSize)
|
||||||
|
err = getErrorIfNegative(ret)
|
||||||
|
return retry.Size(int(cSize)).If(err == errRange)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// the C code sets the size including null byte
|
||||||
|
return string(buf[:cSize-1]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateMirrorPeerBootstrapToken returns a token value, representing the
|
||||||
|
// cluster and pool associated with the given IO context, that can be provided
|
||||||
|
// to ImportMirrorPeerBootstrapToken in order to set up mirroring between
|
||||||
|
// pools.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_peer_bootstrap_create(
|
||||||
|
// rados_ioctx_t io_ctx, char *token, size_t *max_len);
|
||||||
|
func CreateMirrorPeerBootstrapToken(ioctx *rados.IOContext) (string, error) {
|
||||||
|
var (
|
||||||
|
cioctx = cephIoctx(ioctx)
|
||||||
|
err error
|
||||||
|
buf []byte
|
||||||
|
cSize C.size_t
|
||||||
|
)
|
||||||
|
retry.WithSizes(1024, 1<<16, func(size int) retry.Hint {
|
||||||
|
cSize = C.size_t(size)
|
||||||
|
buf = make([]byte, cSize)
|
||||||
|
ret := C.rbd_mirror_peer_bootstrap_create(
|
||||||
|
cioctx,
|
||||||
|
(*C.char)(unsafe.Pointer(&buf[0])),
|
||||||
|
&cSize)
|
||||||
|
err = getErrorIfNegative(ret)
|
||||||
|
return retry.Size(int(cSize)).If(err == errRange)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// the C code sets the size including null byte
|
||||||
|
return string(buf[:cSize-1]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorPeerDirection is used to indicate what direction data is mirrored.
|
||||||
|
type MirrorPeerDirection int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MirrorPeerDirectionRx is equivalent to RBD_MIRROR_PEER_DIRECTION_RX
|
||||||
|
MirrorPeerDirectionRx = MirrorPeerDirection(C.RBD_MIRROR_PEER_DIRECTION_RX)
|
||||||
|
// MirrorPeerDirectionTx is equivalent to RBD_MIRROR_PEER_DIRECTION_TX
|
||||||
|
MirrorPeerDirectionTx = MirrorPeerDirection(C.RBD_MIRROR_PEER_DIRECTION_TX)
|
||||||
|
// MirrorPeerDirectionRxTx is equivalent to RBD_MIRROR_PEER_DIRECTION_RX_TX
|
||||||
|
MirrorPeerDirectionRxTx = MirrorPeerDirection(C.RBD_MIRROR_PEER_DIRECTION_RX_TX)
|
||||||
|
)
|
||||||
|
|
||||||
|
// ImportMirrorPeerBootstrapToken applies the provided bootstrap token to the
|
||||||
|
// pool associated with the IO context to create a mirroring relationship
|
||||||
|
// between pools. The direction parameter controls if data in the pool is a
|
||||||
|
// source, destination, or both.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_peer_bootstrap_import(
|
||||||
|
// rados_ioctx_t io_ctx, rbd_mirror_peer_direction_t direction,
|
||||||
|
// const char *token);
|
||||||
|
func ImportMirrorPeerBootstrapToken(
|
||||||
|
ioctx *rados.IOContext, direction MirrorPeerDirection, token string) error {
|
||||||
|
// instead of taking a length, rbd_mirror_peer_bootstrap_import assumes a
|
||||||
|
// null terminated "c string". We don't use CString because we don't use
|
||||||
|
// Go's string type as we don't want to treat the token as something users
|
||||||
|
// should interpret. If we were doing CString we'd be doing a copy anyway.
|
||||||
|
cToken := C.CString(token)
|
||||||
|
defer C.free(unsafe.Pointer(cToken))
|
||||||
|
|
||||||
|
ret := C.rbd_mirror_peer_bootstrap_import(
|
||||||
|
cephIoctx(ioctx),
|
||||||
|
C.rbd_mirror_peer_direction_t(direction),
|
||||||
|
cToken)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalMirrorImageIDAndStatus values contain an ID string for a RBD image
|
||||||
|
// and that image's GlobalMirrorImageStatus.
|
||||||
|
type GlobalMirrorImageIDAndStatus struct {
|
||||||
|
ID string
|
||||||
|
Status GlobalMirrorImageStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
func mirrorImageGlobalStatusList(
|
||||||
|
ioctx *rados.IOContext, start string,
|
||||||
|
results []GlobalMirrorImageIDAndStatus) (int, error) {
|
||||||
|
// this C function is treated like a "batch" iterator. Based on it's
|
||||||
|
// design it appears expected to call it multiple times to get
|
||||||
|
// the entire result.
|
||||||
|
cStart := C.CString(start)
|
||||||
|
defer C.free(unsafe.Pointer(cStart))
|
||||||
|
|
||||||
|
var (
|
||||||
|
max = C.size_t(len(results))
|
||||||
|
length = C.size_t(0)
|
||||||
|
ids = make([]*C.char, len(results))
|
||||||
|
images = make([]C.rbd_mirror_image_global_status_t, len(results))
|
||||||
|
)
|
||||||
|
ret := C.rbd_mirror_image_global_status_list(
|
||||||
|
cephIoctx(ioctx),
|
||||||
|
cStart,
|
||||||
|
max,
|
||||||
|
(**C.char)(unsafe.Pointer(&ids[0])),
|
||||||
|
(*C.rbd_mirror_image_global_status_t)(unsafe.Pointer(&images[0])),
|
||||||
|
&length)
|
||||||
|
|
||||||
|
for i := 0; i < int(length); i++ {
|
||||||
|
results[i].ID = C.GoString(ids[i])
|
||||||
|
results[i].Status = newGlobalMirrorImageStatus(&images[0])
|
||||||
|
}
|
||||||
|
C.rbd_mirror_image_global_status_list_cleanup(
|
||||||
|
(**C.char)(unsafe.Pointer(&ids[0])),
|
||||||
|
(*C.rbd_mirror_image_global_status_t)(unsafe.Pointer(&images[0])),
|
||||||
|
length)
|
||||||
|
return int(length), getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// statusIterBufSize is intentionally not a constant. The unit tests alter
|
||||||
|
// this value in order to get more code coverage w/o needing to create
|
||||||
|
// very many images.
|
||||||
|
var statusIterBufSize = 64
|
||||||
|
|
||||||
|
// MirrorImageGlobalStatusIter provide methods for iterating over all
|
||||||
|
// the GlobalMirrorImageIdAndStatus values in a pool.
|
||||||
|
type MirrorImageGlobalStatusIter struct {
|
||||||
|
ioctx *rados.IOContext
|
||||||
|
|
||||||
|
buf []GlobalMirrorImageIDAndStatus
|
||||||
|
lastID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMirrorImageGlobalStatusIter creates a new iterator type ready for use.
|
||||||
|
func NewMirrorImageGlobalStatusIter(ioctx *rados.IOContext) *MirrorImageGlobalStatusIter {
|
||||||
|
return &MirrorImageGlobalStatusIter{
|
||||||
|
ioctx: ioctx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next fetches one GlobalMirrorImageIDAndStatus value or a nil value if
|
||||||
|
// iteration is exhausted. The error return will be non-nil if an underlying
|
||||||
|
// error fetching more values occurred.
|
||||||
|
func (iter *MirrorImageGlobalStatusIter) Next() (*GlobalMirrorImageIDAndStatus, error) {
|
||||||
|
if len(iter.buf) == 0 {
|
||||||
|
if err := iter.fetch(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(iter.buf) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
item := iter.buf[0]
|
||||||
|
iter.lastID = item.ID
|
||||||
|
iter.buf = iter.buf[1:]
|
||||||
|
return &item, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close terminates iteration regardless if iteration was completed and
|
||||||
|
// frees any associated resources.
|
||||||
|
func (iter *MirrorImageGlobalStatusIter) Close() error {
|
||||||
|
iter.buf = nil
|
||||||
|
iter.lastID = ""
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (iter *MirrorImageGlobalStatusIter) fetch() error {
|
||||||
|
iter.buf = nil
|
||||||
|
items := make([]GlobalMirrorImageIDAndStatus, statusIterBufSize)
|
||||||
|
n, err := mirrorImageGlobalStatusList(
|
||||||
|
iter.ioctx,
|
||||||
|
iter.lastID,
|
||||||
|
items)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if n > 0 {
|
||||||
|
iter.buf = items[:n]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
45
vendor/github.com/ceph/go-ceph/rbd/rbd.go
generated
vendored
45
vendor/github.com/ceph/go-ceph/rbd/rbd.go
generated
vendored
@ -531,6 +531,33 @@ func (image *Image) Copy2(dest *Image) error {
|
|||||||
return getError(C.rbd_copy2(image.image, dest.image))
|
return getError(C.rbd_copy2(image.image, dest.image))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopy an rbd image to a new image with specific options.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_deep_copy(rbd_image_t src, rados_ioctx_t dest_io_ctx,
|
||||||
|
// const char *destname, rbd_image_options_t dest_opts);
|
||||||
|
func (image *Image) DeepCopy(ioctx *rados.IOContext, destname string, rio *ImageOptions) error {
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if ioctx == nil {
|
||||||
|
return ErrNoIOContext
|
||||||
|
}
|
||||||
|
if destname == "" {
|
||||||
|
return ErrNoName
|
||||||
|
}
|
||||||
|
if rio == nil {
|
||||||
|
return rbdError(C.EINVAL)
|
||||||
|
}
|
||||||
|
|
||||||
|
cDestname := C.CString(destname)
|
||||||
|
defer C.free(unsafe.Pointer(cDestname))
|
||||||
|
|
||||||
|
ret := C.rbd_deep_copy(image.image, cephIoctx(ioctx), cDestname,
|
||||||
|
C.rbd_image_options_t(rio.options))
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
// Flatten removes snapshot references from the image.
|
// Flatten removes snapshot references from the image.
|
||||||
//
|
//
|
||||||
// Implements:
|
// Implements:
|
||||||
@ -831,7 +858,7 @@ func (image *Image) WriteSame(ofs, n uint64, data []byte, flags rados.OpFlags) (
|
|||||||
|
|
||||||
ret := C.rbd_writesame(image.image,
|
ret := C.rbd_writesame(image.image,
|
||||||
C.uint64_t(ofs),
|
C.uint64_t(ofs),
|
||||||
C.uint64_t(n),
|
C.size_t(n),
|
||||||
(*C.char)(unsafe.Pointer(&data[0])),
|
(*C.char)(unsafe.Pointer(&data[0])),
|
||||||
C.size_t(len(data)),
|
C.size_t(len(data)),
|
||||||
C.int(flags))
|
C.int(flags))
|
||||||
@ -916,6 +943,22 @@ func (image *Image) GetId() (string, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetSnapshot updates the rbd image (not the Snapshot) such that the snapshot
|
||||||
|
// is the source of readable data.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_snap_set(rbd_image_t image, const char *snapname);
|
||||||
|
func (image *Image) SetSnapshot(snapname string) error {
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c_snapname := C.CString(snapname)
|
||||||
|
defer C.free(unsafe.Pointer(c_snapname))
|
||||||
|
|
||||||
|
return getError(C.rbd_snap_set(image.image, c_snapname))
|
||||||
|
}
|
||||||
|
|
||||||
// GetTrashList returns a slice of TrashInfo structs, containing information about all RBD images
|
// GetTrashList returns a slice of TrashInfo structs, containing information about all RBD images
|
||||||
// currently residing in the trash.
|
// currently residing in the trash.
|
||||||
func GetTrashList(ioctx *rados.IOContext) ([]TrashInfo, error) {
|
func GetTrashList(ioctx *rados.IOContext) ([]TrashInfo, error) {
|
||||||
|
6
vendor/github.com/ceph/go-ceph/rbd/snapshot.go
generated
vendored
6
vendor/github.com/ceph/go-ceph/rbd/snapshot.go
generated
vendored
@ -149,6 +149,7 @@ func (snapshot *Snapshot) IsProtected() (bool, error) {
|
|||||||
|
|
||||||
// Set updates the rbd image (not the Snapshot) such that the snapshot
|
// Set updates the rbd image (not the Snapshot) such that the snapshot
|
||||||
// is the source of readable data.
|
// is the source of readable data.
|
||||||
|
// This method is deprecated. Refer the SetSnapshot method of the Image type instead.
|
||||||
//
|
//
|
||||||
// Implements:
|
// Implements:
|
||||||
// int rbd_snap_set(rbd_image_t image, const char *snapname);
|
// int rbd_snap_set(rbd_image_t image, const char *snapname);
|
||||||
@ -157,10 +158,7 @@ func (snapshot *Snapshot) Set() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c_snapname := C.CString(snapshot.name)
|
return snapshot.image.SetSnapshot(snapshot.name)
|
||||||
defer C.free(unsafe.Pointer(c_snapname))
|
|
||||||
|
|
||||||
return getError(C.rbd_snap_set(snapshot.image.image, c_snapname))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSnapTimestamp returns the timestamp of a snapshot for an image.
|
// GetSnapTimestamp returns the timestamp of a snapshot for an image.
|
||||||
|
2
vendor/github.com/ceph/go-ceph/rbd/snapshot_octopus.go
generated
vendored
2
vendor/github.com/ceph/go-ceph/rbd/snapshot_octopus.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// +build octopus
|
// +build !nautilus
|
||||||
|
|
||||||
package rbd
|
package rbd
|
||||||
|
|
||||||
|
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@ -46,9 +46,11 @@ github.com/aws/aws-sdk-go/service/sts/stsiface
|
|||||||
github.com/beorn7/perks/quantile
|
github.com/beorn7/perks/quantile
|
||||||
# github.com/blang/semver v3.5.1+incompatible
|
# github.com/blang/semver v3.5.1+incompatible
|
||||||
github.com/blang/semver
|
github.com/blang/semver
|
||||||
# github.com/ceph/go-ceph v0.8.0
|
# github.com/ceph/go-ceph v0.10.0
|
||||||
github.com/ceph/go-ceph/cephfs/admin
|
github.com/ceph/go-ceph/cephfs/admin
|
||||||
|
github.com/ceph/go-ceph/common/commands
|
||||||
github.com/ceph/go-ceph/internal/callbacks
|
github.com/ceph/go-ceph/internal/callbacks
|
||||||
|
github.com/ceph/go-ceph/internal/commands
|
||||||
github.com/ceph/go-ceph/internal/cutil
|
github.com/ceph/go-ceph/internal/cutil
|
||||||
github.com/ceph/go-ceph/internal/errutil
|
github.com/ceph/go-ceph/internal/errutil
|
||||||
github.com/ceph/go-ceph/internal/retry
|
github.com/ceph/go-ceph/internal/retry
|
||||||
|
Loading…
Reference in New Issue
Block a user