iscsi&rpc: Add new initiator information to an existing initiator group

Adding new initiator to an existing initiator group to allow login
will be usual. This patch support the following JSON-RPC commands:
- add_initiators_to_initiator_group
- delete_initiators_from_initiator_group

Both initiator's name and netmask are optional but already added
name or netmask cannot be added.

Test code is added too.

Change-Id: Ic101210b9d00c2b36e37ece23fcba8cfe8e44eb8
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/398361
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Shuhei Matsumoto 2018-02-07 08:22:00 +09:00 committed by Daniel Verkamp
parent c0021d08ce
commit 2982a74df9
7 changed files with 498 additions and 0 deletions

View File

@ -167,6 +167,31 @@ spdk_iscsi_init_grp_delete_all_initiators(struct spdk_iscsi_init_grp *ig)
}
}
static int
spdk_iscsi_init_grp_delete_initiators(struct spdk_iscsi_init_grp *ig, int num_inames, char **inames)
{
int i;
int rc;
for (i = 0; i < num_inames; i++) {
rc = spdk_iscsi_init_grp_delete_initiator(ig, inames[i]);
if (rc < 0) {
goto cleanup;
}
}
return 0;
cleanup:
for (; i > 0; --i) {
rc = spdk_iscsi_init_grp_add_initiator(ig, inames[i - 1]);
if (rc != 0) {
spdk_iscsi_init_grp_delete_all_initiators(ig);
break;
}
}
return -1;
}
static struct spdk_iscsi_initiator_netmask *
spdk_iscsi_init_grp_find_netmask(struct spdk_iscsi_init_grp *ig, const char *mask)
{
@ -275,6 +300,30 @@ spdk_iscsi_init_grp_delete_all_netmasks(struct spdk_iscsi_init_grp *ig)
}
}
static int
spdk_iscsi_init_grp_delete_netmasks(struct spdk_iscsi_init_grp *ig, int num_imasks, char **imasks)
{
int i;
int rc;
for (i = 0; i < num_imasks; i++) {
rc = spdk_iscsi_init_grp_delete_netmask(ig, imasks[i]);
if (rc != 0) {
goto cleanup;
}
}
return 0;
cleanup:
for (; i > 0; --i) {
rc = spdk_iscsi_init_grp_add_netmask(ig, imasks[i - 1]);
if (rc != 0) {
spdk_iscsi_init_grp_delete_all_netmasks(ig);
break;
}
}
return -1;
}
/* Read spdk iscsi target's config file and create initiator group */
static int
@ -461,6 +510,91 @@ cleanup:
return rc;
}
int
spdk_iscsi_init_grp_add_initiators_from_initiator_list(int tag,
int num_initiator_names,
char **initiator_names,
int num_initiator_masks,
char **initiator_masks)
{
int rc = -1;
struct spdk_iscsi_init_grp *ig;
SPDK_DEBUGLOG(SPDK_LOG_ISCSI,
"add initiator to initiator group: tag=%d, #initiators=%d, #masks=%d\n",
tag, num_initiator_names, num_initiator_masks);
pthread_mutex_lock(&g_spdk_iscsi.mutex);
ig = spdk_iscsi_init_grp_find_by_tag(tag);
if (!ig) {
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
SPDK_ERRLOG("initiator group (%d) is not found\n", tag);
return rc;
}
rc = spdk_iscsi_init_grp_add_initiators(ig, num_initiator_names,
initiator_names);
if (rc < 0) {
SPDK_ERRLOG("add initiator name error\n");
goto error;
}
rc = spdk_iscsi_init_grp_add_netmasks(ig, num_initiator_masks,
initiator_masks);
if (rc < 0) {
SPDK_ERRLOG("add initiator netmask error\n");
spdk_iscsi_init_grp_delete_initiators(ig, num_initiator_names,
initiator_names);
}
error:
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
return rc;
}
int
spdk_iscsi_init_grp_delete_initiators_from_initiator_list(int tag,
int num_initiator_names,
char **initiator_names,
int num_initiator_masks,
char **initiator_masks)
{
int rc = -1;
struct spdk_iscsi_init_grp *ig;
SPDK_DEBUGLOG(SPDK_LOG_ISCSI,
"delete initiator from initiator group: tag=%d, #initiators=%d, #masks=%d\n",
tag, num_initiator_names, num_initiator_masks);
pthread_mutex_lock(&g_spdk_iscsi.mutex);
ig = spdk_iscsi_init_grp_find_by_tag(tag);
if (!ig) {
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
SPDK_ERRLOG("initiator group (%d) is not found\n", tag);
return rc;
}
rc = spdk_iscsi_init_grp_delete_initiators(ig, num_initiator_names,
initiator_names);
if (rc < 0) {
SPDK_ERRLOG("delete initiator name error\n");
goto error;
}
rc = spdk_iscsi_init_grp_delete_netmasks(ig, num_initiator_masks,
initiator_masks);
if (rc < 0) {
SPDK_ERRLOG("delete initiator netmask error\n");
spdk_iscsi_init_grp_add_initiators(ig, num_initiator_names,
initiator_names);
goto error;
}
error:
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
return rc;
}
void
spdk_iscsi_init_grp_destroy(struct spdk_iscsi_init_grp *ig)
{

View File

@ -61,6 +61,12 @@ struct spdk_iscsi_init_grp {
int spdk_iscsi_init_grp_create_from_initiator_list(int tag,
int num_initiator_names, char **initiator_names,
int num_initiator_masks, char **initiator_masks);
int spdk_iscsi_init_grp_add_initiators_from_initiator_list(int tag,
int num_initiator_names, char **initiator_names,
int num_initiator_masks, char **initiator_masks);
int spdk_iscsi_init_grp_delete_initiators_from_initiator_list(int tag,
int num_initiator_names, char **initiator_names,
int num_initiator_masks, char **initiator_masks);
int spdk_iscsi_init_grp_register(struct spdk_iscsi_init_grp *ig);
struct spdk_iscsi_init_grp *spdk_iscsi_init_grp_unregister(int tag);
struct spdk_iscsi_init_grp *spdk_iscsi_init_grp_find_by_tag(int tag);

View File

@ -206,6 +206,91 @@ invalid:
}
SPDK_RPC_REGISTER("add_initiator_group", spdk_rpc_add_initiator_group)
static const struct spdk_json_object_decoder rpc_add_or_delete_initiators_decoders[] = {
{"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32},
{"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list, true},
{"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list, true},
};
static void
spdk_rpc_add_initiators_to_initiator_group(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_initiator_group req = {};
struct spdk_json_write_ctx *w;
if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
SPDK_ERRLOG("spdk_json_decode_object failed\n");
goto invalid;
}
if (spdk_iscsi_init_grp_add_initiators_from_initiator_list(req.tag,
req.initiator_list.num_initiators,
req.initiator_list.initiators,
req.netmask_list.num_netmasks,
req.netmask_list.netmasks)) {
SPDK_ERRLOG("add_initiators_from_initiator_list failed\n");
goto invalid;
}
free_rpc_initiator_group(&req);
w = spdk_jsonrpc_begin_result(request);
if (w == NULL) {
return;
}
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(request, w);
return;
invalid:
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
free_rpc_initiator_group(&req);
}
SPDK_RPC_REGISTER("add_initiators_to_initiator_group", spdk_rpc_add_initiators_to_initiator_group)
static void
spdk_rpc_delete_initiators_from_initiator_group(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_initiator_group req = {};
struct spdk_json_write_ctx *w;
if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
SPDK_ERRLOG("spdk_json_decode_object failed\n");
goto invalid;
}
if (spdk_iscsi_init_grp_delete_initiators_from_initiator_list(req.tag,
req.initiator_list.num_initiators,
req.initiator_list.initiators,
req.netmask_list.num_netmasks,
req.netmask_list.netmasks)) {
SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n");
goto invalid;
}
free_rpc_initiator_group(&req);
w = spdk_jsonrpc_begin_result(request);
if (w == NULL) {
return;
}
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(request, w);
return;
invalid:
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
free_rpc_initiator_group(&req);
}
SPDK_RPC_REGISTER("delete_initiators_from_initiator_group",
spdk_rpc_delete_initiators_from_initiator_group)
struct rpc_delete_initiator_group {
int32_t tag;
};

View File

@ -192,6 +192,26 @@ if __name__ == "__main__":
Example: '255.255.0.0 255.248.0.0' etc""")
p.set_defaults(func=rpc.iscsi.add_initiator_group)
p = subparsers.add_parser('add_initiators_to_initiator_group',
help='Add initiators to an existing initiator group')
p.add_argument(
'tag', help='Initiator group tag (unique, integer > 0)', type=int)
p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses,
enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False)
p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes.
This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False)
p.set_defaults(func=rpc.iscsi.add_initiators_to_initiator_group)
p = subparsers.add_parser('delete_initiators_from_initiator_group',
help='Delete initiators from an existing initiator group')
p.add_argument(
'tag', help='Initiator group tag (unique, integer > 0)', type=int)
p.add_argument('-n', dest='initiator_list', help="""Whitespace-separated list of initiator hostnames or IP addresses,
enclosed in quotes. This parameter can be omitted. Example: 'ANY' or '127.0.0.1 192.168.200.100'""", required=False)
p.add_argument('-m', dest='netmask_list', help="""Whitespace-separated list of initiator netmasks enclosed in quotes.
This parameter can be omitted. Example: '255.255.0.0 255.248.0.0' etc""", required=False)
p.set_defaults(func=rpc.iscsi.delete_initiators_from_initiator_group)
p = subparsers.add_parser('delete_target_node',
help='Delete a target node')
p.add_argument('target_node_name',

View File

@ -120,6 +120,34 @@ def add_initiator_group(args):
args.client.call('add_initiator_group', params)
def add_initiators_to_initiator_group(args):
initiators = []
netmasks = []
if args.initiator_list:
for i in args.initiator_list.strip().split(' '):
initiators.append(i)
if args.netmask_list:
for n in args.netmask_list.strip().split(' '):
netmasks.append(n)
params = {'tag': args.tag, 'initiators': initiators, 'netmasks': netmasks}
args.client.call('add_initiators_to_initiator_group', params)
def delete_initiators_from_initiator_group(args):
initiators = []
netmasks = []
if args.initiator_list:
for i in args.initiator_list.strip().split(' '):
initiators.append(i)
if args.netmask_list:
for n in args.netmask_list.strip().split(' '):
netmasks.append(n)
params = {'tag': args.tag, 'initiators': initiators, 'netmasks': netmasks}
args.client.call('delete_initiators_from_initiator_group', params)
def delete_target_node(args):
params = {'name': args.target_node_name}
args.client.call('delete_target_node', params)

View File

@ -259,6 +259,43 @@ def verify_initiator_groups_rpc_methods(rpc_py, rpc_param):
verify(value['netmasks'][0] == rpc_param['netmask'][idx], 1,
"netmasks value is {}, expected {}".format(value['netmasks'][0], rpc_param['netmask'][idx]))
for idx, value in enumerate(rpc_param['netmask']):
tag = idx + 1
rpc.delete_initiators_from_initiator_group(tag, '-n', rpc_param['initiator_name'], '-m', value)
output = rpc.get_initiator_groups()
jsonvalues = json.loads(output)
verify(len(jsonvalues) == tag, 1,
"get_initiator_groups returned {} groups, expected {}".format(len(jsonvalues), tag))
for idx, value in enumerate(jsonvalues):
verify(value['tag'] == idx + 1, 1,
"tag value is {}, expected {}".format(value['tag'], idx + 1))
initiators = value.get('initiators')
verify(len(initiators) == 0, 1,
"length of initiator list is {}, expected 0".format(len(initiators)))
netmasks = value.get('netmasks')
verify(len(netmasks) == 0, 1,
"length of netmask list is {}, expected 0".format(len(netmasks)))
for idx, value in enumerate(rpc_param['netmask']):
tag = idx + 1
rpc.add_initiators_to_initiator_group(tag, '-n', rpc_param['initiator_name'], '-m', value)
output = rpc.get_initiator_groups()
jsonvalues = json.loads(output)
verify(len(jsonvalues) == tag, 1,
"get_initiator_groups returned {} groups, expected {}".format(len(jsonvalues), tag))
tag_list = []
for idx, value in enumerate(jsonvalues):
verify(value['initiators'][0] == rpc_param['initiator_name'], 1,
"initiator value is {}, expected {}".format(value['initiators'][0], rpc_param['initiator_name']))
tag_list.append(value['tag'])
verify(value['tag'] == idx + 1, 1,
"tag value is {}, expected {}".format(value['tag'], idx + 1))
verify(value['netmasks'][0] == rpc_param['netmask'][idx], 1,
"netmasks value is {}, expected {}".format(value['netmasks'][0], rpc_param['netmask'][idx]))
for idx, value in enumerate(tag_list):
rpc.delete_initiator_group(value)
output = rpc.get_initiator_groups()

View File

@ -32,6 +32,7 @@
*/
#include "spdk/stdinc.h"
#include "spdk_cunit.h"
#include "CUnit/Basic.h"
#include "iscsi/init_grp.c"
@ -452,6 +453,181 @@ netmask_overwrite_all_to_any_case(void)
spdk_iscsi_init_grp_destroy(ig);
}
static void
add_delete_initiator_names_case(void)
{
int rc, i;
struct spdk_iscsi_init_grp *ig;
struct spdk_iscsi_initiator_name *iname;
char *names[3] = {"iqn.2018-02.spdk.io:0001", "iqn.2018-02.spdk.io:0002", "iqn.2018-02.spdk.io:0003"};
ig = spdk_iscsi_init_grp_create(1);
SPDK_CU_ASSERT_FATAL(ig != NULL);
rc = spdk_iscsi_init_grp_add_initiators(ig, 3, names);
CU_ASSERT(rc == 0);
for (i = 0; i < 3; i++) {
iname = spdk_iscsi_init_grp_find_initiator(ig, names[i]);
CU_ASSERT(iname != NULL);
}
rc = spdk_iscsi_init_grp_delete_initiators(ig, 3, names);
CU_ASSERT(rc == 0);
if (ig != NULL) {
CU_ASSERT(TAILQ_EMPTY(&ig->initiator_head));
}
spdk_iscsi_init_grp_destroy(ig);
}
static void
add_duplicated_initiator_names_case(void)
{
int rc;
struct spdk_iscsi_init_grp *ig;
char *names[3] = {"iqn.2018-02.spdk.io:0001", "iqn.2018-02.spdk.io:0002", "iqn.2018-02.spdk.io:0001"};
ig = spdk_iscsi_init_grp_create(1);
SPDK_CU_ASSERT_FATAL(ig != NULL);
rc = spdk_iscsi_init_grp_add_initiators(ig, 3, names);
CU_ASSERT(rc != 0);
if (ig != NULL) {
CU_ASSERT(TAILQ_EMPTY(&ig->initiator_head));
}
spdk_iscsi_init_grp_destroy(ig);
}
static void
delete_nonexisting_initiator_names_case(void)
{
int rc, i;
struct spdk_iscsi_init_grp *ig;
struct spdk_iscsi_initiator_name *iname;
char *names1[3] = {"iqn.2018-02.spdk.io:0001", "iqn.2018-02.spdk.io:0002", "iqn.2018-02.spdk.io:0003"};
char *names2[3] = {"iqn.2018-02.spdk.io:0001", "iqn.2018-02.spdk.io:0002", "iqn.2018-02.spdk.io:0004"};
ig = spdk_iscsi_init_grp_create(1);
SPDK_CU_ASSERT_FATAL(ig != NULL);
rc = spdk_iscsi_init_grp_add_initiators(ig, 3, names1);
CU_ASSERT(rc == 0);
for (i = 0; i < 3; i++) {
iname = spdk_iscsi_init_grp_find_initiator(ig, names1[i]);
CU_ASSERT(iname != NULL);
}
rc = spdk_iscsi_init_grp_delete_initiators(ig, 3, names2);
CU_ASSERT(rc != 0);
for (i = 0; i < 3; i++) {
iname = spdk_iscsi_init_grp_find_initiator(ig, names1[i]);
CU_ASSERT(iname != NULL);
}
rc = spdk_iscsi_init_grp_delete_initiators(ig, 3, names1);
CU_ASSERT(rc == 0);
if (ig != NULL) {
CU_ASSERT(TAILQ_EMPTY(&ig->initiator_head));
}
spdk_iscsi_init_grp_destroy(ig);
}
static void
add_delete_netmasks_case(void)
{
int rc, i;
struct spdk_iscsi_init_grp *ig;
struct spdk_iscsi_initiator_netmask *netmask;
char *netmasks[3] = {"192.168.2.0", "192.168.2.1", "192.168.2.2"};
ig = spdk_iscsi_init_grp_create(1);
SPDK_CU_ASSERT_FATAL(ig != NULL);
rc = spdk_iscsi_init_grp_add_netmasks(ig, 3, netmasks);
CU_ASSERT(rc == 0);
for (i = 0; i < 3; i++) {
netmask = spdk_iscsi_init_grp_find_netmask(ig, netmasks[i]);
CU_ASSERT(netmask != NULL);
}
rc = spdk_iscsi_init_grp_delete_netmasks(ig, 3, netmasks);
CU_ASSERT(rc == 0);
if (ig != NULL) {
CU_ASSERT(TAILQ_EMPTY(&ig->netmask_head));
}
spdk_iscsi_init_grp_destroy(ig);
}
static void
add_duplicated_netmasks_case(void)
{
int rc;
struct spdk_iscsi_init_grp *ig;
char *netmasks[3] = {"192.168.2.0", "192.168.2.1", "192.168.2.0"};
ig = spdk_iscsi_init_grp_create(1);
SPDK_CU_ASSERT_FATAL(ig != NULL);
rc = spdk_iscsi_init_grp_add_netmasks(ig, 3, netmasks);
CU_ASSERT(rc != 0);
if (ig != NULL) {
CU_ASSERT(TAILQ_EMPTY(&ig->netmask_head));
}
spdk_iscsi_init_grp_destroy(ig);
}
static void
delete_nonexisting_netmasks_case(void)
{
int rc, i;
struct spdk_iscsi_init_grp *ig;
struct spdk_iscsi_initiator_netmask *netmask;
char *netmasks1[3] = {"192.168.2.0", "192.168.2.1", "192.168.2.2"};
char *netmasks2[3] = {"192.168.2.0", "192.168.2.1", "192.168.2.3"};
ig = spdk_iscsi_init_grp_create(1);
SPDK_CU_ASSERT_FATAL(ig != NULL);
rc = spdk_iscsi_init_grp_add_netmasks(ig, 3, netmasks1);
CU_ASSERT(rc == 0);
for (i = 0; i < 3; i++) {
netmask = spdk_iscsi_init_grp_find_netmask(ig, netmasks1[i]);
CU_ASSERT(netmask != NULL);
}
rc = spdk_iscsi_init_grp_delete_netmasks(ig, 3, netmasks2);
CU_ASSERT(rc != 0);
for (i = 0; i < 3; i++) {
netmask = spdk_iscsi_init_grp_find_netmask(ig, netmasks1[i]);
CU_ASSERT(netmask != NULL);
}
rc = spdk_iscsi_init_grp_delete_netmasks(ig, 3, netmasks1);
CU_ASSERT(rc == 0);
if (ig != NULL) {
CU_ASSERT(TAILQ_EMPTY(&ig->netmask_head));
}
spdk_iscsi_init_grp_destroy(ig);
}
int
main(int argc, char **argv)
{
@ -500,6 +676,18 @@ main(int argc, char **argv)
initiator_name_overwrite_all_to_any_case) == NULL
|| CU_add_test(suite, "overwrite all to any for netmask case",
netmask_overwrite_all_to_any_case) == NULL
|| CU_add_test(suite, "add/delete initiator names case",
add_delete_initiator_names_case) == NULL
|| CU_add_test(suite, "add duplicated initiator names case",
add_duplicated_initiator_names_case) == NULL
|| CU_add_test(suite, "delete nonexisting initiator names case",
delete_nonexisting_initiator_names_case) == NULL
|| CU_add_test(suite, "add/delete netmasks case",
add_delete_netmasks_case) == NULL
|| CU_add_test(suite, "add duplicated netmasks case",
add_duplicated_netmasks_case) == NULL
|| CU_add_test(suite, "delete nonexisting netmasks case",
delete_nonexisting_netmasks_case) == NULL
) {
CU_cleanup_registry();
return CU_get_error();