Пример #1
0
 def add_check_task(check, task):
     if not FirstTimeRun._validate_check_task(check):
         LOG.warning(_("Check %s was not of type method") % check)
         return
     if not FirstTimeRun._validate_check_task(task):
         LOG.warning(_("Task %s was not of type method") % task)
         return
     FirstTimeRun._check_tasks.append(FirstTimeRun.CheckTask(check, task))
Пример #2
0
    def _run_tasks(self):
        """Will try to execute all calls from the internal list"""

        for task in self._tasks:
            try:
                task()
                LOG.info(_("Ran task: %s") % task)
            except Exception as e:
                LOG.error(
                    _("Encountered error during first time"
                      "initialization with task: %s") % e)
Пример #3
0
    def _verify_transitions(self):
        """Iterate the TRANSITIONS dictionary and validate its completeness"""

        for t in self._sclass:
            if t not in self.transitions:
                raise RuntimeError(
                    _("Not all states have required valid transition set"))
            for s in self.transitions[t]:
                if not isinstance(s, self._sclass):
                    raise RuntimeError(_("Not all members of transition set "
                                         "are of same type as state"))
Пример #4
0
    def test_translate_nl(self, m_environ, m_languages_get):
        m_languages_get.return_value = None
        m_environ.get.side_effect = [
            'nl', 'nl', 'nl', 'nl', 'radloggerpy/locale'
        ]

        m_translated_nl = _i18n._("RadLoggerPy opstarten met PID %s")
        m_untranslated = _i18n._("Starting RadLoggerPy service on PID %s")

        self.assertEqual(m_translated_nl,
                         _i18n.translate(m_untranslated, 'nl_NL'))
Пример #5
0
def create_database():
    """Create the database using sqlalchemy, used for first time init """
    file = CONF.database.filename

    try:
        LOG.info(_("Creating database"))
        engine = create_engine(file)
        LOG.info(_("Creating database tables"))
        cd.create_database_tables(engine)
    except Exception as e:
        LOG.error(_("Failed to create database due to error: %s") % e)
        raise e
Пример #6
0
    def _run_checks(self, all_to_init=False):
        """Run all checks from the internal list

        :param all_to_init: True if all checks are required to init False if
                            one check is sufficient
        :return: True if first time init should be run False otherwise
        """

        # store return values for all checks
        values = list()

        for check in self._checks:
            try:
                values.append(check())
            except Exception as e:
                LOG.error(
                    _("Encountered error while performing check for"
                      "first time init: %s") % e)

        has_true = False
        for v in values:
            if v:
                has_true = True
            if v and not all_to_init:
                return True
            elif not v and all_to_init:
                return False
        return has_true
Пример #7
0
def main():
    configurator.setup_config_and_logging(sys.argv, CONF)

    # Display logo's
    LOG.info(ascii_logo.TEXT + ascii_logo.LOGO)

    # Display pid
    LOG.info(_('Starting RadLoggerPy service on PID %s') % os.getpid())

    # Perform first time initialization if required
    FirstTimeRun()

    # Create database session for main thread
    sess = database_manager.create_session()

    # launch device manager
    manager = DeviceManager()

    devices = SerialDeviceObject.find_enabled(sess)
    for device in devices:
        manager.launch_device(device)

    # TODO(Dantali0n): Improve state checking and error handling
    while True:
        manager.check_devices()
        time.sleep(30)

    # close all database sessions that are still left open
    database_manager.close_lingering_sessions()
Пример #8
0
    def add_readings(self, readings):
        """Add the readings to the buffer

        Add all the readings to the buffer and remove any elements not of type
        :py:class: '~.RadiationReading'.

        :param readings: The readings to be added to the data buffer
        :type readings: List of :py:class: '~.RadiationReading' instances
        :return: True if the elements were successfully added False otherwise
        """

        for e in readings:
            if not isinstance(e, RadiationReading):
                LOG.error(
                    _("Element: %s, is not of type "
                      "RadiationReading") % e)
                readings.remove(e)

        lock = self.rwlock.gen_rlock()
        try:
            if lock.acquire():
                self.data.extend(readings)
                self.has_reading = True
                with self.condition:
                    self.condition.notify()
                return True
        finally:
            lock.release()

        return False
