nvmf: Add an nvmf_subsystem_create rpc

Add a new nvmf_subsystem_create RPC. The current RPC,
construct_nvmf_subsystem, is old and jumps through a lot
of hoops to maintain backward compatibility. Leave it in,
but create a new RPC as the main mechanism going forward.

Change-Id: Ia99cb5994a90579956136dac1800ed1fdce482dd
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/425169
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Ben Walker 2018-09-10 10:40:19 -07:00 committed by Jim Harris
parent 10ee6eecb3
commit aedac1a878
4 changed files with 158 additions and 0 deletions

View File

@ -3019,6 +3019,46 @@ Example response:
}
~~~
## nvmf_subsystem_create method {#rpc_nvmf_subsystem_create}
Construct an NVMe over Fabrics target subsystem.
### Parameters
Name | Optional | Type | Description
----------------------- | -------- | ----------- | -----------
nqn | Required | string | Subsystem NQN
serial_number | Optional | string | Serial number of virtual controller
max_namespaces | Optional | number | Maximum number of namespaces that can be attached to the subsystem. Default: 0 (Unlimited)
allow_any_host | Optional | boolean | Allow any host (`true`) or enforce allowed host whitelist (`false`). Default: `false`.
### Example
Example request:
~~~
{
"jsonrpc": "2.0",
"id": 1,
"method": "nvmf_subsystem_create",
"params": {
"nqn": "nqn.2016-06.io.spdk:cnode1",
"allow_any_host": false,
"serial_number": "abcdef",
}
}
~~~
Example response:
~~~
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
~~~
## delete_nvmf_subsystem method {#rpc_delete_nvmf_subsystem}
Delete an existing NVMe-oF subsystem.

View File

@ -795,6 +795,74 @@ invalid:
}
SPDK_RPC_REGISTER("construct_nvmf_subsystem", spdk_rpc_construct_nvmf_subsystem, SPDK_RPC_RUNTIME)
struct rpc_subsystem_create {
char *nqn;
char *serial_number;
uint32_t max_namespaces;
bool allow_any_host;
};
static const struct spdk_json_object_decoder rpc_subsystem_create_decoders[] = {
{"nqn", offsetof(struct rpc_subsystem_create, nqn), spdk_json_decode_string},
{"serial_number", offsetof(struct rpc_subsystem_create, serial_number), spdk_json_decode_string, true},
{"max_namespaces", offsetof(struct rpc_subsystem_create, max_namespaces), spdk_json_decode_uint32, true},
{"allow_any_host", offsetof(struct rpc_subsystem_create, allow_any_host), spdk_json_decode_bool, true},
};
static void
spdk_rpc_nvmf_subsystem_create(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_subsystem_create *req;
struct spdk_nvmf_subsystem *subsystem;
req = calloc(1, sizeof(*req));
if (!req) {
goto invalid;
}
if (spdk_json_decode_object(params, rpc_subsystem_create_decoders,
SPDK_COUNTOF(rpc_subsystem_create_decoders),
req)) {
SPDK_ERRLOG("spdk_json_decode_object failed\n");
goto invalid;
}
subsystem = spdk_nvmf_subsystem_create(g_spdk_nvmf_tgt, req->nqn, SPDK_NVMF_SUBTYPE_NVME,
req->max_namespaces);
if (!subsystem) {
goto invalid;
}
if (req->serial_number) {
if (spdk_nvmf_subsystem_set_sn(subsystem, req->serial_number)) {
SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", req->nqn, req->serial_number);
goto invalid;
}
}
spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host);
free(req->nqn);
free(req->serial_number);
free(req);
spdk_nvmf_subsystem_start(subsystem,
spdk_rpc_nvmf_subsystem_started,
request);
return;
invalid:
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
if (req) {
free(req->nqn);
free(req->serial_number);
}
free(req);
}
SPDK_RPC_REGISTER("nvmf_subsystem_create", spdk_rpc_nvmf_subsystem_create, SPDK_RPC_RUNTIME)
struct rpc_delete_subsystem {
char *nqn;
};

View File

@ -1319,6 +1319,24 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
type=int, default=0)
p.set_defaults(func=construct_nvmf_subsystem)
@call_cmd
def nvmf_subsystem_create(args):
rpc.nvmf.nvmf_subsystem_create(args.client,
nqn=args.nqn,
serial_number=args.serial_number,
allow_any_host=args.allow_any_host,
max_namespaces=args.max_namespaces)
p = subparsers.add_parser('nvmf_subsystem_create', help='Create an NVMe-oF subsystem')
p.add_argument('nqn', help='Subsystem NQN (ASCII)')
p.add_argument("-s", "--serial-number", help="""
Format: 'sn' etc
Example: 'SPDK00000000000001'""", default='0000:00:01.0')
p.add_argument("-a", "--allow-any-host", action='store_true', help="Allow any host to connect (don't enforce host NQN whitelist)")
p.add_argument("-m", "--max-namespaces", help="Maximum number of namespaces allowed",
type=int, default=0)
p.set_defaults(func=nvmf_subsystem_create)
@call_cmd
def delete_nvmf_subsystem(args):
rpc.nvmf.delete_nvmf_subsystem(args.client,

View File

@ -112,6 +112,38 @@ def construct_nvmf_subsystem(client,
return client.call('construct_nvmf_subsystem', params)
def nvmf_subsystem_create(client,
nqn,
serial_number,
allow_any_host=False,
max_namespaces=0):
"""Construct an NVMe over Fabrics target subsystem.
Args:
nqn: Subsystem NQN.
serial_number: Serial number of virtual controller.
allow_any_host: Allow any host (True) or enforce allowed host whitelist (False). Default: False.
max_namespaces: Maximum number of namespaces that can be attached to the subsystem (optional). Default: 0 (Unlimited).
Returns:
True or False
"""
params = {
'nqn': nqn,
}
if serial_number:
params['serial_number'] = serial_number
if allow_any_host:
params['allow_any_host'] = True
if max_namespaces:
params['max_namespaces'] = max_namespaces
return client.call('nvmf_subsystem_create', params)
def nvmf_subsystem_add_listener(client, nqn, trtype, traddr, trsvcid, adrfam):
"""Add a new listen address to an NVMe-oF subsystem.