Esempio n. 1
0
    def start(self, port, connection_timeout):
        """
        Run the maintenance service, accepts a connection. Starts a serial
        redirector when a connection is accepted.
        """
        LOGGER.info('Starting maintenance socket on port ' + str(port))
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.settimeout(connection_timeout)
        sock = System.get_ssl_socket(
            sock,
            private_key_filename=self._privatekey_filename,
            certificate_filename=self._certificate_filename)
        sock.bind(('', port))
        sock.listen(1)

        try:
            LOGGER.info('Waiting for maintenance connection.')
            connection, addr = sock.accept()
            self.handle_connection(connection, str(addr))
            LOGGER.info(
                'Maintenance session ended, closing maintenance socket')
            sock.close()
        except socket.timeout:
            LOGGER.info('Maintenance socket timed out, closing.')
            sock.close()
        except Exception:
            LOGGER.error('Error in maintenance service: %s\n',
                         traceback.format_exc())
            sock.close()
Esempio n. 2
0
    def _run_socket_server(self, port):
        connection_timeout = MaintenanceController.SOCKET_TIMEOUT
        logger.info('Starting maintenance socket on port %s', port)

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.settimeout(connection_timeout)
        sock = System.get_ssl_socket(
            sock,
            private_key_filename=self._privatekey_filename,
            certificate_filename=self._certificate_filename)
        sock.bind(('', port))
        sock.listen(1)

        try:
            logger.info('Waiting for maintenance connection.')
            self._connection, address = sock.accept()
            logger.info('Maintenance connection from %s', str(address))
            self._handle_connection()
            logger.info(
                'Maintenance session ended, closing maintenance socket')
            sock.close()
        except socket.timeout:
            logger.info('Maintenance socket timed out, closing.')
            sock.close()
        except Exception:
            logger.exception('Error in maintenance service')
            sock.close()
Esempio n. 3
0
    def writer(self):
        """ Reads from the socket and writes to the serial port. """
        while not self.__stopped:
            try:
                try:
                    data = self.__connection.recv(1024)
                    if not data:
                        LOGGER.info(
                            'Stopping maintenance mode due to no data.')
                        break
                    if data.startswith('exit'):
                        LOGGER.info('Stopping maintenance mode due to exit.')
                        break
                    self.__gateway_api.send_maintenance_data(data)
                except Exception as exception:
                    if System.handle_socket_exception(self.__connection,
                                                      exception, LOGGER):
                        continue
                    else:
                        break
            except:
                LOGGER.error('Exception in maintenance mode: %s\n',
                             traceback.format_exc())
                break

        self.__stopped = True
        self.__reader_thread.join()
Esempio n. 4
0
    def start(self, port, connection_timeout):
        """
        Run the maintenance service, accepts a connection. Starts a serial
        redirector when a connection is accepted.
        """
        LOGGER.info('Starting maintenance socket on port %s', port)
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.settimeout(connection_timeout)
        sock = System.get_ssl_socket(sock,
                                     private_key_filename=self._privatekey_filename,
                                     certificate_filename=self._certificate_filename)
        sock.bind(('', port))
        sock.listen(1)

        try:
            LOGGER.info('Waiting for maintenance connection.')
            connection, addr = sock.accept()
            self.handle_connection(connection, str(addr))
            LOGGER.info('Maintenance session ended, closing maintenance socket')
            sock.close()
        except socket.timeout:
            LOGGER.info('Maintenance socket timed out, closing.')
            sock.close()
        except Exception:
            LOGGER.error('Error in maintenance service: %s\n', traceback.format_exc())
            sock.close()
