iscsi: Add set_iscsi_discovery_auth RPC to configure CHAP dynamically

An new RPC set_iscsi_discovery_auth enables users to configure
CHAP authentication for discovery sessions dynamically.
Try to use descriptive message in the RPC when error occurs.

Change-Id: I8883d5e054539cf6db091a5b79d0479e62119811
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/420976
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Shuhei Matsumoto 2018-08-22 13:43:18 +09:00 committed by Jim Harris
parent 66723f7f92
commit 6cd1714a99
7 changed files with 166 additions and 1 deletions

View File

@ -29,6 +29,9 @@ method for CHAP authentication in discovery sessions have been changed to
align with `construct_target_node` RPC method. Old names are still usable align with `construct_target_node` RPC method. Old names are still usable
but will be removed in future release. but will be removed in future release.
`set_iscsi_discovery_auth` RPC method has been added to set CHAP authentication
for discovery sessions dynamically.
## v18.07: ## v18.07:
### bdev ### bdev

View File

@ -1873,6 +1873,48 @@ Example response:
} }
} }
~~~ ~~~
## set_iscsi_discovery_auth method {#rpc_set_iscsi_discovery_auth}
Set CHAP authentication for sessions dynamically.
### Parameters
Name | Optional | Type | Description
--------------------------- | -------- | --------| -----------
disable_chap | Optional | boolean | CHAP for discovery session should be disabled (default: `false`)
require_chap | Optional | boolean | CHAP for discovery session should be required (default: `false`)
mutual_chap | Optional | boolean | CHAP for discovery session should be unidirectional (`false`) or bidirectional (`true`) (default: `false`)
chap_group | Optional | number | CHAP group ID for discovery session (default: 0)
Parameters `disable_chap` and `require_chap` are mutually exclusive.
### Example
Example request:
~~~
request:
{
"params": {
"chap_group": 1,
"require_chap": true,
"mutual_chap": true
},
"jsonrpc": "2.0",
"method": "set_iscsi_discovery_auth",
"id": 1
}
~~~
Example response:
~~~
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
~~~
## get_initiator_groups method {#rpc_get_initiator_groups} ## get_initiator_groups method {#rpc_get_initiator_groups}

View File

