Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rbd: add EncryptionLoad2 implementing rbd_encryption_load2 #1061

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
6 changes: 6 additions & 0 deletions docs/api-status.json
Original file line number Diff line number Diff line change
Expand Up @@ -1953,6 +1953,12 @@
"comment": "GroupSnapGetInfo returns a slice of RBD image snapshots that are part of a\ngroup snapshot.\n\nImplements:\n\n\tint rbd_group_snap_get_info(rados_ioctx_t group_p,\n\t const char *group_name,\n\t const char *snap_name,\n\t rbd_group_snap_info2_t *snaps);\n",
"added_in_version": "v0.30.0",
"expected_stable_version": "v0.32.0"
},
{
"name": "Image.EncryptionLoad2",
"comment": "EncryptionLoad2 enables IO on an open encrypted image. Multiple encryption\noption values can be passed to this call in a slice. For more information\nabout how items in the slice are applied to images, and possibly ancestor\nimages refer to the documentation in the C api for rbd_encryption_load2.\n\nImplements:\n\n\tint rbd_encryption_load2(rbd_image_t image,\n\t const rbd_encryption_spec_t *specs,\n\t size_t spec_count);\n",
"added_in_version": "$NEXT_RELEASE",
"expected_stable_version": "$NEXT_RELEASE_STABLE"
}
]
},
Expand Down
1 change: 1 addition & 0 deletions docs/api-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Conn.GetAddrs | v0.31.0 | v0.33.0 |
Name | Added in Version | Expected Stable Version |
---- | ---------------- | ----------------------- |
GroupSnapGetInfo | v0.30.0 | v0.32.0 |
Image.EncryptionLoad2 | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |

### Deprecated APIs

