from typing import List from cocluto.inventory import Inventory from cocluto.SimpaDbUtil import SqlDatabaseReader, SqlFile from urllib.parse import urlparse from abc import ABC, abstractmethod import re class Table(): columns_data: List[List[str]] column_labels: List[str] def __init__(self): self.columns_data = [] self.columns_labels = [] class TableRenderer(ABC): @abstractmethod def render_table(self, table: Table): pass class MarkdownTableRenderer(): @staticmethod def get_md_table_separator_line(columns_width): sep_line = '|' for col_width in columns_width: sep_line += '-' * col_width sep_line += '|' return sep_line def render_table(self, table: Table): assert len(table.column_labels) == len(table.columns_data) num_cols = len(table.columns_data) num_rows = len(table.columns_data[0]) cols_width = [0 for col in range(num_cols)] for icol in range(num_cols): cols_width[icol] = max(cols_width[icol], len(table.column_labels[icol])) for irow in range(num_rows): cols_width[icol] = max(cols_width[icol], len(table.columns_data[icol][irow])) sep_line = MarkdownTableRenderer.get_md_table_separator_line([col_width + 2 for col_width in cols_width]) line_format = "|" + ''.join([" %%%ds |" % col_width for col_width in cols_width]) print(sep_line) print(line_format % tuple(table.column_labels)) print(sep_line) for irow in range(num_rows): row = [] for icol in range(num_cols): row.append(table.columns_data[icol][irow]) print(line_format % tuple(row)) print(sep_line) class WikiTableRenderer(): def render_table(self, table: Table): assert len(table.column_labels) == len(table.columns_data) num_cols = len(table.columns_data) num_rows = len(table.columns_data[0]) cols_width = [0 for col in range(num_cols)] for icol in range(num_cols): cols_width[icol] = max(cols_width[icol], len(table.column_labels[icol])) for irow in range(num_rows): cols_width[icol] = max(cols_width[icol], len(table.columns_data[icol][irow])) cols_width = [col_width + 1 for col_width in cols_width] header_line_format = "^" + ''.join([" %%%ds ^" % col_width for col_width in cols_width]) line_format = "|" + ''.join([" %%%ds |" % col_width for col_width in cols_width]) print(header_line_format % tuple(table.column_labels)) for irow in range(num_rows): row = [] for icol in range(num_cols): row.append(table.columns_data[icol][irow]) print(line_format % tuple(row)) def print_machine_table(machines_fqdn: List[str], inventory: Inventory): table = Table() machines_name = [] machines_spec_id = [] machines_serial_number = [] for machine_fqdn in machines_fqdn: machine_name = machine_fqdn.split('.')[0] machine_spec_id = inventory.machine_name_to_machine_spec_id(machine_name) serial_number = inventory.get_machine_serial_number(machine_name) machines_name.append(machine_name) machines_spec_id.append(machine_spec_id) machines_serial_number.append(serial_number) table.column_labels = [ 'Nom', 'Modèle', 'Numéro de Série' ] table.columns_data = [machines_name, machines_spec_id, machines_serial_number] table_renderer = MarkdownTableRenderer() table_renderer.render_table(table) table_renderer = WikiTableRenderer() table_renderer.render_table(table) # get the list of machines hosted at the dsi def get_hosted_machines_fqdn(inventory: Inventory) -> List[str]: machines_fqdn = [] domain_name = 'ipr.univ-rennes1.fr' dsi_rack_ids = [ 'rack_dsi_h7', 'rack_dsi_i7' ] conditions = [('rack_id == "%s"' % rack_id) for rack_id in dsi_rack_ids] sql_query = 'select machine_id from rackable_machine_to_location where %s;' % ' or '.join(conditions) rows = inventory.query(sql_query) for (machine_id, ) in rows: match = re.match(r'(?P[a-z]+)(?P[0-9]+)_(?P[0-9]+)', machine_id) if match: # handle containers such as physix72_75 from_index = int(match['from']) to_index = int(match['to']) cluster_name = match['cluster_name'] # print(from_index, to_index) for machine_index in range(from_index, to_index + 1): machine_id = '%s%d' % (cluster_name, machine_index) if machine_id == 'physix75': machine_id = 'alambix75' # hack because the inventory expects all machines of a container such as physix72_75 to belong to the same cluster, and it's not the case here machines_fqdn.append('%s.%s' % (machine_id, domain_name)) else: if re.match('^switch', machine_id) is None: # ignore switches, as they belong to the dsi machines_fqdn.append('%s.%s' % (machine_id, domain_name)) return sorted(machines_fqdn) def main(): itinv_db_url = "file:///home/graffy/work/simpaweb/itinv.git/itinv.sql" url_parts = urlparse(itinv_db_url) sql_source = SqlFile(url_parts.path) sql_reader = SqlDatabaseReader(sql_source) inventory = Inventory(sql_reader) machines_fqdn = get_hosted_machines_fqdn(inventory) print('ipr machines hosted at the dsi (%d):' % len(machines_fqdn)) print_machine_table(machines_fqdn, inventory) if __name__ == '__main__': main()