1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
#!/usr/bin/python3
# Copyright (c) 2021, Dell Inc. or its subsidiaries. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
# See the LICENSE file for details.
#
# This file is part of NVMe STorage Appliance Services (nvme-stas).
#
# Authors: Martin Belanger <Martin.Belanger@dell.com>
#
''' STorage Appliance Finder Control Utility
'''
import sys
import json
import pprint
from argparse import ArgumentParser
import dasbus.error
from dasbus.connection import SystemMessageBus
from staslib import defs
def tron(args): # pylint: disable=unused-argument
'''@brief Trace ON'''
bus = SystemMessageBus()
iface = bus.get_proxy(defs.STAFD_DBUS_NAME, defs.STAFD_DBUS_PATH)
iface.tron = True # pylint: disable=assigning-non-slot
print(f'tron = {iface.tron}') # Read value back from stafd and print
def troff(args): # pylint: disable=unused-argument
'''@brief Trace OFF'''
bus = SystemMessageBus()
iface = bus.get_proxy(defs.STAFD_DBUS_NAME, defs.STAFD_DBUS_PATH)
iface.tron = False # pylint: disable=assigning-non-slot
print(f'tron = {iface.tron}') # Read value back from stafd and print
def _extract_cid(ctrl):
return (
ctrl['transport'],
ctrl['traddr'],
ctrl['trsvcid'],
ctrl['host-traddr'],
ctrl['host-iface'],
ctrl['subsysnqn'],
)
def status(args): # pylint: disable=unused-argument
'''@brief retrieve stafd's status information'''
bus = SystemMessageBus()
iface = bus.get_proxy(defs.STAFD_DBUS_NAME, defs.STAFD_DBUS_PATH)
info = json.loads(iface.process_info())
info['controllers'] = iface.list_controllers(True)
for controller in info['controllers']:
transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn = _extract_cid(controller)
controller['log_pages'] = iface.get_log_pages(transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn)
controller.update(
json.loads(iface.controller_info(transport, traddr, trsvcid, host_traddr, host_iface, subsysnqn))
)
print(pprint.pformat(info, width=120))
def ls(args):
'''@brief list the discovery controller's that stafd is
connected (or trying to connect) to.
'''
bus = SystemMessageBus()
iface = bus.get_proxy(defs.STAFD_DBUS_NAME, defs.STAFD_DBUS_PATH)
info = iface.list_controllers(args.detailed)
print(pprint.pformat(info, width=120))
def dlp(args):
'''@brief retrieve a controller's discovery log pages from stafd'''
bus = SystemMessageBus()
iface = bus.get_proxy(defs.STAFD_DBUS_NAME, defs.STAFD_DBUS_PATH)
info = iface.get_log_pages(args.transport, args.traddr, args.trsvcid, args.host_traddr, args.host_iface, args.nqn)
print(pprint.pformat(info, width=120))
def adlp(args):
'''@brief retrieve all of the controller's discovery log pages from stafd'''
bus = SystemMessageBus()
iface = bus.get_proxy(defs.STAFD_DBUS_NAME, defs.STAFD_DBUS_PATH)
info = json.loads(iface.get_all_log_pages(args.detailed))
print(pprint.pformat(info, width=120))
PARSER = ArgumentParser(description='STorage Appliance Finder (STAF)')
PARSER.add_argument('-v', '--version', action='store_true', help='Print version, then exit', default=False)
SUBPARSER = PARSER.add_subparsers(title='Commands')
PRSR = SUBPARSER.add_parser('tron', help='Trace ON')
PRSR.set_defaults(func=tron)
PRSR = SUBPARSER.add_parser('troff', help='Trace OFF')
PRSR.set_defaults(func=troff)
PRSR = SUBPARSER.add_parser('status', help='Show runtime status information about stafd')
PRSR.set_defaults(func=status)
PRSR = SUBPARSER.add_parser('ls', help='List discovery controllers')
PRSR.add_argument(
'-d',
'--detailed',
action='store_true',
help='Print detailed info (default: "%(default)s")',
default=False,
)
PRSR.set_defaults(func=ls)
PRSR = SUBPARSER.add_parser('dlp', help='Show discovery log pages')
PRSR.add_argument(
'-t',
'--transport',
metavar='<trtype>',
action='store',
help='NVMe-over-Fabrics fabric type (default: "%(default)s")',
choices=['tcp', 'rdma', 'fc', 'loop'],
default='tcp',
)
PRSR.add_argument(
'-a',
'--traddr',
metavar='<traddr>',
action='store',
help='Discovery Controller\'s network address',
required=True,
)
PRSR.add_argument(
'-s',
'--trsvcid',
metavar='<trsvcid>',
action='store',
help='Transport service id (for IP addressing, e.g. tcp, rdma, this field is the port number)',
required=True,
)
PRSR.add_argument(
'-w',
'--host-traddr',
metavar='<traddr>',
action='store',
help='Network address used on the host to connect to the Controller (default: "%(default)s")',
default='',
)
PRSR.add_argument(
'-f',
'--host-iface',
metavar='<iface>',
action='store',
help='This field specifies the network interface used on the host to connect to the Controller (default: "%(default)s")',
default='',
)
PRSR.add_argument(
'-n',
'--nqn',
metavar='<nqn>',
action='store',
help='This field specifies the discovery controller\'s NQN. When not specified this option defaults to "%(default)s"',
default=defs.WELL_KNOWN_DISC_NQN,
)
PRSR.set_defaults(func=dlp)
PRSR = SUBPARSER.add_parser('adlp', help='Show all discovery log pages')
PRSR.add_argument(
'-d',
'--detailed',
action='store_true',
help='Print detailed info (default: "%(default)s")',
default=False,
)
PRSR.set_defaults(func=adlp)
ARGS = PARSER.parse_args()
if ARGS.version:
print(f'nvme-stas {defs.VERSION}')
sys.exit(0)
try:
ARGS.func(ARGS)
except dasbus.error.DBusError:
sys.exit('Unable to communicate with stafd over D-Bus. Is stafd running?')
|