]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/scripts/spdkcli/ui_root.py
import 15.2.0 Octopus source
[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 start_subsystem_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.set_log_level("INFO" if self.verbose else "ERROR")
61 r = f(self, **kwargs)
62 self.client.set_log_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_start_subsystem_init(self):
78 if rpc.start_subsystem_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 "start_subsystem_init" not in self.rpc_get_methods(current=True)
103
104 def get_bdevs(self, bdev_type):
105 if self.is_init:
106 self.current_bdevs = rpc.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 get_bdevs_iostat(self, **kwargs):
117 return rpc.bdev.get_bdevs_iostat(self.client, **kwargs)
118
119 @verbose
120 def split_bdev(self, **kwargs):
121 response = rpc.bdev.construct_split_vbdev(self.client, **kwargs)
122 return self.print_array(response)
123
124 @verbose
125 def destruct_split_bdev(self, **kwargs):
126 rpc.bdev.destruct_split_vbdev(self.client, **kwargs)
127
128 @verbose
129 def create_malloc_bdev(self, **kwargs):
130 response = rpc.bdev.construct_malloc_bdev(self.client, **kwargs)
131 return response
132
133 @verbose
134 def delete_malloc_bdev(self, **kwargs):
135 rpc.bdev.delete_malloc_bdev(self.client, **kwargs)
136
137 @verbose
138 def create_iscsi_bdev(self, **kwargs):
139 response = rpc.bdev.construct_iscsi_bdev(self.client, **kwargs)
140 return response
141
142 @verbose
143 def delete_iscsi_bdev(self, **kwargs):
144 rpc.bdev.delete_iscsi_bdev(self.client, **kwargs)
145
146 @verbose
147 def create_aio_bdev(self, **kwargs):
148 response = rpc.bdev.construct_aio_bdev(self.client, **kwargs)
149 return response
150
151 @verbose
152 def delete_aio_bdev(self, **kwargs):
153 rpc.bdev.delete_aio_bdev(self.client, **kwargs)
154
155 @verbose
156 def create_lvol_bdev(self, **kwargs):
157 response = rpc.lvol.construct_lvol_bdev(self.client, **kwargs)
158 return response
159
160 @verbose
161 def destroy_lvol_bdev(self, **kwargs):
162 response = rpc.lvol.destroy_lvol_bdev(self.client, **kwargs)
163 return response
164
165 @verbose
166 def create_nvme_bdev(self, **kwargs):
167 response = rpc.bdev.construct_nvme_bdev(self.client, **kwargs)
168 return response
169
170 @verbose
171 def delete_nvme_controller(self, **kwargs):
172 rpc.bdev.delete_nvme_controller(self.client, **kwargs)
173
174 @verbose
175 def create_null_bdev(self, **kwargs):
176 response = rpc.bdev.construct_null_bdev(self.client, **kwargs)
177 return response
178
179 @verbose
180 def delete_null_bdev(self, **kwargs):
181 rpc.bdev.delete_null_bdev(self.client, **kwargs)
182
183 @verbose
184 def create_error_bdev(self, **kwargs):
185 response = rpc.bdev.construct_error_bdev(self.client, **kwargs)
186
187 @verbose
188 def delete_error_bdev(self, **kwargs):
189 rpc.bdev.delete_error_bdev(self.client, **kwargs)
190
191 @verbose
192 @is_method_available
193 def get_lvol_stores(self):
194 if self.is_init:
195 self.current_lvol_stores = rpc.lvol.get_lvol_stores(self.client)
196 for lvs in self.current_lvol_stores:
197 yield LvolStore(lvs)
198
199 @verbose
200 def create_lvol_store(self, **kwargs):
201 response = rpc.lvol.construct_lvol_store(self.client, **kwargs)
202 return response
203
204 @verbose
205 def delete_lvol_store(self, **kwargs):
206 rpc.lvol.destroy_lvol_store(self.client, **kwargs)
207
208 @verbose
209 def create_pmem_pool(self, **kwargs):
210 response = rpc.pmem.create_pmem_pool(self.client, **kwargs)
211 return response
212
213 @verbose
214 def delete_pmem_pool(self, **kwargs):
215 rpc.pmem.delete_pmem_pool(self.client, **kwargs)
216
217 @verbose
218 def create_pmem_bdev(self, **kwargs):
219 response = rpc.bdev.construct_pmem_bdev(self.client, **kwargs)
220 return response
221
222 @verbose
223 def delete_pmem_bdev(self, **kwargs):
224 response = rpc.bdev.delete_pmem_bdev(self.client, **kwargs)
225 return response
226
227 @verbose
228 def create_rbd_bdev(self, **kwargs):
229 response = rpc.bdev.construct_rbd_bdev(self.client, **kwargs)
230 return response
231
232 @verbose
233 def delete_rbd_bdev(self, **kwargs):
234 response = rpc.bdev.delete_rbd_bdev(self.client, **kwargs)
235 return response
236
237 @verbose
238 def create_virtio_dev(self, **kwargs):
239 response = rpc.vhost.construct_virtio_dev(self.client, **kwargs)
240 return self.print_array(response)
241
242 @verbose
243 def remove_virtio_bdev(self, **kwargs):
244 response = rpc.vhost.remove_virtio_bdev(self.client, **kwargs)
245 return response
246
247 @verbose
248 def construct_raid_bdev(self, **kwargs):
249 rpc.bdev.construct_raid_bdev(self.client, **kwargs)
250
251 @verbose
252 def destroy_raid_bdev(self, **kwargs):
253 rpc.bdev.destroy_raid_bdev(self.client, **kwargs)
254
255 @verbose
256 @is_method_available
257 def get_virtio_scsi_devs(self):
258 if self.is_init:
259 for bdev in rpc.vhost.get_virtio_scsi_devs(self.client):
260 test = Bdev(bdev)
261 yield test
262
263 def list_vhost_ctrls(self):
264 if self.is_init:
265 self.current_vhost_ctrls = rpc.vhost.get_vhost_controllers(self.client)
266
267 @verbose
268 @is_method_available
269 def get_vhost_controllers(self, ctrlr_type):
270 if self.is_init:
271 self.list_vhost_ctrls()
272 for ctrlr in [x for x in self.current_vhost_ctrls if ctrlr_type in list(x["backend_specific"].keys())]:
273 yield VhostCtrlr(ctrlr)
274
275 @verbose
276 def remove_vhost_controller(self, **kwargs):
277 rpc.vhost.remove_vhost_controller(self.client, **kwargs)
278
279 @verbose
280 def create_vhost_scsi_controller(self, **kwargs):
281 rpc.vhost.construct_vhost_scsi_controller(self.client, **kwargs)
282
283 @verbose
284 def create_vhost_blk_controller(self, **kwargs):
285 rpc.vhost.construct_vhost_blk_controller(self.client, **kwargs)
286
287 @verbose
288 def remove_vhost_scsi_target(self, **kwargs):
289 rpc.vhost.remove_vhost_scsi_target(self.client, **kwargs)
290
291 @verbose
292 def add_vhost_scsi_lun(self, **kwargs):
293 rpc.vhost.add_vhost_scsi_lun(self.client, **kwargs)
294
295 def set_vhost_controller_coalescing(self, **kwargs):
296 rpc.vhost.set_vhost_controller_coalescing(self.client, **kwargs)
297
298 @verbose
299 def create_nvmf_transport(self, **kwargs):
300 rpc.nvmf.nvmf_create_transport(self.client, **kwargs)
301
302 def list_nvmf_transports(self):
303 if self.is_init:
304 self.current_nvmf_transports = rpc.nvmf.get_nvmf_transports(self.client)
305
306 @verbose
307 @is_method_available
308 def get_nvmf_transports(self):
309 if self.is_init:
310 self.list_nvmf_transports()
311 for transport in self.current_nvmf_transports:
312 yield NvmfTransport(transport)
313
314 def list_nvmf_subsystems(self):
315 if self.is_init:
316 self.current_nvmf_subsystems = rpc.nvmf.get_nvmf_subsystems(self.client)
317
318 @verbose
319 @is_method_available
320 def get_nvmf_subsystems(self):
321 if self.is_init:
322 self.list_nvmf_subsystems()
323 for subsystem in self.current_nvmf_subsystems:
324 yield NvmfSubsystem(subsystem)
325
326 @verbose
327 def create_nvmf_subsystem(self, **kwargs):
328 rpc.nvmf.nvmf_subsystem_create(self.client, **kwargs)
329
330 @verbose
331 def delete_nvmf_subsystem(self, **kwargs):
332 rpc.nvmf.delete_nvmf_subsystem(self.client, **kwargs)
333
334 @verbose
335 def nvmf_subsystem_add_listener(self, **kwargs):
336 rpc.nvmf.nvmf_subsystem_add_listener(self.client, **kwargs)
337
338 @verbose
339 def nvmf_subsystem_remove_listener(self, **kwargs):
340 rpc.nvmf.nvmf_subsystem_remove_listener(self.client, **kwargs)
341
342 @verbose
343 def nvmf_subsystem_add_host(self, **kwargs):
344 rpc.nvmf.nvmf_subsystem_add_host(self.client, **kwargs)
345
346 @verbose
347 def nvmf_subsystem_remove_host(self, **kwargs):
348 rpc.nvmf.nvmf_subsystem_remove_host(self.client, **kwargs)
349
350 @verbose
351 def nvmf_subsystem_allow_any_host(self, **kwargs):
352 rpc.nvmf.nvmf_subsystem_allow_any_host(self.client, **kwargs)
353
354 @verbose
355 def nvmf_subsystem_add_ns(self, **kwargs):
356 rpc.nvmf.nvmf_subsystem_add_ns(self.client, **kwargs)
357
358 @verbose
359 def nvmf_subsystem_remove_ns(self, **kwargs):
360 rpc.nvmf.nvmf_subsystem_remove_ns(self.client, **kwargs)
361
362 @verbose
363 def nvmf_subsystem_allow_any_host(self, **kwargs):
364 rpc.nvmf.nvmf_subsystem_allow_any_host(self.client, **kwargs)
365
366 @verbose
367 @is_method_available
368 def get_scsi_devices(self):
369 if self.is_init:
370 for device in rpc.iscsi.get_scsi_devices(self.client):
371 yield ScsiObj(device)
372
373 @verbose
374 @is_method_available
375 def get_target_nodes(self):
376 if self.is_init:
377 for tg in rpc.iscsi.get_target_nodes(self.client):
378 yield tg
379
380 @verbose
381 def construct_target_node(self, **kwargs):
382 rpc.iscsi.construct_target_node(self.client, **kwargs)
383
384 @verbose
385 def delete_target_node(self, **kwargs):
386 rpc.iscsi.delete_target_node(self.client, **kwargs)
387
388 @verbose
389 @is_method_available
390 def get_portal_groups(self):
391 if self.is_init:
392 for pg in rpc.iscsi.get_portal_groups(self.client):
393 yield ScsiObj(pg)
394
395 @verbose
396 @is_method_available
397 def get_initiator_groups(self):
398 if self.is_init:
399 for ig in rpc.iscsi.get_initiator_groups(self.client):
400 yield ScsiObj(ig)
401
402 @verbose
403 def construct_portal_group(self, **kwargs):
404 rpc.iscsi.add_portal_group(self.client, **kwargs)
405
406 @verbose
407 def delete_portal_group(self, **kwargs):
408 rpc.iscsi.delete_portal_group(self.client, **kwargs)
409
410 @verbose
411 def construct_initiator_group(self, **kwargs):
412 rpc.iscsi.add_initiator_group(self.client, **kwargs)
413
414 @verbose
415 def delete_initiator_group(self, **kwargs):
416 rpc.iscsi.delete_initiator_group(self.client, **kwargs)
417
418 @verbose
419 @is_method_available
420 def get_iscsi_connections(self, **kwargs):
421 if self.is_init:
422 for ic in rpc.iscsi.get_iscsi_connections(self.client, **kwargs):
423 yield ic
424
425 @verbose
426 def add_initiators_to_initiator_group(self, **kwargs):
427 rpc.iscsi.add_initiators_to_initiator_group(self.client, **kwargs)
428
429 @verbose
430 def delete_initiators_from_initiator_group(self, **kwargs):
431 rpc.iscsi.delete_initiators_from_initiator_group(self.client, **kwargs)
432
433 @verbose
434 def add_pg_ig_maps(self, **kwargs):
435 rpc.iscsi.add_pg_ig_maps(self.client, **kwargs)
436
437 @verbose
438 def delete_pg_ig_maps(self, **kwargs):
439 rpc.iscsi.delete_pg_ig_maps(self.client, **kwargs)
440
441 @verbose
442 def add_secret_to_iscsi_auth_group(self, **kwargs):
443 rpc.iscsi.add_secret_to_iscsi_auth_group(self.client, **kwargs)
444
445 @verbose
446 def delete_secret_from_iscsi_auth_group(self, **kwargs):
447 rpc.iscsi.delete_secret_from_iscsi_auth_group(self.client, **kwargs)
448
449 @verbose
450 @is_method_available
451 def get_iscsi_auth_groups(self, **kwargs):
452 return rpc.iscsi.get_iscsi_auth_groups(self.client, **kwargs)
453
454 @verbose
455 def add_iscsi_auth_group(self, **kwargs):
456 rpc.iscsi.add_iscsi_auth_group(self.client, **kwargs)
457
458 @verbose
459 def delete_iscsi_auth_group(self, **kwargs):
460 rpc.iscsi.delete_iscsi_auth_group(self.client, **kwargs)
461
462 @verbose
463 def set_iscsi_target_node_auth(self, **kwargs):
464 rpc.iscsi.set_iscsi_target_node_auth(self.client, **kwargs)
465
466 @verbose
467 def target_node_add_lun(self, **kwargs):
468 rpc.iscsi.target_node_add_lun(self.client, **kwargs)
469
470 @verbose
471 def set_iscsi_discovery_auth(self, **kwargs):
472 rpc.iscsi.set_iscsi_discovery_auth(self.client, **kwargs)
473
474 @verbose
475 @is_method_available
476 def get_iscsi_global_params(self, **kwargs):
477 return rpc.iscsi.get_iscsi_global_params(self.client, **kwargs)
478
479 def has_subsystem(self, subsystem):
480 for system in rpc.subsystem.get_subsystems(self.client):
481 if subsystem.lower() == system["subsystem"].lower():
482 return True
483 return False
484
485
486 class Bdev(object):
487 def __init__(self, bdev_info):
488 """
489 All class attributes are set based on what information is received
490 from get_bdevs RPC call.
491 # TODO: Document in docstring parameters which describe bdevs.
492 # TODO: Possible improvement: JSON schema might be used here in future
493 """
494 for i in list(bdev_info.keys()):
495 setattr(self, i, bdev_info[i])
496
497
498 class LvolStore(object):
499 def __init__(self, lvs_info):
500 """
501 All class attributes are set based on what information is received
502 from get_bdevs RPC call.
503 # TODO: Document in docstring parameters which describe bdevs.
504 # TODO: Possible improvement: JSON schema might be used here in future
505 """
506 for i in list(lvs_info.keys()):
507 setattr(self, i, lvs_info[i])
508
509
510 class VhostCtrlr(object):
511 def __init__(self, ctrlr_info):
512 """
513 All class attributes are set based on what information is received
514 from get_vhost_controllers RPC call.
515 # TODO: Document in docstring parameters which describe bdevs.
516 # TODO: Possible improvement: JSON schema might be used here in future
517 """
518 for i in list(ctrlr_info.keys()):
519 setattr(self, i, ctrlr_info[i])
520
521
522 class NvmfTransport(object):
523 def __init__(self, transport_info):
524 """
525 All class attributes are set based on what information is received
526 from get_nvmf_transport RPC call.
527 # TODO: Document in docstring parameters which describe bdevs.
528 # TODO: Possible improvement: JSON schema might be used here in future
529 """
530 for i in transport_info.keys():
531 setattr(self, i, transport_info[i])
532
533
534 class NvmfSubsystem(object):
535 def __init__(self, subsystem_info):
536 """
537 All class attributes are set based on what information is received
538 from get_nvmf_subsystem RPC call.
539 # TODO: Document in docstring parameters which describe bdevs.
540 # TODO: Possible improvement: JSON schema might be used here in future
541 """
542 for i in subsystem_info.keys():
543 setattr(self, i, subsystem_info[i])
544
545
546 class ScsiObj(object):
547 def __init__(self, device_info):
548 """
549 All class attributes are set based on what information is received
550 from iscsi related RPC calls.
551 # TODO: Document in docstring parameters which describe bdevs.
552 # TODO: Possible improvement: JSON schema might be used here in future
553 """
554 for i in device_info.keys():
555 setattr(self, i, device_info[i])