Esempio n. 5
0
class VpnController(object):
    """ Contains methods to check the vpn status, start and stop the vpn. """

    vpn_service = System.get_vpn_service()
    start_cmd = "systemctl start " + vpn_service + " > /dev/null"
    stop_cmd = "systemctl stop " + vpn_service + " > /dev/null"
    check_cmd = "systemctl is-active " + vpn_service + " > /dev/null"

    def __init__(self):
        self.vpn_connected = False
        t_vpn_connected = Thread(target=self._vpn_connected)
        t_vpn_connected.daemon = True
        t_vpn_connected.start()

    @staticmethod
    def start_vpn():
        """ Start openvpn """
        logger.info('Starting VPN')
        return subprocess.call(VpnController.start_cmd, shell=True) == 0

    @staticmethod
    def stop_vpn():
        """ Stop openvpn """
        logger.info('Stopping VPN')
        return subprocess.call(VpnController.stop_cmd, shell=True) == 0

    @staticmethod
    def check_vpn():
        """ Check if openvpn is running """
        return subprocess.call(VpnController.check_cmd, shell=True) == 0

    def _vpn_connected(self):
        """ Checks if the VPN tunnel is connected """
        while True:
            try:
                routes = subprocess.check_output(
                    'ip r | grep tun | grep via || true', shell=True).strip()
                # example output:
                # 10.0.0.0/24 via 10.37.0.5 dev tun0\n
                # 10.37.0.1 via 10.37.0.5 dev tun0
                result = False
                if routes:
                    vpn_servers = [
                        route.split(' ')[0] for route in routes.split('\n')
                        if '/' not in route
                    ]
                    for vpn_server in vpn_servers:
                        if VPNService.ping(vpn_server, verbose=False):
                            result = True
                            break
                self.vpn_connected = result
            except Exception as ex:
                logger.info(
                    'Exception occured during vpn connectivity test: {0}'.
                    format(ex))
                self.vpn_connected = False
            time.sleep(5)
Esempio n. 6
0
    def setup_logger(log_level=logging.INFO, enable_update_logging=False):
        """
        Setup the OpenMotics logger.
        :param log_level: Sets the main log level for OpenMotics logging to the default StreamHandler/SysLogHandler
        :param enable_update_logging: Enables logging to the `update_log` file. This will always log in DEBUG
        """

        import constants
        from platform_utils import System

        # Remove all log handlers (since python2 `defaultConfig` has no `force` flag)
        root_logger = logging.getLogger()
        while root_logger.handlers:
            root_logger.removeHandler(root_logger.handlers[0])

        # Setup basic stream handler
        logging.basicConfig(format=Logs.LOG_FORMAT, level=logging.INFO)
        openmotics_log_level = log_level

        # Alter some system loggers
        requests_logger = logging.getLogger(
            'requests.packages.urllib3.connectionpool')
        requests_logger.setLevel(logging.WARNING)

        update_handler = None
        if enable_update_logging:
            update_handler = handlers.RotatingFileHandler(
                constants.get_update_log_location(),
                maxBytes=3 * 1024**2,
                backupCount=2)
            update_handler.setLevel(logging.DEBUG)
            update_handler.setFormatter(logging.Formatter(Logs.LOG_FORMAT))
            openmotics_log_level = min(log_level, logging.DEBUG)

        syslog_handler = None
        if System.get_operating_system().get('ID') == System.OS.BUILDROOT:
            syslog_handler = handlers.SysLogHandler(address='/dev/log')
            syslog_handler.setLevel(log_level)
            syslog_handler.setFormatter(logging.Formatter(Logs.LOG_FORMAT))

        for logger_namespace in ['openmotics', 'gateway']:
            _logger = logging.getLogger(logger_namespace)
            _logger.setLevel(openmotics_log_level)
            _logger.propagate = True

            for extra_handler in [update_handler, syslog_handler]:
                # Add extra handlers, where available
                if extra_handler is not None:
                    _logger.addHandler(extra_handler)
Esempio n. 7
0
def setup_logger():
    """ Setup the OpenMotics logger. """

    logger.setLevel(logging.INFO)
    logger.propagate = False

    handler = logging.StreamHandler()
    handler.setLevel(logging.INFO)
    handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
    logger.addHandler(handler)

    if System.get_operating_system().get('ID') == System.OS.BUILDROOT:
        syslog_handler = logging.handlers.SysLogHandler(address='/dev/log')
        syslog_handler.setLevel(logging.INFO)
        syslog_handler.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
        logger.addHandler(syslog_handler)