Expand Down
2 changes: 1 addition & 1 deletion entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ test_pkg() {

ulimit -c unlimited
testbin="./${pkg}/${pkg##*/}.test"
show go test -v "${testargs[@]}" -o "${testbin}" "./${pkg}"
show go test -timeout 15m -v "${testargs[@]}" -o "${testbin}" "./${pkg}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this always the case that we hit the timeout with these additional tests?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, running all 3 new tests causes the rbd run to take just over 10m. Note that rbd is the only package that takes this long, but I am far too lazy to try and customize the timeout only for rbd.

ret=$(($?+ret))
if ls "${pkg}"/core.* >/dev/null 2>&1; then
echo "Found coredump"
Expand Down
4 changes: 2 additions & 2 deletions rbd/encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (opts EncryptionOptionsLUKS1) allocateEncryptionOptions() cEncryptionData {
var cOpts C.rbd_encryption_luks1_format_options_t
var retData cEncryptionData
cOpts.alg = C.rbd_encryption_algorithm_t(opts.Alg)
//CBytes allocates memory which we'll free by calling cOptsFree()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was just outdated? Because I don't see any change regarding cOptsFree.

// CBytes allocates memory. it will be freed when cEncryptionData.free is called
cOpts.passphrase = (*C.char)(C.CBytes(opts.Passphrase))
cOpts.passphrase_size = C.size_t(len(opts.Passphrase))
retData.opts = C.rbd_encryption_options_t(&cOpts)
Expand All @@ -78,7 +78,7 @@ func (opts EncryptionOptionsLUKS2) allocateEncryptionOptions() cEncryptionData {
var cOpts C.rbd_encryption_luks2_format_options_t
var retData cEncryptionData
cOpts.alg = C.rbd_encryption_algorithm_t(opts.Alg)
//CBytes allocates memory which we'll free by calling cOptsFree()
// CBytes allocates memory. it will be freed when cEncryptionData.free is called
cOpts.passphrase = (*C.char)(C.CBytes(opts.Passphrase))
cOpts.passphrase_size = C.size_t(len(opts.Passphrase))
retData.opts = C.rbd_encryption_options_t(&cOpts)
Expand Down
100 changes: 100 additions & 0 deletions rbd/encryption_load2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//go:build !octopus && !pacific && !quincy && ceph_preview

package rbd

// #cgo LDFLAGS: -lrbd
// /* force XSI-complaint strerror_r() */
// #define _POSIX_C_SOURCE 200112L
// #undef _GNU_SOURCE
// #include <stdlib.h>
// #include <rbd/librbd.h>
import "C"

import (
"unsafe"
)

type encryptionOptions2 interface {
EncryptionOptions
writeEncryptionSpec(spec *C.rbd_encryption_spec_t) func()
}

func (opts EncryptionOptionsLUKS1) writeEncryptionSpec(spec *C.rbd_encryption_spec_t) func() {
/* only C memory should be attached to spec */
cPassphrase := (*C.char)(C.CBytes(opts.Passphrase))
cOptsSize := C.size_t(C.sizeof_rbd_encryption_luks1_format_options_t)
cOpts := (*C.rbd_encryption_luks1_format_options_t)(C.malloc(cOptsSize))
cOpts.alg = C.rbd_encryption_algorithm_t(opts.Alg)
cOpts.passphrase = cPassphrase
cOpts.passphrase_size = C.size_t(len(opts.Passphrase))

spec.format = C.RBD_ENCRYPTION_FORMAT_LUKS1
spec.opts = C.rbd_encryption_options_t(cOpts)
spec.opts_size = cOptsSize
return func() {
C.free(unsafe.Pointer(cOpts.passphrase))
C.free(unsafe.Pointer(cOpts))
}
}

func (opts EncryptionOptionsLUKS2) writeEncryptionSpec(spec *C.rbd_encryption_spec_t) func() {
/* only C memory should be attached to spec */
cPassphrase := (*C.char)(C.CBytes(opts.Passphrase))
cOptsSize := C.size_t(C.sizeof_rbd_encryption_luks2_format_options_t)
cOpts := (*C.rbd_encryption_luks2_format_options_t)(C.malloc(cOptsSize))
cOpts.alg = C.rbd_encryption_algorithm_t(opts.Alg)
cOpts.passphrase = cPassphrase
cOpts.passphrase_size = C.size_t(len(opts.Passphrase))

spec.format = C.RBD_ENCRYPTION_FORMAT_LUKS2
spec.opts = C.rbd_encryption_options_t(cOpts)
spec.opts_size = cOptsSize
return func() {
C.free(unsafe.Pointer(cOpts.passphrase))
C.free(unsafe.Pointer(cOpts))
}
}

// EncryptionLoad2 enables IO on an open encrypted image. Multiple encryption
// option values can be passed to this call in a slice. For more information
// about how items in the slice are applied to images, and possibly ancestor
// images refer to the documentation in the C api for rbd_encryption_load2.
//
// Implements:
//
// int rbd_encryption_load2(rbd_image_t image,
// const rbd_encryption_spec_t *specs,
// size_t spec_count);
func (image *Image) EncryptionLoad2(opts []EncryptionOptions) error {
if image.image == nil {
return ErrImageNotOpen
}
for _, o := range opts {
if _, ok := o.(encryptionOptions2); !ok {
return ErrImageNotOpen /* fixme */
}
}

length := len(opts)
cspecs := (*C.rbd_encryption_spec_t)(C.malloc(
C.size_t(C.sizeof_rbd_encryption_spec_t * length)))
specs := unsafe.Slice(cspecs, length)
freeFuncs := make([]func(), length)

for idx, option := range opts {
f := option.(encryptionOptions2).writeEncryptionSpec(&specs[idx])
freeFuncs[idx] = f
}
defer func() {
for _, f := range freeFuncs {
f()
}
C.free(unsafe.Pointer(cspecs))
}()

ret := C.rbd_encryption_load2(
image.image,
cspecs,
C.size_t(length))
return getError(ret)
}
Loading