diff --git a/CMake/testscripts/test_python_with_coverage.run.in b/CMake/testscripts/test_python_with_coverage.run.in index 4a9d606c315ab59989a878cf524973cc96058c25..045d1b63beaf4e0d4f3e49b67b7aea6c39cbd8d1 100755 --- a/CMake/testscripts/test_python_with_coverage.run.in +++ b/CMake/testscripts/test_python_with_coverage.run.in @@ -7,8 +7,9 @@ COVERAGE_EXCLUDE_LINES="[report]\nexclude_lines = \n if __name__ == .__main__.\ if type "coverage@PYTHON_VERSION@" >& /dev/null; then COVERAGE=coverage@PYTHON_VERSION@ >&1 echo "Using ${COVERAGE}" -elif type "python-coverage" >& /dev/null; then - COVERAGE=python-coverage +elif type "python@PYTHON_VERSION@-coverage" >& /dev/null; then + COVERAGE=python@PYTHON_VERSION@-coverage + >&1 echo "Using ${COVERAGE}" else COVERAGE="" >&1 echo "Cannot find coverage@PYTHON_VERSION@/python-coverage... Continuing without it" diff --git a/LCU/Maintenance/DBInterface/monitoringdb/models/wincc.py b/LCU/Maintenance/DBInterface/monitoringdb/models/wincc.py index 82a090b1f91df8fe69fa3bda2d8befe129ec8d15..12d5b6aee7778d321223e36b7a9ba8be8f07ade0 100644 --- a/LCU/Maintenance/DBInterface/monitoringdb/models/wincc.py +++ b/LCU/Maintenance/DBInterface/monitoringdb/models/wincc.py @@ -21,88 +21,132 @@ def to_status(status_code): return STATUS_CODE_TO_STATUS.get(status_code, 'UNKNOWN') -class WinCCAntennaStatusManager(models.Manager): - def latest_status_per_station_and_component_type(self, station, - component_type, - to_date): - antenna_type = to_antenna_type(component_type) - if antenna_type: - return self.latest_status_per_station_and_antenna_type(station, antenna_type, - to_date) - else: - return OrderedDict() - - @staticmethod - def format_result(raw_query_result, antenna_type): - results = OrderedDict() - for row in raw_query_result: - status_description = OrderedDict() - results[str(row.antenna_id)] = status_description - status_description['inserted_at'] = row.last_entry_timestamp - status_description['status'] = to_status(row.status_code) - status_description['status_code'] = row.status_code - status_description['reason'] = row.status_code_reason - status_description['last_modified'] = row.status_code_modified_at - - if antenna_type is 'HBA': - elements = OrderedDict() - status_description['elements'] = elements - - for i in range(16): - element_status = OrderedDict() - elements[str(i)] = element_status - - element_status['status_code'] = getattr(row, "element_%.02d" % i, ) - element_status['status'] = to_status(element_status['status_code']) - - element_status['reason'] = getattr(row, "element_%.02d_reason" % i, ) - element_status['last_modified'] = getattr(row, - "element_%.02d_modified_at" % i, ) - return results - - def latest_status_per_station_and_antenna_type(self, station, antenna_type, to_date): - raw_results = super().raw(''' - SELECT * - FROM antenna_statuses master - INNER JOIN ( - SELECT station, antenna_type, antenna_id, MAX("timestamp") last_entry_timestamp - FROM antenna_statuses - WHERE timestamp <= %s - GROUP BY station, antenna_type, antenna_id - ) slave ON master.station=slave.station AND master.antenna_type=slave.antenna_type AND master.antenna_id = slave.antenna_id AND last_entry_timestamp=master.timestamp - WHERE master.station=%s AND master.antenna_type=%s - ''', [to_date, station.rstrip('C'), antenna_type]) - - return WinCCAntennaStatusManager.format_result(raw_results, antenna_type) - - def latest_status_per_station_and_component_type_antenna_id(self, station, - component_type, - component_id, - to_date): - antenna_type = to_antenna_type(component_type) - if antenna_type: - return self.latest_status_per_station_and_antenna_type_antenna_id(station, antenna_type, - component_id, - to_date) - else: - return OrderedDict() - - def latest_status_per_station_and_antenna_type_antenna_id(self, station, - antenna_type, - antenna_id, - to_date): - raw_results = super().raw(''' - SELECT * - FROM antenna_statuses master - INNER JOIN ( - SELECT station, antenna_type, antenna_id, MAX("timestamp") last_entry_timestamp - FROM antenna_statuses - WHERE timestamp <= %s - GROUP BY station, antenna_type, antenna_id - ) slave ON master.station=slave.station AND master.antenna_type=slave.antenna_type AND master.antenna_id = slave.antenna_id AND last_entry_timestamp=master.timestamp - WHERE master.station=%s AND master.antenna_type=%s AND master.antenna_id=%s - ''', [to_date, station.rstrip('C'), antenna_type, antenna_id]) - return WinCCAntennaStatusManager.format_result(raw_results, antenna_type) +def _format_result(raw_query_result, antenna_type): + results = OrderedDict() + for row in raw_query_result: + status_description = OrderedDict() + results[str(row.antenna_id)] = status_description + status_description['inserted_at'] = row.last_entry_timestamp + status_description['status'] = to_status(row.status_code) + status_description['status_code'] = row.status_code + status_description['reason'] = row.status_code_reason + status_description['last_modified'] = row.status_code_modified_at + + if antenna_type is 'HBA': + elements = OrderedDict() + status_description['elements'] = elements + + for i in range(16): + element_status = OrderedDict() + elements[str(i)] = element_status + + element_status['status_code'] = getattr(row, "element_%.02d" % i, ) + element_status['status'] = to_status(element_status['status_code']) + + element_status['reason'] = getattr(row, "element_%.02d_reason" % i, ) + element_status['last_modified'] = getattr(row, + "element_%.02d_modified_at" % i, ) + return results + + +def latest_status_per_station_and_antenna_type(queryset, station, antenna_type, to_date): + """ + Retrieve the latest antenna statuses for a given station and antenna type + :param queryset: source queryset + :param station: station name + :type station: str + :param component_type: component type name + :type component_type: str + :param to_date: select the latest test before the to date + :type to_date: datetime.datetime + :return: the status of an antenna per antenna id + """ + raw_results = queryset.raw(''' + SELECT * + FROM antenna_statuses master + INNER JOIN ( + SELECT station, antenna_type, antenna_id, MAX("timestamp") last_entry_timestamp + FROM antenna_statuses + WHERE timestamp <= %s + GROUP BY station, antenna_type, antenna_id + ) slave ON master.station=slave.station AND master.antenna_type=slave.antenna_type AND master.antenna_id = slave.antenna_id AND last_entry_timestamp=master.timestamp + WHERE master.station=%s AND master.antenna_type=%s + ''', [to_date, station.rstrip('C'), antenna_type]) + + return _format_result(raw_results, antenna_type) + + +def latest_status_per_station_and_component_type(queryset, station, component_type, to_date): + """ + Retrieve the latest antenna statuses for a given station and component type + :param queryset: source queryset + :param station: station name + :type station: str + :param component_type: component type name + :type component_type: str + :param to_date: select the latest test before the to date + :type to_date: datetime.datetime + :return: the status of an antenna per antenna id + """ + antenna_type = to_antenna_type(component_type) + if antenna_type: + return latest_status_per_station_and_antenna_type(queryset, station, antenna_type, + to_date) + else: + return OrderedDict() + + +def latest_status_per_station_and_component_type_antenna_id(queryset, station, + component_type, + component_id, + to_date): + """ + Retrieve the latest antenna statuses for a given station and component type and id + :param queryset: source queryset + :param station: station name + :type station: str + :param component_type: component type name + :type component_type: str + :param to_date: select the latest test before the to date + :type to_date: datetime.datetime + :return: the status of an antenna per antenna id + """ + antenna_type = to_antenna_type(component_type) + if antenna_type: + return latest_status_per_station_and_antenna_type_antenna_id(queryset, station, antenna_type, + component_id, + to_date) + else: + return OrderedDict() + + +def latest_status_per_station_and_antenna_type_antenna_id(queryset, station, + antenna_type, + antenna_id, + to_date): + """ + Retrieve the latest antenna statuses for a given station and antenna type and id + :param queryset: source queryset + :param station: station name + :type station: str + :param component_type: component type name + :type component_type: str + :param to_date: select the latest test before the to date + :type to_date: datetime.datetime + :return: the status of an antenna per antenna id + """ + raw_results = queryset.raw(''' + SELECT * + FROM antenna_statuses master + INNER JOIN ( + SELECT station, antenna_type, antenna_id, MAX("timestamp") last_entry_timestamp + FROM antenna_statuses + WHERE timestamp <= %s + GROUP BY station, antenna_type, antenna_id + ) slave ON master.station=slave.station AND master.antenna_type=slave.antenna_type AND master.antenna_id = slave.antenna_id AND last_entry_timestamp=master.timestamp + WHERE master.station=%s AND master.antenna_type=%s AND master.antenna_id=%s + ''', [to_date, station.rstrip('C'), antenna_type, antenna_id]) + return _format_result(raw_results, antenna_type) class WinCCAntennaStatus(models.Model): @@ -112,7 +156,6 @@ class WinCCAntennaStatus(models.Model): indexes = [ models.Index(fields=['station', 'antenna_type', 'antenna_id', 'timestamp']) ] - objects = WinCCAntennaStatusManager() timestamp = models.DateTimeField(auto_now_add=True) station = models.CharField(max_length=10, default=None) diff --git a/LCU/Maintenance/DBInterface/monitoringdb/views/controllers.py b/LCU/Maintenance/DBInterface/monitoringdb/views/controllers.py index a2717eb51011984f8fd117eb852cdb9d8378dfbf..760afd18da173e2cb77b3de4326e2a45eead571d 100644 --- a/LCU/Maintenance/DBInterface/monitoringdb/views/controllers.py +++ b/LCU/Maintenance/DBInterface/monitoringdb/views/controllers.py @@ -13,7 +13,9 @@ from lofar.maintenance.monitoringdb.models.rtsm import RTSMErrorSummary, MODE_TO from lofar.maintenance.monitoringdb.models.rtsm import RTSMObservation from lofar.maintenance.monitoringdb.models.station import Station from lofar.maintenance.monitoringdb.models.station_test import StationTest -from lofar.maintenance.monitoringdb.models.wincc import WinCCAntennaStatus +from lofar.maintenance.monitoringdb.models.wincc import WinCCAntennaStatus,\ + latest_status_per_station_and_component_type,\ + latest_status_per_station_and_component_type_antenna_id from rest_framework import status from rest_framework.response import Response from rest_framework.reverse import reverse @@ -814,11 +816,12 @@ class ControllerStationComponentErrors(ValidableReadOnlyView): test_summary['start_date'] = station_test.start_datetime test_summary['end_date'] = station_test.end_datetime component_errors_dict = OrderedDict() - antenna_statuses = \ - WinCCAntennaStatus.objects. \ - latest_status_per_station_and_component_type(self.station_name, - failing_component_type, - to_date=station_test.end_datetime) + antenna_statuses = latest_status_per_station_and_component_type( + WinCCAntennaStatus.objects, + self.station_name, + failing_component_type, + to_date=station_test.end_datetime) + test_summary['status'] = antenna_statuses test_summary['component_errors'] = component_errors_dict component_errors = station_test.component_errors \ @@ -862,11 +865,11 @@ class ControllerStationComponentErrors(ValidableReadOnlyView): rtsm_summary['start_date'] = rtsm_observation.start_datetime rtsm_summary['end_date'] = rtsm_observation.end_datetime rtsm_summary['observation_id'] = rtsm_observation.observation_id - antenna_statuses = \ - WinCCAntennaStatus.objects. \ - latest_status_per_station_and_component_type(self.station_name, - component_name, - to_date=rtsm_observation.end_datetime) + antenna_statuses = latest_status_per_station_and_component_type( + WinCCAntennaStatus.objects, + self.station_name, + component_name, + to_date=rtsm_observation.end_datetime) rtsm_summary['status'] = antenna_statuses component_errors_dict = OrderedDict() rtsm_summary['component_errors'] = component_errors_dict @@ -943,8 +946,9 @@ class ControllerStationComponentErrors(ValidableReadOnlyView): payload[component_type]['errors'] = sorted(station_test_errors_per_type + rtsm_errors_per_type, key=lambda item: item['start_date'], reverse=True) - payload[component_type]['current_status'] = WinCCAntennaStatus.objects. \ - latest_status_per_station_and_component_type(self.station_name, + payload[component_type]['current_status'] =\ + latest_status_per_station_and_component_type(WinCCAntennaStatus.objects, + self.station_name, component_type, to_date=datetime.datetime.now()) return Response(status=status.HTTP_200_OK, data=payload) @@ -1028,13 +1032,13 @@ class ControllerStationComponentElementErrors(ValidableReadOnlyView): end_date=observation['end_datetime'], test_type='R', component_errors=dict()) - antenna_statuses = \ - WinCCAntennaStatus.objects. \ - latest_status_per_station_and_component_type_antenna_id(self.station_name, - self.component_type, - self.antenna_id, - to_date=observation[ - 'end_datetime']) + antenna_statuses = latest_status_per_station_and_component_type_antenna_id( + WinCCAntennaStatus.objects, + self.station_name, + self.component_type, + self.antenna_id, + to_date=observation[ + 'end_datetime']) entry['status'] = antenna_statuses @@ -1055,11 +1059,12 @@ class ControllerStationComponentElementErrors(ValidableReadOnlyView): end_date=station_test['end_datetime'], test_type='S', component_errors=dict()) - antenna_statuses = WinCCAntennaStatus.objects. \ - latest_status_per_station_and_component_type_antenna_id(self.station_name, - self.component_type, - self.antenna_id, - to_date=station_test['end_datetime']) + antenna_statuses = latest_status_per_station_and_component_type_antenna_id( + WinCCAntennaStatus.objects, + self.station_name, + self.component_type, + self.antenna_id, + to_date=station_test['end_datetime']) entry['status'] = antenna_statuses result.append(entry) @@ -1100,13 +1105,13 @@ class ControllerStationComponentElementErrors(ValidableReadOnlyView): test_type='R', component_errors=dict()) - antenna_statuses = \ - WinCCAntennaStatus.objects. \ - latest_status_per_station_and_component_type_antenna_id(self.station_name, - self.component_type, - self.antenna_id, - to_date=item[ - 'observation__end_datetime']) + antenna_statuses = latest_status_per_station_and_component_type_antenna_id( + WinCCAntennaStatus.objects, + self.station_name, + self.component_type, + self.antenna_id, + to_date=item[ + 'observation__end_datetime']) errors[observation_pk]['status'] = antenna_statuses @@ -1149,11 +1154,12 @@ class ControllerStationComponentElementErrors(ValidableReadOnlyView): end_date=component_error.station_test.end_datetime, test_type='S', component_errors=dict()) - antenna_statuses = WinCCAntennaStatus.objects.\ - latest_status_per_station_and_component_type_antenna_id(self.station_name, - self.component_type, - self.antenna_id, - to_date=component_error.station_test.end_datetime) + antenna_statuses = latest_status_per_station_and_component_type_antenna_id( + WinCCAntennaStatus.objects, + self.station_name, + self.component_type, + self.antenna_id, + to_date=component_error.station_test.end_datetime) errors[station_test_pk]['status'] = antenna_statuses @@ -1188,10 +1194,11 @@ class ControllerStationComponentElementErrors(ValidableReadOnlyView): payload = OrderedDict() payload['errors'] = combined_and_sorted - payload['current_status'] = WinCCAntennaStatus.objects.\ - latest_status_per_station_and_component_type_antenna_id(self.station_name, - self.component_type, - self.antenna_id, - to_date=datetime.datetime.now()) + payload['current_status'] = latest_status_per_station_and_component_type_antenna_id( + WinCCAntennaStatus.objects, + self.station_name, + self.component_type, + self.antenna_id, + to_date=datetime.datetime.now()) return Response(status=status.HTTP_200_OK, data=payload) diff --git a/LCU/Maintenance/DBInterface/test/models/test_wincc_models.py b/LCU/Maintenance/DBInterface/test/models/test_wincc_models.py index ae1f428d7e5eaf568d2ac45cc64fdc38d52ba345..3aaea635fae326a44e1e59f50d8ec8377645eb1c 100644 --- a/LCU/Maintenance/DBInterface/test/models/test_wincc_models.py +++ b/LCU/Maintenance/DBInterface/test/models/test_wincc_models.py @@ -1,5 +1,7 @@ from django.test import TestCase -from lofar.maintenance.monitoringdb.models.wincc import WinCCAntennaStatus +from lofar.maintenance.monitoringdb.models.wincc import WinCCAntennaStatus,\ + latest_status_per_station_and_component_type_antenna_id,\ + latest_status_per_station_and_component_type from datetime import datetime import django.db.utils as db_utils @@ -78,11 +80,20 @@ class WinCCAntennaStatusTest(TestCase): order_by('-timestamp').first() self.assertGreaterEqual(saved_entity.timestamp, before_last_insertion_timestamp) - result = WinCCAntennaStatus.objects.\ - latest_status_per_station_and_component_type('CS001', - 'HBA', - datetime.now()) + result = latest_status_per_station_and_component_type(WinCCAntennaStatus.objects, + 'CS001', + 'HBA', + datetime.now()) self.assertIn('1', result) self.assertIn('2', result) self.assertGreaterEqual(result['1']["inserted_at"], before_last_insertion_timestamp) + + result = latest_status_per_station_and_component_type_antenna_id(WinCCAntennaStatus.objects, + 'CS001', + 'HBA', + 1, + datetime.now()) + self.assertIn('1', result) + self.assertNotIn('2', result) + self.assertGreaterEqual(result['1']["inserted_at"], before_last_insertion_timestamp)