Пример #9
0
    def take_action(self, parsed_args):
        args = dict(parsed_args._get_kwargs())

        if 'device' in args or 'name' in args:
            """Set device for MeasurementObject if any device params are set"""
            dev_obj = DeviceObject()
            if args['device']:
                dev_obj.id = args['device']
                del args['device']
            if args['name']:
                dev_obj.name = args['name']
                del args['name']
            args['device'] = dev_obj

        measure_obj = MeasurementObject(**args)

        data = MeasurementObject.find(self.app.database_session, measure_obj,
                                      True)

        if len(data) == 0:
            raise RuntimeWarning(_("No measurements found"))

        fields = ('timestamp', 'device', 'cpm', 'μSv/h')
        values = []
        for result in data:
            value = (result.timestamp, result.device.id, result.cpm,
                     result.svh)
            values.append(value)

        return [fields, values]
Пример #10
0
    def __init__(self):
        """Run all checks and if required all initialization tasks"""

        if self._run_checks():
            LOG.info(_("Performing first time initialization"))
            self._run_tasks()

        self._run_check_tasks()
Пример #11
0
    def transition(self, state: enum.Enum):
        """Transition from the current state to a new desired state

        :param state: The new desired state
        :raises RuntimeWarning: This warning is raised when the new desired
                state requires an illegal transition
        """

        if not isinstance(state, self._sclass):
            raise RuntimeWarning(
                _("State is not of same type as POSSIBLE_STATES"))

        if state in self.transitions[self._state]:
            self._state = state
        else:
            raise RuntimeWarning(
                _("Transition from %(initial)s to %(to)s state is not valid") %
                {'initial': self._state, 'to': state})
Пример #12
0
 def _init(self):
     self.stop = False
     parity = PARITY_CHOICES_R[self.info.parity].value
     try:
         self.serial = serial.Serial(port=self.info.port,
                                     baudrate=self.info.baudrate,
                                     parity=parity,
                                     stopbits=self.info.stopbits,
                                     bytesize=self.info.bytesize)
     except serial.serialutil.SerialException as e:
         if e.errno == errno.EACCES:
             LOG.critical(_("Insufficient permissions " "to open device."))
             raise DeviceException
         elif e.errno == errno.ENOENT:
             LOG.critical(_("Device does not exist"))
             raise DeviceException
         else:
             LOG.critical(_("Device error %d") % e.errno)
             raise DeviceException
Пример #13
0
 def _run_check_tasks(self):
     """Run each of the checks and tasks as a pair"""
     for check_task in self._check_tasks:
         try:
             if check_task.check():
                 check_task.task()
         except Exception as e:
             LOG.error(
                 _("Encountered error during execution of "
                   "CheckTask: %s") % e)
Пример #14
0
    def initialize_app(self, argv):
        # update configuration (sets CONF.version amongst others)
        parse_args(argv=())

        # Display logo
        self.LOG.info(ascii_logo.TEXT + ascii_logo.LOGO)

        # Perform first time initialization if required
        FirstTimeRun()

        # Display version
        self.LOG.info(_('Initializing radloggercli %s') % CONF.version)
Пример #15
0
    def set_cpm(self, cpm):
        """Set the counts per minute to the new value

        :param cpm: Counts per minute
        :type cpm: int
        """

        if cpm < 0:
            LOG.warning(_("RadiationReading can not have negative cpm"))
            return

        self._cpm = cpm
Пример #16
0
    def take_action(self, parsed_args):
        args = dict(parsed_args._get_kwargs())
        device_obj = SerialDeviceObject(**args)

        try:
            data = SerialDeviceObject.find(self.app.database_session,
                                           device_obj, False)
        except MultipleResultsFound:
            raise RuntimeWarning(_("Multiple devices found"))

        if data is None:
            raise RuntimeWarning(_("Device could not be found"))

        fields = ('id', 'name', 'measurement type', 'interface',
                  'implementation', 'port', 'baudrate', 'bytesize', 'parity',
                  'stopbits', 'timeout')
        values = (data.id, data.name, data.type, data.interface,
                  data.implementation, data.port, data.baudrate, data.bytesize,
                  data.parity, data.stopbits, data.timeout)

        return (fields, values)
Пример #17
0
def check_database_missing():
    """Check if the database is missing, used for first time init

    :return: True if the database does not exist False if it does
    """
    file = CONF.database.filename

    LOG.info(_("Checking if database: %s exists") % file)

    if not os.path.isfile(file):
        LOG.warning(_("Database file does not exist in configured path"))
        return True

    try:
        engine = create_engine(file)
        if not database_exists(engine.url):
            return True
    except Exception as e:
        LOG.warning(e)
        return True

    return False
Пример #18
0
    def __init__(self, transitions: _U, states: enum.Enum = None):

        if states and isinstance(states, enum.Enum):
            self.POSSIBLE_STATES = states
        elif not isinstance(self.POSSIBLE_STATES, enum.Enum):
            raise RuntimeError(_("Neither POSSIBLE_STATES nor states are of"
                                 "type Enum"))

        self._sclass = self.POSSIBLE_STATES.__class__

        self.transitions = transitions
        self._verify_transitions()

        self.reset_state()