@ -364,6 +364,8 @@ struct spdk_iscsi_opts *spdk_iscsi_opts_alloc(void);
void spdk_iscsi_opts_free(struct spdk_iscsi_opts *opts); void spdk_iscsi_opts_free(struct spdk_iscsi_opts *opts);
struct spdk_iscsi_opts *spdk_iscsi_opts_copy(struct spdk_iscsi_opts *src); struct spdk_iscsi_opts *spdk_iscsi_opts_copy(struct spdk_iscsi_opts *src);
void spdk_iscsi_opts_info_json(struct spdk_json_write_ctx *w); void spdk_iscsi_opts_info_json(struct spdk_json_write_ctx *w);
int spdk_iscsi_set_discovery_auth(bool disable_chap, bool require_chap,
bool mutual_chap, int32_t chap_group);
void spdk_iscsi_send_nopin(struct spdk_iscsi_conn *conn); void spdk_iscsi_send_nopin(struct spdk_iscsi_conn *conn);
void spdk_iscsi_task_response(struct spdk_iscsi_conn *conn, void spdk_iscsi_task_response(struct spdk_iscsi_conn *conn,

View File

@ -41,7 +41,7 @@
#include "spdk/rpc.h" #include "spdk/rpc.h"
#include "spdk/util.h" #include "spdk/util.h"
#include "spdk/event.h" #include "spdk/event.h"
#include "spdk/string.h"
#include "spdk_internal/log.h" #include "spdk_internal/log.h"
static void static void
@ -1057,3 +1057,51 @@ spdk_rpc_get_iscsi_global_params(struct spdk_jsonrpc_request *request,
spdk_jsonrpc_end_result(request, w); spdk_jsonrpc_end_result(request, w);
} }
SPDK_RPC_REGISTER("get_iscsi_global_params", spdk_rpc_get_iscsi_global_params, SPDK_RPC_RUNTIME) SPDK_RPC_REGISTER("get_iscsi_global_params", spdk_rpc_get_iscsi_global_params, SPDK_RPC_RUNTIME)
struct rpc_discovery_auth {
bool disable_chap;
bool require_chap;
bool mutual_chap;
int32_t chap_group;
};
static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = {
{"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true},
{"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true},
{"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true},
{"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true},
};
static void
spdk_rpc_set_iscsi_discovery_auth(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_discovery_auth req = {};
struct spdk_json_write_ctx *w;
int rc;
if (spdk_json_decode_object(params, rpc_discovery_auth_decoders,
SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) {
SPDK_ERRLOG("spdk_json_decode_object failed\n");
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"Invalid parameters");
return;
}
rc = spdk_iscsi_set_discovery_auth(req.disable_chap, req.require_chap,
req.mutual_chap, req.chap_group);
if (rc < 0) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"Invalid combination of CHAP params");
return;
}
w = spdk_jsonrpc_begin_result(request);
if (w == NULL) {
return;
}
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(request, w);
}
SPDK_RPC_REGISTER("set_iscsi_discovery_auth", spdk_rpc_set_iscsi_discovery_auth, SPDK_RPC_RUNTIME)

View File

@ -754,6 +754,26 @@ spdk_iscsi_set_global_params(struct spdk_iscsi_opts *opts)
return 0; return 0;
} }
int
spdk_iscsi_set_discovery_auth(bool disable_chap, bool require_chap, bool mutual_chap,
int32_t chap_group)
{
if (!spdk_iscsi_check_chap_params(disable_chap, require_chap, mutual_chap,
chap_group)) {
SPDK_ERRLOG("CHAP params are illegal combination\n");
return -EINVAL;
}
pthread_mutex_lock(&g_spdk_iscsi.mutex);
g_spdk_iscsi.disable_chap = disable_chap;
g_spdk_iscsi.require_chap = require_chap;
g_spdk_iscsi.mutual_chap = mutual_chap;
g_spdk_iscsi.chap_group = chap_group;
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
return 0;
}
static int static int
spdk_iscsi_initialize_global_params(void) spdk_iscsi_initialize_global_params(void)
{ {

View File

@ -530,6 +530,25 @@ if __name__ == "__main__":
p.add_argument('-u', '--min-connections-per-core', help='Allocation unit of connections per core', type=int) p.add_argument('-u', '--min-connections-per-core', help='Allocation unit of connections per core', type=int)
p.set_defaults(func=set_iscsi_options) p.set_defaults(func=set_iscsi_options)
@call_cmd
def set_iscsi_discovery_auth(args):
rpc.iscsi.set_iscsi_discovery_auth(
args.client,
disable_chap=args.disable_chap,
require_chap=args.require_chap,
mutual_chap=args.mutual_chap,
chap_group=args.chap_group)
p = subparsers.add_parser('set_iscsi_discovery_auth', help="""Set CHAP authentication for discovery session.""")
p.add_argument('-d', '--disable-chap', help="""CHAP for discovery session should be disabled.
*** Mutually exclusive with --require-chap""", action='store_true')
p.add_argument('-r', '--require-chap', help="""CHAP for discovery session should be required.
*** Mutually exclusive with --disable-chap""", action='store_true')
p.add_argument('-m', '--mutual-chap', help='CHAP for discovery session should be mutual', action='store_true')
p.add_argument('-g', '--chap-group', help="""Authentication group ID for discovery session.
*** Authentication group must be precreated ***""", type=int)
p.set_defaults(func=set_iscsi_discovery_auth)
@call_cmd @call_cmd
def get_portal_groups(args): def get_portal_groups(args):
print_dict(rpc.iscsi.get_portal_groups(args.client)) print_dict(rpc.iscsi.get_portal_groups(args.client))

View File

@ -83,6 +83,37 @@ def set_iscsi_options(
return client.call('set_iscsi_options', params) return client.call('set_iscsi_options', params)
def set_iscsi_discovery_auth(
client,
disable_chap=None,
require_chap=None,
mutual_chap=None,
chap_group=None):
"""Set CHAP authentication for discovery service.
Args:
disable_chap: CHAP for discovery session should be disabled (optional)
require_chap: CHAP for discovery session should be required (optional)
mutual_chap: CHAP for discovery session should be mutual (optional)
chap_group: Authentication group ID for discovery session (optional)
Returns:
True or False
"""
params = {}
if disable_chap:
params['disable_chap'] = disable_chap
if require_chap:
params['require_chap'] = require_chap
if mutual_chap:
params['mutual_chap'] = mutual_chap
if chap_group:
params['chap_group'] = chap_group
return client.call('set_iscsi_discovery_auth', params)
def get_portal_groups(client): def get_portal_groups(client):
"""Display current portal group configuration. """Display current portal group configuration.