From 1340c1b9800498f20c00432df9af8382b5eaf4eb Mon Sep 17 00:00:00 2001 From: Guillaume Raffy Date: Tue, 29 Sep 2020 19:09:42 +0200 Subject: [PATCH] added a configurator for poweredge c6420 based on prices coming from a tab separated value file --- ...0716-price.dat => c6420-20200716-price.tsv | 0 concho/config.py | 2 + concho/dell.py | 92 ++++++++++++++++++- concho/procs_chooser.py | 12 ++- 4 files changed, 100 insertions(+), 6 deletions(-) rename c6420-20200716-price.dat => c6420-20200716-price.tsv (100%) diff --git a/c6420-20200716-price.dat b/c6420-20200716-price.tsv similarity index 100% rename from c6420-20200716-price.dat rename to c6420-20200716-price.tsv diff --git a/concho/config.py b/concho/config.py index f53459c..d0f09b1 100644 --- a/concho/config.py +++ b/concho/config.py @@ -18,6 +18,8 @@ class Chassis(Item): self.num_cpu_slots_per_server = 2 if re.match('dell-poweredge-r9.*', uid): self.num_cpu_slots_per_server = 4 + if re.match('dell-poweredge-c6.*', uid): + self.max_num_servers = 4 self.num_dimm_slots_per_channel = 2 class Dimm(Item): diff --git a/concho/dell.py b/concho/dell.py index 3ad7e3d..061abfd 100644 --- a/concho/dell.py +++ b/concho/dell.py @@ -408,8 +408,8 @@ class DellConfiguratorParser(): @classmethod def price_str_as_float(cls, price_as_str): - match = re.match(r'^\s*(?P[-+]?)\s*(?P[0-9.]*)\s*€\s*$', price_as_str) - assert match + match = re.match(r'^\s*(?P[-+]?)\s*(?P[0-9.]*)\s*€\s*$', price_as_str.replace(',','')) + assert match, 'unexpected price string (%s)' % price_as_str # print(match['sign'], match['numbers']) price_as_float = float("%s%s" % (match['sign'], match['numbers'])) return price_as_float @@ -594,6 +594,9 @@ class DellConfiguratorParser(): configurator.chassis.price = base_price - configurator.base_config.num_cpus * configurator.get_item_price(configurator.base_config.cpu.uid) - configurator.base_config.ram_price class DellMatinfoConfigurator(Configurator): + ''' + a configurator using the web page from dell matinfo + ''' def __init__(self, dell_configurator_html_file_path): super().__init__(self) @@ -613,3 +616,88 @@ class DellMatinfoConfigurator(Configurator): return config + +class DellMatinfoCsvConfigurator(Configurator): + ''' + a configurator using the excel sheet from dell matinfo + + eg the excel sheet sent to guillaume.raffy@univ-rennes1.fr on 16/07/2020 + ''' + + + def __init__(self, dell_csv_file_path): + super().__init__(self) + self.base_config = None + self.chassis = None + self.parse_csv_configurator(dell_csv_file_path) + + + def parse_csv_configurator(self, dell_csv_file_path): + COLUMN_LABEL = 0 + COLUMN_MODEL = 1 + COLUMN_PRICE = 4 + + with open(dell_csv_file_path, 'rt') as csv_file: + + self.base_config = Config(self) + + proc_options = Module('processor') + ram_options = Module('ram') + + for line in csv_file.readlines(): + line_cells = line.split('\t') + label = line_cells[COLUMN_LABEL] + match = re.match(r'^CAT3_Configuration n°1 \(Châssis rempli de serveurs identiques\)$', label) + if match: + match = re.match(r'poweredge (?Pc6[0-9]20)', line_cells[COLUMN_MODEL].lower()) + assert match, "failed to recognize the chassis in '%s'" % line_cells[COLUMN_MODEL].lower() + self.chassis = Option(Chassis('dell-poweredge-%s' % match['chassis_id']), DellConfiguratorParser.price_str_as_float(line_cells[COLUMN_PRICE])) + continue + + # 2 processeurs Intel Xeon Silver 4210R 2.4GHz, 13.75M Cache,9.60GT/s, 2UPI, Turbo, HT,10C/20T (100W) - DDR4-2400 + match = re.match(r'^2 processeurs Intel Xeon (?PSilver|Gold|Platinium) (?P[0-9][0-9][0-9][0-9][RLYU]?).*$', label) + if match: + cpu_class = match['cpu_class'].lower() + if cpu_class == 'platinium': + cpu_class = 'platinum' + base_cpu_id = "intel-xeon-%s-%s" % (cpu_class, match['cpu_number'].lower()) + assert self.chassis is not None + self.base_config.num_servers = self.chassis.item.max_num_servers + self.base_config.num_cpu_per_server = self.chassis.item.num_cpu_slots_per_server + self.base_config.set_cpu(Cpu(base_cpu_id)) + continue + + match = re.match(r'^Passage à 2 Processeurs Intel Xeon (?PSilver|Gold|Platinium) (?P[0-9][0-9][0-9][0-9][RLYU]?).*', label) + if match: + price = DellConfiguratorParser.price_str_as_float(line_cells[COLUMN_PRICE]) + cpu_class = match['cpu_class'].lower() + if cpu_class == 'platinium': + cpu_class = 'platinum' + cpu_id = "intel-xeon-%s-%s" % (cpu_class, match['cpu_number'].lower()) + option = Option(Cpu(cpu_id), price/self.chassis.item.max_num_servers/self.chassis.item.num_cpu_slots_per_server) + proc_options.add_option(option) + continue + + # Ajout d'une barette de 8Go 2667 Mhz DDR-4 - Pour les 4 serveurs + match = re.match(r'^Ajout d\'une barette de (?P[0-9]+)Go (?P[0-9][0-9][0-9][0-9]) Mhz (?PDDR-4) - Pour les 4 serveurs$', label) + if match: + price_for_four = DellConfiguratorParser.price_str_as_float(line_cells[COLUMN_PRICE]) + dimm = Dimm(mem_type='rdimm', num_gb=int(match['num_gb']), num_mhz=int(match['num_mhz'])) + option = Option(dimm, price_for_four/4.0) + ram_options.add_option(option) + continue + + assert len(proc_options.options) > 0 + assert len(ram_options.options) > 0 + self.add_module(proc_options) + self.add_module(ram_options) + + def create_config(self): + # config = copy.deepcopy(self.base_config) + config = Config(self) + config.num_servers = self.base_config.num_servers + config.num_cpu_per_server = self.base_config.num_cpu_per_server + config.set_cpu(self.base_config.cpu) + config.cpu_slots_mem = copy.deepcopy(self.base_config.cpu_slots_mem) + + return config diff --git a/concho/procs_chooser.py b/concho/procs_chooser.py index 847f24b..3381727 100644 --- a/concho/procs_chooser.py +++ b/concho/procs_chooser.py @@ -89,7 +89,7 @@ def plot_system_efficiency(): def getColorCodeFromItemLabel(label): generation=label[-1] - (model, proc_id, ram_size) = re.split('_', label) + (num_servers, model, proc_id, ram_size) = re.split('_', label) saturation = { 'sandy bridge':0.0, 'ivy bridge':0.2, @@ -135,8 +135,10 @@ def plot_system_efficiency(): item_speed = numpy.array([]) item_label = numpy.array([]) configurators = [ - dell.DellMatinfoConfigurator('rcrc1406676-4834664 - Cat2 Conf4 PowerEdge R640 - Dell.html')] - # dell.DellPowerEdgeR940()] + dell.DellMatinfoCsvConfigurator('c6420-20200716-price.tsv'), + dell.DellMatinfoConfigurator('rcrc1406676-4834664 - Cat2 Conf4 PowerEdge R640 - Dell.html'), + # dell.DellPowerEdgeR940(), + ] for configurator in configurators: for cpu in configurator.get_cpu_options(): if not cpu.architecture in ['coffeelake', 'skylake','cascadelake']: @@ -145,7 +147,9 @@ def plot_system_efficiency(): config.num_cpu_per_server = config.configurator.chassis.item.num_cpu_slots_per_server config.set_cpu(cpu) config.set_ram(ram_per_core=4.0e9) - item_label = numpy.append( item_label, config.chassis.uid + '_' + cpu.uid + '_' + str(config.ram_size) + 'gb' ) + + config_label = str(config.num_servers) + '_' + config.chassis.uid + '_' + cpu.uid + '_' + str(config.ram_size/config.num_servers) + 'gb' + item_label = numpy.append( item_label, config_label) # print('procOptionPrice', procOptionPrice) # config_price = procOptionPrice # config_price += config.get_empty_price()