Пример #19
0
    def take_action(self, parsed_args):
        args = dict(parsed_args._get_kwargs())
        device_obj = DeviceObject(**args)

        if device_obj.id is None and device_obj.name is None:
            raise RuntimeWarning(
                _("Either the id or name must be specified to "
                  "remove a device"))

        try:
            data = DeviceObject.delete(self.app.database_session, device_obj,
                                       False)
        except MultipleResultsFound:
            raise RuntimeWarning(_("Multiple devices found"))

        if data is None:
            raise RuntimeWarning(_("Device could not be found"))

        fields = ('id', 'name', 'interface', 'implementation')
        values = (data.id, data.name, data.interface, data.implementation)

        self.app.LOG.info(_("Device removed successfully"))
        return (fields, values)
Пример #20
0
    def run(self):
        """Entry point for devices to initialize and start running

        Serves as the entry point for devices and calls _init and _run. In
        addition handles any required state transitions

        Any exception encountered will be raised so DeviceManager can handle it
        appropriately.
        """

        if self._statemachine.get_state() is DeviceStates.ERROR:
            "Recover device from error state"
            LOG.info(_("Restarting {} device of implementation {} from "
                       "previous error state.")
                     .format(self.info.name, self.info.implementation))
            self._statemachine.reset_state()
        elif self._statemachine.get_state() is not DeviceStates.STOPPED:
            "Not logging a message here, DeviceManager can easily do that"
            raise RuntimeError(_("Can not start same device {} multiple times")
                               .format(self.info.name))

        try:
            self._statemachine.transition(DeviceStates.INITIALIZING)
            self._init()
        except Exception:
            self._statemachine.transition(DeviceStates.ERROR)
            raise

        try:
            self._statemachine.transition(DeviceStates.RUNNING)
            self._run()
        except Exception:
            self._statemachine.transition(DeviceStates.ERROR)
            raise

        if self._statemachine.get_state() is DeviceStates.RUNNING:
            self._statemachine.transition(DeviceStates.STOPPED)
Пример #21
0
def create_session():
    """Create a session using the appropriate configuration

    :return: Returns an sqlalchemy session or None if a error occurred
    :rtype: Instance of :py:class: 'orm.Session'
    """
    file = CONF.database.filename

    try:
        sess = orm.sessionmaker(bind=create_engine(file))
        return sess()
    except Exception as e:
        LOG.error(_("Failed to create session due to exception: %s") % e)

    return None
Пример #22
0
    def take_action(self, parsed_args):
        args = dict(parsed_args._get_kwargs())
        device_obj = DeviceObject(**args)

        details = args['detailed']

        try:
            data = DeviceObject.find(
                self.app.database_session, device_obj, False)
        except MultipleResultsFound:
            raise RuntimeWarning(_("Multiple devices found"))

        if data is None:
            raise RuntimeWarning(_("Device could not be found"))

        fields = (
            'id', 'name', 'measurement type', 'interface', 'implementation')
        values = (
            data.id, data.name, data.type, data.interface, data.implementation)

        if details and data.interface == \
                INTERFACE_CHOICES[DeviceInterfaces.SERIAL]:
            data = SerialDeviceObject.find(
                self.app.database_session, device_obj, False)
            fields += ('port', 'baudrate', 'bytesize', 'parity',
                       'stopbits', 'timeout')
            values += (data.port, data.baudrate, data.bytesize, data.parity,
                       data.stopbits, data.timeout)
        elif details and data.interface == \
                INTERFACE_CHOICES[DeviceInterfaces.ETHERNET]:
            pass
        elif details and data.interface == \
                INTERFACE_CHOICES[DeviceInterfaces.USB]:
            pass

        return (fields, values)
Пример #23
0
    def get_data(self):
        """Return a collection of radiation monitoring data if any is available

        Retrieves the currently stored collection of radiation monitoring data
        and subsequently clears it.

        :return: Collection of RadiationReading objects
        :rtype: List of :py:class: '~.RadiationReading' instances
        """
        got_data = self.data.fetch_clear_readings()
        if got_data:
            return got_data
        else:
            LOG.error(_("Unable to retrieve data for: %s") % self.NAME)
            return []
Пример #24
0
    def __init__(self):
        num_workers = CONF.devices.concurrent_worker_amount

        if num_workers is -1:
            num_workers = multiprocessing.cpu_count()
            LOG.info(
                _("Configured device manager for %d workers") % num_workers)

        self._condition = Condition()

        self._mng_devices = []
        "List of ManagedDevice devices see :py:class:`ManagedDevice`"
        self._threadpool = futurist.ThreadPoolExecutor(max_workers=num_workers)
        # self._threadpool = futurist.GreenThreadPoolExecutor(
        #    max_workers=num_workers)

        self.get_device_map()
