xref: /spdk/test/iscsi_tgt/rpc_config/rpc_config.py (revision c7acbd6bef98bb47b167bdcbe5efc40128fa190b)
1#!/usr/bin/env python3
2#  SPDX-License-Identifier: BSD-3-Clause
3#  Copyright (C) 2016 Intel Corporation
4#  All rights reserved.
5#
6
7import os
8import os.path
9import re
10import sys
11import time
12import json
13import random
14from subprocess import check_call, call, check_output, Popen, PIPE, CalledProcessError
15
16if (len(sys.argv) == 6):
17    target_ip = sys.argv[2]
18    initiator_ip = sys.argv[3]
19    port = sys.argv[4]
20    netmask = sys.argv[5]
21
22other_ip = '127.0.0.6'
23initiator_name = 'ANY'
24portal_tag = '1'
25initiator_tag = '1'
26
27rpc_param = {
28    'target_ip': target_ip,
29    'initiator_ip': initiator_ip,
30    'port': port,
31    'initiator_name': initiator_name,
32    'netmask': netmask,
33    'lun_total': 3,
34    'malloc_bdev_size': 64,
35    'malloc_block_size': 512,
36    'queue_depth': 64,
37    'target_name': 'Target3',
38    'alias_name': 'Target3_alias',
39    'disable_chap': True,
40    'mutual_chap': False,
41    'require_chap': False,
42    'chap_group': 0,
43    'header_digest': False,
44    'data_digest': False,
45    'log_flag': 'rpc',
46    'cpumask': 0x1
47}
48
49
50class RpcException(Exception):
51
52    def __init__(self, retval, msg):
53        super(RpcException, self).__init__(msg)
54        self.retval = retval
55        self.message = msg
56
57
58class spdk_rpc(object):
59
60    def __init__(self, rpc_py):
61        self.rpc_py = rpc_py
62
63    def __getattr__(self, name):
64        def call(*args):
65            cmd = "{} {}".format(self.rpc_py, name)
66            for arg in args:
67                cmd += " {}".format(arg)
68            return check_output(cmd, shell=True).decode("utf-8")
69        return call
70
71
72def verify(expr, retcode, msg):
73    if not expr:
74        raise RpcException(retcode, msg)
75
76
77def verify_log_flag_rpc_methods(rpc_py, rpc_param):
78    rpc = spdk_rpc(rpc_py)
79    output = rpc.log_get_flags()
80    jsonvalue = json.loads(output)
81    verify(not jsonvalue[rpc_param['log_flag']], 1,
82           "log_get_flags returned {}, expected false".format(jsonvalue))
83    rpc.log_set_flag(rpc_param['log_flag'])
84    output = rpc.log_get_flags()
85    jsonvalue = json.loads(output)
86    verify(jsonvalue[rpc_param['log_flag']], 1,
87           "log_get_flags returned {}, expected true".format(jsonvalue))
88    rpc.log_clear_flag(rpc_param['log_flag'])
89    output = rpc.log_get_flags()
90    jsonvalue = json.loads(output)
91    verify(not jsonvalue[rpc_param['log_flag']], 1,
92           "log_get_flags returned {}, expected false".format(jsonvalue))
93
94    print("verify_log_flag_rpc_methods passed")
95
96
97def verify_iscsi_connection_rpc_methods(rpc_py):
98    rpc = spdk_rpc(rpc_py)
99    output = rpc.iscsi_get_connections()
100    jsonvalue = json.loads(output)
101    verify(not jsonvalue, 1,
102           "iscsi_get_connections returned {}, expected empty".format(jsonvalue))
103
104    rpc.bdev_malloc_create(rpc_param['malloc_bdev_size'], rpc_param['malloc_block_size'])
105    rpc.iscsi_create_portal_group(portal_tag, "{}:{}".format(rpc_param['target_ip'], str(rpc_param['port'])))
106    rpc.iscsi_create_initiator_group(initiator_tag, rpc_param['initiator_name'], rpc_param['netmask'])
107
108    lun_mapping = "Malloc" + str(rpc_param['lun_total']) + ":0"
109    net_mapping = portal_tag + ":" + initiator_tag
110    rpc.iscsi_create_target_node(rpc_param['target_name'], rpc_param['alias_name'], lun_mapping,
111                                 net_mapping, rpc_param['queue_depth'], '-d')
112    check_output('iscsiadm -m discovery -t st -p {}'.format(rpc_param['target_ip']), shell=True)
113    check_output('iscsiadm -m node --login', shell=True)
114    name = json.loads(rpc.iscsi_get_target_nodes())[0]['name']
115    output = rpc.iscsi_get_connections()
116    jsonvalues = json.loads(output)
117    verify(jsonvalues[0]['target_node_name'] == rpc_param['target_name'], 1,
118           "target node name value is {}, expected {}".format(jsonvalues[0]['target_node_name'], rpc_param['target_name']))
119    verify(jsonvalues[0]['initiator_addr'] == rpc_param['initiator_ip'], 1,
120           "initiator address values is {}, expected {}".format(jsonvalues[0]['initiator_addr'], rpc_param['initiator_ip']))
121    verify(jsonvalues[0]['target_addr'] == rpc_param['target_ip'], 1,
122           "target address values is {}, expected {}".format(jsonvalues[0]['target_addr'], rpc_param['target_ip']))
123
124    check_output('iscsiadm -m node --logout', shell=True)
125    check_output('iscsiadm -m node -o delete', shell=True)
126    rpc.iscsi_delete_initiator_group(initiator_tag)
127    rpc.iscsi_delete_portal_group(portal_tag)
128    rpc.iscsi_delete_target_node(name)
129    output = rpc.iscsi_get_connections()
130    jsonvalues = json.loads(output)
131    verify(not jsonvalues, 1,
132           "iscsi_get_connections returned {}, expected empty".format(jsonvalues))
133
134    print("verify_iscsi_connection_rpc_methods passed")
135
136
137def verify_scsi_devices_rpc_methods(rpc_py):
138    rpc = spdk_rpc(rpc_py)
139    output = rpc.scsi_get_devices()
140    jsonvalue = json.loads(output)
141    verify(not jsonvalue, 1,
142           "scsi_get_devices returned {}, expected empty".format(jsonvalue))
143
144    rpc.bdev_malloc_create(rpc_param['malloc_bdev_size'], rpc_param['malloc_block_size'])
145    rpc.iscsi_create_portal_group(portal_tag, "{}:{}".format(rpc_param['target_ip'], str(rpc_param['port'])))
146    rpc.iscsi_create_initiator_group(initiator_tag, rpc_param['initiator_name'], rpc_param['netmask'])
147
148    lun_mapping = "Malloc" + str(rpc_param['lun_total']) + ":0"
149    net_mapping = portal_tag + ":" + initiator_tag
150    rpc.iscsi_create_target_node(rpc_param['target_name'], rpc_param['alias_name'], lun_mapping,
151                                 net_mapping, rpc_param['queue_depth'], '-d')
152    check_output('iscsiadm -m discovery -t st -p {}'.format(rpc_param['target_ip']), shell=True)
153    check_output('iscsiadm -m node --login', shell=True)
154    name = json.loads(rpc.iscsi_get_target_nodes())[0]['name']
155    output = rpc.iscsi_get_options()
156    jsonvalues = json.loads(output)
157    nodebase = jsonvalues['node_base']
158    output = rpc.scsi_get_devices()
159    jsonvalues = json.loads(output)
160    verify(jsonvalues[0]['device_name'] == nodebase + ":" + rpc_param['target_name'], 1,
161           "device name value is {}, expected {}".format(jsonvalues[0]['device_name'], rpc_param['target_name']))
162    verify(jsonvalues[0]['id'] == 0, 1,
163           "device id value is {}, expected 0".format(jsonvalues[0]['id']))
164
165    check_output('iscsiadm -m node --logout', shell=True)
166    check_output('iscsiadm -m node -o delete', shell=True)
167    rpc.iscsi_delete_initiator_group(initiator_tag)
168    rpc.iscsi_delete_portal_group(portal_tag)
169    rpc.iscsi_delete_target_node(name)
170    output = rpc.scsi_get_devices()
171    jsonvalues = json.loads(output)
172    verify(not jsonvalues, 1,
173           "scsi_get_devices returned {}, expected empty".format(jsonvalues))
174
175    print("verify_scsi_devices_rpc_methods passed")
176
177
178def create_malloc_bdevs_rpc_methods(rpc_py, rpc_param):
179    rpc = spdk_rpc(rpc_py)
180
181    for i in range(1, rpc_param['lun_total'] + 1):
182        rpc.bdev_malloc_create(rpc_param['malloc_bdev_size'], rpc_param['malloc_block_size'])
183
184    print("create_malloc_bdevs_rpc_methods passed")
185
186
187def verify_portal_groups_rpc_methods(rpc_py, rpc_param):
188    rpc = spdk_rpc(rpc_py)
189    output = rpc.iscsi_get_portal_groups()
190    jsonvalues = json.loads(output)
191    verify(not jsonvalues, 1,
192           "iscsi_get_portal_groups returned {} groups, expected empty".format(jsonvalues))
193
194    lo_ip = (target_ip, other_ip)
195    for idx, value in enumerate(lo_ip):
196        # The portal group tag must start at 1
197        tag = idx + 1
198        rpc.iscsi_create_portal_group(tag, "{}:{}".format(value, rpc_param['port']))
199        output = rpc.iscsi_get_portal_groups()
200        jsonvalues = json.loads(output)
201        verify(len(jsonvalues) == tag, 1,
202               "iscsi_get_portal_groups returned {} groups, expected {}".format(len(jsonvalues), tag))
203
204    tag_list = []
205    for idx, value in enumerate(jsonvalues):
206        verify(value['portals'][0]['host'] == lo_ip[idx], 1,
207               "host value is {}, expected {}".format(value['portals'][0]['host'], rpc_param['target_ip']))
208        verify(value['portals'][0]['port'] == str(rpc_param['port']), 1,
209               "port value is {}, expected {}".format(value['portals'][0]['port'], str(rpc_param['port'])))
210        tag_list.append(value['tag'])
211        verify(value['tag'] == idx + 1, 1,
212               "tag value is {}, expected {}".format(value['tag'], idx + 1))
213
214    for idx, value in enumerate(tag_list):
215        rpc.iscsi_delete_portal_group(value)
216        output = rpc.iscsi_get_portal_groups()
217        jsonvalues = json.loads(output)
218        verify(len(jsonvalues) == (len(tag_list) - (idx + 1)), 1,
219               "get_portal_group returned {} groups, expected {}".format(len(jsonvalues), (len(tag_list) - (idx + 1))))
220        if not jsonvalues:
221            break
222
223        for jidx, jvalue in enumerate(jsonvalues):
224            verify(jvalue['portals'][0]['host'] == lo_ip[idx + jidx + 1], 1,
225                   "host value is {}, expected {}".format(jvalue['portals'][0]['host'], lo_ip[idx + jidx + 1]))
226            verify(jvalue['portals'][0]['port'] == str(rpc_param['port']), 1,
227                   "port value is {}, expected {}".format(jvalue['portals'][0]['port'], str(rpc_param['port'])))
228            verify(jvalue['tag'] != value or jvalue['tag'] == tag_list[idx + jidx + 1], 1,
229                   "tag value is {}, expected {} and not {}".format(jvalue['tag'], tag_list[idx + jidx + 1], value))
230
231    print("verify_portal_groups_rpc_methods passed")
232
233
234def verify_initiator_groups_rpc_methods(rpc_py, rpc_param):
235    rpc = spdk_rpc(rpc_py)
236    output = rpc.iscsi_get_initiator_groups()
237    jsonvalues = json.loads(output)
238    verify(not jsonvalues, 1,
239           "iscsi_get_initiator_groups returned {}, expected empty".format(jsonvalues))
240    for idx, value in enumerate(rpc_param['netmask']):
241        # The initiator group tag must start at 1
242        tag = idx + 1
243        rpc.iscsi_create_initiator_group(tag, rpc_param['initiator_name'], value)
244        output = rpc.iscsi_get_initiator_groups()
245        jsonvalues = json.loads(output)
246        verify(len(jsonvalues) == tag, 1,
247               "iscsi_get_initiator_groups returned {} groups, expected {}".format(len(jsonvalues), tag))
248
249    tag_list = []
250    for idx, value in enumerate(jsonvalues):
251        verify(value['initiators'][0] == rpc_param['initiator_name'], 1,
252               "initiator value is {}, expected {}".format(value['initiators'][0], rpc_param['initiator_name']))
253        tag_list.append(value['tag'])
254        verify(value['tag'] == idx + 1, 1,
255               "tag value is {}, expected {}".format(value['tag'], idx + 1))
256        verify(value['netmasks'][0] == rpc_param['netmask'][idx], 1,
257               "netmasks value is {}, expected {}".format(value['netmasks'][0], rpc_param['netmask'][idx]))
258
259    for idx, value in enumerate(rpc_param['netmask']):
260        tag = idx + 1
261        rpc.iscsi_initiator_group_remove_initiators(tag, '-n', rpc_param['initiator_name'], '-m', value)
262
263    output = rpc.iscsi_get_initiator_groups()
264    jsonvalues = json.loads(output)
265    verify(len(jsonvalues) == tag, 1,
266           "iscsi_get_initiator_groups returned {} groups, expected {}".format(len(jsonvalues), tag))
267
268    for idx, value in enumerate(jsonvalues):
269        verify(value['tag'] == idx + 1, 1,
270               "tag value is {}, expected {}".format(value['tag'], idx + 1))
271        initiators = value.get('initiators')
272        verify(len(initiators) == 0, 1,
273               "length of initiator list is {}, expected 0".format(len(initiators)))
274        netmasks = value.get('netmasks')
275        verify(len(netmasks) == 0, 1,
276               "length of netmask list is {}, expected 0".format(len(netmasks)))
277
278    for idx, value in enumerate(rpc_param['netmask']):
279        tag = idx + 1
280        rpc.iscsi_initiator_group_add_initiators(tag, '-n', rpc_param['initiator_name'], '-m', value)
281    output = rpc.iscsi_get_initiator_groups()
282    jsonvalues = json.loads(output)
283    verify(len(jsonvalues) == tag, 1,
284           "iscsi_get_initiator_groups returned {} groups, expected {}".format(len(jsonvalues), tag))
285
286    tag_list = []
287    for idx, value in enumerate(jsonvalues):
288        verify(value['initiators'][0] == rpc_param['initiator_name'], 1,
289               "initiator value is {}, expected {}".format(value['initiators'][0], rpc_param['initiator_name']))
290        tag_list.append(value['tag'])
291        verify(value['tag'] == idx + 1, 1,
292               "tag value is {}, expected {}".format(value['tag'], idx + 1))
293        verify(value['netmasks'][0] == rpc_param['netmask'][idx], 1,
294               "netmasks value is {}, expected {}".format(value['netmasks'][0], rpc_param['netmask'][idx]))
295
296    for idx, value in enumerate(tag_list):
297        rpc.iscsi_delete_initiator_group(value)
298        output = rpc.iscsi_get_initiator_groups()
299        jsonvalues = json.loads(output)
300        verify(len(jsonvalues) == (len(tag_list) - (idx + 1)), 1,
301               "iscsi_get_initiator_groups returned {} groups, expected {}".format(len(jsonvalues), (len(tag_list) - (idx + 1))))
302        if not jsonvalues:
303            break
304        for jidx, jvalue in enumerate(jsonvalues):
305            verify(jvalue['initiators'][0] == rpc_param['initiator_name'], 1,
306                   "initiator value is {}, expected {}".format(jvalue['initiators'][0], rpc_param['initiator_name']))
307            verify(jvalue['tag'] != value or jvalue['tag'] == tag_list[idx + jidx + 1], 1,
308                   "tag value is {}, expected {} and not {}".format(jvalue['tag'], tag_list[idx + jidx + 1], value))
309            verify(jvalue['netmasks'][0] == rpc_param['netmask'][idx + jidx + 1], 1,
310                   "netmasks value is {}, expected {}".format(jvalue['netmasks'][0], rpc_param['netmask'][idx + jidx + 1]))
311
312    print("verify_initiator_groups_rpc_method passed.")
313
314
315def verify_target_nodes_rpc_methods(rpc_py, rpc_param):
316    rpc = spdk_rpc(rpc_py)
317    output = rpc.iscsi_get_options()
318    jsonvalues = json.loads(output)
319    nodebase = jsonvalues['node_base']
320    output = rpc.iscsi_get_target_nodes()
321    jsonvalues = json.loads(output)
322    verify(not jsonvalues, 1,
323           "iscsi_get_target_nodes returned {}, expected empty".format(jsonvalues))
324
325    rpc.bdev_malloc_create(rpc_param['malloc_bdev_size'], rpc_param['malloc_block_size'])
326    rpc.iscsi_create_portal_group(portal_tag, "{}:{}".format(rpc_param['target_ip'], str(rpc_param['port'])))
327    rpc.iscsi_create_initiator_group(initiator_tag, rpc_param['initiator_name'], rpc_param['netmask'])
328
329    lun_mapping = "Malloc" + str(rpc_param['lun_total']) + ":0"
330    net_mapping = portal_tag + ":" + initiator_tag
331    rpc.iscsi_create_target_node(rpc_param['target_name'], rpc_param['alias_name'], lun_mapping,
332                                 net_mapping, rpc_param['queue_depth'], '-d')
333    output = rpc.iscsi_get_target_nodes()
334    jsonvalues = json.loads(output)
335    verify(len(jsonvalues) == 1, 1,
336           "iscsi_get_target_nodes returned {} nodes, expected 1".format(len(jsonvalues)))
337    bdev_name = jsonvalues[0]['luns'][0]['bdev_name']
338    verify(bdev_name == "Malloc" + str(rpc_param['lun_total']), 1,
339           "bdev_name value is {}, expected Malloc{}".format(jsonvalues[0]['luns'][0]['bdev_name'], str(rpc_param['lun_total'])))
340    name = jsonvalues[0]['name']
341    verify(name == nodebase + ":" + rpc_param['target_name'], 1,
342           "target name value is {}, expected {}".format(name, nodebase + ":" + rpc_param['target_name']))
343    verify(jsonvalues[0]['alias_name'] == rpc_param['alias_name'], 1,
344           "target alias_name value is {}, expected {}".format(jsonvalues[0]['alias_name'], rpc_param['alias_name']))
345    verify(jsonvalues[0]['luns'][0]['lun_id'] == 0, 1,
346           "lun id value is {}, expected 0".format(jsonvalues[0]['luns'][0]['lun_id']))
347    verify(jsonvalues[0]['pg_ig_maps'][0]['ig_tag'] == int(initiator_tag), 1,
348           "initiator group tag value is {}, expected {}".format(jsonvalues[0]['pg_ig_maps'][0]['ig_tag'], initiator_tag))
349    verify(jsonvalues[0]['queue_depth'] == rpc_param['queue_depth'], 1,
350           "queue depth value is {}, expected {}".format(jsonvalues[0]['queue_depth'], rpc_param['queue_depth']))
351    verify(jsonvalues[0]['pg_ig_maps'][0]['pg_tag'] == int(portal_tag), 1,
352           "portal group tag value is {}, expected {}".format(jsonvalues[0]['pg_ig_maps'][0]['pg_tag'], portal_tag))
353    verify(jsonvalues[0]['disable_chap'] == rpc_param['disable_chap'], 1,
354           "disable chap value is {}, expected {}".format(jsonvalues[0]['disable_chap'], rpc_param['disable_chap']))
355    verify(jsonvalues[0]['mutual_chap'] == rpc_param['mutual_chap'], 1,
356           "chap mutual value is {}, expected {}".format(jsonvalues[0]['mutual_chap'], rpc_param['mutual_chap']))
357    verify(jsonvalues[0]['require_chap'] == rpc_param['require_chap'], 1,
358           "chap required value is {}, expected {}".format(jsonvalues[0]['require_chap'], rpc_param['require_chap']))
359    verify(jsonvalues[0]['chap_group'] == rpc_param['chap_group'], 1,
360           "chap auth group value is {}, expected {}".format(jsonvalues[0]['chap_group'], rpc_param['chap_group']))
361    verify(jsonvalues[0]['header_digest'] == rpc_param['header_digest'], 1,
362           "header digest value is {}, expected {}".format(jsonvalues[0]['header_digest'], rpc_param['header_digest']))
363    verify(jsonvalues[0]['data_digest'] == rpc_param['data_digest'], 1,
364           "data digest value is {}, expected {}".format(jsonvalues[0]['data_digest'], rpc_param['data_digest']))
365    lun_id = '1'
366    rpc.iscsi_target_node_add_lun(name, bdev_name, "-i", lun_id)
367    output = rpc.iscsi_get_target_nodes()
368    jsonvalues = json.loads(output)
369    verify(jsonvalues[0]['luns'][1]['bdev_name'] == "Malloc" + str(rpc_param['lun_total']), 1,
370           "bdev_name value is {}, expected Malloc{}".format(jsonvalues[0]['luns'][0]['bdev_name'], str(rpc_param['lun_total'])))
371    verify(jsonvalues[0]['luns'][1]['lun_id'] == 1, 1,
372           "lun id value is {}, expected 1".format(jsonvalues[0]['luns'][1]['lun_id']))
373
374    rpc.iscsi_delete_target_node(name)
375    output = rpc.iscsi_get_target_nodes()
376    jsonvalues = json.loads(output)
377    verify(not jsonvalues, 1,
378           "iscsi_get_target_nodes returned {}, expected empty".format(jsonvalues))
379
380    rpc.iscsi_create_target_node(rpc_param['target_name'], rpc_param['alias_name'], lun_mapping,
381                                 net_mapping, rpc_param['queue_depth'], '-d')
382
383    rpc.iscsi_delete_portal_group(portal_tag)
384    rpc.iscsi_delete_initiator_group(initiator_tag)
385    rpc.iscsi_delete_target_node(name)
386    output = rpc.iscsi_get_target_nodes()
387    jsonvalues = json.loads(output)
388    if not jsonvalues:
389        print("This issue will be fixed later.")
390
391    print("verify_target_nodes_rpc_methods passed.")
392
393
394def help_get_interface_ip_list(rpc_py, nic_name):
395    rpc = spdk_rpc(rpc_py)
396    nics = json.loads(rpc.net_get_interfaces())
397    nic = list([x for x in nics if x["name"] == nic_name])
398    verify(len(nic) != 0, 1,
399           "Nic name: {} is not found in {}".format(nic_name, [x["name"] for x in nics]))
400    return nic[0]["ip_addr"]
401
402
403if __name__ == "__main__":
404
405    rpc_py = sys.argv[1]
406
407    try:
408        verify_log_flag_rpc_methods(rpc_py, rpc_param)
409        create_malloc_bdevs_rpc_methods(rpc_py, rpc_param)
410        verify_portal_groups_rpc_methods(rpc_py, rpc_param)
411        verify_initiator_groups_rpc_methods(rpc_py, rpc_param)
412        verify_target_nodes_rpc_methods(rpc_py, rpc_param)
413        verify_scsi_devices_rpc_methods(rpc_py)
414        verify_iscsi_connection_rpc_methods(rpc_py)
415    except RpcException as e:
416        print("{}. Exiting with status {}".format(e.message, e.retval))
417        raise e
418    except Exception as e:
419        raise e
420
421    sys.exit(0)
422