]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/scripts/spdkcli/ui_root.py
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / scripts / spdkcli / ui_root.py
1 from .ui_node import UINode, UIBdevs, UILvolStores, UIVhosts
2 from .ui_node_nvmf import UINVMf
3 from .ui_node_iscsi import UIISCSI
4 import rpc.client
5 import rpc
6 from functools import wraps
7
8
9 class UIRoot(UINode):
10 """
11 Root node for CLI menu tree structure. Refreshes running config on startup.
12 """
13 def __init__(self, client, shell):
14 UINode.__init__(self, "/", shell=shell)
15 self.current_bdevs = []
16 self.current_lvol_stores = []
17 self.current_vhost_ctrls = []
18 self.current_nvmf_transports = []
19 self.current_nvmf_subsystems = []
20 self.set_rpc_target(client)
21 self.verbose = False
22 self.is_init = self.check_init()
23 self.methods = []
24
25 def refresh(self):
26 self.methods = self.rpc_get_methods(current=True)
27 if self.is_init is False:
28 methods = "\n".join(self.methods)
29 self.shell.log.warning("SPDK Application is not yet initialized.\n"
30 "Please initialize subsystems with framework_start_init command.\n"
31 "List of available commands in current state:\n"
32 "%s" % methods)
33 else:
34 # Pass because we'd like to build main tree structure for "ls"
35 # even if state is uninitialized
36 pass
37
38 self._children = set([])
39 UIBdevs(self)
40 UILvolStores(self)
41 if self.has_subsystem("vhost"):
42 UIVhosts(self)
43 if self.has_subsystem("nvmf"):
44 UINVMf(self)
45 if self.has_subsystem("iscsi"):
46 UIISCSI(self)
47
48 def set_rpc_target(self, client):
49 self.client = client
50
51 def print_array(self, a):
52 return " ".join(a)
53
54 def verbose(f):
55 # For any configuration calls (create, delete, construct, etc.)
56 # Check if verbose option is to be used and set appropriately.
57 # Do not use for "get_*" methods so that output is not
58 # flooded.
59 def w(self, **kwargs):
60 self.client.log_set_level("INFO" if self.verbose else "ERROR")
61 r = f(self, **kwargs)
62 self.client.log_set_level("ERROR")
63 return r
64 return w
65
66 def is_method_available(f):
67 # Check if method f is available for given spdk target
68 def w(self, **kwargs):
69 if f.__name__ in self.methods:
70 r = f(self, **kwargs)
71 return r
72 # If given method is not avaialble return empty list
73 # similar to real get_* like rpc
74 return []
75 return w
76
77 def ui_command_framework_start_init(self):
78 if rpc.framework_start_init(self.client):
79 self.is_init = True
80 self.refresh()
81
82 def ui_command_load_config(self, filename):
83 with open(filename, "r") as fd:
84 rpc.load_config(self.client, fd)
85
86 def ui_command_load_subsystem_config(self, filename):
87 with open(filename, "r") as fd:
88 rpc.load_subsystem_config(self.client, fd)
89
90 def ui_command_save_config(self, filename, indent=2):
91 with open(filename, "w") as fd:
92 rpc.save_config(self.client, fd, indent)
93
94 def ui_command_save_subsystem_config(self, filename, subsystem, indent=2):
95 with open(filename, "w") as fd:
96 rpc.save_subsystem_config(self.client, fd, indent, subsystem)
97
98 def rpc_get_methods(self, current=False):
99 return rpc.rpc_get_methods(self.client, current=current)
100
101 def check_init(self):
102 return "framework_start_init" not in self.rpc_get_methods(current=True)
103
104 def bdev_get_bdevs(self, bdev_type):
105 if self.is_init:
106 self.current_bdevs = rpc.bdev.bdev_get_bdevs(self.client)
107 # Following replace needs to be done in order for some of the bdev
108 # listings to work: logical volumes, split disk.
109 # For example logical volumes: listing in menu is "Logical_Volume"
110 # (cannot have space), but the product name in SPDK is "Logical Volume"
111 bdev_type = bdev_type.replace("_", " ")
112 for bdev in [x for x in self.current_bdevs if bdev_type in x["product_name"].lower()]:
113 test = Bdev(bdev)
114 yield test
115
116 def bdev_get_iostat(self, **kwargs):
117 return rpc.bdev.bdev_get_iostat(self.client, **kwargs)
118
119 @verbose
120 def bdev_split_create(self, **kwargs):
121 response = rpc.bdev.bdev_split_create(self.client, **kwargs)
122 return self.print_array(response)
123
124 @verbose
125 def bdev_split_delete(self, **kwargs):
126 rpc.bdev.bdev_split_delete(self.client, **kwargs)
127
128 @verbose
129 def create_malloc_bdev(self, **kwargs):
130 response = rpc.bdev.bdev_malloc_create(self.client, **kwargs)
131 return response
132
133 @verbose
134 def bdev_malloc_delete(self, **kwargs):
135 rpc.bdev.bdev_malloc_delete(self.client, **kwargs)
136
137 @verbose
138 def create_iscsi_bdev(self, **kwargs):
139 response = rpc.bdev.bdev_iscsi_create(self.client, **kwargs)
140 return response
141
142 @verbose
143 def bdev_iscsi_delete(self, **kwargs):
144 rpc.bdev.bdev_iscsi_delete(self.client, **kwargs)
145
146 @verbose
147 def bdev_aio_create(self, **kwargs):
148 response = rpc.bdev.bdev_aio_create(self.client, **kwargs)
149 return response
150
151 @verbose
152 def bdev_aio_delete(self, **kwargs):
153 rpc.bdev.bdev_aio_delete(self.client, **kwargs)
154
155 @verbose
156 def create_lvol_bdev(self, **kwargs):
157 response = rpc.lvol.bdev_lvol_create(self.client, **kwargs)
158 return response
159
160 @verbose
161 def bdev_lvol_delete(self, **kwargs):
162 response = rpc.lvol.bdev_lvol_delete(self.client, **kwargs)
163 return response
164
165 @verbose
166 def create_nvme_bdev(self, **kwargs):
167 response = rpc.bdev.bdev_nvme_attach_controller(self.client, **kwargs)
168 return response
169
170 @verbose
171 def bdev_nvme_detach_controller(self, **kwargs):
172 rpc.bdev.bdev_nvme_detach_controller(self.client, **kwargs)
173
174 @verbose
175 def bdev_null_create(self, **kwargs):
176 response = rpc.bdev.bdev_null_create(self.client, **kwargs)
177 return response
178
179 @verbose
180 def bdev_null_delete(self, **kwargs):
181 rpc.bdev.bdev_null_delete(self.client, **kwargs)
182
183 @verbose
184 def create_error_bdev(self, **kwargs):
185 response = rpc.bdev.bdev_error_create(self.client, **kwargs)
186
187 @verbose
188 def bdev_error_delete(self, **kwargs):
189 rpc.bdev.bdev_error_delete(self.client, **kwargs)
190
191 @verbose
192 @is_method_available
193 def bdev_lvol_get_lvstores(self):
194 if self.is_init:
195 self.current_lvol_stores = rpc.lvol.bdev_lvol_get_lvstores(self.client)
196 for lvs in self.current_lvol_stores:
197 yield LvolStore(lvs)
198
199 @verbose
200 def bdev_lvol_create_lvstore(self, **kwargs):
201 response = rpc.lvol.bdev_lvol_create_lvstore(self.client, **kwargs)
202 return response
203
204 @verbose
205 def bdev_lvol_delete_lvstore(self, **kwargs):
206 rpc.lvol.bdev_lvol_delete_lvstore(self.client, **kwargs)
207
208 @verbose
209 def bdev_pmem_create_pool(self, **kwargs):
210 response = rpc.pmem.bdev_pmem_create_pool(self.client, **kwargs)
211 return response
212
213 @verbose
214 def bdev_pmem_delete_pool(self, **kwargs):
215 rpc.pmem.bdev_pmem_delete_pool(self.client, **kwargs)
216
217 @verbose
218 def bdev_pmem_get_pool_info(self, **kwargs):
219 response = rpc.pmem.bdev_pmem_get_pool_info(self.client, **kwargs)
220 return response
221
222 @verbose
223 def bdev_pmem_create(self, **kwargs):
224 response = rpc.bdev.bdev_pmem_create(self.client, **kwargs)
225 return response
226
227 @verbose
228 def bdev_pmem_delete(self, **kwargs):
229 response = rpc.bdev.bdev_pmem_delete(self.client, **kwargs)
230 return response
231
232 @verbose
233 def create_rbd_bdev(self, **kwargs):
234 response = rpc.bdev.bdev_rbd_create(self.client, **kwargs)
235 return response
236
237 @verbose
238 def bdev_rbd_delete(self, **kwargs):
239 response = rpc.bdev.bdev_rbd_delete(self.client, **kwargs)
240 return response
241
242 @verbose
243 def create_virtio_dev(self, **kwargs):
244 response = rpc.vhost.bdev_virtio_attach_controller(self.client, **kwargs)
245 return self.print_array(response)
246
247 @verbose
248 def bdev_virtio_detach_controller(self, **kwargs):
249 response = rpc.vhost.bdev_virtio_detach_controller(self.client, **kwargs)
250 return response
251
252 @verbose
253 def bdev_raid_create(self, **kwargs):
254 rpc.bdev.bdev_raid_create(self.client, **kwargs)
255
256 @verbose
257 def bdev_raid_delete(self, **kwargs):
258 rpc.bdev.bdev_raid_delete(self.client, **kwargs)
259
260 @verbose
261 @is_method_available
262 def bdev_virtio_scsi_get_devices(self):
263 if self.is_init:
264 for bdev in rpc.vhost.bdev_virtio_scsi_get_devices(self.client):
265 test = Bdev(bdev)
266 yield test
267
268 def list_vhost_ctrls(self):
269 if self.is_init:
270 self.current_vhost_ctrls = rpc.vhost.vhost_get_controllers(self.client)
271
272 @verbose
273 @is_method_available
274 def vhost_get_controllers(self, ctrlr_type):
275 if self.is_init:
276 self.list_vhost_ctrls()
277 for ctrlr in [x for x in self.current_vhost_ctrls if ctrlr_type in list(x["backend_specific"].keys())]:
278 yield VhostCtrlr(ctrlr)
279
280 @verbose
281 def vhost_delete_controller(self, **kwargs):
282 rpc.vhost.vhost_delete_controller(self.client, **kwargs)
283
284 @verbose
285 def vhost_create_scsi_controller(self, **kwargs):
286 rpc.vhost.vhost_create_scsi_controller(self.client, **kwargs)
287
288 @verbose
289 def vhost_create_blk_controller(self, **kwargs):
290 rpc.vhost.vhost_create_blk_controller(self.client, **kwargs)
291
292 @verbose
293 def vhost_scsi_controller_remove_target(self, **kwargs):
294 rpc.vhost.vhost_scsi_controller_remove_target(self.client, **kwargs)
295
296 @verbose
297 def vhost_scsi_controller_add_target(self, **kwargs):
298 rpc.vhost.vhost_scsi_controller_add_target(self.client, **kwargs)
299
300 def vhost_controller_set_coalescing(self, **kwargs):
301 rpc.vhost.vhost_controller_set_coalescing(self.client, **kwargs)
302
303 @verbose
304 def create_nvmf_transport(self, **kwargs):
305 rpc.nvmf.nvmf_create_transport(self.client, **kwargs)
306
307 def list_nvmf_transports(self):
308 if self.is_init:
309 self.current_nvmf_transports = rpc.nvmf.nvmf_get_transports(self.client)
310
311 @verbose
312 @is_method_available
313 def nvmf_get_transports(self):
314 if self.is_init:
315 self.list_nvmf_transports()
316 for transport in self.current_nvmf_transports:
317 yield NvmfTransport(transport)
318
319 def list_nvmf_subsystems(self):
320 if self.is_init:
321 self.current_nvmf_subsystems = rpc.nvmf.nvmf_get_subsystems(self.client)
322
323 @verbose
324 @is_method_available
325 def nvmf_get_subsystems(self):
326 if self.is_init:
327 self.list_nvmf_subsystems()
328 for subsystem in self.current_nvmf_subsystems:
329 yield NvmfSubsystem(subsystem)
330
331 @verbose
332 def create_nvmf_subsystem(self, **kwargs):
333 rpc.nvmf.nvmf_create_subsystem(self.client, **kwargs)
334
335 @verbose
336 def nvmf_delete_subsystem(self, **kwargs):
337 rpc.nvmf.nvmf_delete_subsystem(self.client, **kwargs)
338
339 @verbose
340 def nvmf_subsystem_add_listener(self, **kwargs):
341 rpc.nvmf.nvmf_subsystem_add_listener(self.client, **kwargs)
342
343 @verbose
344 def nvmf_subsystem_remove_listener(self, **kwargs):
345 rpc.nvmf.nvmf_subsystem_remove_listener(self.client, **kwargs)
346
347 @verbose
348 def nvmf_subsystem_add_host(self, **kwargs):
349 rpc.nvmf.nvmf_subsystem_add_host(self.client, **kwargs)
350
351 @verbose
352 def nvmf_subsystem_remove_host(self, **kwargs):
353 rpc.nvmf.nvmf_subsystem_remove_host(self.client, **kwargs)
354
355 @verbose
356 def nvmf_subsystem_allow_any_host(self, **kwargs):
357 rpc.nvmf.nvmf_subsystem_allow_any_host(self.client, **kwargs)
358
359 @verbose
360 def nvmf_subsystem_add_ns(self, **kwargs):
361 rpc.nvmf.nvmf_subsystem_add_ns(self.client, **kwargs)
362
363 @verbose
364 def nvmf_subsystem_remove_ns(self, **kwargs):
365 rpc.nvmf.nvmf_subsystem_remove_ns(self.client, **kwargs)
366
367 @verbose
368 def nvmf_subsystem_allow_any_host(self, **kwargs):
369 rpc.nvmf.nvmf_subsystem_allow_any_host(self.client, **kwargs)
370
371 @verbose
372 @is_method_available
373 def scsi_get_devices(self):
374 if self.is_init:
375 for device in rpc.iscsi.scsi_get_devices(self.client):
376 yield ScsiObj(device)
377
378 @verbose
379 @is_method_available
380 def iscsi_get_target_nodes(self):
381 if self.is_init:
382 for tg in rpc.iscsi.iscsi_get_target_nodes(self.client):
383 yield tg
384
385 @verbose
386 def iscsi_create_target_node(self, **kwargs):
387 rpc.iscsi.iscsi_create_target_node(self.client, **kwargs)
388
389 @verbose
390 def iscsi_delete_target_node(self, **kwargs):
391 rpc.iscsi.iscsi_delete_target_node(self.client, **kwargs)
392
393 @verbose
394 @is_method_available
395 def iscsi_get_portal_groups(self):
396 if self.is_init:
397 for pg in rpc.iscsi.iscsi_get_portal_groups(self.client):
398 yield ScsiObj(pg)
399
400 @verbose
401 @is_method_available
402 def iscsi_get_initiator_groups(self):
403 if self.is_init:
404 for ig in rpc.iscsi.iscsi_get_initiator_groups(self.client):
405 yield ScsiObj(ig)
406
407 @verbose
408 def construct_portal_group(self, **kwargs):
409 rpc.iscsi.iscsi_create_portal_group(self.client, **kwargs)
410
411 @verbose
412 def iscsi_delete_portal_group(self, **kwargs):
413 rpc.iscsi.iscsi_delete_portal_group(self.client, **kwargs)
414
415 @verbose
416 def construct_initiator_group(self, **kwargs):
417 rpc.iscsi.iscsi_create_initiator_group(self.client, **kwargs)
418
419 @verbose
420 def iscsi_delete_initiator_group(self, **kwargs):
421 rpc.iscsi.iscsi_delete_initiator_group(self.client, **kwargs)
422
423 @verbose
424 @is_method_available
425 def iscsi_get_connections(self, **kwargs):
426 if self.is_init:
427 for ic in rpc.iscsi.iscsi_get_connections(self.client, **kwargs):
428 yield ic
429
430 @verbose
431 def iscsi_initiator_group_add_initiators(self, **kwargs):
432 rpc.iscsi.iscsi_initiator_group_add_initiators(self.client, **kwargs)
433
434 @verbose
435 def iscsi_initiator_group_remove_initiators(self, **kwargs):
436 rpc.iscsi.iscsi_initiator_group_remove_initiators(self.client, **kwargs)
437
438 @verbose
439 def iscsi_target_node_add_pg_ig_maps(self, **kwargs):
440 rpc.iscsi.iscsi_target_node_add_pg_ig_maps(self.client, **kwargs)
441
442 @verbose
443 def iscsi_target_node_remove_pg_ig_maps(self, **kwargs):
444 rpc.iscsi.iscsi_target_node_remove_pg_ig_maps(self.client, **kwargs)
445
446 @verbose
447 def iscsi_auth_group_add_secret(self, **kwargs):
448 rpc.iscsi.iscsi_auth_group_add_secret(self.client, **kwargs)
449
450 @verbose
451 def iscsi_auth_group_remove_secret(self, **kwargs):
452 rpc.iscsi.iscsi_auth_group_remove_secret(self.client, **kwargs)
453
454 @verbose
455 @is_method_available
456 def iscsi_get_auth_groups(self, **kwargs):
457 return rpc.iscsi.iscsi_get_auth_groups(self.client, **kwargs)
458
459 @verbose
460 def iscsi_create_auth_group(self, **kwargs):
461 rpc.iscsi.iscsi_create_auth_group(self.client, **kwargs)
462
463 @verbose
464 def iscsi_delete_auth_group(self, **kwargs):
465 rpc.iscsi.iscsi_delete_auth_group(self.client, **kwargs)
466
467 @verbose
468 def iscsi_target_node_set_auth(self, **kwargs):
469 rpc.iscsi.iscsi_target_node_set_auth(self.client, **kwargs)
470
471 @verbose
472 def iscsi_target_node_add_lun(self, **kwargs):
473 rpc.iscsi.iscsi_target_node_add_lun(self.client, **kwargs)
474
475 @verbose
476 def iscsi_set_discovery_auth(self, **kwargs):
477 rpc.iscsi.iscsi_set_discovery_auth(self.client, **kwargs)
478
479 @verbose
480 @is_method_available
481 def iscsi_get_options(self, **kwargs):
482 return rpc.iscsi.iscsi_get_options(self.client, **kwargs)
483
484 def has_subsystem(self, subsystem):
485 for system in rpc.subsystem.framework_get_subsystems(self.client):
486 if subsystem.lower() == system["subsystem"].lower():
487 return True
488 return False
489
490
491 class Bdev(object):
492 def __init__(self, bdev_info):
493 """
494 All class attributes are set based on what information is received
495 from bdev_get_bdevs RPC call.
496 # TODO: Document in docstring parameters which describe bdevs.
497 # TODO: Possible improvement: JSON schema might be used here in future
498 """
499 for i in list(bdev_info.keys()):
500 setattr(self, i, bdev_info[i])
501
502
503 class LvolStore(object):
504 def __init__(self, lvs_info):
505 """
506 All class attributes are set based on what information is received
507 from bdev_get_bdevs RPC call.
508 # TODO: Document in docstring parameters which describe bdevs.
509 # TODO: Possible improvement: JSON schema might be used here in future
510 """
511 for i in list(lvs_info.keys()):
512 setattr(self, i, lvs_info[i])
513
514
515 class VhostCtrlr(object):
516 def __init__(self, ctrlr_info):
517 """
518 All class attributes are set based on what information is received
519 from vhost_get_controllers RPC call.
520 # TODO: Document in docstring parameters which describe bdevs.
521 # TODO: Possible improvement: JSON schema might be used here in future
522 """
523 for i in list(ctrlr_info.keys()):
524 setattr(self, i, ctrlr_info[i])
525
526
527 class NvmfTransport(object):
528 def __init__(self, transport_info):
529 """
530 All class attributes are set based on what information is received
531 from get_nvmf_transport RPC call.
532 # TODO: Document in docstring parameters which describe bdevs.
533 # TODO: Possible improvement: JSON schema might be used here in future
534 """
535 for i in transport_info.keys():
536 setattr(self, i, transport_info[i])
537
538
539 class NvmfSubsystem(object):
540 def __init__(self, subsystem_info):
541 """
542 All class attributes are set based on what information is received
543 from get_nvmf_subsystem RPC call.
544 # TODO: Document in docstring parameters which describe bdevs.
545 # TODO: Possible improvement: JSON schema might be used here in future
546 """
547 for i in subsystem_info.keys():
548 setattr(self, i, subsystem_info[i])
549
550
551 class ScsiObj(object):
552 def __init__(self, device_info):
553 """
554 All class attributes are set based on what information is received
555 from iscsi related RPC calls.
556 # TODO: Document in docstring parameters which describe bdevs.
557 # TODO: Possible improvement: JSON schema might be used here in future
558 """
559 for i in device_info.keys():
560 setattr(self, i, device_info[i])