Пример #25
0
    def _filter(filter_object, ignore=[]):
        """Filters the object depending on it's set attributes

        Removes certain empty objects such as empty collections but not empty
        strings or byte arrays.
        """

        if ignore:
            LOG.warning(
                _("Use of deprecated ignore parameter on database "
                  "object filter!"))

        return {
            key: name
            for (key, name) in vars(filter_object).items()
            if hasattr(filter_object.__class__, key) and (
                key not in ignore or (seq_but_not_str(key and key)))
        }
Пример #26
0
    def take_action(self, parsed_args):
        args = dict(parsed_args._get_kwargs())
        device_obj = DeviceObject(**args)

        data = DeviceObject.find(self.app.database_session, device_obj, True)

        if len(data) == 0:
            raise RuntimeWarning(_("No devices found"))

        fields = ('id', 'name', 'measurement type', 'interface',
                  'implementation')
        values = []
        for result in data:
            value = (result.id, result.name, result.type, result.interface,
                     result.implementation)
            values.append(value)

        return [fields, values]
Пример #27
0
    def find(session, reference, allow_multiple=True):
        reference._build_object()

        """Only look for serial devices"""
        reference.m_device.interface = DeviceInterfaces.SERIAL

        base_filters = reference._filter(reference.m_device)

        """Check if reference is base or child type when setting filters"""
        if hasattr(reference, 'm_serial_device'):
            filters = reference._filter(reference.m_serial_device)
        else:
            LOG.warning(_("Reference should be of type SerialDeviceObject"))
            filters = {}

        query = session.query(Device).filter_by(**base_filters)\
            .join(SerialDevice).filter_by(**filters)

        if allow_multiple:
            results = query.all()

            if results is None:
                return None

            ret_results = list()
            for result in results:
                dev = SerialDeviceObject()
                dev.m_device = result
                dev.m_serial_device = result.serial[0]
                dev._build_attributes()
                ret_results.append(dev)

            return ret_results
        else:
            result = query.one_or_none()

            if result is None:
                return None

            dev = SerialDeviceObject()
            dev.m_device = result
            dev.m_serial_device = result.serial[0]
            dev._build_attributes()
            return dev
Пример #28
0
    def take_action(self, parsed_args):
        args = dict(parsed_args._get_kwargs())
        device_obj = SerialDeviceObject(**args)

        data = SerialDeviceObject.find(
            self.app.database_session, device_obj, True)

        if len(data) == 0:
            raise RuntimeWarning(_("No devices found"))

        fields = (
            'id', 'name', 'measurement type', 'interface', 'implementation',
            'port', 'baudrate', 'bytesize', 'parity', 'stopbits', 'timeout')
        values = []
        for result in data:
            value = (result.id, result.name, result.type, result.interface,
                     result.implementation, result.port, result.baudrate,
                     result.bytesize, result.parity, result.stopbits,
                     result.timeout)
            values.append(value)

        return [fields, values]
Пример #29
0
    def add(session, reference):
        reference._build_object()
        """Measurement.device_id must be set to populate the field"""
        if reference.m_measurement.device_id is None \
                and hasattr(reference.device, 'id') and reference.device.id:
            """If no device_id is set find it through device id"""
            reference.m_measurement.device_id = reference.device.id
        elif reference.m_measurement.device_id is None and reference.device:
            """If no device_id find it through device"""
            dev = DeviceObject.find(session, reference.device, False)
            if dev is None:
                raise RuntimeError(_("No associateable Device found"))
            reference.m_measurement.device_id = dev.id

        session.add(reference.m_measurement)

        try:
            return session.commit()
        except Exception:
            session.rollback()
            # TODO(Dantali0n): These errors are horrendous for users to
            #                  understand an error abstraction is needed.
            raise
Пример #30
0
    def check_devices(self):
        """Check the status of the devices and handle failures

        TODO(Dantali0n): This method should use the get_state method of devices
                         instead of relying on the futures to much.
        """

        removals = []
        for mng_device in self._mng_devices:
            future_exception = mng_device.future.exception()

            if type(future_exception) is not DeviceException:
                LOG.error(_("Unhandled Exception"))

            if mng_device.future.done() and CONF.devices.restart_on_error:
                mng_device.future =\
                    self._threadpool.submit(mng_device.device.run)
            elif mng_device.future.done():
                removals.append(mng_device)

        "Clean up the managed devices that have run to completion"
        for device in removals:
            self._mng_devices.remove(device)