Commit aedac1a8 authored by Ben Walker's avatar Ben Walker Committed by Jim Harris
Browse files

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: default avatarBen 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: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 10ee6eec
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -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.
+68 −0
Original line number Diff line number Diff line
@@ -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;
};
+18 −0
Original line number Diff line number Diff line
@@ -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,
+32 −0
Original line number Diff line number Diff line
@@ -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.