Esempio n. 8
0
    def _handle_connection(self):
        """
        Handles one incoming connection.
        """
        try:
            self._connection.settimeout(1)
            self._connection.sendall(
                'Activating maintenance mode, waiting for other actions to complete ...\n'
            )
            self._activate()
            self._connection.sendall('Connected\n')
            while self._maintenance_communicator.is_active():
                try:
                    try:
                        data = self._connection.recv(1024)
                        if not data:
                            logger.info(
                                'Stopping maintenance mode due to no data.')
                            break
                        if data.startswith('exit'):
                            logger.info(
                                'Stopping maintenance mode due to exit.')
                            break

                        self._maintenance_communicator.write(data)
                    except Exception as exception:
                        if System.handle_socket_exception(
                                self._connection, exception, logger):
                            continue
                        else:
                            logger.exception(
                                'Unexpected exception receiving connection data'
                            )
                            break
                except Exception:
                    logger.exception('Exception in maintenance mode')
                    break
        except InMaintenanceModeException:
            self._connection.sendall('Maintenance mode already active.\n')
        finally:
            self._deactivate()
            logger.info('Maintenance mode deactivated')
            self._connection.close()
            self._connection = None
Esempio n. 9
0
def update_gateway_backend(tarball, date, version):
    try:
        backup_dir = os.path.join(PREFIX, 'backup')
        python_dir = os.path.join(PREFIX, 'python')
        etc_dir = os.path.join(PREFIX, 'etc')
        cmd(['mkdir', '-p', backup_dir])


        # TODO: symlink, blue green deployment
        cmd(['mkdir', '-p', os.path.join(backup_dir, date)])
        cmd(['mkdir', '-p', os.path.join(backup_dir, date, 'hex')])
        cmd(['mv', python_dir, os.path.join(backup_dir, date)])
        cmd(['cp', '-r', etc_dir, os.path.join(backup_dir, date)])
        cmd('cp {0} {1} || true'.format(os.path.join(PREFIX, '*.hex'), os.path.join(backup_dir, date, 'hex')), shell=True)  # Add the '|| true' to the end of the command to be sure it exits with exit code 0!

        # Cleanup for old versions.
        old_dist_dir = os.path.join(PREFIX, 'dist-packages')
        if os.path.exists(old_dist_dir):
            cmd(['mv', old_dist_dir, os.path.join(backup_dir, date)])

        logger.info('Extracting gateway')
        cmd(['mkdir', '-p', python_dir])
        run_tarball_extract(tarball, python_dir)
        cmd(['sync'])

        plugins = glob.glob('{}/{}/python/plugins/*/'.format(backup_dir, date))
        if plugins:
            logger.info('Restoring plugins')
            for plugin in plugins:
                cmd(['cp', '-r', plugin, os.path.join(python_dir, 'plugins')])

        logger.info('Running post-update')

        system_os = System.get_operating_system().get('ID')
        if system_os != System.OS.BUILDROOT:
            cmd(['bash', os.path.join(python_dir, 'post-update.sh')])
        cmd(['sync'])
    except Exception as exc:
        logger.exception('Updating Gateway service failed')
        return exc
Esempio n. 10
0
    def test_get_ip_address(self):
        expected_ip_address = "192.168.0.126"

        platform_specifics = {
            'ANGSTROM': {
                'operating_system': {
                    'ID': 'angstrom'
                },
                'ifconfig_output': ANGSTROM_IFCONFIG_OUTPUT
            },
            'DEBIAN': {
                'operating_system': {
                    'ID': 'debian'
                },
                'ifconfig_output': DEBIAN_IFCONFIG_OUTPUT
            }
        }
        for platform, details in platform_specifics.items():
            with mock.patch.object(subprocess, 'check_output', return_value=details['ifconfig_output']),\
                 mock.patch.object(System, 'get_operating_system', return_value=details['operating_system']):
                ip_address = System.get_ip_address()
                self.assertEqual(expected_ip_address, ip_address)
