2018-02-06 18:42:18 +01:00
|
|
|
# encoding: utf-8
|
|
|
|
import datetime
|
2018-08-28 15:27:29 +02:00
|
|
|
from Lib import SimpaDbUtil
|
|
|
|
|
|
|
|
|
|
|
|
class MachineSpecIdNotFound(Exception):
|
|
|
|
def __init__(self, machine_name):
|
|
|
|
message = "failed to find the machine_spec_id for the machine '%s'" % machine_name
|
|
|
|
super(MachineSpecIdNotFound, self).__init__(message)
|
|
|
|
self.machine_name = machine_name
|
|
|
|
|
|
|
|
|
|
|
|
class PlugTypeNotFound(Exception):
|
|
|
|
def __init__(self, machine_spec_id, plug_name):
|
|
|
|
message = "failed to find the plug_type for the machine_spec_id '%s' and plug_name '%s'" % (machine_spec_id, plug_name)
|
|
|
|
super(PlugTypeNotFound, self).__init__(message)
|
|
|
|
self.machine_spec_id = machine_spec_id
|
|
|
|
self.plug_name = plug_name
|
2018-02-06 18:42:18 +01:00
|
|
|
|
|
|
|
|
2018-08-27 17:17:09 +02:00
|
|
|
class Inventory(object):
|
2018-08-28 15:27:29 +02:00
|
|
|
|
2018-02-06 18:42:18 +01:00
|
|
|
def __init__(self, sql_reader):
|
|
|
|
"""
|
2018-08-27 17:17:09 +02:00
|
|
|
:param SimpaDbUtil.SqlDatabaseReader sql_reader: the inventory database
|
2018-02-06 18:42:18 +01:00
|
|
|
"""
|
|
|
|
super(Inventory, self).__init__()
|
|
|
|
self._sql_reader = sql_reader
|
|
|
|
|
|
|
|
def query(self, sql_query):
|
|
|
|
return self._sql_reader.query(sql_query)
|
2018-02-13 17:49:21 +01:00
|
|
|
|
|
|
|
def get_machine_serial_number(self, machine_name):
|
|
|
|
'''
|
|
|
|
returns the serial number of the given machine
|
|
|
|
'''
|
2018-08-27 17:17:09 +02:00
|
|
|
machine_serial_number = self._sql_reader.get_table_attr('machines', 'name', machine_name, 'serial_number')
|
2018-02-13 17:49:21 +01:00
|
|
|
return machine_serial_number
|
|
|
|
|
|
|
|
def get_machine_name(self, machine_serial_number):
|
|
|
|
'''
|
|
|
|
returns the user-friendly name of the given machine
|
|
|
|
'''
|
2018-08-27 17:17:09 +02:00
|
|
|
machine_name = self._sql_reader.get_table_attr('machines', 'serial_number', machine_serial_number, 'name')
|
2018-02-13 17:49:21 +01:00
|
|
|
return machine_name
|
|
|
|
|
2018-08-27 17:17:09 +02:00
|
|
|
def machine_name_to_machine_spec_id(self, machine_name):
|
2019-06-19 09:31:41 +02:00
|
|
|
try:
|
|
|
|
machine_spec_id = self._sql_reader.get_table_attr('machines', 'name', machine_name, 'machine_spec_id')
|
|
|
|
except SimpaDbUtil.TableAttrNotFound as e: # @UnusedVariable
|
|
|
|
raise MachineSpecIdNotFound(machine_name)
|
2018-02-06 18:42:18 +01:00
|
|
|
return machine_spec_id
|
|
|
|
|
|
|
|
# electricity related methods
|
|
|
|
|
2018-08-27 17:17:09 +02:00
|
|
|
def machine_spec_id_to_power_consumption(self, machine_spec_id):
|
2018-08-28 15:27:29 +02:00
|
|
|
try:
|
|
|
|
power_consumption = self._sql_reader.get_table_attr('machine_spec_to_power_consumption', 'machine_spec_id', machine_spec_id, 'power_consumption')
|
|
|
|
except SimpaDbUtil.TableAttrNotFound as e: # @UnusedVariable
|
|
|
|
# some passive machines such as pdus are not detailed in the machine_spec_to_power_consumption because they don't consume power
|
|
|
|
power_consumption = 0.0
|
2018-02-06 18:42:18 +01:00
|
|
|
return power_consumption
|
|
|
|
|
|
|
|
def get_plug_type_attr(self, plug_type, attr_name):
|
2018-08-28 15:27:29 +02:00
|
|
|
"""
|
|
|
|
:param str plug_type: eg 'c14'
|
|
|
|
"""
|
2018-02-06 18:42:18 +01:00
|
|
|
# INSERT INTO `powerplug_type_desc` (`plug_type_id`, `genre`, `max_amps`) VALUES
|
|
|
|
# ('iec60309_blue_pne6h_32a_m', 'm', 32.0),
|
2018-08-27 17:17:09 +02:00
|
|
|
attr_value = self._sql_reader.get_table_attr('powerplug_type_desc', 'plug_type_id', plug_type, attr_name)
|
2018-02-06 18:42:18 +01:00
|
|
|
return attr_value
|
|
|
|
|
2018-08-28 15:27:29 +02:00
|
|
|
def get_plug_type(self, machine_name, plug_name):
|
|
|
|
"""
|
|
|
|
:param str machine_name: eg 'pdu4'
|
|
|
|
:param str plug_name: eg 'o4'
|
|
|
|
"""
|
|
|
|
machine_spec_id = None
|
|
|
|
try:
|
|
|
|
machine_spec_id = self.machine_name_to_machine_spec_id(machine_name)
|
|
|
|
except SimpaDbUtil.TableAttrNotFound as e: # @UnusedVariable
|
|
|
|
raise MachineSpecIdNotFound(machine_name)
|
2018-02-06 18:42:18 +01:00
|
|
|
if machine_spec_id is not None:
|
|
|
|
# INSERT INTO `powerplug_desc` (`machine_spec_id`, `powerplug_id`, `plug_type`) VALUES
|
2018-08-27 17:17:09 +02:00
|
|
|
# ('atos_mpdu_2901382', 'i', 'iec60309_blue_pne6h_32a_m'),
|
2018-08-28 15:27:29 +02:00
|
|
|
rows = self._sql_reader.query("SELECT plug_type FROM powerplug_desc WHERE machine_spec_id='%s' AND powerplug_id='%s'" % (machine_spec_id, plug_name))
|
2018-02-06 18:42:18 +01:00
|
|
|
if len(rows) > 0:
|
|
|
|
plug_type = rows[0][0]
|
2018-08-28 15:27:29 +02:00
|
|
|
else:
|
|
|
|
raise PlugTypeNotFound(machine_spec_id, plug_name)
|
|
|
|
return plug_type
|
|
|
|
|
|
|
|
def read_plug_capacity(self, plug):
|
|
|
|
"""
|
|
|
|
:param PowerDiagram.Plug plug: the power plug of a 'device' we're interested in (eg pdu4.o1)
|
|
|
|
"""
|
|
|
|
plug_capacity = None
|
|
|
|
plug_type = None
|
|
|
|
try:
|
|
|
|
plug_type = self.get_plug_type(plug.machine.name, plug.name)
|
|
|
|
except MachineSpecIdNotFound:
|
|
|
|
# some machines are not actual machines (eg edf, ups1pdu)
|
|
|
|
pass
|
|
|
|
except PlugTypeNotFound:
|
|
|
|
# some plugs are just plain connections, with no actual plug types
|
|
|
|
pass
|
|
|
|
if plug_type is not None:
|
|
|
|
# print('plug_type : %s' % plug_type)
|
|
|
|
|
|
|
|
plug_capacity = self.get_plug_type_attr(plug_type, 'max_amps')
|
|
|
|
# if plug_capacity:
|
|
|
|
# print('plug_capacity : %f A' % plug_capacity)
|
2018-02-06 18:42:18 +01:00
|
|
|
# print("read_plug_capacity : plug capacity for plug.machine.name="+plug.machine.name+" plug="+str(plug)+" : "+ str(plug_capacity)+ "A")
|
|
|
|
return plug_capacity
|
|
|
|
|
|
|
|
# cluster related methods
|
|
|
|
|
2018-02-13 17:49:21 +01:00
|
|
|
def get_machine_purchase_date(self, machine_id):
|
2018-08-27 17:17:09 +02:00
|
|
|
ordering_id = self._sql_reader.get_table_attr('machines', 'name', machine_id, 'command_id')
|
2018-02-06 18:42:18 +01:00
|
|
|
# print(ordering_id)
|
|
|
|
# handle case of multiple orders
|
|
|
|
ordering_id = ordering_id.split('+')[0]
|
|
|
|
if len(ordering_id) == 0:
|
|
|
|
return None
|
2018-08-27 17:17:09 +02:00
|
|
|
ordering_date_as_str = self._sql_reader.get_table_attr('orderings', 'ordering_id', ordering_id, 'ordering_date')
|
2018-02-06 18:42:18 +01:00
|
|
|
if ordering_date_as_str is None:
|
|
|
|
return None
|
|
|
|
if len(ordering_date_as_str) == 0:
|
|
|
|
return None
|
|
|
|
ordering_date = datetime.datetime.strptime(ordering_date_as_str, '%d/%m/%Y')
|
|
|
|
return ordering_date
|
|
|
|
|
|
|
|
def get_cpu_dflops(self, cpu_model):
|
|
|
|
'''
|
|
|
|
returns the number of double precision operation per second this cpu can achieve
|
2018-08-27 17:17:09 +02:00
|
|
|
'''
|
|
|
|
# INSERT INTO `cpu_specs` (`cpu_model`, `num_cores`, `clock_speed`, `dflops_per_core_per_cycle`, `comment`) VALUES
|
|
|
|
# ('intel_xeon_x5550', 4, 2.67, 4, ''),
|
|
|
|
num_cores = int(self._sql_reader.get_table_attr('cpu_specs', 'cpu_model', cpu_model, 'num_cores'))
|
|
|
|
clock_speed = float(self._sql_reader.get_table_attr('cpu_specs', 'cpu_model', cpu_model, 'clock_speed')) * 1.e9
|
|
|
|
dflops_per_core_per_cycle = int(self._sql_reader.get_table_attr('cpu_specs', 'cpu_model', cpu_model, 'dflops_per_core_per_cycle'))
|
2018-02-07 11:07:56 +01:00
|
|
|
# print(num_cores, clock_speed, dflops_per_core_per_cycle)
|
2018-02-06 18:42:18 +01:00
|
|
|
return clock_speed * dflops_per_core_per_cycle * num_cores
|
|
|
|
|
2018-06-27 15:23:51 +02:00
|
|
|
def get_num_cpus(self, computer_name):
|
2018-08-27 17:17:09 +02:00
|
|
|
return int(self._sql_reader.get_table_attr('computer_to_cpu', 'computer_id', computer_name, 'num_cpu'))
|
2018-06-27 15:23:51 +02:00
|
|
|
|
|
|
|
def get_cpu_model(self, computer_name):
|
2018-08-27 17:17:09 +02:00
|
|
|
return self._sql_reader.get_table_attr('computer_to_cpu', 'computer_id', computer_name, 'cpu_model')
|
2018-06-27 15:23:51 +02:00
|
|
|
|
|
|
|
def get_cpu_frequency(self, computer_name):
|
2018-08-27 17:17:09 +02:00
|
|
|
cpu_model = self._sql_reader.get_table_attr('computer_to_cpu', 'computer_id', computer_name, 'cpu_model')
|
|
|
|
return float(self._sql_reader.get_table_attr('cpu_specs', 'cpu_model', cpu_model, 'clock_speed'))
|
2018-06-27 15:23:51 +02:00
|
|
|
|
2018-02-13 17:49:21 +01:00
|
|
|
def get_computer_dflops(self, computer_name):
|
2018-02-07 11:07:56 +01:00
|
|
|
# print(computer_serial_number)
|
2018-08-27 17:17:09 +02:00
|
|
|
num_cpus = int(self._sql_reader.get_table_attr( 'computer_to_cpu', 'computer_id', computer_name, 'num_cpu'))
|
|
|
|
cpu_model = self._sql_reader.get_table_attr('computer_to_cpu', 'computer_id', computer_name, 'cpu_model')
|
|
|
|
flops = num_cpus * self.get_cpu_dflops(cpu_model)
|
2018-02-06 18:42:18 +01:00
|
|
|
return flops
|
|
|
|
|
|
|
|
def get_computer_options_price(self, computer_name):
|
|
|
|
options_price = 0.0
|
|
|
|
if computer_name == 'simpatix58' or computer_name == 'simpatix59':
|
2018-08-27 17:17:09 +02:00
|
|
|
return 7675.0 / 4 * 2 # each of these computers has 2 nvidia fermi C2050 gpus
|
2018-02-06 18:42:18 +01:00
|
|
|
return options_price
|
|
|
|
|
2018-02-13 17:49:21 +01:00
|
|
|
def get_item_container(self, item_id):
|
|
|
|
"""
|
|
|
|
:param str item_id: the identifier of an inventory item (a machine (eg simpa-switch002), a group of machines (ceph), etc.)
|
|
|
|
:return str: the item that contains the given item, None if this item has no contrainer
|
|
|
|
"""
|
|
|
|
container_id = None
|
|
|
|
rows = self._sql_reader.query("SELECT container_id FROM container WHERE part_id='%s'" % item_id)
|
|
|
|
if len(rows) > 0:
|
|
|
|
container_id = rows[0][0]
|
|
|
|
return container_id
|
|
|
|
|
2018-02-14 16:18:22 +01:00
|
|
|
def get_item_price(self, item_id, include_contents=False, include_maintenance=False):
|
2018-02-13 17:49:21 +01:00
|
|
|
"""
|
|
|
|
:param str item_id: the identifier of an inventory item (a machine (eg simpa-switch002), a group of machines (ceph), etc.)
|
|
|
|
:return float: the price of the item exluding taxes
|
|
|
|
"""
|
2018-08-27 17:17:09 +02:00
|
|
|
item_price = self._sql_reader.get_table_attr('machines', 'name', item_id, 'price_ex_vat')
|
|
|
|
if item_price is None:
|
2018-02-13 17:49:21 +01:00
|
|
|
item_price = 0.0
|
|
|
|
else:
|
|
|
|
item_price = float(item_price)
|
2018-02-14 16:18:22 +01:00
|
|
|
if include_maintenance:
|
|
|
|
# INSERT INTO `maintenance` (`maintenance_id`, `machine_id`, `price_ex_vat`, `command_id`, `comment`) VALUES
|
|
|
|
rows = self._sql_reader.query("SELECT price_ex_vat FROM maintenance WHERE machine_id='%s'" % item_id)
|
|
|
|
for row in rows:
|
|
|
|
maintenance_price_ex_vat = float(row[0])
|
|
|
|
item_price += maintenance_price_ex_vat
|
|
|
|
|
2018-02-13 17:49:21 +01:00
|
|
|
if include_contents:
|
|
|
|
# add the price of included parts
|
|
|
|
rows = self._sql_reader.query("SELECT part_id FROM container WHERE container_id='%s'" % item_id)
|
|
|
|
for row in rows:
|
|
|
|
part_id = row[0]
|
2018-02-14 16:18:22 +01:00
|
|
|
item_price += self.get_item_price(part_id, include_contents, include_maintenance)
|
2018-08-27 17:17:09 +02:00
|
|
|
# print(u'price of %s : %.2f € HT' % (item_id, item_price))
|
2018-02-13 17:49:21 +01:00
|
|
|
return item_price
|
|
|
|
|
|
|
|
def get_item_ownership(self, item_id):
|
2018-08-27 17:17:09 +02:00
|
|
|
ownership = []
|
2018-02-06 18:42:18 +01:00
|
|
|
|
2018-02-13 17:49:21 +01:00
|
|
|
rows = self._sql_reader.query("SELECT * FROM ownership WHERE machine_id='%s'" % item_id)
|
2018-02-06 18:42:18 +01:00
|
|
|
for row in rows:
|
2018-08-27 17:17:09 +02:00
|
|
|
(machine_id, owner, owner_ratio, comment) = row # @UnusedVariable
|
|
|
|
ownership.append({'owner': owner, 'owner_ratio': owner_ratio})
|
2018-02-06 18:42:18 +01:00
|
|
|
return ownership
|
|
|
|
|
2018-02-13 17:49:21 +01:00
|
|
|
def get_item_use(self, item_id):
|
2018-08-27 17:17:09 +02:00
|
|
|
ownership = []
|
2018-02-13 17:49:21 +01:00
|
|
|
|
|
|
|
rows = self._sql_reader.query("SELECT * FROM machine_users")
|
|
|
|
for row in rows:
|
2018-08-27 17:17:09 +02:00
|
|
|
(machine_id, user, user_ratio, comment) = row # @UnusedVariable
|
2018-02-13 17:49:21 +01:00
|
|
|
if machine_id == item_id:
|
2018-08-27 17:17:09 +02:00
|
|
|
ownership.append({'user': user, 'user_ratio': user_ratio})
|
2018-02-13 17:49:21 +01:00
|
|
|
return ownership
|