diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index f05c8262e..9fd29af8a 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -3569,6 +3569,7 @@ rbd_name | Required | string | Image name block_size | Required | number | Block size config | Optional | string map | Explicit librados configuration cluster_name | Optional | string | Rados cluster object name created in this module. +uuid | Optional | string | UUID of new bdev If no config is specified, Ceph configuration files must exist with all relevant settings for accessing the pool. If a config map is @@ -3601,7 +3602,8 @@ Example request with `key` from `/etc/ceph/ceph.client.admin.keyring`: "mon_host": "192.168.7.1:6789,192.168.7.2:6789", "key": "AQDwf8db7zR1GRAA5k7NKXjS5S5V4mntwUDnGQ==", } - "block_size": 4096 + "block_size": 4096, + "uuid": "76210ea4-7920-40a0-a07b-8992a7443c76" }, "jsonrpc": "2.0", "method": "bdev_rbd_create", diff --git a/module/bdev/rbd/bdev_rbd.c b/module/bdev/rbd/bdev_rbd.c index 918020c4c..791966b11 100644 --- a/module/bdev/rbd/bdev_rbd.c +++ b/module/bdev/rbd/bdev_rbd.c @@ -852,6 +852,7 @@ static void bdev_rbd_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w) { struct bdev_rbd *rbd = bdev->ctxt; + char uuid_str[SPDK_UUID_STRING_LEN]; spdk_json_write_object_begin(w); @@ -877,6 +878,9 @@ bdev_rbd_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w spdk_json_write_object_end(w); } + spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid); + spdk_json_write_named_string(w, "uuid", uuid_str); + spdk_json_write_object_end(w); spdk_json_write_object_end(w); @@ -1128,7 +1132,8 @@ bdev_rbd_create(struct spdk_bdev **bdev, const char *name, const char *user_id, const char *const *config, const char *rbd_name, uint32_t block_size, - const char *cluster_name) + const char *cluster_name, + const struct spdk_uuid *uuid) { struct bdev_rbd *rbd; int ret; @@ -1189,6 +1194,12 @@ bdev_rbd_create(struct spdk_bdev **bdev, const char *name, const char *user_id, return ret; } + if (uuid) { + rbd->disk.uuid = *uuid; + } else { + spdk_uuid_generate(&rbd->disk.uuid); + } + if (name) { rbd->disk.name = strdup(name); } else { diff --git a/module/bdev/rbd/bdev_rbd.h b/module/bdev/rbd/bdev_rbd.h index c7399251c..1deef34cc 100644 --- a/module/bdev/rbd/bdev_rbd.h +++ b/module/bdev/rbd/bdev_rbd.h @@ -54,7 +54,7 @@ typedef void (*spdk_delete_rbd_complete)(void *cb_arg, int bdeverrno); int bdev_rbd_create(struct spdk_bdev **bdev, const char *name, const char *user_id, const char *pool_name, const char *const *config, - const char *rbd_name, uint32_t block_size, const char *cluster_name); + const char *rbd_name, uint32_t block_size, const char *cluster_name, const struct spdk_uuid *uuid); /** * Delete rbd bdev. * diff --git a/module/bdev/rbd/bdev_rbd_rpc.c b/module/bdev/rbd/bdev_rbd_rpc.c index b066c1ee9..acc16e845 100644 --- a/module/bdev/rbd/bdev_rbd_rpc.c +++ b/module/bdev/rbd/bdev_rbd_rpc.c @@ -33,6 +33,7 @@ #include "bdev_rbd.h" #include "spdk/util.h" +#include "spdk/uuid.h" #include "spdk/string.h" #include "spdk/log.h" @@ -44,6 +45,7 @@ struct rpc_create_rbd { uint32_t block_size; char **config; char *cluster_name; + char *uuid; }; static void @@ -55,6 +57,7 @@ free_rpc_create_rbd(struct rpc_create_rbd *req) free(req->rbd_name); bdev_rbd_free_config(req->config); free(req->cluster_name); + free(req->uuid); } static int @@ -106,7 +109,8 @@ static const struct spdk_json_object_decoder rpc_create_rbd_decoders[] = { {"rbd_name", offsetof(struct rpc_create_rbd, rbd_name), spdk_json_decode_string}, {"block_size", offsetof(struct rpc_create_rbd, block_size), spdk_json_decode_uint32}, {"config", offsetof(struct rpc_create_rbd, config), bdev_rbd_decode_config, true}, - {"cluster_name", offsetof(struct rpc_create_rbd, cluster_name), spdk_json_decode_string, true} + {"cluster_name", offsetof(struct rpc_create_rbd, cluster_name), spdk_json_decode_string, true}, + {"uuid", offsetof(struct rpc_create_rbd, uuid), spdk_json_decode_string, true} }; static void @@ -117,6 +121,8 @@ rpc_bdev_rbd_create(struct spdk_jsonrpc_request *request, struct spdk_json_write_ctx *w; struct spdk_bdev *bdev; int rc = 0; + struct spdk_uuid *uuid = NULL; + struct spdk_uuid decoded_uuid; if (spdk_json_decode_object(params, rpc_create_rbd_decoders, SPDK_COUNTOF(rpc_create_rbd_decoders), @@ -127,10 +133,19 @@ rpc_bdev_rbd_create(struct spdk_jsonrpc_request *request, goto cleanup; } + if (req.uuid) { + if (spdk_uuid_parse(&decoded_uuid, req.uuid)) { + spdk_jsonrpc_send_error_response(request, -EINVAL, + "Failed to parse bdev UUID"); + goto cleanup; + } + uuid = &decoded_uuid; + } + rc = bdev_rbd_create(&bdev, req.name, req.user_id, req.pool_name, (const char *const *)req.config, req.rbd_name, - req.block_size, req.cluster_name); + req.block_size, req.cluster_name, uuid); if (rc) { spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); goto cleanup; diff --git a/scripts/rpc.py b/scripts/rpc.py index 235923b67..228907915 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -700,7 +700,8 @@ if __name__ == "__main__": pool_name=args.pool_name, rbd_name=args.rbd_name, block_size=args.block_size, - cluster_name=args.cluster_name)) + cluster_name=args.cluster_name, + uuid=args.uuid)) p = subparsers.add_parser('bdev_rbd_create', aliases=['construct_rbd_bdev'], help='Add a bdev with ceph rbd backend') @@ -712,6 +713,7 @@ if __name__ == "__main__": p.add_argument('rbd_name', help='rbd image name') p.add_argument('block_size', help='rbd block size', type=int) p.add_argument('-c', '--cluster-name', help="cluster name to identify the Rados cluster", required=False) + p.add_argument('-u', '--uuid', help="UUID of the bdev") p.set_defaults(func=bdev_rbd_create) def bdev_rbd_delete(args): diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index a8684ffaa..87fde800b 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -733,7 +733,7 @@ def bdev_rbd_get_clusters_info(client, name): @deprecated_alias('construct_rbd_bdev') -def bdev_rbd_create(client, pool_name, rbd_name, block_size, name=None, user=None, config=None, cluster_name=None): +def bdev_rbd_create(client, pool_name, rbd_name, block_size, name=None, user=None, config=None, cluster_name=None, uuid=None): """Create a Ceph RBD block device. Args: @@ -744,6 +744,7 @@ def bdev_rbd_create(client, pool_name, rbd_name, block_size, name=None, user=Non user: Ceph user name (optional) config: map of config keys to values (optional) cluster_name: Name to identify Rados cluster (optional) + uuid: UUID of block device (optional) Returns: Name of created block device. @@ -762,6 +763,8 @@ def bdev_rbd_create(client, pool_name, rbd_name, block_size, name=None, user=Non params['config'] = config if cluster_name is not None: params['cluster_name'] = cluster_name + if uuid is not None: + params['uuid'] = uuid return client.call('bdev_rbd_create', params)