rebase: bump go-ceph version to v0.16.0

go-ceph v0.16.0 contains subvolume metadata APIs and subvolume snapshot
metadata APIs.

Please note, as the APIs can not be tested in the go-ceph CI, it requires
build-tag `ceph_ci_untested`.

Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
This commit is contained in:
Prasanna Kumar Kalever 2022-06-15 11:04:25 +05:30 committed by mergify[bot]
parent 025b90f74c
commit 23c324898a
26 changed files with 384 additions and 113 deletions

View File

@ -47,8 +47,8 @@ endif
GO_PROJECT=github.com/ceph/ceph-csi GO_PROJECT=github.com/ceph/ceph-csi
CEPH_VERSION ?= $(shell . $(CURDIR)/build.env ; echo $${CEPH_VERSION}) CEPH_VERSION ?= $(shell . $(CURDIR)/build.env ; echo $${CEPH_VERSION})
# TODO: ceph_preview tag may be removed with go-ceph 0.16.0 # TODO: ceph_preview tag may be removed with go-ceph 0.17.0
# TODO: ceph_ci_untested is added for NFS-export management (go-ceph#655) # TODO: ceph_ci_untested is added for subvolume metadata (go-ceph#691) and snapshot metadata management (go-ceph#698)
GO_TAGS_LIST ?= $(CEPH_VERSION) ceph_preview ceph_ci_untested GO_TAGS_LIST ?= $(CEPH_VERSION) ceph_preview ceph_ci_untested
# go build flags # go build flags

4
go.mod
View File