Esempio n. 11
0
class VpnController(object):
    """ Contains methods to check the vpn status, start and stop the vpn. """

    vpn_service = System.get_vpn_service()
    start_cmd = "systemctl start " + vpn_service + " > /dev/null"
    stop_cmd = "systemctl stop " + vpn_service + " > /dev/null"
    check_cmd = "systemctl is-active " + vpn_service + " > /dev/null"

    def __init__(self):
        pass

    @staticmethod
    def start_vpn():
        """ Start openvpn """
        return subprocess.call(VpnController.start_cmd, shell=True) == 0

    @staticmethod
    def stop_vpn():
        """ Stop openvpn """
        return subprocess.call(VpnController.stop_cmd, shell=True) == 0

    @staticmethod
    def check_vpn():
        """ Check if openvpn is running """
        return subprocess.call(VpnController.check_cmd, shell=True) == 0

    @staticmethod
    def vpn_connected():
        """ Checks if the VPN tunnel is connected """
        try:
            route = subprocess.check_output('ip r | grep tun | grep via || true', shell=True).strip()
            if not route:
                return False
            vpn_server = route.split(' ')[0]
            return ping(vpn_server)
        except Exception as ex:
            LOGGER.log('Exception occured during vpn connectivity test: {0}'.format(ex))
            return False
Esempio n. 12
0
    def writer(self):
        """ Reads from the socket and writes to the serial port. """
        while not self.__stopped:
            try:
                try:
                    data = self.__connection.recv(1024)
                    if not data:
                        LOGGER.info('Stopping maintenance mode due to no data.')
                        break
                    if data.startswith('exit'):
                        LOGGER.info('Stopping maintenance mode due to exit.')
                        break
                    self.__gateway_api.send_maintenance_data(data)
                except Exception as exception:
                    if System.handle_socket_exception(self.__connection, exception, LOGGER):
                        continue
                    else:
                        break
            except Exception:
                LOGGER.error('Exception in maintenance mode: %s\n', traceback.format_exc())
                break

        self.__stopped = True
        self.__reader_thread.join()
