2023-10-06 16:03:38 +02:00
from typing import List , IO
2023-10-06 10:58:39 +02:00
from cocluto . inventory import Inventory
from cocluto . SimpaDbUtil import SqlDatabaseReader , SqlFile
from urllib . parse import urlparse
2023-10-06 14:27:49 +02:00
from abc import ABC , abstractmethod
2023-10-06 16:59:49 +02:00
# from sys import stdout
2023-10-06 14:06:10 +02:00
import re
2023-10-06 10:58:39 +02:00
2023-10-06 14:27:49 +02:00
class Table ( ) :
columns_data : List [ List [ str ] ]
column_labels : List [ str ]
2023-10-06 10:58:39 +02:00
2023-10-06 14:27:49 +02:00
def __init__ ( self ) :
self . columns_data = [ ]
self . columns_labels = [ ]
2023-10-06 10:58:39 +02:00
2023-10-06 14:27:49 +02:00
class TableRenderer ( ABC ) :
@abstractmethod
2023-10-06 16:03:38 +02:00
def render_table ( self , table : Table , file : IO ) :
2023-10-06 14:27:49 +02:00
pass
2023-10-06 10:58:39 +02:00
2023-10-06 16:03:38 +02:00
class TsvTableRenderer ( TableRenderer ) :
def render_table ( self , table : Table , file : IO ) :
assert len ( table . column_labels ) == len ( table . columns_data )
num_cols = len ( table . columns_data )
num_rows = len ( table . columns_data [ 0 ] )
file . write ( ' # %s \n ' % ' \t ' . join ( table . column_labels ) )
for irow in range ( num_rows ) :
row = [ ]
for icol in range ( num_cols ) :
row . append ( table . columns_data [ icol ] [ irow ] )
file . write ( ' %s \n ' % ' \t ' . join ( row ) )
class MarkdownTableRenderer ( TableRenderer ) :
2023-10-06 10:58:39 +02:00
2023-10-06 14:27:49 +02:00
@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
2023-10-06 16:03:38 +02:00
def render_table ( self , table : Table , file : IO ) :
2023-10-06 14:27:49 +02:00
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 ( [ " %% %d s | " % col_width for col_width in cols_width ] )
2023-10-06 16:03:38 +02:00
file . write ( ' %s \n ' % sep_line )
file . write ( ' %s \n ' % ( line_format % tuple ( table . column_labels ) ) )
file . write ( ' %s \n ' % sep_line )
2023-10-06 10:58:39 +02:00
for irow in range ( num_rows ) :
2023-10-06 14:27:49 +02:00
row = [ ]
for icol in range ( num_cols ) :
row . append ( table . columns_data [ icol ] [ irow ] )
2023-10-06 16:03:38 +02:00
file . write ( ' %s \n ' % ( line_format % tuple ( row ) ) )
file . write ( ' %s \n ' % sep_line )
2023-10-06 14:27:49 +02:00
2023-10-06 16:03:38 +02:00
class WikiTableRenderer ( TableRenderer ) :
2023-10-06 14:27:49 +02:00
2023-10-06 16:03:38 +02:00
def render_table ( self , table : Table , file : IO ) :
2023-10-06 14:27:49 +02:00
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 ) ]
2023-10-06 10:58:39 +02:00
for icol in range ( num_cols ) :
2023-10-06 14:27:49 +02:00
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 ( [ " %% %d s ^ " % col_width for col_width in cols_width ] )
line_format = " | " + ' ' . join ( [ " %% %d s | " % col_width for col_width in cols_width ] )
2023-10-06 16:03:38 +02:00
file . write ( ' %s \n ' % ( header_line_format % tuple ( table . column_labels ) ) )
2023-10-06 14:27:49 +02:00
for irow in range ( num_rows ) :
row = [ ]
for icol in range ( num_cols ) :
row . append ( table . columns_data [ icol ] [ irow ] )
2023-10-06 10:58:39 +02:00
2023-10-06 16:03:38 +02:00
file . write ( ' %s \n ' % ( line_format % tuple ( row ) ) )
2023-10-06 10:58:39 +02:00
2023-10-06 16:03:38 +02:00
def print_machine_table ( machines_fqdn : List [ str ] , inventory : Inventory , out_file : IO , table_renderer : Table ) :
2023-10-06 10:58:39 +02:00
2023-10-06 14:27:49 +02:00
table = Table ( )
2023-10-06 10:58:39 +02:00
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 )
2023-10-06 14:27:49 +02:00
table . column_labels = [
' Nom ' ,
' Modèle ' ,
' Numéro de Série '
]
table . columns_data = [ machines_name , machines_spec_id , machines_serial_number ]
2023-10-06 16:03:38 +02:00
table_renderer . render_table ( table , out_file )
2023-10-06 10:58:39 +02:00
2023-10-06 14:06:10 +02:00
# 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 '
2023-10-06 10:58:39 +02:00
]
2023-10-06 14:06:10 +02:00
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<cluster_name>[a-z]+)(?P<from>[0-9]+)_(?P<to>[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 ) )
2023-10-06 16:59:49 +02:00
table_renderer = TsvTableRenderer ( )
2023-10-06 16:03:38 +02:00
2023-10-06 16:59:49 +02:00
with open ( ' ipr-machines-at-dsi.csv ' , ' wt ' ) as tsv_file :
print_machine_table ( machines_fqdn , inventory , tsv_file , table_renderer )
2023-10-06 14:06:10 +02:00
if __name__ == ' __main__ ' :
main ( )