@ -7,8 +7,8 @@ require (
github.com/aws/aws-sdk-go v1.44.28 github.com/aws/aws-sdk-go v1.44.28
github.com/aws/aws-sdk-go-v2/service/sts v1.16.7 github.com/aws/aws-sdk-go-v2/service/sts v1.16.7
github.com/ceph/ceph-csi/api v0.0.0-00010101000000-000000000000 github.com/ceph/ceph-csi/api v0.0.0-00010101000000-000000000000
// TODO: API for managing NFS-exports requires `ceph_ci_untested` build-tag // TODO: API for managing subvolume metadata and snapshot metadata requires `ceph_ci_untested` build-tag
github.com/ceph/go-ceph v0.15.0 github.com/ceph/go-ceph v0.16.0
github.com/container-storage-interface/spec v1.6.0 github.com/container-storage-interface/spec v1.6.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.2-0.20211220115741-32fa508dadbe github.com/csi-addons/spec v0.1.2-0.20211220115741-32fa508dadbe

9
go.sum
View File

@ -182,8 +182,8 @@ github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
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/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.15.0 h1:ILB3NaLWOtt4u/2d8I8HZTC4Ycm1PsOYVar3IFU1xlo= github.com/ceph/go-ceph v0.16.0 h1:hEhVfEFsLoGJF+i3r7Wwh4QlMN+MnWqNxfic9v6GV04=
github.com/ceph/go-ceph v0.15.0/go.mod h1:mafFpf5Vg8Ai8Bd+FAMvKBHLmtdpTXdRP/TNq8XWegY= github.com/ceph/go-ceph v0.16.0/go.mod h1:SzhpLdyU+ixxJ68bbqoEa481P5N5d5lv5jVMxcRMLfU=
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
@ -404,9 +404,9 @@ github.com/gocql/gocql v0.0.0-20190402132108-0e1d5de854df/go.mod h1:4Fw1eo5iaEhD
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
@ -1396,7 +1396,6 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -84,10 +84,20 @@ type CloneSource struct {
type CloneStatus struct { type CloneStatus struct {
State CloneState `json:"state"` State CloneState `json:"state"`
Source CloneSource `json:"source"` Source CloneSource `json:"source"`
// failure can be obtained through .GetFailure()
failure *CloneFailure
}
// CloneFailure reports details of a failure after a subvolume clone failed.
type CloneFailure struct {
Errno string `json:"errno"`
ErrStr string `json:"errstr"`
} }
type cloneStatusWrapper struct { type cloneStatusWrapper struct {
Status CloneStatus `json:"status"` Status CloneStatus `json:"status"`
Failure CloneFailure `json:"failure"`
} }
func parseCloneStatus(res response) (*CloneStatus, error) { func parseCloneStatus(res response) (*CloneStatus, error) {
@ -95,6 +105,9 @@ func parseCloneStatus(res response) (*CloneStatus, error) {
if err := res.NoStatus().Unmarshal(&status).End(); err != nil { if err := res.NoStatus().Unmarshal(&status).End(); err != nil {
return nil, err return nil, err
} }
if status.Failure.Errno != "" || status.Failure.ErrStr != "" {
status.Status.failure = &status.Failure
}
return &status.Status, nil return &status.Status, nil
} }

View File

@ -0,0 +1,13 @@
//go:build ceph_preview
// +build ceph_preview
package admin
// GetFailure returns details about the CloneStatus when in CloneFailed state.
//
// Similar To:
// Reading the .failure object from the JSON returned by "ceph fs subvolume
// snapshot clone"
func (cs *CloneStatus) GetFailure() *CloneFailure {
return cs.failure
}

View File

@ -93,6 +93,15 @@ func parseListNames(res response) ([]string, error) {
return vl, nil return vl, nil
} }
func parseListKeyValues(res response) (map[string]string, error) {
var x map[string]string
if err := res.NoStatus().Unmarshal(&x).End(); err != nil {
return nil, err
}
return x, nil
}
// 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) {

104
vendor/github.com/ceph/go-ceph/cephfs/admin/metadata.go generated vendored Normal file
View File

@ -0,0 +1,104 @@
//go:build !(nautilus || octopus) && ceph_preview && ceph_ci_untested
// +build !nautilus,!octopus,ceph_preview,ceph_ci_untested
package admin
import "C"
// GetMetadata gets custom metadata on the subvolume in a volume belonging to
// an optional subvolume group based on provided key name.
//
// Similar To:
// ceph fs subvolume metadata get <vol_name> <sub_name> <key_name> [--group_name <subvol_group_name>]
func (fsa *FSAdmin) GetMetadata(volume, group, subvolume, key string) (string, error) {
m := map[string]string{
"prefix": "fs subvolume metadata get",
"format": "json",
"vol_name": volume,
"sub_name": subvolume,
"key_name": key,
}
if group != NoGroup {
m["group_name"] = group
}
return parsePathResponse(fsa.marshalMgrCommand(m))
}
// SetMetadata sets custom metadata on the subvolume in a volume belonging to
// an optional subvolume group as a key-value pair.
//
// Similar To:
// ceph fs subvolume metadata set <vol_name> <sub_name> <key_name> <value> [--group_name <subvol_group_name>]
func (fsa *FSAdmin) SetMetadata(volume, group, subvolume, key, value string) error {
m := map[string]string{
"prefix": "fs subvolume metadata set",
"format": "json",
"vol_name": volume,
"sub_name": subvolume,
"key_name": key,
"value": value,
}
if group != NoGroup {
m["group_name"] = group
}
return fsa.marshalMgrCommand(m).NoData().End()
}
// RemoveMetadata removes custom metadata set on the subvolume in a volume
// belonging to an optional subvolume group using the metadata key.
//
// Similar To:
// ceph fs subvolume metadata rm <vol_name> <sub_name> <key_name> [--group_name <subvol_group_name>]
func (fsa *FSAdmin) RemoveMetadata(volume, group, subvolume, key string) error {
return fsa.rmSubVolumeMetadata(volume, group, subvolume, key, commonRmFlags{})
}
// ForceRemoveMetadata attempt to forcefully remove custom metadata set on
// the subvolume in a volume belonging to an optional subvolume group using
// the metadata key.
//
// Similar To:
// ceph fs subvolume metadata rm <vol_name> <sub_name> <key_name> [--group_name <subvol_group_name>] --force
func (fsa *FSAdmin) ForceRemoveMetadata(volume, group, subvolume, key string) error {
return fsa.rmSubVolumeMetadata(volume, group, subvolume, key, commonRmFlags{force: true})
}
func (fsa *FSAdmin) rmSubVolumeMetadata(volume, group, subvolume, key string, o commonRmFlags) error {
m := map[string]string{
"prefix": "fs subvolume metadata rm",
"format": "json",
"vol_name": volume,
"sub_name": subvolume,
"key_name": key,
}
if group != NoGroup {
m["group_name"] = group
}
return fsa.marshalMgrCommand(mergeFlags(m, o)).NoData().End()
}
// ListMetadata lists custom metadata (key-value pairs) set on the subvolume
// in a volume belonging to an optional subvolume group.
//
// Similar To:
// ceph fs subvolume metadata ls <vol_name> <sub_name> [--group_name <subvol_group_name>]
func (fsa *FSAdmin) ListMetadata(volume, group, subvolume string) (map[string]string, error) {
m := map[string]string{
"prefix": "fs subvolume metadata ls",
"format": "json",
"vol_name": volume,
"sub_name": subvolume,
}
if group != NoGroup {
m["group_name"] = group
}
return parseListKeyValues(fsa.marshalMgrCommand(m))
}

View File

@ -6,28 +6,6 @@ import (
const mirroring = "mirroring" const mirroring = "mirroring"
// EnableModule will enable the specified manager module.
//
// Deprecated: use the equivalent function in cluster/admin/manager.
//
// Similar To:
// ceph mgr module enable <module> [--force]
func (fsa *FSAdmin) EnableModule(module string, force bool) error {
mgradmin := manager.NewFromConn(fsa.conn)
return mgradmin.EnableModule(module, force)
}
// DisableModule will disable the specified manager module.
//
// Deprecated: use the equivalent function in cluster/admin/manager.
//
// Similar To:
// ceph mgr module disable <module>
func (fsa *FSAdmin) DisableModule(module string) error {
mgradmin := manager.NewFromConn(fsa.conn)
return mgradmin.DisableModule(module)
}
// EnableMirroringModule will enable the mirroring module for cephfs. // EnableMirroringModule will enable the mirroring module for cephfs.
// //
// Similar To: // Similar To:

View File

@ -0,0 +1,109 @@
//go:build !(nautilus || octopus) && ceph_preview && ceph_ci_untested
// +build !nautilus,!octopus,ceph_preview,ceph_ci_untested
package admin
import "C"
// GetSnapshotMetadata gets custom metadata on the subvolume snapshot in a
// volume belonging to an optional subvolume group based on provided key name.
//
// Similar To:
// ceph fs subvolume snapshot metadata get <vol_name> <sub_name> <snap_name> <key_name> [--group_name <subvol_group_name>]
func (fsa *FSAdmin) GetSnapshotMetadata(volume, group, subvolume, snapname, key string) (string, error) {
m := map[string]string{
"prefix": "fs subvolume snapshot metadata get",
"format": "json",
"vol_name": volume,
"sub_name": subvolume,
"snap_name": snapname,
"key_name": key,
}
if group != NoGroup {
m["group_name"] = group
}
return parsePathResponse(fsa.marshalMgrCommand(m))
}
// SetSnapshotMetadata sets custom metadata on the subvolume snapshot in a
// volume belonging to an optional subvolume group as a key-value pair.
//
// Similar To:
// ceph fs subvolume snapshot metadata set <vol_name> <sub_name> <snap_name> <key_name> <value> [--group_name <subvol_group_name>]
func (fsa *FSAdmin) SetSnapshotMetadata(volume, group, subvolume, snapname, key, value string) error {
m := map[string]string{
"prefix": "fs subvolume snapshot metadata set",
"format": "json",
"vol_name": volume,
"sub_name": subvolume,
"snap_name": snapname,
"key_name": key,
"value": value,
}
if group != NoGroup {
m["group_name"] = group
}
return fsa.marshalMgrCommand(m).NoData().End()
}
// RemoveSnapshotMetadata removes custom metadata set on the subvolume
// snapshot in a volume belonging to an optional subvolume group using the
// metadata key.
//
// Similar To:
// ceph fs subvolume snapshot metadata rm <vol_name> <sub_name> <snap_name> <key_name> [--group_name <subvol_group_name>]
func (fsa *FSAdmin) RemoveSnapshotMetadata(volume, group, subvolume, snapname, key string) error {
return fsa.rmSubVolumeSnapShotMetadata(volume, group, subvolume, snapname, key, commonRmFlags{})
}
// ForceRemoveSnapshotMetadata attempt to forcefully remove custom metadata
// set on the subvolume snapshot in a volume belonging to an optional
// subvolume group using the metadata key.
//
// Similar To:
// ceph fs subvolume snapshot metadata rm <vol_name> <sub_name> <snap_name> <key_name> [--group_name <subvol_group_name>] --force
func (fsa *FSAdmin) ForceRemoveSnapshotMetadata(volume, group, subvolume, snapname, key string) error {
return fsa.rmSubVolumeSnapShotMetadata(volume, group, subvolume, snapname, key, commonRmFlags{force: true})
}
func (fsa *FSAdmin) rmSubVolumeSnapShotMetadata(volume, group, subvolume, snapname, key string, o commonRmFlags) error {
m := map[string]string{
"prefix": "fs subvolume snapshot metadata rm",
"format": "json",
"vol_name": volume,
"sub_name": subvolume,
"snap_name": snapname,
"key_name": key,
}
if group != NoGroup {
m["group_name"] = group
}
return fsa.marshalMgrCommand(mergeFlags(m, o)).NoData().End()
}
// ListSnapshotMetadata lists custom metadata (key-value pairs) set on the subvolume
// snapshot in a volume belonging to an optional subvolume group.
//
// Similar To:
// ceph fs subvolume snapshot metadata ls <vol_name> <sub_name> <snap_name> [--group_name <subvol_group_name>]
func (fsa *FSAdmin) ListSnapshotMetadata(volume, group, subvolume, snapname string) (map[string]string, error) {
m := map[string]string{
"prefix": "fs subvolume snapshot metadata ls",
"format": "json",
"vol_name": volume,
"sub_name": subvolume,
"snap_name": snapname,
}
if group != NoGroup {
m["group_name"] = group
}
return parseListKeyValues(fsa.marshalMgrCommand(m))
}

View File

@ -2,6 +2,7 @@ package admin
import ( import (
"bytes" "bytes"
"encoding/json"
) )
var ( var (
@ -114,8 +115,40 @@ type VolumeStatus struct {
Pools []VolumePool `json:"pools"` Pools []VolumePool `json:"pools"`
} }
func parseVolumeStatus(res response) (*VolumeStatus, error) { type mdsVersionField struct {
var vs VolumeStatus Version string
Items []struct {
Version string `json:"version"`
}
}
func (m *mdsVersionField) UnmarshalJSON(data []byte) (err error) {
if err = json.Unmarshal(data, &m.Version); err == nil {
return
}
return json.Unmarshal(data, &m.Items)
}
// volumeStatusResponse deals with the changing output of the mgr
// api json
type volumeStatusResponse struct {
Pools []VolumePool `json:"pools"`
MDSVersion mdsVersionField `json:"mds_version"`
}
func (v *volumeStatusResponse) volumeStatus() *VolumeStatus {
vstatus := &VolumeStatus{}
vstatus.Pools = v.Pools
if v.MDSVersion.Version != "" {
vstatus.MDSVersion = v.MDSVersion.Version
} else if len(v.MDSVersion.Items) > 0 {
vstatus.MDSVersion = v.MDSVersion.Items[0].Version
}
return vstatus
}
func parseVolumeStatus(res response) (*volumeStatusResponse, error) {
var vs volumeStatusResponse
res = res.NoStatus() res = res.NoStatus()
if !res.Ok() { if !res.Ok() {
return nil, res.End() return nil, res.End()
@ -142,5 +175,9 @@ func (fsa *FSAdmin) VolumeStatus(name string) (*VolumeStatus, error) {
"prefix": "fs status", "prefix": "fs status",
"format": "json", "format": "json",
}) })
return parseVolumeStatus(res) v, err := parseVolumeStatus(res)
if err != nil {
return nil, err
}
return v.volumeStatus(), nil
} }

View File

@ -1,5 +1,5 @@
//go:build !(nautilus || octopus) && ceph_preview && ceph_ci_untested //go:build !(nautilus || octopus) && ceph_preview
// +build !nautilus,!octopus,ceph_preview,ceph_ci_untested // +build !nautilus,!octopus,ceph_preview
package nfs package nfs
@ -15,7 +15,6 @@ type Admin struct {
// NewFromConn creates an new management object from a preexisting // NewFromConn creates an new management object from a preexisting
// rados connection. The existing connection can be rados.Conn or any // rados connection. The existing connection can be rados.Conn or any
// type implementing the RadosCommander interface. // type implementing the RadosCommander interface.
// PREVIEW
func NewFromConn(conn ccom.RadosCommander) *Admin { func NewFromConn(conn ccom.RadosCommander) *Admin {
return &Admin{conn} return &Admin{conn}
} }

View File

@ -1,5 +1,5 @@
//go:build !(nautilus || octopus) && ceph_preview && ceph_ci_untested //go:build !(nautilus || octopus) && ceph_preview
// +build !nautilus,!octopus,ceph_preview,ceph_ci_untested // +build !nautilus,!octopus,ceph_preview
package nfs package nfs
@ -108,7 +108,6 @@ func parseExportInfo(res commands.Response) (ExportInfo, error) {
} }
// CreateCephFSExport will create a new NFS export for a CephFS file system. // CreateCephFSExport will create a new NFS export for a CephFS file system.
// PREVIEW
// //
// Similar To: // Similar To:
// ceph nfs export create cephfs // ceph nfs export create cephfs
@ -126,7 +125,6 @@ func (nfsa *Admin) CreateCephFSExport(spec CephFSExportSpec) (
const delSucc = "Successfully deleted export" const delSucc = "Successfully deleted export"
// RemoveExport will remove an NFS export based on the pseudo-path of the export. // RemoveExport will remove an NFS export based on the pseudo-path of the export.
// PREVIEW
// //
// Similar To: // Similar To:
// ceph nfs export rm // ceph nfs export rm
@ -142,7 +140,6 @@ func (nfsa *Admin) RemoveExport(clusterID, pseudoPath string) error {
} }
// ListDetailedExports will return a list of exports with details. // ListDetailedExports will return a list of exports with details.
// PREVIEW
// //
// Similar To: // Similar To:
// ceph nfs export ls --detailed // ceph nfs export ls --detailed
@ -166,7 +163,6 @@ func (nfsa *Admin) ListDetailedExports(clusterID string) ([]ExportInfo, error) {
// ExportInfo will return a structure describing the export specified by it's // ExportInfo will return a structure describing the export specified by it's
// pseudo-path. // pseudo-path.
// PREVIEW
// //
// Similar To: // Similar To:
// ceph nfs export info // ceph nfs export info

View File

@ -1,5 +1,5 @@
//go:build ptrguard //go:build !no_ptrguard
// +build ptrguard // +build !no_ptrguard
package cutil package cutil

View File

@ -1,5 +1,5 @@
//go:build !ptrguard //go:build no_ptrguard
// +build !ptrguard // +build no_ptrguard
package cutil package cutil

View File

@ -43,6 +43,11 @@ const (
// CreateIdempotent if used with IOContext.Create() and the object // CreateIdempotent if used with IOContext.Create() and the object
// already exists, the function will not return an error. // already exists, the function will not return an error.
CreateIdempotent = C.LIBRADOS_CREATE_IDEMPOTENT CreateIdempotent = C.LIBRADOS_CREATE_IDEMPOTENT
defaultListObjectsResultSize = 1000
// listEndSentinel is the value returned by rados_list_object_list_is_end
// when a cursor has reached the end of a pool
listEndSentinel = 1
) )
//revive:disable:var-naming old-yet-exported public api //revive:disable:var-naming old-yet-exported public api
@ -302,22 +307,36 @@ type ObjectListFunc func(oid string)
// RadosAllNamespaces before calling this function to return objects from all // RadosAllNamespaces before calling this function to return objects from all
// namespaces // namespaces
func (ioctx *IOContext) ListObjects(listFn ObjectListFunc) error { func (ioctx *IOContext) ListObjects(listFn ObjectListFunc) error {
var ctx C.rados_list_ctx_t pageResults := C.size_t(defaultListObjectsResultSize)
ret := C.rados_nobjects_list_open(ioctx.ioctx, &ctx) var filterLen C.size_t
if ret < 0 { results := make([]C.rados_object_list_item, pageResults)
return getError(ret)
next := C.rados_object_list_begin(ioctx.ioctx)
if next == nil {
return ErrNotFound
} }
defer func() { C.rados_nobjects_list_close(ctx) }() defer C.rados_object_list_cursor_free(ioctx.ioctx, next)
finish := C.rados_object_list_end(ioctx.ioctx)
if finish == nil {
return ErrNotFound
}
defer C.rados_object_list_cursor_free(ioctx.ioctx, finish)
for { for {
var cEntry *C.char ret := C.rados_object_list(ioctx.ioctx, next, finish, pageResults, nil, filterLen, (*C.rados_object_list_item)(unsafe.Pointer(&results[0])), &next)
ret := C.rados_nobjects_list_next(ctx, &cEntry, nil, nil) if ret < 0 {
if ret == -C.ENOENT {
return nil
} else if ret < 0 {
return getError(ret) return getError(ret)
} }
listFn(C.GoString(cEntry))
numEntries := int(ret)
for i := 0; i < numEntries; i++ {
item := results[i]
listFn(C.GoStringN(item.oid, (C.int)(item.oid_length)))
}
if C.rados_object_list_is_end(ioctx.ioctx, next) == listEndSentinel {
return nil
}
} }
} }

View File

@ -1,6 +1,3 @@
//go:build ceph_preview
// +build ceph_preview
package rados package rados
// #cgo LDFLAGS: -lrados // #cgo LDFLAGS: -lrados
@ -12,7 +9,6 @@ import "C"
// AssertVersion ensures that the object exists and that its internal version // AssertVersion ensures that the object exists and that its internal version
// number is equal to "ver" before reading. "ver" should be a version number // number is equal to "ver" before reading. "ver" should be a version number
// previously obtained with IOContext.GetLastVersion(). // previously obtained with IOContext.GetLastVersion().
// PREVIEW
// //
// Implements: // Implements:
// void rados_read_op_assert_version(rados_read_op_t read_op, // void rados_read_op_assert_version(rados_read_op_t read_op,

View File

@ -16,7 +16,6 @@ import (
// SetLocator sets the key for mapping objects to pgs within an io context. // SetLocator sets the key for mapping objects to pgs within an io context.
// Until a different locator key is set, all objects in this io context will be placed in the same pg. // Until a different locator key is set, all objects in this io context will be placed in the same pg.
// To reset the locator, an empty string must be set. // To reset the locator, an empty string must be set.
// PREVIEW
// //
// Implements: // Implements:
// void rados_ioctx_locator_set_key(rados_ioctx_t io, const char *key); // void rados_ioctx_locator_set_key(rados_ioctx_t io, const char *key);

View File

@ -1,6 +1,3 @@
//go:build ceph_preview
// +build ceph_preview
package rados package rados
// #cgo LDFLAGS: -lrados // #cgo LDFLAGS: -lrados
@ -12,7 +9,6 @@ import "C"
// AssertVersion ensures that the object exists and that its internal version // AssertVersion ensures that the object exists and that its internal version
// number is equal to "ver" before writing. "ver" should be a version number // number is equal to "ver" before writing. "ver" should be a version number
// previously obtained with IOContext.GetLastVersion(). // previously obtained with IOContext.GetLastVersion().
// PREVIEW
// //
// Implements: // Implements:
// void rados_read_op_assert_version(rados_read_op_t read_op, // void rados_read_op_assert_version(rados_read_op_t read_op,

View File

@ -1,6 +1,3 @@
//go:build ceph_preview
// +build ceph_preview
package rados package rados
// #cgo LDFLAGS: -lrados // #cgo LDFLAGS: -lrados
@ -10,7 +7,6 @@ package rados
import "C" import "C"
// Remove object. // Remove object.
// PREVIEW
// //
// Implements: // Implements:
// void rados_write_op_remove(rados_write_op_t write_op) // void rados_write_op_remove(rados_write_op_t write_op)

View File

@ -1,6 +1,3 @@
//go:build ceph_preview
// +build ceph_preview
package rados package rados
// #cgo LDFLAGS: -lrados // #cgo LDFLAGS: -lrados
@ -14,7 +11,6 @@ import (
) )
// SetXattr sets an xattr. // SetXattr sets an xattr.
// PREVIEW
// //
// Implements: // Implements:
// void rados_write_op_setxattr(rados_write_op_t write_op, // void rados_write_op_setxattr(rados_write_op_t write_op,

View File

@ -1,6 +1,3 @@
//go:build ceph_preview
// +build ceph_preview
package rados package rados
// #cgo LDFLAGS: -lrados // #cgo LDFLAGS: -lrados
@ -58,7 +55,6 @@ func (s *ReadOpOmapGetValsByKeysStep) update() error {
// ReadOpOmapGetValsByKeysStep's internal iterator. // ReadOpOmapGetValsByKeysStep's internal iterator.
// If there are no more elements to retrieve, (nil, nil) is returned. // If there are no more elements to retrieve, (nil, nil) is returned.
// May be called only after Operate() finished. // May be called only after Operate() finished.
// PREVIEW
func (s *ReadOpOmapGetValsByKeysStep) Next() (*OmapKeyValue, error) { func (s *ReadOpOmapGetValsByKeysStep) Next() (*OmapKeyValue, error) {
if !s.canIterate { if !s.canIterate {
return nil, ErrOperationIncomplete return nil, ErrOperationIncomplete
@ -88,7 +84,6 @@ func (s *ReadOpOmapGetValsByKeysStep) Next() (*OmapKeyValue, error) {
} }
// GetOmapValuesByKeys starts iterating over specific key/value pairs. // GetOmapValuesByKeys starts iterating over specific key/value pairs.
// PREVIEW
// //
// Implements: // Implements:
// void rados_read_op_omap_get_vals_by_keys2(rados_read_op_t read_op, // void rados_read_op_omap_get_vals_by_keys2(rados_read_op_t read_op,

View File

@ -1,6 +1,3 @@
//go:build ceph_preview
// +build ceph_preview
package rados package rados
// #cgo LDFLAGS: -lrados // #cgo LDFLAGS: -lrados
@ -49,7 +46,6 @@ func newReadOpReadStep() *ReadOpReadStep {
// Read bytes from offset into buffer. // Read bytes from offset into buffer.
// len(buffer) is the maximum number of bytes read from the object. // len(buffer) is the maximum number of bytes read from the object.
// buffer[:ReadOpReadStep.BytesRead] then contains object data. // buffer[:ReadOpReadStep.BytesRead] then contains object data.
// PREVIEW
// //
// Implements: // Implements:
// void rados_read_op_read(rados_read_op_t read_op, // void rados_read_op_read(rados_read_op_t read_op,

View File

@ -1,6 +1,3 @@
//go:build ceph_preview
// +build ceph_preview
package rados package rados
/* /*
@ -69,7 +66,6 @@ var (
) )
// Watch creates a Watcher for the specified object. // Watch creates a Watcher for the specified object.
// PREVIEW
// //
// A Watcher receives all notifications that are sent to the object on which it // A Watcher receives all notifications that are sent to the object on which it
// has been created. It exposes two read-only channels: Events() receives all // has been created. It exposes two read-only channels: Events() receives all
@ -103,7 +99,6 @@ func (ioctx *IOContext) Watch(obj string) (*Watcher, error) {
// WatchWithTimeout creates a watcher on an object. Same as Watcher(), but // WatchWithTimeout creates a watcher on an object. Same as Watcher(), but
// different timeout than the default can be specified. // different timeout than the default can be specified.
// PREVIEW
// //
// Implements: // Implements:
// int rados_watch3(rados_ioctx_t io, const char *o, uint64_t *cookie, // int rados_watch3(rados_ioctx_t io, const char *o, uint64_t *cookie,
@ -142,26 +137,22 @@ func (ioctx *IOContext) WatchWithTimeout(oid string, timeout time.Duration) (*Wa
} }
// ID returns the WatcherId of the Watcher // ID returns the WatcherId of the Watcher
// PREVIEW
func (w *Watcher) ID() WatcherID { func (w *Watcher) ID() WatcherID {
return w.id return w.id
} }
// Events returns a read-only channel, that receives all notifications that are // Events returns a read-only channel, that receives all notifications that are
// sent to the object of the Watcher. // sent to the object of the Watcher.
// PREVIEW
func (w *Watcher) Events() <-chan NotifyEvent { func (w *Watcher) Events() <-chan NotifyEvent {
return w.events return w.events
} }
// Errors returns a read-only channel, that receives all errors for the Watcher. // Errors returns a read-only channel, that receives all errors for the Watcher.
// PREVIEW
func (w *Watcher) Errors() <-chan error { func (w *Watcher) Errors() <-chan error {
return w.errors return w.errors
} }
// Check on the status of a Watcher. // Check on the status of a Watcher.
// PREVIEW
// //
// Returns the time since it was last confirmed. If there is an error, the // Returns the time since it was last confirmed. If there is an error, the
// Watcher is no longer valid, and should be destroyed with the Delete() method. // Watcher is no longer valid, and should be destroyed with the Delete() method.
@ -177,7 +168,6 @@ func (w *Watcher) Check() (time.Duration, error) {
} }
// Delete the watcher. This closes both the event and error channel. // Delete the watcher. This closes both the event and error channel.
// PREVIEW
// //
// Implements: // Implements:
// int rados_unwatch2(rados_ioctx_t io, uint64_t cookie) // int rados_unwatch2(rados_ioctx_t io, uint64_t cookie)
@ -203,7 +193,6 @@ func (w *Watcher) Delete() error {
// Notify sends a notification with the provided data to all Watchers of the // Notify sends a notification with the provided data to all Watchers of the
// specified object. // specified object.
// PREVIEW
// //
// CAUTION: even if the error is not nil. the returned slices // CAUTION: even if the error is not nil. the returned slices
// might still contain data. // might still contain data.
@ -213,7 +202,6 @@ func (ioctx *IOContext) Notify(obj string, data []byte) ([]NotifyAck, []NotifyTi
// NotifyWithTimeout is like Notify() but with a different timeout than the // NotifyWithTimeout is like Notify() but with a different timeout than the
// default. // default.
// PREVIEW
// //
// Implements: // Implements:
// int rados_notify2(rados_ioctx_t io, const char* o, const char* buf, int buf_len, // int rados_notify2(rados_ioctx_t io, const char* o, const char* buf, int buf_len,
@ -246,7 +234,6 @@ func (ioctx *IOContext) NotifyWithTimeout(obj string, data []byte, timeout time.
// Ack sends an acknowledgement with the specified response data to the notfier // Ack sends an acknowledgement with the specified response data to the notfier
// of the NotifyEvent. If a notify is not ack'ed, the originating Notify() call // of the NotifyEvent. If a notify is not ack'ed, the originating Notify() call
// blocks and eventiually times out. // blocks and eventiually times out.
// PREVIEW
// //
// Implements: // Implements:
// int rados_notify_ack(rados_ioctx_t io, const char *o, uint64_t notify_id, // int rados_notify_ack(rados_ioctx_t io, const char *o, uint64_t notify_id,
@ -276,7 +263,6 @@ func (ne *NotifyEvent) Ack(response []byte) error {
} }
// WatcherFlush flushes all pending notifications of the cluster. // WatcherFlush flushes all pending notifications of the cluster.
// PREVIEW
// //
// Implements: // Implements:
// int rados_watch_flush(rados_t cluster) // int rados_watch_flush(rados_t cluster)

View File

@ -13,30 +13,28 @@ import "C"
import ( import (
"unsafe" "unsafe"
"github.com/ceph/go-ceph/internal/retry"
ts "github.com/ceph/go-ceph/internal/timespec" ts "github.com/ceph/go-ceph/internal/timespec"
"github.com/ceph/go-ceph/rados" "github.com/ceph/go-ceph/rados"
) )
// GetImageNames returns the list of current RBD images. // GetImageNames returns the list of current RBD images.
func GetImageNames(ioctx *rados.IOContext) ([]string, error) { func GetImageNames(ioctx *rados.IOContext) ([]string, error) {
var ( var images []C.rbd_image_spec_t
err error size := C.size_t(4096)
images []C.rbd_image_spec_t for {
size C.size_t
)
retry.WithSizes(32, 4096, func(s int) retry.Hint {
size = C.size_t(s)
images = make([]C.rbd_image_spec_t, size) images = make([]C.rbd_image_spec_t, size)
ret := C.rbd_list2( ret := C.rbd_list2(
cephIoctx(ioctx), cephIoctx(ioctx),
(*C.rbd_image_spec_t)(unsafe.Pointer(&images[0])), (*C.rbd_image_spec_t)(unsafe.Pointer(&images[0])),
&size) &size)
err = getErrorIfNegative(ret) err := getErrorIfNegative(ret)
return retry.Size(int(size)).If(err == errRange) if err != nil {
}) if err == errRange {
if err != nil { continue
return nil, err }
return nil, err
}
break
} }
defer C.rbd_image_spec_list_cleanup((*C.rbd_image_spec_t)(unsafe.Pointer(&images[0])), size) defer C.rbd_image_spec_list_cleanup((*C.rbd_image_spec_t)(unsafe.Pointer(&images[0])), size)

37
vendor/github.com/ceph/go-ceph/rbd/snapshot_rename.go generated vendored Normal file
View File

@ -0,0 +1,37 @@
//go:build ceph_preview
// +build ceph_preview
package rbd
// #cgo LDFLAGS: -lrbd
// #include <stdlib.h>
// #include <rbd/librbd.h>
import "C"
import (
"unsafe"
)
// Rename a snapshot.
//
// Implements:
// int rbd_snap_rename(rbd_image_t image, const char *snapname,
// const char* dstsnapsname);
func (snapshot *Snapshot) Rename(destName string) error {
if err := snapshot.validate(imageNeedsIOContext | imageIsOpen | imageNeedsName | snapshotNeedsName); err != nil {
return err
}
cSrcName := C.CString(snapshot.name)
cDestName := C.CString(destName)
defer C.free(unsafe.Pointer(cSrcName))
defer C.free(unsafe.Pointer(cDestName))
err := C.rbd_snap_rename(snapshot.image.image, cSrcName, cDestName)
if err != 0 {
return getError(err)
}
snapshot.name = destName
return nil
}

2
vendor/modules.txt vendored
View File

@ -119,7 +119,7 @@ github.com/cenkalti/backoff/v3
github.com/ceph/ceph-csi/api/deploy/kubernetes/nfs github.com/ceph/ceph-csi/api/deploy/kubernetes/nfs
github.com/ceph/ceph-csi/api/deploy/kubernetes/rbd github.com/ceph/ceph-csi/api/deploy/kubernetes/rbd
github.com/ceph/ceph-csi/api/deploy/ocp github.com/ceph/ceph-csi/api/deploy/ocp
# github.com/ceph/go-ceph v0.15.0 # github.com/ceph/go-ceph v0.16.0
## explicit; go 1.12 ## explicit; go 1.12
github.com/ceph/go-ceph/cephfs/admin github.com/ceph/go-ceph/cephfs/admin
github.com/ceph/go-ceph/common/admin/manager github.com/ceph/go-ceph/common/admin/manager