Esempio n. 13
0
    def start(
                master_controller=INJECTED,  # type: MasterController
                maintenance_controller=INJECTED,  # type: MaintenanceController
                power_communicator=INJECTED,  # type: PowerCommunicator
                power_serial=INJECTED,  # type: RS485
                metrics_controller=INJECTED,  # type: MetricsController
                passthrough_service=INJECTED,  # type: PassthroughService
                scheduling_controller=INJECTED,  # type: SchedulingController
                metrics_collector=INJECTED,  # type: MetricsCollector
                web_service=INJECTED,  # type: WebService
                web_interface=INJECTED,  # type: WebInterface
                watchdog=INJECTED,  # type: Watchdog
                plugin_controller=INJECTED,  # type: PluginController
                event_sender=INJECTED,  # type: EventSender
                thermostat_controller=INJECTED,  # type: ThermostatController
                output_controller=INJECTED,  # type: OutputController
                input_controller=INJECTED,  # type: InputController
                pulse_counter_controller=INJECTED,  # type: PulseCounterController
                sensor_controller=INJECTED,  # type: SensorController
                shutter_controller=INJECTED,  # type: ShutterController
                group_action_controller=INJECTED,  # type: GroupActionController
                frontpanel_controller=INJECTED,  # type: FrontpanelController
                module_controller=INJECTED,  # type: ModuleController
                user_controller=INJECTED,  # type: UserController
                ventilation_controller=INJECTED,  # type: VentilationController
                pubsub=INJECTED  # type: PubSub
    ):
        """ Main function. """
        logger.info('Starting OM core service...')

        # MasterController should be running
        master_controller.start()

        # Sync ORM with sources of thruth
        output_controller.run_sync_orm()
        input_controller.run_sync_orm()
        pulse_counter_controller.run_sync_orm()
        sensor_controller.run_sync_orm()
        shutter_controller.run_sync_orm()

        # Execute data migration(s)
        # TODO: Make the master communication work before executing the migrations (needs eeprom use or other)
        if not System.get_operating_system().get('ID') == System.OS.BUILDROOT:
            FeatureMigrator.migrate()
            RoomsMigrator.migrate()
            InputMigrator.migrate()
            ScheduleMigrator.migrate()
            UserMigrator.migrate()
            ConfigMigrator.migrate()

        # Start rest of the stack
        maintenance_controller.start()
        if power_communicator:
            power_serial.start()
            power_communicator.start()
        metrics_controller.start()
        if passthrough_service:
            passthrough_service.start()
        scheduling_controller.start()
        user_controller.start()
        module_controller.start()
        thermostat_controller.start()
        ventilation_controller.start()
        metrics_collector.start()
        web_service.start()
        if frontpanel_controller:
            frontpanel_controller.start()
        event_sender.start()
        watchdog.start()
        plugin_controller.start()
        output_controller.start()
        input_controller.start()
        pulse_counter_controller.start()
        sensor_controller.start()
        shutter_controller.start()
        group_action_controller.start()
        pubsub.start()

        web_interface.set_service_state(True)
        signal_request = {'stop': False}

        def stop(signum, frame):
            """ This function is called on SIGTERM. """
            _ = signum, frame
            logger.info('Stopping OM core service...')
            watchdog.stop()
            output_controller.stop()
            input_controller.stop()
            pulse_counter_controller.stop()
            sensor_controller.stop()
            shutter_controller.stop()
            group_action_controller.stop()
            web_service.stop()
            if power_communicator:
                power_communicator.stop()
            master_controller.stop()
            maintenance_controller.stop()
            metrics_collector.stop()
            metrics_controller.stop()
            user_controller.stop()
            ventilation_controller.start()
            thermostat_controller.stop()
            plugin_controller.stop()
            if frontpanel_controller:
                frontpanel_controller.stop()
            event_sender.stop()
            pubsub.stop()
            logger.info('Stopping OM core service... Done')
            signal_request['stop'] = True

        try:
            import prctl
            prctl.set_name('omservice')
        except ImportError:
            pass

        signal(SIGTERM, stop)
        logger.info('Starting OM core service... Done')
        while not signal_request['stop']:
            time.sleep(1)
Esempio n. 14
0
 def get_local_ip_address(self):
     """ Get the local ip address. """
     _ = self  # Needs to be an instance method
     return System.get_ip_address()
Esempio n. 15
0
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
Tool to bootload the slave modules (output, dimmer, input and temperature).

@author: fryckbos
"""

import argparse
from ConfigParser import ConfigParser
from serial import Serial

from platform_utils import System
System.import_eggs()

import constants
import master.master_api as master_api
from master.master_communicator import MasterCommunicator
from master.eeprom_controller import EepromFile, EepromAddress

import intelhex
import time
import sys
import traceback


def create_bl_action(cmd, input):
    """ Create a bootload action, this uses the command and the inputs
    to calculate the crc for the action, the crc is added to input.
