]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | from configshell_fb import ConfigNode, ExecutionError |
2 | from uuid import UUID | |
3 | from rpc.client import JSONRPCException | |
4 | import json | |
5 | ||
6 | ||
7 | def convert_bytes_to_human(size): | |
8 | if not size: | |
9 | return "" | |
10 | for x in ["bytes", "K", "M", "G", "T"]: | |
11 | if size < 1024.0: | |
12 | return "%3.1f%s" % (size, x) | |
13 | size /= 1024.0 | |
14 | ||
15 | ||
16 | class UINode(ConfigNode): | |
17 | def __init__(self, name, parent=None, shell=None): | |
18 | ConfigNode.__init__(self, name, parent, shell) | |
19 | ||
20 | def refresh(self): | |
21 | for child in self.children: | |
22 | child.refresh() | |
23 | ||
9f95a23c TL |
24 | def refresh_node(self): |
25 | self.refresh() | |
26 | ||
11fdf7f2 TL |
27 | def ui_command_refresh(self): |
28 | self.refresh() | |
29 | ||
30 | def ui_command_ll(self, path=None, depth=None): | |
31 | """ | |
32 | Alias for ls. | |
33 | """ | |
34 | self.ui_command_ls(path, depth) | |
35 | ||
36 | def execute_command(self, command, pparams=[], kparams={}): | |
37 | try: | |
38 | result = ConfigNode.execute_command(self, command, | |
39 | pparams, kparams) | |
9f95a23c TL |
40 | except Exception as e: |
41 | raise e | |
11fdf7f2 TL |
42 | else: |
43 | self.shell.log.debug("Command %s succeeded." % command) | |
44 | return result | |
9f95a23c TL |
45 | finally: |
46 | if self.shell.interactive and\ | |
47 | command in ["create", "delete", "delete_all", "add_initiator", | |
f67539c2 TL |
48 | "allow_any_host", "bdev_split_create", "add_lun", |
49 | "iscsi_target_node_add_pg_ig_maps", "remove_target", "add_secret", | |
50 | "bdev_split_delete", "bdev_pmem_delete_pool", | |
51 | "bdev_pmem_create_pool", "delete_secret_all", | |
9f95a23c | 52 | "delete_initiator", "set_auth", "delete_secret", |
f67539c2 | 53 | "iscsi_target_node_remove_pg_ig_maps", "load_config", |
9f95a23c TL |
54 | "load_subsystem_config"]: |
55 | self.get_root().refresh() | |
56 | self.refresh_node() | |
11fdf7f2 TL |
57 | |
58 | ||
59 | class UIBdevs(UINode): | |
60 | def __init__(self, parent): | |
61 | UINode.__init__(self, "bdevs", parent) | |
62 | self.refresh() | |
63 | ||
64 | def refresh(self): | |
65 | self._children = set([]) | |
66 | UIMallocBdev(self) | |
67 | UIAIOBdev(self) | |
68 | UILvolBdev(self) | |
69 | UINvmeBdev(self) | |
70 | UINullBdev(self) | |
71 | UIErrorBdev(self) | |
72 | UISplitBdev(self) | |
73 | UIPmemBdev(self) | |
74 | UIRbdBdev(self) | |
75 | UIiSCSIBdev(self) | |
76 | UIVirtioBlkBdev(self) | |
77 | UIVirtioScsiBdev(self) | |
9f95a23c | 78 | UIRaidBdev(self) |
11fdf7f2 TL |
79 | |
80 | ||
81 | class UILvolStores(UINode): | |
82 | def __init__(self, parent): | |
83 | UINode.__init__(self, "lvol_stores", parent) | |
84 | self.refresh() | |
85 | ||
86 | def refresh(self): | |
87 | self._children = set([]) | |
f67539c2 | 88 | for lvs in self.get_root().bdev_lvol_get_lvstores(): |
11fdf7f2 TL |
89 | UILvsObj(lvs, self) |
90 | ||
9f95a23c TL |
91 | def delete(self, name, uuid): |
92 | if name is None and uuid is None: | |
93 | self.shell.log.error("Please specify one of the identifiers: " | |
94 | "lvol store name or UUID") | |
f67539c2 | 95 | self.get_root().bdev_lvol_delete_lvstore(lvs_name=name, uuid=uuid) |
9f95a23c | 96 | |
11fdf7f2 TL |
97 | def ui_command_create(self, name, bdev_name, cluster_size=None): |
98 | """ | |
99 | Creates logical volume store on target bdev. | |
100 | ||
101 | Arguments: | |
102 | name - Friendly name to use alongside with UUID identifier. | |
103 | bdev_name - On which bdev to create the lvol store. | |
104 | cluster_size - Cluster size to use when creating lvol store, in bytes. Default: 4194304. | |
105 | """ | |
106 | ||
107 | cluster_size = self.ui_eval_param(cluster_size, "number", None) | |
f67539c2 | 108 | self.get_root().bdev_lvol_create_lvstore(lvs_name=name, bdev_name=bdev_name, cluster_sz=cluster_size) |
11fdf7f2 TL |
109 | |
110 | def ui_command_delete(self, name=None, uuid=None): | |
111 | """ | |
112 | Deletes logical volume store from configuration. | |
113 | This will also delete all logical volume bdevs created on this lvol store! | |
114 | ||
115 | Arguments: | |
116 | name - Friendly name of the logical volume store to be deleted. | |
117 | uuid - UUID number of the logical volume store to be deleted. | |
118 | """ | |
9f95a23c TL |
119 | self.delete(name, uuid) |
120 | ||
121 | def ui_command_delete_all(self): | |
122 | rpc_messages = "" | |
123 | for lvs in self._children: | |
124 | try: | |
125 | self.delete(None, lvs.lvs.uuid) | |
126 | except JSONRPCException as e: | |
127 | rpc_messages += e.message | |
128 | if rpc_messages: | |
129 | raise JSONRPCException(rpc_messages) | |
11fdf7f2 TL |
130 | |
131 | def summary(self): | |
132 | return "Lvol stores: %s" % len(self.children), None | |
133 | ||
134 | ||
135 | class UIBdev(UINode): | |
136 | def __init__(self, name, parent): | |
137 | UINode.__init__(self, name, parent) | |
138 | self.refresh() | |
139 | ||
140 | def refresh(self): | |
141 | self._children = set([]) | |
f67539c2 | 142 | for bdev in self.get_root().bdev_get_bdevs(self.name): |
11fdf7f2 TL |
143 | UIBdevObj(bdev, self) |
144 | ||
145 | def ui_command_get_bdev_iostat(self, name=None): | |
f67539c2 | 146 | ret = self.get_root().bdev_get_iostat(name=name) |
9f95a23c TL |
147 | self.shell.log.info(json.dumps(ret, indent=2)) |
148 | ||
149 | def ui_command_delete_all(self): | |
150 | """Delete all bdevs from this tree node.""" | |
151 | rpc_messages = "" | |
152 | for bdev in self._children: | |
153 | try: | |
154 | self.delete(bdev.name) | |
155 | except JSONRPCException as e: | |
156 | rpc_messages += e.message | |
157 | if rpc_messages: | |
158 | raise JSONRPCException(rpc_messages) | |
11fdf7f2 TL |
159 | |
160 | def summary(self): | |
161 | return "Bdevs: %d" % len(self.children), None | |
162 | ||
163 | ||
164 | class UIMallocBdev(UIBdev): | |
165 | def __init__(self, parent): | |
166 | UIBdev.__init__(self, "malloc", parent) | |
167 | ||
9f95a23c | 168 | def delete(self, name): |
f67539c2 | 169 | self.get_root().bdev_malloc_delete(name=name) |
9f95a23c | 170 | |
11fdf7f2 TL |
171 | def ui_command_create(self, size, block_size, name=None, uuid=None): |
172 | """ | |
173 | Construct a Malloc bdev. | |
174 | ||
175 | Arguments: | |
176 | size - Size in megabytes. | |
177 | block_size - Integer, block size to use when constructing bdev. | |
178 | name - Optional argument. Custom name to use for bdev. If not provided | |
179 | then name will be "MallocX" where X is next available ID. | |
180 | uuid - Optional parameter. Custom UUID to use. If empty then random | |
181 | will be generated. | |
182 | """ | |
183 | ||
184 | size = self.ui_eval_param(size, "number", None) | |
185 | block_size = self.ui_eval_param(block_size, "number", None) | |
9f95a23c TL |
186 | ret_name = self.get_root().create_malloc_bdev(num_blocks=size * 1024 * 1024 // block_size, |
187 | block_size=block_size, | |
188 | name=name, uuid=uuid) | |
189 | self.shell.log.info(ret_name) | |
11fdf7f2 TL |
190 | |
191 | def ui_command_delete(self, name): | |
192 | """ | |
193 | Deletes malloc bdev from configuration. | |
194 | ||
195 | Arguments: | |
196 | name - Is a unique identifier of the malloc bdev to be deleted - UUID number or name alias. | |
197 | """ | |
9f95a23c | 198 | self.delete(name) |
11fdf7f2 TL |
199 | |
200 | ||
201 | class UIAIOBdev(UIBdev): | |
202 | def __init__(self, parent): | |
203 | UIBdev.__init__(self, "aio", parent) | |
204 | ||
9f95a23c | 205 | def delete(self, name): |
f67539c2 | 206 | self.get_root().bdev_aio_delete(name=name) |
9f95a23c | 207 | |
11fdf7f2 TL |
208 | def ui_command_create(self, name, filename, block_size): |
209 | """ | |
210 | Construct an AIO bdev. | |
211 | Backend file must exist before trying to create an AIO bdev. | |
212 | ||
213 | Arguments: | |
214 | name - Optional argument. Custom name to use for bdev. If not provided | |
215 | then name will be "MallocX" where X is next available ID. | |
216 | filename - Path to AIO backend. | |
217 | block_size - Integer, block size to use when constructing bdev. | |
218 | """ | |
219 | ||
220 | block_size = self.ui_eval_param(block_size, "number", None) | |
f67539c2 | 221 | ret_name = self.get_root().bdev_aio_create(name=name, |
9f95a23c TL |
222 | block_size=int(block_size), |
223 | filename=filename) | |
224 | self.shell.log.info(ret_name) | |
11fdf7f2 TL |
225 | |
226 | def ui_command_delete(self, name): | |
227 | """ | |
228 | Deletes aio bdev from configuration. | |
229 | ||
230 | Arguments: | |
231 | name - Is a unique identifier of the aio bdev to be deleted - UUID number or name alias. | |
232 | """ | |
9f95a23c | 233 | self.delete(name) |
11fdf7f2 TL |
234 | |
235 | ||
236 | class UILvolBdev(UIBdev): | |
237 | def __init__(self, parent): | |
238 | UIBdev.__init__(self, "logical_volume", parent) | |
239 | ||
9f95a23c | 240 | def delete(self, name): |
f67539c2 | 241 | self.get_root().bdev_lvol_delete(name=name) |
9f95a23c | 242 | |
11fdf7f2 TL |
243 | def ui_command_create(self, name, size, lvs, thin_provision=None): |
244 | """ | |
245 | Construct a Logical Volume bdev. | |
246 | ||
247 | Arguments: | |
248 | name - Friendly name to use for creating logical volume bdev. | |
249 | size - Size in megabytes. | |
250 | lvs - Identifier of logical volume store on which the bdev should be | |
251 | created. Can be either a friendly name or UUID. | |
252 | thin_provision - Whether the bdev should be thick or thin provisioned. | |
253 | Default is False, and created bdevs are thick-provisioned. | |
254 | """ | |
255 | uuid = None | |
256 | lvs_name = None | |
257 | try: | |
258 | UUID(lvs) | |
259 | uuid = lvs | |
260 | except ValueError: | |
261 | lvs_name = lvs | |
262 | ||
263 | size = self.ui_eval_param(size, "number", None) | |
264 | size *= (1024 * 1024) | |
265 | thin_provision = self.ui_eval_param(thin_provision, "bool", False) | |
266 | ||
9f95a23c TL |
267 | ret_uuid = self.get_root().create_lvol_bdev(lvol_name=name, size=size, |
268 | lvs_name=lvs_name, uuid=uuid, | |
269 | thin_provision=thin_provision) | |
270 | self.shell.log.info(ret_uuid) | |
11fdf7f2 TL |
271 | |
272 | def ui_command_delete(self, name): | |
273 | """ | |
274 | Deletes lvol bdev from configuration. | |
275 | ||
276 | Arguments: | |
277 | name - Is a unique identifier of the lvol bdev to be deleted - UUID number or name alias. | |
278 | """ | |
9f95a23c | 279 | self.delete(name) |
11fdf7f2 TL |
280 | |
281 | ||
282 | class UINvmeBdev(UIBdev): | |
283 | def __init__(self, parent): | |
284 | UIBdev.__init__(self, "nvme", parent) | |
285 | ||
9f95a23c | 286 | def delete(self, name): |
f67539c2 | 287 | self.get_root().bdev_nvme_detach_controller(name=name) |
9f95a23c | 288 | |
11fdf7f2 TL |
289 | def ui_command_create(self, name, trtype, traddr, |
290 | adrfam=None, trsvcid=None, subnqn=None): | |
11fdf7f2 TL |
291 | if "rdma" in trtype and None in [adrfam, trsvcid, subnqn]: |
292 | self.shell.log.error("Using RDMA transport type." | |
293 | "Please provide arguments for adrfam, trsvcid and subnqn.") | |
9f95a23c TL |
294 | ret_name = self.get_root().create_nvme_bdev(name=name, trtype=trtype, |
295 | traddr=traddr, adrfam=adrfam, | |
296 | trsvcid=trsvcid, subnqn=subnqn) | |
297 | self.shell.log.info(ret_name) | |
298 | ||
299 | def ui_command_delete_all(self): | |
300 | rpc_messages = "" | |
301 | ctrlrs = [x.name for x in self._children] | |
302 | ctrlrs = [x.rsplit("n", 1)[0] for x in ctrlrs] | |
303 | ctrlrs = set(ctrlrs) | |
304 | for ctrlr in ctrlrs: | |
305 | try: | |
306 | self.delete(ctrlr) | |
307 | except JSONRPCException as e: | |
308 | rpc_messages += e.messages | |
309 | if rpc_messages: | |
310 | raise JSONRPCException(rpc_messages) | |
11fdf7f2 TL |
311 | |
312 | def ui_command_delete(self, name): | |
313 | """ | |
314 | Deletes NVMe controller from configuration. | |
315 | ||
316 | Arguments: | |
317 | name - Is a unique identifier of the NVMe controller to be deleted. | |
318 | """ | |
9f95a23c | 319 | self.delete(name) |
11fdf7f2 TL |
320 | |
321 | ||
322 | class UINullBdev(UIBdev): | |
323 | def __init__(self, parent): | |
324 | UIBdev.__init__(self, "null", parent) | |
325 | ||
9f95a23c | 326 | def delete(self, name): |
f67539c2 | 327 | self.get_root().bdev_null_delete(name=name) |
9f95a23c | 328 | |
11fdf7f2 TL |
329 | def ui_command_create(self, name, size, block_size, uuid=None): |
330 | """ | |
331 | Construct a Null bdev. | |
332 | ||
333 | Arguments: | |
334 | name - Name to use for bdev. | |
335 | size - Size in megabytes. | |
336 | block_size - Integer, block size to use when constructing bdev. | |
337 | uuid - Optional parameter. Custom UUID to use. If empty then random | |
338 | will be generated. | |
339 | """ | |
340 | ||
341 | size = self.ui_eval_param(size, "number", None) | |
342 | block_size = self.ui_eval_param(block_size, "number", None) | |
343 | num_blocks = size * 1024 * 1024 // block_size | |
f67539c2 | 344 | ret_name = self.get_root().bdev_null_create(num_blocks=num_blocks, |
9f95a23c TL |
345 | block_size=block_size, |
346 | name=name, uuid=uuid) | |
347 | self.shell.log.info(ret_name) | |
11fdf7f2 TL |
348 | |
349 | def ui_command_delete(self, name): | |
350 | """ | |
351 | Deletes null bdev from configuration. | |
352 | ||
353 | Arguments: | |
354 | name - Is a unique identifier of the null bdev to be deleted - UUID number or name alias. | |
355 | """ | |
9f95a23c | 356 | self.delete(name) |
11fdf7f2 TL |
357 | |
358 | ||
359 | class UIErrorBdev(UIBdev): | |
360 | def __init__(self, parent): | |
361 | UIBdev.__init__(self, "error", parent) | |
362 | ||
9f95a23c | 363 | def delete(self, name): |
f67539c2 | 364 | self.get_root().bdev_error_delete(name=name) |
9f95a23c | 365 | |
11fdf7f2 TL |
366 | def ui_command_create(self, base_name): |
367 | """ | |
368 | Construct a error injection bdev. | |
369 | ||
370 | Arguments: | |
371 | base_name - base bdev name on top of which error bdev will be created. | |
372 | """ | |
373 | ||
9f95a23c | 374 | self.get_root().create_error_bdev(base_name=base_name) |
11fdf7f2 TL |
375 | |
376 | def ui_command_delete(self, name): | |
377 | """ | |
378 | Deletes error bdev from configuration. | |
379 | ||
380 | Arguments: | |
381 | name - Is a unique identifier of the error bdev to be deleted - UUID number or name alias. | |
382 | """ | |
9f95a23c | 383 | self.delete(name) |
11fdf7f2 TL |
384 | |
385 | ||
386 | class UISplitBdev(UIBdev): | |
387 | def __init__(self, parent): | |
388 | UIBdev.__init__(self, "split_disk", parent) | |
389 | ||
9f95a23c TL |
390 | def delete(self, name): |
391 | pass | |
392 | ||
f67539c2 | 393 | def ui_command_bdev_split_create(self, base_bdev, split_count, split_size_mb=None): |
11fdf7f2 | 394 | """ |
f67539c2 | 395 | Create split block devices from a base bdev. |
11fdf7f2 TL |
396 | |
397 | Arguments: | |
398 | base_bdev - Name of bdev to split | |
399 | split_count - Number of split bdevs to create | |
400 | split_size_mb- Size of each split volume in MiB (optional) | |
401 | """ | |
402 | ||
403 | split_count = self.ui_eval_param(split_count, "number", None) | |
404 | split_size_mb = self.ui_eval_param(split_size_mb, "number", None) | |
405 | ||
f67539c2 TL |
406 | ret_name = self.get_root().bdev_split_create(base_bdev=base_bdev, |
407 | split_count=split_count, | |
408 | split_size_mb=split_size_mb) | |
9f95a23c | 409 | self.shell.log.info(ret_name) |
11fdf7f2 | 410 | |
f67539c2 TL |
411 | def ui_command_bdev_split_delete(self, base_bdev): |
412 | """Delete split block devices associated with base bdev. | |
11fdf7f2 TL |
413 | |
414 | Args: | |
415 | base_bdev: name of previously split bdev | |
416 | """ | |
417 | ||
f67539c2 | 418 | self.get_root().bdev_split_delete(base_bdev=base_bdev) |
11fdf7f2 TL |
419 | |
420 | ||
421 | class UIPmemBdev(UIBdev): | |
422 | def __init__(self, parent): | |
423 | UIBdev.__init__(self, "pmemblk", parent) | |
424 | ||
9f95a23c | 425 | def delete(self, name): |
f67539c2 | 426 | self.get_root().bdev_pmem_delete(name=name) |
9f95a23c | 427 | |
f67539c2 | 428 | def ui_command_bdev_pmem_create_pool(self, pmem_file, total_size, block_size): |
11fdf7f2 TL |
429 | total_size = self.ui_eval_param(total_size, "number", None) |
430 | block_size = self.ui_eval_param(block_size, "number", None) | |
431 | num_blocks = int((total_size * 1024 * 1024) / block_size) | |
432 | ||
f67539c2 TL |
433 | self.get_root().bdev_pmem_create_pool(pmem_file=pmem_file, |
434 | num_blocks=num_blocks, | |
435 | block_size=block_size) | |
11fdf7f2 | 436 | |
f67539c2 TL |
437 | def ui_command_bdev_pmem_delete_pool(self, pmem_file): |
438 | self.get_root().bdev_pmem_delete_pool(pmem_file=pmem_file) | |
11fdf7f2 | 439 | |
f67539c2 TL |
440 | def ui_command_bdev_pmem_get_pool_info(self, pmem_file): |
441 | ret = self.get_root().bdev_pmem_get_pool_info(pmem_file=pmem_file) | |
442 | self.shell.log.info(json.dumps(ret, indent=2)) | |
11fdf7f2 TL |
443 | |
444 | def ui_command_create(self, pmem_file, name): | |
f67539c2 | 445 | ret_name = self.get_root().bdev_pmem_create(pmem_file=pmem_file, |
9f95a23c TL |
446 | name=name) |
447 | self.shell.log.info(ret_name) | |
11fdf7f2 TL |
448 | |
449 | def ui_command_delete(self, name): | |
450 | """ | |
451 | Deletes pmem bdev from configuration. | |
452 | ||
453 | Arguments: | |
454 | name - Is a unique identifier of the pmem bdev to be deleted - UUID number or name alias. | |
455 | """ | |
9f95a23c | 456 | self.delete(name) |
11fdf7f2 TL |
457 | |
458 | ||
459 | class UIRbdBdev(UIBdev): | |
460 | def __init__(self, parent): | |
461 | UIBdev.__init__(self, "rbd", parent) | |
462 | ||
9f95a23c | 463 | def delete(self, name): |
f67539c2 | 464 | self.get_root().bdev_rbd_delete(name=name) |
9f95a23c | 465 | |
11fdf7f2 TL |
466 | def ui_command_create(self, pool_name, rbd_name, block_size, name=None): |
467 | block_size = self.ui_eval_param(block_size, "number", None) | |
468 | ||
9f95a23c TL |
469 | ret_name = self.get_root().create_rbd_bdev(pool_name=pool_name, |
470 | rbd_name=rbd_name, | |
471 | block_size=block_size, | |
472 | name=name) | |
473 | self.shell.log.info(ret_name) | |
11fdf7f2 TL |
474 | |
475 | def ui_command_delete(self, name): | |
476 | """ | |
477 | Deletes rbd bdev from configuration. | |
478 | ||
479 | Arguments: | |
480 | name - Is a unique identifier of the rbd bdev to be deleted - UUID number or name alias. | |
481 | """ | |
9f95a23c | 482 | self.delete(name) |
11fdf7f2 TL |
483 | |
484 | ||
485 | class UIiSCSIBdev(UIBdev): | |
486 | def __init__(self, parent): | |
487 | UIBdev.__init__(self, "iscsi", parent) | |
488 | ||
9f95a23c | 489 | def delete(self, name): |
f67539c2 | 490 | self.get_root().bdev_iscsi_delete(name=name) |
9f95a23c | 491 | |
11fdf7f2 TL |
492 | def ui_command_create(self, name, url, initiator_iqn): |
493 | """ | |
494 | Create iSCSI bdev in configuration by connecting to remote | |
495 | iSCSI target. | |
496 | ||
497 | Arguments: | |
498 | name - name to be used as an ID for created iSCSI bdev. | |
499 | url - iscsi url pointing to LUN on remote iSCSI target. | |
500 | Example: iscsi://127.0.0.1:3260/iqn.2018-06.org.spdk/0. | |
501 | initiator_iqn - IQN to use for initiating connection with the target. | |
502 | """ | |
9f95a23c TL |
503 | ret_name = self.get_root().create_iscsi_bdev(name=name, |
504 | url=url, | |
505 | initiator_iqn=initiator_iqn) | |
506 | self.shell.log.info(ret_name) | |
11fdf7f2 TL |
507 | |
508 | def ui_command_delete(self, name): | |
509 | """ | |
510 | Deletes iSCSI bdev from configuration. | |
511 | ||
512 | Arguments: | |
513 | name - name of the iscsi bdev to be deleted. | |
514 | """ | |
9f95a23c | 515 | self.delete(name) |
11fdf7f2 TL |
516 | |
517 | ||
518 | class UIVirtioBlkBdev(UIBdev): | |
519 | def __init__(self, parent): | |
520 | UIBdev.__init__(self, "virtioblk_disk", parent) | |
521 | ||
522 | def ui_command_create(self, name, trtype, traddr, | |
523 | vq_count=None, vq_size=None): | |
524 | ||
525 | vq_count = self.ui_eval_param(vq_count, "number", None) | |
526 | vq_size = self.ui_eval_param(vq_size, "number", None) | |
527 | ||
9f95a23c TL |
528 | ret = self.get_root().create_virtio_dev(name=name, |
529 | trtype=trtype, | |
530 | traddr=traddr, | |
531 | dev_type="blk", | |
532 | vq_count=vq_count, | |
533 | vq_size=vq_size) | |
534 | ||
535 | self.shell.log.info(ret) | |
11fdf7f2 TL |
536 | |
537 | def ui_command_delete(self, name): | |
538 | """ | |
539 | Deletes virtio scsi bdev from configuration. | |
540 | ||
541 | Arguments: | |
542 | name - Is a unique identifier of the virtio scsi bdev to be deleted - UUID number or name alias. | |
543 | """ | |
f67539c2 | 544 | self.get_root().bdev_virtio_detach_controller(name=name) |
11fdf7f2 TL |
545 | |
546 | ||
547 | class UIVirtioScsiBdev(UIBdev): | |
548 | def __init__(self, parent): | |
549 | UIBdev.__init__(self, "virtioscsi_disk", parent) | |
550 | ||
551 | def refresh(self): | |
552 | self._children = set([]) | |
f67539c2 | 553 | for bdev in self.get_root().bdev_virtio_scsi_get_devices(): |
11fdf7f2 TL |
554 | UIVirtioScsiBdevObj(bdev, self) |
555 | ||
556 | def ui_command_create(self, name, trtype, traddr, | |
557 | vq_count=None, vq_size=None): | |
558 | ||
559 | vq_count = self.ui_eval_param(vq_count, "number", None) | |
560 | vq_size = self.ui_eval_param(vq_size, "number", None) | |
561 | ||
9f95a23c TL |
562 | ret = self.get_root().create_virtio_dev(name=name, |
563 | trtype=trtype, | |
564 | traddr=traddr, | |
565 | dev_type="scsi", | |
566 | vq_count=vq_count, | |
567 | vq_size=vq_size) | |
11fdf7f2 | 568 | |
9f95a23c | 569 | self.shell.log.info(ret) |
11fdf7f2 | 570 | |
9f95a23c | 571 | def ui_command_delete(self, name): |
f67539c2 | 572 | self.get_root().bdev_virtio_detach_controller(name=name) |
11fdf7f2 TL |
573 | |
574 | ||
575 | class UIBdevObj(UINode): | |
576 | def __init__(self, bdev, parent): | |
577 | self.bdev = bdev | |
578 | # Using bdev name also for lvol bdevs, which results in displying | |
579 | # UUID instead of alias. This is because alias naming convention | |
580 | # (lvol_store_name/lvol_bdev_name) conflicts with configshell paths | |
581 | # ("/" as separator). | |
582 | # Solution: show lvol alias in "summary field" for now. | |
583 | # TODO: Possible next steps: | |
584 | # - Either change default separator in tree for smth else | |
585 | # - or add a UI command which would be able to autocomplete | |
586 | # "cd" command based on objects alias and match is to the | |
587 | # "main" bdev name. | |
588 | UINode.__init__(self, self.bdev.name, parent) | |
589 | ||
590 | def ui_command_show_details(self): | |
591 | self.shell.log.info(json.dumps(vars(self.bdev), indent=2)) | |
592 | ||
593 | def summary(self): | |
594 | size = convert_bytes_to_human(self.bdev.block_size * self.bdev.num_blocks) | |
595 | size = "=".join(["Size", size]) | |
596 | ||
597 | in_use = "Not claimed" | |
598 | if bool(self.bdev.claimed): | |
599 | in_use = "Claimed" | |
600 | ||
601 | alias = None | |
602 | if self.bdev.aliases: | |
603 | alias = self.bdev.aliases[0] | |
604 | ||
605 | info = ", ".join([_f for _f in [alias, size, in_use] if _f]) | |
606 | return info, True | |
607 | ||
608 | ||
609 | class UIVirtioScsiBdevObj(UIBdevObj): | |
610 | def __init__(self, bdev, parent): | |
611 | UIBdevObj.__init__(self, bdev, parent) | |
612 | self.refresh() | |
613 | ||
614 | def refresh(self): | |
615 | self._children = set([]) | |
f67539c2 | 616 | for bdev in self.get_root().bdev_get_bdevs("virtio_scsi_disk"): |
11fdf7f2 TL |
617 | if self.bdev.name in bdev.name: |
618 | UIBdevObj(bdev, self) | |
619 | ||
620 | def summary(self): | |
621 | if "socket" in list(self.bdev.virtio.keys()): | |
622 | info = self.bdev.virtio["socket"] | |
623 | if "pci_address" in list(self.bdev.virtio.keys()): | |
624 | info = self.bdev.virtio["pci_address"] | |
625 | return info, True | |
626 | ||
627 | ||
628 | class UILvsObj(UINode): | |
629 | def __init__(self, lvs, parent): | |
630 | UINode.__init__(self, lvs.name, parent) | |
631 | self.lvs = lvs | |
632 | ||
633 | def ui_command_show_details(self): | |
634 | self.shell.log.info(json.dumps(vars(self.lvs), indent=2)) | |
635 | ||
636 | def summary(self): | |
637 | size = convert_bytes_to_human(self.lvs.total_data_clusters * self.lvs.cluster_size) | |
638 | free = convert_bytes_to_human(self.lvs.free_clusters * self.lvs.cluster_size) | |
639 | if not free: | |
640 | free = "0" | |
641 | size = "=".join(["Size", size]) | |
642 | free = "=".join(["Free", free]) | |
643 | info = ", ".join([str(size), str(free)]) | |
644 | return info, True | |
645 | ||
646 | ||
647 | class UIVhosts(UINode): | |
648 | def __init__(self, parent): | |
649 | UINode.__init__(self, "vhost", parent) | |
650 | self.refresh() | |
651 | ||
652 | def refresh(self): | |
653 | self._children = set([]) | |
654 | self.get_root().list_vhost_ctrls() | |
655 | UIVhostBlk(self) | |
656 | UIVhostScsi(self) | |
657 | ||
658 | ||
659 | class UIVhost(UINode): | |
660 | def __init__(self, name, parent): | |
661 | UINode.__init__(self, name, parent) | |
662 | self.refresh() | |
663 | ||
664 | def ui_command_delete(self, name): | |
665 | """ | |
666 | Delete a Vhost controller from configuration. | |
667 | ||
668 | Arguments: | |
669 | name - Controller name. | |
670 | """ | |
f67539c2 | 671 | self.get_root().vhost_delete_controller(ctrlr=name) |
11fdf7f2 TL |
672 | |
673 | ||
674 | class UIVhostBlk(UIVhost): | |
675 | def __init__(self, parent): | |
676 | UIVhost.__init__(self, "block", parent) | |
677 | self.refresh() | |
678 | ||
679 | def refresh(self): | |
680 | self._children = set([]) | |
f67539c2 | 681 | for ctrlr in self.get_root().vhost_get_controllers(ctrlr_type=self.name): |
11fdf7f2 TL |
682 | UIVhostBlkCtrlObj(ctrlr, self) |
683 | ||
684 | def ui_command_create(self, name, bdev, cpumask=None, readonly=False): | |
685 | """ | |
f67539c2 | 686 | Create a Vhost BLK controller. |
11fdf7f2 TL |
687 | |
688 | Arguments: | |
689 | name - Controller name. | |
690 | bdev - Which bdev to attach to the controller. | |
691 | cpumask - Optional. Integer to specify mask of CPUs to use. | |
692 | Default: 1. | |
693 | readonly - Whether controller should be read only or not. | |
694 | Default: False. | |
695 | """ | |
f67539c2 | 696 | self.get_root().vhost_create_blk_controller(ctrlr=name, |
9f95a23c TL |
697 | dev_name=bdev, |
698 | cpumask=cpumask, | |
699 | readonly=bool(readonly)) | |
11fdf7f2 TL |
700 | |
701 | ||
702 | class UIVhostScsi(UIVhost): | |
703 | def __init__(self, parent): | |
704 | UIVhost.__init__(self, "scsi", parent) | |
705 | self.refresh() | |
706 | ||
707 | def refresh(self): | |
708 | self._children = set([]) | |
f67539c2 | 709 | for ctrlr in self.get_root().vhost_get_controllers(ctrlr_type=self.name): |
11fdf7f2 TL |
710 | UIVhostScsiCtrlObj(ctrlr, self) |
711 | ||
712 | def ui_command_create(self, name, cpumask=None): | |
713 | """ | |
f67539c2 | 714 | Create a Vhost SCSI controller. |
11fdf7f2 TL |
715 | |
716 | Arguments: | |
717 | name - Controller name. | |
718 | cpumask - Optional. Integer to specify mask of CPUs to use. | |
719 | Default: 1. | |
720 | """ | |
f67539c2 | 721 | self.get_root().vhost_create_scsi_controller(ctrlr=name, |
9f95a23c | 722 | cpumask=cpumask) |
11fdf7f2 TL |
723 | |
724 | ||
725 | class UIVhostCtrl(UINode): | |
726 | # Base class for SCSI and BLK controllers, do not instantiate | |
727 | def __init__(self, ctrlr, parent): | |
728 | self.ctrlr = ctrlr | |
729 | UINode.__init__(self, self.ctrlr.ctrlr, parent) | |
730 | self.refresh() | |
731 | ||
732 | def ui_command_show_details(self): | |
733 | self.shell.log.info(json.dumps(vars(self.ctrlr), indent=2)) | |
734 | ||
735 | def ui_command_set_coalescing(self, delay_base_us, iops_threshold): | |
736 | delay_base_us = self.ui_eval_param(delay_base_us, "number", None) | |
737 | iops_threshold = self.ui_eval_param(iops_threshold, "number", None) | |
738 | ||
f67539c2 | 739 | self.get_root().vhost_controller_set_coalescing(ctrlr=self.ctrlr.ctrlr, |
9f95a23c TL |
740 | delay_base_us=delay_base_us, |
741 | iops_threshold=iops_threshold) | |
11fdf7f2 TL |
742 | |
743 | ||
744 | class UIVhostScsiCtrlObj(UIVhostCtrl): | |
745 | def refresh(self): | |
746 | self._children = set([]) | |
747 | for lun in self.ctrlr.backend_specific["scsi"]: | |
748 | UIVhostTargetObj(lun, self) | |
749 | ||
750 | def ui_command_remove_target(self, target_num): | |
751 | """ | |
752 | Remove target node from SCSI controller. | |
753 | ||
754 | Arguments: | |
755 | target_num - Integer identifier of target node to delete. | |
756 | """ | |
f67539c2 TL |
757 | self.get_root().vhost_scsi_controller_remove_target(ctrlr=self.ctrlr.ctrlr, |
758 | scsi_target_num=int(target_num)) | |
759 | for ctrlr in self.get_root().vhost_get_controllers(ctrlr_type="scsi"): | |
9f95a23c TL |
760 | if ctrlr.ctrlr == self.ctrlr.ctrlr: |
761 | self.ctrlr = ctrlr | |
11fdf7f2 TL |
762 | |
763 | def ui_command_add_lun(self, target_num, bdev_name): | |
764 | """ | |
765 | Add LUN to SCSI target node. | |
766 | Currently only one LUN (which is LUN ID 0) per target is supported. | |
767 | Adding LUN to not existing target node will create that node. | |
768 | ||
769 | Arguments: | |
770 | target_num - Integer identifier of target node to modify. | |
771 | bdev - Which bdev to add as LUN. | |
772 | """ | |
f67539c2 TL |
773 | self.get_root().vhost_scsi_controller_add_target(ctrlr=self.ctrlr.ctrlr, |
774 | scsi_target_num=int(target_num), | |
775 | bdev_name=bdev_name) | |
776 | for ctrlr in self.get_root().vhost_get_controllers(ctrlr_type="scsi"): | |
9f95a23c TL |
777 | if ctrlr.ctrlr == self.ctrlr.ctrlr: |
778 | self.ctrlr = ctrlr | |
11fdf7f2 TL |
779 | |
780 | def summary(self): | |
781 | info = self.ctrlr.socket | |
782 | return info, True | |
783 | ||
784 | ||
785 | class UIVhostBlkCtrlObj(UIVhostCtrl): | |
786 | def refresh(self): | |
787 | self._children = set([]) | |
788 | UIVhostLunDevObj(self.ctrlr.backend_specific["block"]["bdev"], self) | |
789 | ||
790 | def summary(self): | |
791 | ro = None | |
792 | if self.ctrlr.backend_specific["block"]["readonly"]: | |
793 | ro = "Readonly" | |
794 | info = ", ".join([_f for _f in [self.ctrlr.socket, ro] if _f]) | |
795 | return info, True | |
796 | ||
797 | ||
798 | class UIVhostTargetObj(UINode): | |
799 | def __init__(self, target, parent): | |
800 | self.target = target | |
801 | # Next line: configshell does not allow paths with spaces. | |
802 | UINode.__init__(self, target["target_name"].replace(" ", "_"), parent) | |
803 | self.refresh() | |
804 | ||
805 | def refresh(self): | |
806 | self._children = set([]) | |
807 | for target in self.target["luns"]: | |
808 | UIVhostLunDevObj(target["bdev_name"], self) | |
809 | ||
810 | def ui_command_show_details(self): | |
811 | self.shell.log.info(json.dumps(self.target, indent=2)) | |
812 | ||
813 | def summary(self): | |
814 | luns = "LUNs: %s" % len(self.target["luns"]) | |
815 | id = "TargetID: %s" % self.target["scsi_dev_num"] | |
816 | info = ",".join([luns, id]) | |
817 | return info, True | |
818 | ||
819 | ||
820 | class UIVhostLunDevObj(UINode): | |
821 | def __init__(self, name, parent): | |
822 | UINode.__init__(self, name, parent) | |
9f95a23c TL |
823 | |
824 | ||
825 | class UIRaidBdev(UIBdev): | |
826 | def __init__(self, parent): | |
827 | UIBdev.__init__(self, "raid_volume", parent) | |
828 | ||
829 | def delete(self, name): | |
f67539c2 | 830 | self.get_root().bdev_raid_delete(name=name) |
9f95a23c TL |
831 | |
832 | def ui_command_create(self, name, raid_level, base_bdevs, strip_size_kb): | |
833 | """ | |
834 | Creates a raid bdev of the provided base_bdevs | |
835 | ||
836 | Arguments: | |
837 | name - raid bdev name | |
838 | raid_level - raid level, supported values 0 | |
839 | base_bdevs - base bdevs name, whitespace separated list in quotes | |
840 | strip_size_kb - strip size of raid bdev in KB, supported values like 8, 16, 32, 64, 128, 256, etc | |
841 | """ | |
842 | base_bdevs_array = [] | |
843 | for u in base_bdevs.strip().split(" "): | |
844 | base_bdevs_array.append(u) | |
845 | ||
9f95a23c TL |
846 | strip_size_kb = self.ui_eval_param(strip_size_kb, "number", None) |
847 | ||
f67539c2 TL |
848 | ret_name = self.get_root().bdev_raid_create(name=name, |
849 | raid_level=raid_level, | |
850 | base_bdevs=base_bdevs_array, | |
851 | strip_size_kb=strip_size_kb) | |
9f95a23c TL |
852 | self.shell.log.info(ret_name) |
853 | ||
854 | def ui_command_delete(self, name): | |
855 | """ | |
856 | Deletes this raid bdev object | |
857 | ||
858 | Arguments: | |
859 | name - raid bdev name | |
860 | """ | |
861 | self.delete(name) |