Loading csp-lmc-common/csp_lmc_common/CspMaster.py +20 −11 Original line number Original line Diff line number Diff line Loading @@ -280,6 +280,8 @@ class CspMaster(SKAMaster): if all(value == CmdExecState.IDLE for value in self._cmd_execution_state.values()) or (not any(self._cmd_execution_state)): if all(value == CmdExecState.IDLE for value in self._cmd_execution_state.values()) or (not any(self._cmd_execution_state)): self.logger.debug("_cmd_execution_state:{}".format(self._cmd_execution_state.items())) self.logger.debug("_cmd_execution_state:{}".format(self._cmd_execution_state.items())) self.set_state(self._se_state[self.CspCbf]) self.set_state(self._se_state[self.CspCbf]) self.set_change_event('State', self._se_state[self.CspCbf]) self.set_archive_event('State', self._se_state[self.CspCbf]) if self._admin_mode in [AdminMode.OFFLINE, AdminMode.NOT_FITTED, AdminMode.RESERVED]: if self._admin_mode in [AdminMode.OFFLINE, AdminMode.NOT_FITTED, AdminMode.RESERVED]: self.set_state(tango.DevState.DISABLE) self.set_state(tango.DevState.DISABLE) self.logger.debug("CspState: {}".format(self.get_state())) self.logger.debug("CspState: {}".format(self.get_state())) Loading Loading @@ -439,7 +441,7 @@ class CspMaster(SKAMaster): # tango_cmd_name: is the TANGO command name with the capital letter # tango_cmd_name: is the TANGO command name with the capital letter # In the dictionary keys, is generally used the command name in lower letters # In the dictionary keys, is generally used the command name in lower letters cmd_name = tango_cmd_name.lower() cmd_name = tango_cmd_name.lower() self.logger.debug("cmd_name: {} dev_state: {}".format(cmd_name, self.logger.info("cmd_name: {} dev_state: {}".format(cmd_name, dev_successful_state)) dev_successful_state)) num_of_failed_device = 0 num_of_failed_device = 0 self._num_dev_completed_task[cmd_name] = 0 self._num_dev_completed_task[cmd_name] = 0 Loading Loading @@ -477,6 +479,8 @@ class CspMaster(SKAMaster): # IDLE and the thread exit. After it is received the callback message with the # IDLE and the thread exit. After it is received the callback message with the # error message generated by the CbfMaster but the # error message generated by the CbfMaster but the # self._cmd_execution_state results RUNNING and the device stucks # self._cmd_execution_state results RUNNING and the device stucks if device_proxy.state() == dev_successful_state: continue device_proxy.command_inout_asynch(tango_cmd_name, self._cmd_ended_cb) device_proxy.command_inout_asynch(tango_cmd_name, self._cmd_ended_cb) except tango.DevFailed as df: except tango.DevFailed as df: # It should not happen! Verify # It should not happen! Verify Loading Loading @@ -593,7 +597,7 @@ class CspMaster(SKAMaster): with self._cmd_exec_state_lock: with self._cmd_exec_state_lock: self._cmd_execution_state[cmd_name] = CmdExecState.IDLE self._cmd_execution_state[cmd_name] = CmdExecState.IDLE def _enable_subarrays(self, tango_cmd_name): def _switch_subarrays(self, tango_cmd_name): """ """ Helper method to execute the On[Off] command on the CSP subarrays. Helper method to execute the On[Off] command on the CSP subarrays. Loading @@ -605,10 +609,6 @@ class CspMaster(SKAMaster): if subarray_action not in ['on', 'off']: if subarray_action not in ['on', 'off']: self.logger.warning(f"Invalid command {subarray_action} to issue on CSP subarray") self.logger.warning(f"Invalid command {subarray_action} to issue on CSP subarray") return return master_state = self.get_state() if (subarray_action, master_state) not in [('on', tango.DevState.ON), ('off', tango.DevState.STANDBY)]: self.logger.warning("CSPMaster is not in the proper state ({})".format(self.get_state())) return try: try: subarray_group = tango.Group("CSPSubarray") subarray_group = tango.Group("CSPSubarray") for subarray in self.CspSubarrays: for subarray in self.CspSubarrays: Loading @@ -635,6 +635,12 @@ class CspMaster(SKAMaster): except Exception: except Exception: self.logger.error("command {} failed on subarray".format(subarray_action)) self.logger.error("command {} failed on subarray".format(subarray_action)) def _enable_subarrays(self): return self._switch_subarrays('On') def _disable_subarrays(self): return self._switch_subarrays('Off') def _se_write_adminMode(self, value, device_fqdn): def _se_write_adminMode(self, value, device_fqdn): """ """ *Class method.* *Class method.* Loading Loading @@ -1224,6 +1230,8 @@ class CspMaster(SKAMaster): # property '__value' # property '__value' #attribute_properties = csp_tango_db.get_device_attribute_property(self.get_name(), #attribute_properties = csp_tango_db.get_device_attribute_property(self.get_name(), # {'adminMode': ['__value']}) # {'adminMode': ['__value']}) self.set_change_event("state", True, True) self.set_archive_event("state", True, True) # set init values for the CSP Element and Sub-element SCM states # set init values for the CSP Element and Sub-element SCM states self.set_state(tango.DevState.INIT) self.set_state(tango.DevState.INIT) self._health_state = HealthState.OK self._health_state = HealthState.OK Loading Loading @@ -1886,18 +1894,19 @@ class CspMaster(SKAMaster): try: try: # start the thread # start the thread # set the CSP command execution running flag # set the CSP command execution running flag self.logger.debug("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) self.logger.info("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) with self._cmd_exec_state_lock: with self._cmd_exec_state_lock: self._cmd_execution_state['on'] = CmdExecState.RUNNING self._cmd_execution_state['on'] = CmdExecState.RUNNING self._command_thread['on'].start() self._command_thread['on'].start() self.logger.debug("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) self.logger.debug("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) # To temporarily solve SKB-26 -> join the thread to synchronize the command # To temporarily solve SKB-26 -> join the thread to synchronize the command self._command_thread['on'].join() self._command_thread['on'].join() self._enable_subarrays() self._update_csp_state() self._update_csp_state() self.logger.info("CSP State:{}".format(self.get_state())) self.logger.info("CSP State:{}".format(self.get_state())) self._enable_subarrays('On') except Exception as e: except Exception: # reset the sub-element command exec state # reset the sub-element command exec state self.logger.error(f"Received error {e}") self._se_cmd_execution_state.clear() self._se_cmd_execution_state.clear() self._cmd_execution_state['on'] = CmdExecState.IDLE self._cmd_execution_state['on'] = CmdExecState.IDLE tango.Except.throw_exception("Command failed", tango.Except.throw_exception("Command failed", Loading Loading @@ -2063,12 +2072,12 @@ class CspMaster(SKAMaster): self._cmd_execution_state['standby'] = CmdExecState.RUNNING self._cmd_execution_state['standby'] = CmdExecState.RUNNING # start the thread # start the thread self._command_thread['standby'].start() self._command_thread['standby'].start() self.logger.debug("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) self.logger.info("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) # To temprarily solve the SKB-26 -> join the thread to synchronize the command # To temprarily solve the SKB-26 -> join the thread to synchronize the command self._command_thread['standby'].join() self._command_thread['standby'].join() self._update_csp_state() self._update_csp_state() self.logger.info("CSP State:{}".format(self.get_state())) self.logger.info("CSP State:{}".format(self.get_state())) self._enable_subarrays('Off') self._disable_subarrays() except Exception: except Exception: # reset the sub-element command exec state # reset the sub-element command exec state self._se_cmd_execution_state.clear() self._se_cmd_execution_state.clear() Loading csp-lmc-common/csp_lmc_common/CspSubarray.py +19 −22 Original line number Original line Diff line number Diff line Loading @@ -332,7 +332,7 @@ class CspSubarray(SKASubarray): # Implemented as a nested default dictionary # Implemented as a nested default dictionary # keys: FQDN # keys: FQDN # values: default dictionary (keys: command name, values: the duration (in sec)) # values: default dictionary (keys: command name, values: the duration (in sec)) device._sc_subarray_cmd_duration_expected = defaultdict(lambda: defaultdict(lambda: 5)) device._sc_subarray_cmd_duration_expected = defaultdict(lambda: defaultdict(lambda: 10)) # _sc_subarray_scan_configuration: report the scan configuration # _sc_subarray_scan_configuration: report the scan configuration # for each sub-array sub-component (CBF, PSS subarray, PSTBeams) # for each sub-array sub-component (CBF, PSS subarray, PSTBeams) Loading Loading @@ -435,7 +435,8 @@ class CspSubarray(SKASubarray): device.connect_to_subarray_subcomponent(device.PssSubarray) device.connect_to_subarray_subcomponent(device.PssSubarray) # put the device to OFF/EMPTY: no transition is allowed from INIT state # put the device to OFF/EMPTY: no transition is allowed from INIT state self.succeeded() self.succeeded() if device._sc_subarray_state[device.CbfSubarray] is not DevState.ON: subarray_state = device._sc_subarray_state[device.CbfSubarray] if subarray_state is not DevState.ON: return return # put the device to ON/EMPTY # put the device to ON/EMPTY on_handler.succeeded() on_handler.succeeded() Loading @@ -457,7 +458,7 @@ class CspSubarray(SKASubarray): """ """ Helper method to monitor the CSP Subarray observing state at re-initialization if Helper method to monitor the CSP Subarray observing state at re-initialization if the observing state is in a transitional state. the observing state is in a transitional state. NOTE: Currently onlt the SCANNING obsState is handled. NOTE: Currently only the SCANNING obsState is handled. :param csp_obs_state: the CSP.LMC Subarray observing state. :param csp_obs_state: the CSP.LMC Subarray observing state. :type csp_obs_state: string :type csp_obs_state: string Loading Loading @@ -546,6 +547,7 @@ class CspSubarray(SKASubarray): def do(self): def do(self): super().do() super().do() device = self.target device = self.target device_in_error = 0 self.logger.info("Call On Command") self.logger.info("Call On Command") for fqdn in device._sc_subarray_fqdn: for fqdn in device._sc_subarray_fqdn: try: try: Loading @@ -560,10 +562,12 @@ class CspSubarray(SKASubarray): device._health_state = HealthState.DEGRADED device._health_state = HealthState.DEGRADED continue continue else: else: return (ResultCode.FAILED, message) device_in_error += 1 except tango.DevFailed as tango_err: except tango.DevFailed as tango_err: message = str(tango_err.args[0].desc) message = str(tango_err.args[0].desc) return (ResultCode.FAILED, message) device_in_error += 1 if device_in_error: return (ResultCode.FAILED, "Command On failed") message = "On command completed OK" message = "On command completed OK" self.logger.info(message) self.logger.info(message) return (ResultCode.OK, message) return (ResultCode.OK, message) Loading Loading @@ -671,7 +675,7 @@ class CspSubarray(SKASubarray): # the dictionary with the scan configuration # the dictionary with the scan configuration self.logger.info("ConfigureCommand at {}".format(time.time())) self.logger.info(f"ConfigureCommand at {time.time()}") target_device = self.target target_device = self.target try: try: # if the stored configuration attribute is not empty, check # if the stored configuration attribute is not empty, check Loading Loading @@ -703,6 +707,8 @@ class CspSubarray(SKASubarray): for device in target_device._sc_subarray_assigned_fqdn: for device in target_device._sc_subarray_assigned_fqdn: # reset the command progress counter for each # reset the command progress counter for each # sub-array component # sub-array component self.logger.info(f"ConfigureCommand exec_state {target_device._sc_subarray_cmd_exec_state[device]['configurescan']}") target_device._sc_subarray_cmd_exec_state[device]['configurescan'] = CmdExecState.IDLE if target_device._sc_subarray_obs_state[device] == ObsState.READY: if target_device._sc_subarray_obs_state[device] == ObsState.READY: target_device._reconfiguring = True target_device._reconfiguring = True target_device._sc_subarray_cmd_progress[device]['configurescan'] = 0 target_device._sc_subarray_cmd_progress[device]['configurescan'] = 0 Loading Loading @@ -735,20 +741,14 @@ class CspSubarray(SKASubarray): # NOTE: CBF/PSS sub-array checks for the validity of its # NOTE: CBF/PSS sub-array checks for the validity of its # configuration. Failure in configuration throws an exception that is # configuration. Failure in configuration throws an exception that is # caught via the _cmd_ended_cb callback # caught via the _cmd_ended_cb callback """ try: # read the timeout configured for the operation on the device self._sc_subarray_cmd_duration_expected[device]['configurescan'] = proxy.configureDelayExpected except AttributeError as attr_err: self.logger.info("No attribute {} on device {}".format(str(attr_err), device)) """ try: try: # read the timeout configured for the operation on the device # read the timeout configured for the operation on the device target_device._sc_subarray_cmd_duration_expected[device]['configurescan'] = target_device._get_expected_delay(proxy, "configureDelayExpected") target_device._sc_subarray_cmd_duration_expected[device]['configurescan'] = target_device._get_expected_delay(proxy, "configureDelayExpected") #self.logger.info("config delay: {}".format(target_device._sc_subarray_cmd_duration_expected[device]['configurescan'])) except tango.DevFailed as tango_err: except tango.DevFailed as tango_err: self.logger.info("No attribute {} on device {}".format(tango_err.args[0].desc, device)) self.logger.info("No attribute {} on device {}. Use default value {}".format(tango_err.args[0].desc, device, target_device._sc_subarray_cmd_duration_expected[device]['configurescan')) if target_device._sc_subarray_cmd_duration_expected[device]['configurescan'] > target_device._config_delay_expected: target_device._config_delay_expected = target_device._sc_subarray_cmd_duration_expected[device]['configurescan'] try: try: target_device._timeout_expired = False target_device._timeout_expired = False target_device._failure_raised = False target_device._failure_raised = False Loading @@ -774,11 +774,6 @@ class CspSubarray(SKASubarray): self.logger.debug("configure starting time: {}".format(target_device._sc_subarray_cmd_starting_time[device])) self.logger.debug("configure starting time: {}".format(target_device._sc_subarray_cmd_starting_time[device])) # end for loop on devices # end for loop on devices # TODO: evaluate the global timeout as the max of the single sub-element # timeouts # configure the timeout for the operation if target_device._config_delay_expected > 0: target_device._cmd_duration_expected['configurescan'] = target_device._config_delay_expected self.logger.debug("_config_delay_expected :{}".format(target_device._config_delay_expected)) self.logger.debug("_config_delay_expected :{}".format(target_device._config_delay_expected)) # invoke the constructor for the command thread # invoke the constructor for the command thread thread_args = [target_device._sc_subarray_assigned_fqdn, argin] thread_args = [target_device._sc_subarray_assigned_fqdn, argin] Loading Loading @@ -1400,6 +1395,8 @@ class CspSubarray(SKASubarray): self.logger.info("Creating group for Reset {}".format(device_list)) self.logger.info("Creating group for Reset {}".format(device_list)) sc_group = tango.Group("ResetGroup") sc_group = tango.Group("ResetGroup") for device in device_list: for device in device_list: if target_device._sc_subarray_state[device] != tango.DevState.FAULT: continue sc_group.add(device) sc_group.add(device) except Exception: except Exception: self.logger.error("TANGO Group command failed") self.logger.error("TANGO Group command failed") Loading Loading @@ -1717,7 +1714,7 @@ class CspSubarray(SKASubarray): def _get_expected_delay(self, proxy,attr_name): def _get_expected_delay(self, proxy,attr_name): try: try: attr_value = proxy.read_attribute(attr_name) attr_value = proxy.read_attribute(attr_name) return attr_value.value() return attr_value.value except AttributeError as attr_err: except AttributeError as attr_err: self.logger.info("No attribute {} on device {}".format(str(attr_err), proxy)) self.logger.info("No attribute {} on device {}".format(str(attr_err), proxy)) tango.Except.throw_exception("Attribute Error", str(attr_err), "", tango.ErrSeverity.ERR) tango.Except.throw_exception("Attribute Error", str(attr_err), "", tango.ErrSeverity.ERR) Loading csp-lmc-mid/Dockerfile +2 −2 Original line number Original line Diff line number Diff line FROM nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.2 AS buildenv FROM nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.3.1 AS buildenv FROM nexus.engageska-portugal.pt/ska-docker/ska-python-runtime:9.3.2 AS runtime FROM nexus.engageska-portugal.pt/ska-docker/ska-python-runtime:9.3.3.1 AS runtime # create ipython profile to so that itango doesn't fail if ipython hasn't run yet # create ipython profile to so that itango doesn't fail if ipython hasn't run yet RUN ipython profile create RUN ipython profile create Loading csp-lmc-mid/charts/mid-csp/data/midcspconfig.json +0 −4 Original line number Original line Diff line number Diff line Loading @@ -262,10 +262,6 @@ "polled_attr": [ "polled_attr": [ "healthstate", "healthstate", "1000", "1000", "adminmode", "1000", "state", "1000", "csppssadminmode", "csppssadminmode", "1000", "1000", "csppstadminmode", "csppstadminmode", Loading csp-lmc-mid/tests/integration/MidCspMaster_test.py +13 −15 Original line number Original line Diff line number Diff line Loading @@ -14,7 +14,6 @@ import sys import os import os import time import time import logging import logging import unittest import numpy as np import numpy as np # Tango imports # Tango imports import tango import tango Loading @@ -40,7 +39,7 @@ LOGGER = logging.getLogger(__name__) # Device test case # Device test case @pytest.mark.usefixtures("midcsp_master", "midcsp_subarray01", "cbf_master") @pytest.mark.usefixtures("midcsp_master", "midcsp_subarray01", "cbf_master") class TestBase(unittest.TestCase): class TestBase(object): fixture_names = () fixture_names = () @pytest.fixture(autouse=True) @pytest.fixture(autouse=True) Loading Loading @@ -69,8 +68,7 @@ class TestCspMaster(TestBase): if state == DevState.STANDBY: if state == DevState.STANDBY: argin = ["mid_csp_cbf/sub_elt/master",] argin = ["mid_csp_cbf/sub_elt/master",] self.midcsp_master.On(argin) self.midcsp_master.On(argin) prober_state = Probe(self.midcsp_master, "State", DevState.ON, f"CSP Master not ON") state = self.midcsp_master.State() Poller(3, 0.1).check(prober_state) if state == DevState.ON: if state == DevState.ON: return return Loading @@ -79,8 +77,6 @@ class TestCspMaster(TestBase): Test for execution of On command when the CbfMaster is in the right state Test for execution of On command when the CbfMaster is in the right state """ """ self._setup_master() self._setup_master() prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.ON, f"CSPSubarray not ON") Poller(4, 0.2).check(prober_subarray_state) assert self.midcsp_subarray01.state() == DevState.ON assert self.midcsp_subarray01.state() == DevState.ON def test_Standby_valid_state(self): def test_Standby_valid_state(self): Loading @@ -91,24 +87,26 @@ class TestCspMaster(TestBase): assert self.midcsp_master.state() == DevState.ON assert self.midcsp_master.state() == DevState.ON argin = ["mid_csp_cbf/sub_elt/master",] argin = ["mid_csp_cbf/sub_elt/master",] self.midcsp_master.Standby(argin) self.midcsp_master.Standby(argin) prober_state = Probe(self.midcsp_master, "State", DevState.STANDBY, assert self.midcsp_master.state() == DevState.STANDBY f"CSP Master not STANDBY") Poller(4, 0.2).check(prober_state) def test_issue_Standby_AFTER_On_command(self): @pytest.mark.sequence @pytest.mark.parametrize('execution_number', range(3)) def test_sequence_ON_STABDBY_commands(self, execution_number): """ """ Issue the Standby command just after the On command, without waiting Issue the Standby command just after the On command, without waiting on the State value. on the State value. To solve SKB-26 bug, the power commands are now executed in To solve SKB-26 bug, the power commands are now executed in synch way. synch way. Repeat the test a number times = execution_number """ """ self._setup_master() self._setup_master() argin = ["mid_csp_cbf/sub_elt/master",] argin = ["mid_csp_cbf/sub_elt/master",] self.midcsp_master.On(argin) self.midcsp_master.Standby(argin) self.midcsp_master.Standby(argin) prober_state = Probe(self.midcsp_master, "State", DevState.STANDBY, assert self.midcsp_subarray01.state() == DevState.OFF f"CSP Master not STANDBY") assert self.midcsp_master.state() == DevState.STANDBY Poller(4, 0.2).check(prober_state) self.midcsp_master.On(argin) assert self.midcsp_subarray01.state() == DevState.ON assert self.midcsp_master.state() == DevState.ON ''' ''' def test_cspmaster_state_WHEN_adminmode_is_offline(self): def test_cspmaster_state_WHEN_adminmode_is_offline(self): Loading Loading
csp-lmc-common/csp_lmc_common/CspMaster.py +20 −11 Original line number Original line Diff line number Diff line Loading @@ -280,6 +280,8 @@ class CspMaster(SKAMaster): if all(value == CmdExecState.IDLE for value in self._cmd_execution_state.values()) or (not any(self._cmd_execution_state)): if all(value == CmdExecState.IDLE for value in self._cmd_execution_state.values()) or (not any(self._cmd_execution_state)): self.logger.debug("_cmd_execution_state:{}".format(self._cmd_execution_state.items())) self.logger.debug("_cmd_execution_state:{}".format(self._cmd_execution_state.items())) self.set_state(self._se_state[self.CspCbf]) self.set_state(self._se_state[self.CspCbf]) self.set_change_event('State', self._se_state[self.CspCbf]) self.set_archive_event('State', self._se_state[self.CspCbf]) if self._admin_mode in [AdminMode.OFFLINE, AdminMode.NOT_FITTED, AdminMode.RESERVED]: if self._admin_mode in [AdminMode.OFFLINE, AdminMode.NOT_FITTED, AdminMode.RESERVED]: self.set_state(tango.DevState.DISABLE) self.set_state(tango.DevState.DISABLE) self.logger.debug("CspState: {}".format(self.get_state())) self.logger.debug("CspState: {}".format(self.get_state())) Loading Loading @@ -439,7 +441,7 @@ class CspMaster(SKAMaster): # tango_cmd_name: is the TANGO command name with the capital letter # tango_cmd_name: is the TANGO command name with the capital letter # In the dictionary keys, is generally used the command name in lower letters # In the dictionary keys, is generally used the command name in lower letters cmd_name = tango_cmd_name.lower() cmd_name = tango_cmd_name.lower() self.logger.debug("cmd_name: {} dev_state: {}".format(cmd_name, self.logger.info("cmd_name: {} dev_state: {}".format(cmd_name, dev_successful_state)) dev_successful_state)) num_of_failed_device = 0 num_of_failed_device = 0 self._num_dev_completed_task[cmd_name] = 0 self._num_dev_completed_task[cmd_name] = 0 Loading Loading @@ -477,6 +479,8 @@ class CspMaster(SKAMaster): # IDLE and the thread exit. After it is received the callback message with the # IDLE and the thread exit. After it is received the callback message with the # error message generated by the CbfMaster but the # error message generated by the CbfMaster but the # self._cmd_execution_state results RUNNING and the device stucks # self._cmd_execution_state results RUNNING and the device stucks if device_proxy.state() == dev_successful_state: continue device_proxy.command_inout_asynch(tango_cmd_name, self._cmd_ended_cb) device_proxy.command_inout_asynch(tango_cmd_name, self._cmd_ended_cb) except tango.DevFailed as df: except tango.DevFailed as df: # It should not happen! Verify # It should not happen! Verify Loading Loading @@ -593,7 +597,7 @@ class CspMaster(SKAMaster): with self._cmd_exec_state_lock: with self._cmd_exec_state_lock: self._cmd_execution_state[cmd_name] = CmdExecState.IDLE self._cmd_execution_state[cmd_name] = CmdExecState.IDLE def _enable_subarrays(self, tango_cmd_name): def _switch_subarrays(self, tango_cmd_name): """ """ Helper method to execute the On[Off] command on the CSP subarrays. Helper method to execute the On[Off] command on the CSP subarrays. Loading @@ -605,10 +609,6 @@ class CspMaster(SKAMaster): if subarray_action not in ['on', 'off']: if subarray_action not in ['on', 'off']: self.logger.warning(f"Invalid command {subarray_action} to issue on CSP subarray") self.logger.warning(f"Invalid command {subarray_action} to issue on CSP subarray") return return master_state = self.get_state() if (subarray_action, master_state) not in [('on', tango.DevState.ON), ('off', tango.DevState.STANDBY)]: self.logger.warning("CSPMaster is not in the proper state ({})".format(self.get_state())) return try: try: subarray_group = tango.Group("CSPSubarray") subarray_group = tango.Group("CSPSubarray") for subarray in self.CspSubarrays: for subarray in self.CspSubarrays: Loading @@ -635,6 +635,12 @@ class CspMaster(SKAMaster): except Exception: except Exception: self.logger.error("command {} failed on subarray".format(subarray_action)) self.logger.error("command {} failed on subarray".format(subarray_action)) def _enable_subarrays(self): return self._switch_subarrays('On') def _disable_subarrays(self): return self._switch_subarrays('Off') def _se_write_adminMode(self, value, device_fqdn): def _se_write_adminMode(self, value, device_fqdn): """ """ *Class method.* *Class method.* Loading Loading @@ -1224,6 +1230,8 @@ class CspMaster(SKAMaster): # property '__value' # property '__value' #attribute_properties = csp_tango_db.get_device_attribute_property(self.get_name(), #attribute_properties = csp_tango_db.get_device_attribute_property(self.get_name(), # {'adminMode': ['__value']}) # {'adminMode': ['__value']}) self.set_change_event("state", True, True) self.set_archive_event("state", True, True) # set init values for the CSP Element and Sub-element SCM states # set init values for the CSP Element and Sub-element SCM states self.set_state(tango.DevState.INIT) self.set_state(tango.DevState.INIT) self._health_state = HealthState.OK self._health_state = HealthState.OK Loading Loading @@ -1886,18 +1894,19 @@ class CspMaster(SKAMaster): try: try: # start the thread # start the thread # set the CSP command execution running flag # set the CSP command execution running flag self.logger.debug("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) self.logger.info("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) with self._cmd_exec_state_lock: with self._cmd_exec_state_lock: self._cmd_execution_state['on'] = CmdExecState.RUNNING self._cmd_execution_state['on'] = CmdExecState.RUNNING self._command_thread['on'].start() self._command_thread['on'].start() self.logger.debug("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) self.logger.debug("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) # To temporarily solve SKB-26 -> join the thread to synchronize the command # To temporarily solve SKB-26 -> join the thread to synchronize the command self._command_thread['on'].join() self._command_thread['on'].join() self._enable_subarrays() self._update_csp_state() self._update_csp_state() self.logger.info("CSP State:{}".format(self.get_state())) self.logger.info("CSP State:{}".format(self.get_state())) self._enable_subarrays('On') except Exception as e: except Exception: # reset the sub-element command exec state # reset the sub-element command exec state self.logger.error(f"Received error {e}") self._se_cmd_execution_state.clear() self._se_cmd_execution_state.clear() self._cmd_execution_state['on'] = CmdExecState.IDLE self._cmd_execution_state['on'] = CmdExecState.IDLE tango.Except.throw_exception("Command failed", tango.Except.throw_exception("Command failed", Loading Loading @@ -2063,12 +2072,12 @@ class CspMaster(SKAMaster): self._cmd_execution_state['standby'] = CmdExecState.RUNNING self._cmd_execution_state['standby'] = CmdExecState.RUNNING # start the thread # start the thread self._command_thread['standby'].start() self._command_thread['standby'].start() self.logger.debug("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) self.logger.info("self._cmd_execution_state: {}".format(self._cmd_execution_state.items())) # To temprarily solve the SKB-26 -> join the thread to synchronize the command # To temprarily solve the SKB-26 -> join the thread to synchronize the command self._command_thread['standby'].join() self._command_thread['standby'].join() self._update_csp_state() self._update_csp_state() self.logger.info("CSP State:{}".format(self.get_state())) self.logger.info("CSP State:{}".format(self.get_state())) self._enable_subarrays('Off') self._disable_subarrays() except Exception: except Exception: # reset the sub-element command exec state # reset the sub-element command exec state self._se_cmd_execution_state.clear() self._se_cmd_execution_state.clear() Loading
csp-lmc-common/csp_lmc_common/CspSubarray.py +19 −22 Original line number Original line Diff line number Diff line Loading @@ -332,7 +332,7 @@ class CspSubarray(SKASubarray): # Implemented as a nested default dictionary # Implemented as a nested default dictionary # keys: FQDN # keys: FQDN # values: default dictionary (keys: command name, values: the duration (in sec)) # values: default dictionary (keys: command name, values: the duration (in sec)) device._sc_subarray_cmd_duration_expected = defaultdict(lambda: defaultdict(lambda: 5)) device._sc_subarray_cmd_duration_expected = defaultdict(lambda: defaultdict(lambda: 10)) # _sc_subarray_scan_configuration: report the scan configuration # _sc_subarray_scan_configuration: report the scan configuration # for each sub-array sub-component (CBF, PSS subarray, PSTBeams) # for each sub-array sub-component (CBF, PSS subarray, PSTBeams) Loading Loading @@ -435,7 +435,8 @@ class CspSubarray(SKASubarray): device.connect_to_subarray_subcomponent(device.PssSubarray) device.connect_to_subarray_subcomponent(device.PssSubarray) # put the device to OFF/EMPTY: no transition is allowed from INIT state # put the device to OFF/EMPTY: no transition is allowed from INIT state self.succeeded() self.succeeded() if device._sc_subarray_state[device.CbfSubarray] is not DevState.ON: subarray_state = device._sc_subarray_state[device.CbfSubarray] if subarray_state is not DevState.ON: return return # put the device to ON/EMPTY # put the device to ON/EMPTY on_handler.succeeded() on_handler.succeeded() Loading @@ -457,7 +458,7 @@ class CspSubarray(SKASubarray): """ """ Helper method to monitor the CSP Subarray observing state at re-initialization if Helper method to monitor the CSP Subarray observing state at re-initialization if the observing state is in a transitional state. the observing state is in a transitional state. NOTE: Currently onlt the SCANNING obsState is handled. NOTE: Currently only the SCANNING obsState is handled. :param csp_obs_state: the CSP.LMC Subarray observing state. :param csp_obs_state: the CSP.LMC Subarray observing state. :type csp_obs_state: string :type csp_obs_state: string Loading Loading @@ -546,6 +547,7 @@ class CspSubarray(SKASubarray): def do(self): def do(self): super().do() super().do() device = self.target device = self.target device_in_error = 0 self.logger.info("Call On Command") self.logger.info("Call On Command") for fqdn in device._sc_subarray_fqdn: for fqdn in device._sc_subarray_fqdn: try: try: Loading @@ -560,10 +562,12 @@ class CspSubarray(SKASubarray): device._health_state = HealthState.DEGRADED device._health_state = HealthState.DEGRADED continue continue else: else: return (ResultCode.FAILED, message) device_in_error += 1 except tango.DevFailed as tango_err: except tango.DevFailed as tango_err: message = str(tango_err.args[0].desc) message = str(tango_err.args[0].desc) return (ResultCode.FAILED, message) device_in_error += 1 if device_in_error: return (ResultCode.FAILED, "Command On failed") message = "On command completed OK" message = "On command completed OK" self.logger.info(message) self.logger.info(message) return (ResultCode.OK, message) return (ResultCode.OK, message) Loading Loading @@ -671,7 +675,7 @@ class CspSubarray(SKASubarray): # the dictionary with the scan configuration # the dictionary with the scan configuration self.logger.info("ConfigureCommand at {}".format(time.time())) self.logger.info(f"ConfigureCommand at {time.time()}") target_device = self.target target_device = self.target try: try: # if the stored configuration attribute is not empty, check # if the stored configuration attribute is not empty, check Loading Loading @@ -703,6 +707,8 @@ class CspSubarray(SKASubarray): for device in target_device._sc_subarray_assigned_fqdn: for device in target_device._sc_subarray_assigned_fqdn: # reset the command progress counter for each # reset the command progress counter for each # sub-array component # sub-array component self.logger.info(f"ConfigureCommand exec_state {target_device._sc_subarray_cmd_exec_state[device]['configurescan']}") target_device._sc_subarray_cmd_exec_state[device]['configurescan'] = CmdExecState.IDLE if target_device._sc_subarray_obs_state[device] == ObsState.READY: if target_device._sc_subarray_obs_state[device] == ObsState.READY: target_device._reconfiguring = True target_device._reconfiguring = True target_device._sc_subarray_cmd_progress[device]['configurescan'] = 0 target_device._sc_subarray_cmd_progress[device]['configurescan'] = 0 Loading Loading @@ -735,20 +741,14 @@ class CspSubarray(SKASubarray): # NOTE: CBF/PSS sub-array checks for the validity of its # NOTE: CBF/PSS sub-array checks for the validity of its # configuration. Failure in configuration throws an exception that is # configuration. Failure in configuration throws an exception that is # caught via the _cmd_ended_cb callback # caught via the _cmd_ended_cb callback """ try: # read the timeout configured for the operation on the device self._sc_subarray_cmd_duration_expected[device]['configurescan'] = proxy.configureDelayExpected except AttributeError as attr_err: self.logger.info("No attribute {} on device {}".format(str(attr_err), device)) """ try: try: # read the timeout configured for the operation on the device # read the timeout configured for the operation on the device target_device._sc_subarray_cmd_duration_expected[device]['configurescan'] = target_device._get_expected_delay(proxy, "configureDelayExpected") target_device._sc_subarray_cmd_duration_expected[device]['configurescan'] = target_device._get_expected_delay(proxy, "configureDelayExpected") #self.logger.info("config delay: {}".format(target_device._sc_subarray_cmd_duration_expected[device]['configurescan'])) except tango.DevFailed as tango_err: except tango.DevFailed as tango_err: self.logger.info("No attribute {} on device {}".format(tango_err.args[0].desc, device)) self.logger.info("No attribute {} on device {}. Use default value {}".format(tango_err.args[0].desc, device, target_device._sc_subarray_cmd_duration_expected[device]['configurescan')) if target_device._sc_subarray_cmd_duration_expected[device]['configurescan'] > target_device._config_delay_expected: target_device._config_delay_expected = target_device._sc_subarray_cmd_duration_expected[device]['configurescan'] try: try: target_device._timeout_expired = False target_device._timeout_expired = False target_device._failure_raised = False target_device._failure_raised = False Loading @@ -774,11 +774,6 @@ class CspSubarray(SKASubarray): self.logger.debug("configure starting time: {}".format(target_device._sc_subarray_cmd_starting_time[device])) self.logger.debug("configure starting time: {}".format(target_device._sc_subarray_cmd_starting_time[device])) # end for loop on devices # end for loop on devices # TODO: evaluate the global timeout as the max of the single sub-element # timeouts # configure the timeout for the operation if target_device._config_delay_expected > 0: target_device._cmd_duration_expected['configurescan'] = target_device._config_delay_expected self.logger.debug("_config_delay_expected :{}".format(target_device._config_delay_expected)) self.logger.debug("_config_delay_expected :{}".format(target_device._config_delay_expected)) # invoke the constructor for the command thread # invoke the constructor for the command thread thread_args = [target_device._sc_subarray_assigned_fqdn, argin] thread_args = [target_device._sc_subarray_assigned_fqdn, argin] Loading Loading @@ -1400,6 +1395,8 @@ class CspSubarray(SKASubarray): self.logger.info("Creating group for Reset {}".format(device_list)) self.logger.info("Creating group for Reset {}".format(device_list)) sc_group = tango.Group("ResetGroup") sc_group = tango.Group("ResetGroup") for device in device_list: for device in device_list: if target_device._sc_subarray_state[device] != tango.DevState.FAULT: continue sc_group.add(device) sc_group.add(device) except Exception: except Exception: self.logger.error("TANGO Group command failed") self.logger.error("TANGO Group command failed") Loading Loading @@ -1717,7 +1714,7 @@ class CspSubarray(SKASubarray): def _get_expected_delay(self, proxy,attr_name): def _get_expected_delay(self, proxy,attr_name): try: try: attr_value = proxy.read_attribute(attr_name) attr_value = proxy.read_attribute(attr_name) return attr_value.value() return attr_value.value except AttributeError as attr_err: except AttributeError as attr_err: self.logger.info("No attribute {} on device {}".format(str(attr_err), proxy)) self.logger.info("No attribute {} on device {}".format(str(attr_err), proxy)) tango.Except.throw_exception("Attribute Error", str(attr_err), "", tango.ErrSeverity.ERR) tango.Except.throw_exception("Attribute Error", str(attr_err), "", tango.ErrSeverity.ERR) Loading
csp-lmc-mid/Dockerfile +2 −2 Original line number Original line Diff line number Diff line FROM nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.2 AS buildenv FROM nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.3.1 AS buildenv FROM nexus.engageska-portugal.pt/ska-docker/ska-python-runtime:9.3.2 AS runtime FROM nexus.engageska-portugal.pt/ska-docker/ska-python-runtime:9.3.3.1 AS runtime # create ipython profile to so that itango doesn't fail if ipython hasn't run yet # create ipython profile to so that itango doesn't fail if ipython hasn't run yet RUN ipython profile create RUN ipython profile create Loading
csp-lmc-mid/charts/mid-csp/data/midcspconfig.json +0 −4 Original line number Original line Diff line number Diff line Loading @@ -262,10 +262,6 @@ "polled_attr": [ "polled_attr": [ "healthstate", "healthstate", "1000", "1000", "adminmode", "1000", "state", "1000", "csppssadminmode", "csppssadminmode", "1000", "1000", "csppstadminmode", "csppstadminmode", Loading
csp-lmc-mid/tests/integration/MidCspMaster_test.py +13 −15 Original line number Original line Diff line number Diff line Loading @@ -14,7 +14,6 @@ import sys import os import os import time import time import logging import logging import unittest import numpy as np import numpy as np # Tango imports # Tango imports import tango import tango Loading @@ -40,7 +39,7 @@ LOGGER = logging.getLogger(__name__) # Device test case # Device test case @pytest.mark.usefixtures("midcsp_master", "midcsp_subarray01", "cbf_master") @pytest.mark.usefixtures("midcsp_master", "midcsp_subarray01", "cbf_master") class TestBase(unittest.TestCase): class TestBase(object): fixture_names = () fixture_names = () @pytest.fixture(autouse=True) @pytest.fixture(autouse=True) Loading Loading @@ -69,8 +68,7 @@ class TestCspMaster(TestBase): if state == DevState.STANDBY: if state == DevState.STANDBY: argin = ["mid_csp_cbf/sub_elt/master",] argin = ["mid_csp_cbf/sub_elt/master",] self.midcsp_master.On(argin) self.midcsp_master.On(argin) prober_state = Probe(self.midcsp_master, "State", DevState.ON, f"CSP Master not ON") state = self.midcsp_master.State() Poller(3, 0.1).check(prober_state) if state == DevState.ON: if state == DevState.ON: return return Loading @@ -79,8 +77,6 @@ class TestCspMaster(TestBase): Test for execution of On command when the CbfMaster is in the right state Test for execution of On command when the CbfMaster is in the right state """ """ self._setup_master() self._setup_master() prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.ON, f"CSPSubarray not ON") Poller(4, 0.2).check(prober_subarray_state) assert self.midcsp_subarray01.state() == DevState.ON assert self.midcsp_subarray01.state() == DevState.ON def test_Standby_valid_state(self): def test_Standby_valid_state(self): Loading @@ -91,24 +87,26 @@ class TestCspMaster(TestBase): assert self.midcsp_master.state() == DevState.ON assert self.midcsp_master.state() == DevState.ON argin = ["mid_csp_cbf/sub_elt/master",] argin = ["mid_csp_cbf/sub_elt/master",] self.midcsp_master.Standby(argin) self.midcsp_master.Standby(argin) prober_state = Probe(self.midcsp_master, "State", DevState.STANDBY, assert self.midcsp_master.state() == DevState.STANDBY f"CSP Master not STANDBY") Poller(4, 0.2).check(prober_state) def test_issue_Standby_AFTER_On_command(self): @pytest.mark.sequence @pytest.mark.parametrize('execution_number', range(3)) def test_sequence_ON_STABDBY_commands(self, execution_number): """ """ Issue the Standby command just after the On command, without waiting Issue the Standby command just after the On command, without waiting on the State value. on the State value. To solve SKB-26 bug, the power commands are now executed in To solve SKB-26 bug, the power commands are now executed in synch way. synch way. Repeat the test a number times = execution_number """ """ self._setup_master() self._setup_master() argin = ["mid_csp_cbf/sub_elt/master",] argin = ["mid_csp_cbf/sub_elt/master",] self.midcsp_master.On(argin) self.midcsp_master.Standby(argin) self.midcsp_master.Standby(argin) prober_state = Probe(self.midcsp_master, "State", DevState.STANDBY, assert self.midcsp_subarray01.state() == DevState.OFF f"CSP Master not STANDBY") assert self.midcsp_master.state() == DevState.STANDBY Poller(4, 0.2).check(prober_state) self.midcsp_master.On(argin) assert self.midcsp_subarray01.state() == DevState.ON assert self.midcsp_master.state() == DevState.ON ''' ''' def test_cspmaster_state_WHEN_adminmode_is_offline(self): def test_cspmaster_state_WHEN_adminmode_is_offline(self): Loading