def show(cls, args, lstmsg): tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) tbl.add_headers(ResourceConnectionCommands._headers) tbl.set_groupby(args.groupby if args.groupby else [ResourceConnectionCommands._headers[0].name]) props_str_size = 30 for rsc_con in [ x for x in lstmsg.resource_connections if "DELETED" not in x.flags ]: opts = [ os.path.basename(x) + '=' + rsc_con.properties[x] for x in rsc_con.properties ] props_str = ",".join(opts) tbl.add_row([ rsc_con.node_a, rsc_con.node_b, props_str if len(props_str) < props_str_size else props_str[:props_str_size] + '...', rsc_con.port if rsc_con.port else '' ]) tbl.show()
def show_physical_storage(cls, args, physical_storage_list): """ :param args: :param PhysicalStorageList physical_storage_list: :return: """ tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) for hdr in cls._phys_storage_headers: tbl.add_header(hdr) for devices in physical_storage_list.physical_devices: node_rows = [] for node, node_devices in devices.nodes.items(): s = node + '[' node_out_devs = [] for device_obj in node_devices: ns = device_obj.device node_data = [] if device_obj.serial: node_data.append(device_obj.serial) if device_obj.wwn: node_data.append(device_obj.wwn) if node_data: ns += '(' + ','.join(node_data) + ')' node_out_devs.append(ns) s += ','.join(node_out_devs) + ']' node_rows.append(s) tbl.add_row( [devices.size, devices.rotational, "\n".join(node_rows)]) tbl.show()
def show_remotes(args, remotes): """ :param args: :param linstor.responses.RemoteListResponse remotes: :return: """ tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) tbl.add_column("Name") tbl.add_column("Type") tbl.add_column("Info") rows = [] for s3 in remotes.s3_remotes: rows.append({ "name": s3.remote_name, "type": "S3", "info": "{r}.{e}/{b}".format(r=s3.region, e=s3.endpoint, b=s3.bucket) }) for lin_remote in remotes.linstor_remotes: rows.append({ "name": lin_remote.remote_name, "type": "Linstor", "info": lin_remote.url }) for remote in rows: tbl.add_row([remote["name"], remote["type"], remote["info"]]) tbl.show()
def test_cell_color(self): tbl = Table(colors=True, utf8=False) tbl.add_header(TableHeader("FirstName")) tbl.add_header(TableHeader("LastName")) tbl.add_header(TableHeader("Age")) tbl.add_header(TableHeader("Comment")) tbl.add_row(["Max", "Mustermann", tbl.color_cell("62", Color.RED), ""]) tbl.add_row(["Heinrich", "Mueller", "29", ""]) tbl.show()
def show_backups(cls, args, lstmsg): tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) if args.others: for hdr in cls._backup_other_headers: tbl.add_header(hdr) for entry in lstmsg.other.files: tbl.add_row([entry]) else: backup_hdr = list(cls._backup_headers) for hdr in backup_hdr: tbl.add_header(hdr) if args.show_id: tbl.add_header(linstor_client.TableHeader("Backup Name(ID)")) for backup in lstmsg.linstor: # resource, snapshot, finish time, base, status row = [backup.origin_rsc_name, backup.origin_snap_name] if backup.finished_timestamp: row += [ datetime.fromtimestamp( int(backup.finished_timestamp / 1000)) ] else: row += [""] row += [backup.based_on[0:-5] if backup.based_on else ""] status_text = "Success" status_color = Color.GREEN if backup.shipping: status_text = "Shipping" status_color = Color.YELLOW elif not backup.restorable: status_text = "Not restorable" status_color = Color.RED row += [tbl.color_cell(status_text, status_color)] if args.show_id: row += [backup.id] tbl.add_row(row) tbl.show()
def test_multiline_colums(self): tbl = Table() tbl.add_header(TableHeader("id")) tbl.add_header(TableHeader("description")) tbl.add_header(TableHeader("text")) tbl.add_row([ "0", "In a land far far away in a time long long ago\nThere were 3 pigs with 3 wigs and a chair to despair\n" + "in a house with no mouse.", "PlaceCount: 2\nDisklessOnRemaining: True\nStoragePool: DfltStorPool\nLayerList: storage,drbd" ]) table_out = tbl.show() self.assertEqual( """+---------------------------------------------------------------------------------------+ | id | description | text | |=======================================================================================| | 0 | In a land far far away in a time long long ago | PlaceCount: 2 | | | There were 3 pigs with 3 wigs and a chair to despair | DisklessOnRemaining: True | | | in a house with no mouse. | StoragePool: DfltStorPool | | | | LayerList: storage,drbd | +---------------------------------------------------------------------------------------+ """, table_out) tbl = Table() tbl.add_header(TableHeader("id")) tbl.add_header(TableHeader("vlmgroups")) tbl.add_header(TableHeader("text")) tbl.add_header(TableHeader("description")) tbl.add_row(["DfltRscGrp", "", "", ""]) tbl.add_row( ["testrg", "0", "PlaceCount: 2\nStoragePool: DfltStorPool", "bla"]) table_out = tbl.show() self.assertEqual( """+------------------------------------------------------------------+ | id | vlmgroups | text | description | |==================================================================| | DfltRscGrp | | | | |------------------------------------------------------------------| | testrg | 0 | PlaceCount: 2 | bla | | | | StoragePool: DfltStorPool | | +------------------------------------------------------------------+ """, table_out)
def show_volumes(cls, args, lstmsg): """ :param args: :param responses.ResourceResponse lstmsg: resource response data to display :return: None """ tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) tbl.add_column("Node") tbl.add_column("Resource") tbl.add_column("StoragePool") tbl.add_column("VolNr", just_txt='>') tbl.add_column("MinorNr", just_txt='>') tbl.add_column("DeviceName") tbl.add_column("Allocated", just_txt='>') tbl.add_column("InUse", color=Output.color(Color.DARKGREEN, args.no_color)) tbl.add_column("State", color=Output.color(Color.DARKGREEN, args.no_color), just_txt='>') rsc_state_lkup = { x.node_name + x.name: x for x in lstmsg.resource_states } reports = [] for rsc in lstmsg.resources: if not args.all and apiconsts.FLAG_TIE_BREAKER in rsc.flags: continue # skip tie breaker resources if apiconsts.FLAG_RSC_INACTIVE in rsc.flags: continue # do not show non existing volumes for inactive resources rsc_state = rsc_state_lkup.get(rsc.node_name + rsc.name) rsc_usage = "" if rsc_state and rsc_state.in_use is not None: if rsc_state.in_use: rsc_usage = tbl.color_cell("InUse", Color.GREEN) else: rsc_usage = "Unused" for vlm in rsc.volumes: vlm_state = cls.get_volume_state( rsc_state.volume_states, vlm.number) if rsc_state else None state_txt, color = cls.volume_state_cell( vlm_state, rsc.flags, vlm.flags) has_errors = any([x.is_error() for x in vlm.reports]) conn_failed = (rsc.layer_data.drbd_resource and any(not v.connected for k, v in rsc.layer_data. drbd_resource.connections.items())) if conn_failed: color = Color.RED state = tbl.color_cell(state_txt, color) if color else state_txt if has_errors: state = tbl.color_cell("Error", Color.RED) for x in vlm.reports: reports.append(x) vlm_drbd_data = vlm.drbd_data tbl.add_row([ rsc.node_name, rsc.name, vlm.storage_pool_name, str(vlm.number), str(vlm_drbd_data.drbd_volume_definition.minor) if vlm_drbd_data else "", vlm.device_path, SizeCalc.approximate_size_string(vlm.allocated_size) if vlm.allocated_size else "", rsc_usage, state ]) tbl.show() for x in reports: Output.handle_ret(x, args.no_color, warn_as_error=args.warn_as_error)
def show_backups_info(cls, args, lstmsg): rsc_tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) rsc_tbl.add_column("Resource") rsc_tbl.add_column("Snapshot") rsc_tbl.add_column("Full Backup") rsc_tbl.add_column("Latest Backup") rsc_tbl.add_column("Backup Count") rsc_tbl.add_column("Download Size") rsc_tbl.add_column("Allocated Size") # table will only have a single row row = [ lstmsg.rsc, lstmsg.snap, lstmsg.full, lstmsg.latest, lstmsg.count ] row += [ SizeCalc.approximate_size_string(lstmsg.dl_size), SizeCalc.approximate_size_string(lstmsg.alloc_size) ] rsc_tbl.add_row(row) rsc_tbl.show() stor_pool_tbl = Table(utf8=not args.no_utf8, colors=not args.no_color, pastable=args.pastable) stor_pool_tbl.add_column("Origin StorPool (Type)") if args.target_node: stor_pool_tbl.add_column("Target Pool") stor_pool_tbl.add_column("Remaining Free Space") stor_pool_tbl.add_column("Volume to Download") stor_pool_tbl.add_column("Type") stor_pool_tbl.add_column("Download Size") stor_pool_tbl.add_column("Allocated Size") stor_pool_tbl.add_column("Usable Size") for stor_pool in lstmsg.storpools: row = [stor_pool.name + " (" + stor_pool.provider_kind + ")"] if args.target_node: row += [ stor_pool.target_name, ] if stor_pool.remaining_space < 0: row += [ stor_pool_tbl.color_cell( "-" + SizeCalc.approximate_size_string( -stor_pool.remaining_space), Color.RED) ] else: row += [ SizeCalc.approximate_size_string( stor_pool.remaining_space) ] vlm_to_dl_cell = [] type_cell = [] dl_size_cell = [] alloc_size_cell = [] usable_size_cell = [] for volume in stor_pool.volumes: vlm_to_dl_cell += [volume.name if volume.name else "-"] type_cell += [volume.layer_type] dl_size_cell += [ SizeCalc.approximate_size_string(volume.dl_size) if volume.dl_size else "-" ] alloc_size_cell += [ SizeCalc.approximate_size_string(volume.alloc_size) if volume.alloc_size else "-" ] usable_size_cell += [ SizeCalc.approximate_size_string(volume.usable_size) if volume.usable_size else "-" ] row += [ "\n".join(vlm_to_dl_cell), "\n".join(type_cell), "\n".join(dl_size_cell), "\n".join(alloc_size_cell), "\n".join(usable_size_cell) ] stor_pool_tbl.add_row(row) stor_pool_tbl.show()