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