Esempio n. 16
0
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
The main module for the OpenMotics
"""
from __future__ import absolute_import

from platform_utils import System
System.import_libs()

import constants
import logging
import logging.handlers
import time
from signal import SIGTERM, signal

from bus.om_bus_client import MessageClient
from bus.om_bus_service import MessageService
from gateway.initialize import initialize
from gateway.migrations.rooms import RoomsMigrator
from gateway.migrations.features_data_migrations import FeatureMigrator
from gateway.migrations.inputs import InputMigrator
from gateway.migrations.schedules import ScheduleMigrator
from gateway.migrations.users import UserMigrator
Esempio n. 17
0
def start_services():
    for service in SUPERVISOR_SERVICES:
        try:
            cmd_wait_output(System.run_service_action('start', service))
        except Exception:
            logger.warning('Starting {} failed'.format(service))
Esempio n. 18
0
 def _restart():
     # type: () -> None
     logger.info('Restarting for factory reset...')
     System.restart_service('openmotics')
Esempio n. 19
0
def stop_services():
    for service in SUPERVISOR_SERVICES:
        proc = System.run_service_action('stop', service)
        proc.wait()
Esempio n. 20
0
def check_services():
    for service in SUPERVISOR_SERVICES:
        status_output, _ = cmd_wait_output(System.run_service_action('status', service))
        if 'no such process' in status_output.decode('utf-8').lower():
            raise Exception('Could not find service "{}"'.format(service))
Esempio n. 21
0
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
The vpn_service asks the OpenMotics cloud it a vpn tunnel should be opened. It starts openvpn
if required. On each check the vpn_service sends some status information about the outputs and
thermostats to the cloud, to keep the status information in the cloud in sync.
"""

from platform_utils import System
System.import_eggs()

import os
import glob
import gobject
import sys
import requests
import time
import subprocess
import traceback
import constants
import threading

from collections import deque
from ConfigParser import ConfigParser
from datetime import datetime
Esempio n. 22
0
 def get_local_ip_address(self):
     """ Get the local ip address. """
     _ = self  # Needs to be an instance method
     return System.get_ip_address()
Esempio n. 23
0
class VpnController(object):
    """ Contains methods to check the vpn status, start and stop the vpn. """
    if System.get_operating_system().get('ID') == System.OS.BUILDROOT:
        vpn_binary = 'openvpn'
        config_location = '/etc/openvpn/client/'
        start_cmd = 'cd {} ; {} --suppress-timestamps --nobind --config vpn.conf > /dev/null'.format(
            config_location, vpn_binary)
        stop_cmd = 'killall {} > /dev/null'.format(vpn_binary)
        check_cmd = 'ps -a | grep {} | grep -v "grep" > /dev/null'.format(
            vpn_binary)
    else:
        vpn_service = System.get_vpn_service()
        start_cmd = 'systemctl start {0} > /dev/null'.format(vpn_service)
        stop_cmd = 'systemctl stop {0} > /dev/null'.format(vpn_service)
        check_cmd = 'systemctl is-active {0} > /dev/null'.format(vpn_service)

    def __init__(self):
        self.vpn_connected = False
        self._vpn_tester = DaemonThread(name='vpnctl',
                                        target=self._vpn_connected,
                                        interval=5)

    def start(self):
        self._vpn_tester.start()

    @staticmethod
    def start_vpn():
        """ Start openvpn """
        logger.info('Starting VPN')
        return subprocess.call(VpnController.start_cmd, shell=True) == 0

    @staticmethod
    def stop_vpn():
        """ Stop openvpn """
        logger.info('Stopping VPN')
        return subprocess.call(VpnController.stop_cmd, shell=True) == 0

    @staticmethod
    def check_vpn():
        """ Check if openvpn is running """
        return subprocess.call(VpnController.check_cmd, shell=True) == 0

    def _vpn_connected(self):
        """ Checks if the VPN tunnel is connected """
        try:
            routes = subprocess.check_output(
                'ip r | grep tun | grep via || true', shell=True).strip()
            # example output:
            # 10.0.0.0/24 via 10.37.0.5 dev tun0\n
            # 10.37.0.1 via 10.37.0.5 dev tun0
            result = False
            if routes:
                if not isinstance(
                        routes, str):  # to ensure python 2 and 3 compatibility
                    routes = routes.decode()

                vpn_servers = [
                    route.split(' ')[0] for route in routes.split('\n')
                    if '/' not in route
                ]
                for vpn_server in vpn_servers:
                    if TaskExecutor._ping(vpn_server, verbose=False):
                        result = True
                        break
            self.vpn_connected = result
        except Exception as ex:
            logger.info(
                'Exception occured during vpn connectivity test: {0}'.format(
                    ex))
            self.vpn_connected = False