def run(self):
     tries = config.config()['log_synchronization']['tries']
     period = 60*config.config()['log_synchronization']['period']
     server_ip = config.config()['network']['server_ip']
     server_port = config.config()['network']['server_port']
     while True:
         try:
             with db.manager().transaction():
                 log.logger().info('Sending log to server...')
                 _log = proto.man_message()
                 _log.message_type = 'log'
                 db.manager().get_log(_log.db)
                 while tries > 0:
                     try:
                         self.__conn.send_message((server_ip, server_port), _log.SerializeToString())
                         break
                     except Exception as exc:
                         log.logger().error('Log synchronizer: ' + repr(exc))
                         tries -= 1
                 if tries > 0: 
                     db.manager().drop_log()
                     log.logger().info('Log successfully sent.')
                 else: 
                     raise LogSyncError('Log sending failed.')
         except LogSyncError as err:
             log.logger().info(err.value)
         except Exception as exc:
             log.logger().error(repr(exc))
         tries = config.config()['log_synchronization']['tries']
         time.sleep(period)
    def get_log(self, msg = None, select_for_update = False, **kwargs):
        logger().info('getting log from database to proto message')

        if msg is None:
            if kwargs.has_key('msg'):
                msg = kwargs['msg']
            else:
                msg = man_db_msg_pb2.man_message.FullMANDB()

        if select_for_update is None:
            if kwargs.has_key('select_for_update'):
                select_for_update = kwargs['select_for_update']
 
        try:
            logs = Log.select()
            for log in logs:
                log_msg = msg.log.add()

                log_msg.time = str(log.time)
                log_msg.decision = log.decision
                log_msg.point_id = log.point.id
                if log.code: log_msg.code = log.code
                if log.code_type: log_msg.code_type = log.code_type

            return msg

        except Exception:
            logger().error('failed to get log data from database to proto message')
            raise
 def _send_signal(self, hw_addr, device_id, signal):
     # `one uint32`-signal lvl3 protocol:
     msg_lvl2 = lprotocols.out_lvl2_common.pack_msg(hw_addr, device_id, 1, signal)
     serv_inf_int, data_int = lprotocols.out_lvl1.pack_msg(device_id, lprotocols.out_lvl2_common.version, msg_lvl2[0])
     data_str = struct.pack('Q', data_int) # v0.2 lprotocols use only 64bit msgs
     response_code = self._local_net_send((hw_addr, device_id), (serv_inf_int, data_str))
     if (response_code == None):
         log.logger().info(self._info + ': target device ({0}, {1}) did not respond'.format(hw_addr, device_id))
    def __enter__(self):
        logger().debug('Start transaction')

        # Create new transaction connection and swap with the current connection
        self.__connection_old = sqlobject.sqlhub.threadConnection
        transaction_connection = sqlobject.sqlhub.threadConnection.transaction()
        sqlobject.sqlhub.threadConnection = transaction_connection

        return sqlobject.sqlhub.threadConnection
    def drop_log(self):
        logger().info('dropping log from database')

        try:
            self.connection().query(self.connection().sqlrepr(Delete(Log.sqlmeta.table, None)))

        except Exception:
            logger().error('failed to drop log from database')
            raise
    def local_message_handler(self, msg_str):
        try:
            msg_int = struct.unpack("Q", msg_str)
            version, data = lprotocols.in_lvl1.unpack_msg(msg_int[0])
            handler = self._local_handlers[version]
            args = handler[1].unpack_msg(data)
            handler[0](*args)

        except Exception as exc:
            log.logger().error("failed to handle local message: " + traceback.format_exc())
    def drop_sync_data(self):
        logger().info('dropping sync data from database')

        try:
            for relation in self.__drop_relations:
                self.connection().query(self.connection().sqlrepr(Delete(relation.sqlmeta.table, None)))

        except Exception:
            logger().error('failed to drop sync data from database')
            raise
    def load_log(self, msg = None, **kwargs):
        logger().info('loading log to database from proto message')

        if msg is None:
            if kwargs.has_key('msg'):
                msg = kwargs['msg']

        try:
            for log in msg.log:
                Log(time = date_time.datetime_from_string(log.time), decision = log.decision, point = log.point_id, code = (log.HasField('code') and log.code or None), code_type = (log.HasField('code_type') and log.code_type or None))

        except Exception:
            logger().error('failed to load log to database from proto message') 
            raise
    def __exit__(self, exc_type, exc_value, exc_info):
        if exc_type is None:
            sqlobject.sqlhub.threadConnection.commit()
            sqlobject.sqlhub.threadConnection = self.__connection_old
            self.__connection_old = None

            logger().debug('Transaction success')
        else:
            sqlobject.sqlhub.threadConnection.rollback()
            sqlobject.sqlhub.threadConnection = self.__connection_old
            self.__connection_old = None

            logger().error('Transaction failed')

            raise exc_type, exc_value
        pass
    def load_sync_data(self, msg = None, **kwargs):
        logger().info('loading sync data to database from proto message')

        if msg is None:
            if kwargs.has_key('msg'):
                msg = kwargs['msg']

        try:
            # DatabaseSendLog and Log relations are not participate in full synchronization
                
            for node in msg.node:
                Node(id = node.id, ip = (node.HasField('ip') and node.ip or None))
    
            for controller in msg.controller:
                Controller(id = controller.id, address = controller.address, node = controller.node_id)
    
            for point in msg.point:
                Point(id = point.id, type = point.type, controller = point.controller_id, reader = (point.HasField('reader') and point.reader or None))
    
            for point_group in msg.point_group:
                PointGroup(id = point_group.id, name = point_group.name)
    
            for point_group_link in msg.point_group_link:
                PointGroupLink(id = point_group_link.id, point = point_group_link.point_id, point_group = point_group_link.point_group_id)
    
            for user in msg.user:
                User(id = user.id, name = (user.HasField('name') and user.name or None), surname = (user.HasField('surname') and user.surname or None), patronymic = (user.HasField('patronymic') and user.patronymic or None), gender = (user.HasField('gender') and user.gender or None))
    
            for em_marine_card in msg.em_marine_card:
                EmMarineCard(id = em_marine_card.id, code = em_marine_card.code, user = em_marine_card.user_id)
    
            for user_group in msg.user_group:
                UserGroup(id = user_group.id, name = user_group.name)
    
            for user_group_link in msg.user_group_link:
                UserGroupLink(id = user_group_link.id, user = user_group_link.user_id, user_group = user_group_link.user_group_id)
    
            for script in msg.script:
                Script(id = script.id, condition_code = script.condition_code)
    
            for access in msg.access:
                Access(id = access.id, script = access.script_id, point_group = access.point_group_id, user_group = access.user_group_id)

        except Exception:
            logger().error('failed to load sync data to database from proto message')
            raise
 def run(self):
     '''
     @brief cycle saves message when its recieved
     '''
     self._keep_working = True
     log.logger().info('IncomingCANserver: started')
     while (self._keep_working):
         success = True
         try:
             msg = can_socket.recieve_some_data(self._socket)
             # can_socket module itself raises no exceptions, so make in here:
             if (msg == -1):
                 raise Exception('Error in can_socket.recieve_data args:('+str(self._socket)+')')
             elif (msg == None):
                 success = False
         except Exception as exc:
             success = False
             log.logger().error('IncomingCANserver: error while reading message: ' + traceback.format_exc())
         if (success):
             self._handler(msg)
         time.sleep(self._timer_period)
def log_handler(msg):
    try:
        log.logger().info('Got log, synchronizing...')
        with database.manager().transaction():
            database.manager().load_log(msg.db)
            log.logger().info('Log successfully synchronized.')
    except Exception as exc:
        log.logger().error(repr(exc))
 def handle(self):
     try:
         head = ''
         body = ''
         body_remain = 0
         while True:
             head_char = self.request.recv(1)
             if (head_char == head_delim):
                 break
             else:
                 head += head_char
         body_remain = int(head)
         while body_remain > 0:
             #head is a string int!!!!11
             buff = self.request.recv(body_remain)
             body_remain -= len(buff)
             body += buff
         message = proto.man_message()
         message.ParseFromString(body)
     except Exception as exc:
         log.logger().error('IncomingTCPserver: error while reading message: ' + repr(exc))
     handler = self.server.handlers_dict[message.message_type]
     handler(message)
 def __check_access(code, point_id):
     scripts = db.Script.select(db.AND(db.Script.q.id == db.Access.q.script, db.Access.q.user_group == db.UserGroup.q.id, db.UserGroup.q.id == db.UserGroupLink.q.user_group, db.UserGroupLink.q.user == db.User.q.id, db.User.q.id == db.EmMarineCard.q.user, db.Access.q.point_group == db.PointGroup.q.id, db.PointGroup.q.id == db.PointGroupLink.q.point_group, db.PointGroupLink.q.point == db.Point.q.id, db.EmMarineCard.q.code == code, db.Point.q.id == point_id), distinct = True)
     
     #res format : (helper_name, additional_data)
     #res = (None, None)
     
     # Run each script in order.
     priority_max = -1
     priority = 0
     for script in scripts:
         log.logger().info('check_access: checking condition code')
         log.logger().debug('\n' + script.condition_code)
         
         try:
             # Execute condition_code definition in 'code_env' environment
             code_env = {}
             exec(script.condition_code, code_env)
             priority = code_env['self_priority']
             if (priority > priority_max):
                 priority_max = priority 
                 res = code_env['check']()
         except Exception, exc:
             raise Exception('failed to check condition code: ' + repr(exc))
 def send(self, msg):
     '''
     @param serv_inf: int32 CAN_ID+EFF/RTR/ERR flags
     @param data: char[8]
     @return sent bytes
     can raise exception
     '''
     # in local protocols v0.2 msg len is conts: 8B
     serv_inf, data = msg
     if (len(data) > self.CAN_MAX_DATA_LEN):
         raise Exception ('data string is >8bytes: serv_inf={0}'.format(serv_inf, data))
     log.logger().debug('OutcomingCANserver: sending message: serv_inf={0}'.format(serv_inf, data))
     #TODO: confirmation
     
     self._socket_lock.acquire()
     try:
         bs = can_socket.send_frame(self._socket, data, serv_inf)
         # can_socket module itself raises no exceptions, so make in here:
         if (bs == -1):
             raise Exception('Error in can_socket.send_frame args:(socket={0}, serv_inf={1})'\
                                 .format(self._socket, serv_inf))
     finally:
         self._socket_lock.release()
     return bs
def save_db_handler(msg):
    try:
        log.logger().info("got new db, synchronizing...")
        with db.manager().transaction():
            db.manager().drop_sync_data()
            db.manager().load_sync_data(msg.db)

        log.logger().info("successfully synchronized")

    except Exception, exc:
        log.logger().error("failed to reset local database: " + traceback.format_exc())
 def run(self):
     nodes = self.__msg.db.node
     tries = config.config()['server']['tries']
     while ((len(nodes) > 0) and (tries > 0)):
         problematic_nodes = []
         for node in nodes:
             if node.ip:
                 try:
                     log.logger().info('Synchronizer: processing node with id=%s, ip=%s', node.id, node.ip)
                     self.__conn.send_message((node.ip, config.config()['server']['nodes_port']), self.__msg.SerializeToString())
                     log.logger().info('Synchronizer: finished processing node with id=%s, ip=%s', node.id, node.ip)
                 except Exception as exc:
                     problematic_nodes.append(node)
                     log.logger().error('error while sending message: ' + repr(exc))
         if len(problematic_nodes) > 0: tries -= 1
         nodes = problematic_nodes
         sending_delay = config.config()['server']['sending_delay']
         time.sleep(sending_delay)
     if tries: self.__everything_OK = True
 def start(self):
     try:
         log.logger().info('Server started.')
         self.__servers.start_servers()
         
         while True:
             wait = 60 * float(config.config()['server']['sync_period'])
             
             new_db = proto.man_message()
             new_db.message_type = 'new_db'
             database.manager().get_sync_data(new_db.db)
             sync = Synchronizer(new_db, self.__servers.server_out).start()
             time.sleep(wait)
             
     except KeyboardInterrupt:
         log.logger().warning('Stopping server on user command.')
     except Exception as exc:
         log.logger().error(repr(exc))
                     
     finally: self.stop()
 def process_msg(self, msg, hw_addr_recieved, device_id_recieved):
     '''
      - checks recieved key
      - sends respose to device when and if needed (in handler)
      - writes decision to log
     '''
     try:
         if (self._is_busy):
             log.logger().info(self._info + ' REFUSED a request from ({0}, {1}) ; it is busy'.format(hw_addr_recieved, device_id_recieved))
             return
         self._is_busy = True
         
         log.logger().debug(self._info + ': procesing msg from ({0}, {1})'.format(hw_addr_recieved, device_id_recieved))
         key = lprotocols.in_lvl3_32ints.unpack(msg)[0]
         
         decision_str = 'deny'
         hw_addr_sending = hw_addr_recieved
         device_id_sending = None
         if (device_id_recieved == self.__parameters['devices']['out']['reader']):
             direction =  '_out'
             device_id_sending = self.__parameters['devices']['out']['lock']
         elif (device_id_recieved == self.__parameters['devices']['in']['reader']):
             direction =  '_in'
             device_id_sending = self.__parameters['devices']['in']['lock']
         else:
             raise Exception('unknown device_id')
         
         #TODO: make logger thread: connect it on creation, save log through it
         db.initialize() #connect this thread to db
         helper_name, handler_args = self._AccessPoint__check_access(key, self.__parameters['id'])
         # key sending is a kostyil - create new, but bounded thread:
         decision_str = self.script_helpers[helper_name](key, hw_addr_sending, device_id_sending, handler_args)
         
         self._is_busy = False
     except Exception as exc:
         log.logger().error(self._info + ': error while processing msg from ({0}, {1}): '\
                                 .format(hw_addr_recieved, device_id_recieved) + '\n\t' + traceback.format_exc())
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Project Master Device.  If not, see <http://www.gnu.org/licenses/>.


import os
from shared import log, config, database
from node.node import Node

default_log_conf_path = os.path.dirname(os.path.abspath(__file__)) + '/../config/node_logging.conf'
default_conf_path = os.path.dirname(os.path.abspath(__file__)) + '/../config/node_config.yml'

log.initialize(default_log_conf_path)
config.initialize(default_conf_path)

db_connection_string = 'sqlite:' + os.path.abspath(config.config()['database']['filename'])
db_debug_mode = config.config()['database']['debug']

database.initialize(db_connection_string, db_debug_mode)

if __name__ == '__main__':
    try:
        node = Node()
        node.start()
    except KeyboardInterrupt:
        log.logger().warning('Stopping node on user command.')
        node.stop()
 def __del__(self):
     if self.__everything_OK:
         log.logger().info('Synchronizer: synchronization complete.') 
     else:
         log.logger().error('Synchronizer: something bad happened.')
     log.logger().info('Synchronization thread dead.')
 def stop(self):
     self.__servers.shutdown()
     log.logger().info('Server stopped.')
 def __init__(self, msg, conn):
     Thread.__init__(self)
     log.logger().info('Synchronization thread started.')
     self.__msg = msg
     self.__conn = conn
     self.__everything_OK = False
 def start_servers(self):
     self.server_in.start()
     log.logger().info('TCPserver: started')
 def shutdown(self):
     self.server_in.shutdown()
     log.logger().info('TCPserver: stopped')
 def __init__(self, local_net_send):
     log.logger().info('initializing PointsManager')
     
     try:
         extenions = config()['extensions']
         
         self.points = {}
         
         for point_ext in extenions:
             log.logger().info('loading extension %s' % point_ext)
             
             try:
                 point_mod = __import__('node.extensions.' + point_ext + '.' + point_ext, fromlist = ['node', 'extensions', point_ext])
                 point_class = getattr(point_mod, point_ext)
                 
                 for point_parameters in point_class.config():
                     log.logger().info('creating access point')
                     
                     try:
                         point_object = point_class(point_parameters, local_net_send)
                         addresses = point_object.address_list()
                         for addr in addresses:
                             self.points[addr] = point_object
                     
                     except DbError, exc:
                         log.logger().error('failed to create access point: ' + traceback.format_exc())
                     
             except Exception, exc:
                 log.logger().error('failed to load extension: ' + traceback.format_exc())
     
     except Exception:
         log.logger().fatal('failed to initialize PointsManager')
         raise
    def get_sync_data(self, msg = None, select_for_update = False, **kwargs):
        logger().info('getting sync data from database to proto message')

        if msg is None:
            if kwargs.has_key('msg'):
                msg = kwargs['msg']
            else:
                msg = man_db_msg_pb2.man_message.FullMANDB()

        if select_for_update is None:
            if kwargs.has_key('select_for_update'):
                select_for_update = kwargs['select_for_update']
 
        try:
            nodes = Node.select(forUpdate = select_for_update)
            for node in nodes:
                node_msg = msg.node.add()

                node_msg.id = node.id
                if node.ip: node_msg.ip = node.ip

            controllers = Controller.select(forUpdate = select_for_update)
            for controller in controllers:
                controller_msg = msg.controller.add()

                controller_msg.id = controller.id
                controller_msg.address = controller.address
                controller_msg.node_id = controller.node.id

            points = Point.select(forUpdate = select_for_update)
            for point in points:
                point_msg = msg.point.add()

                point_msg.id = point.id
                point_msg.type = point.type
                point_msg.controller_id = point.controller.id
                if point.reader: point_msg.reader = point.reader

            point_groups = PointGroup.select(forUpdate = select_for_update)
            for point_group in point_groups:
                point_group_msg = msg.point_group.add()

                point_group_msg.id = point_group.id
                point_group_msg.name = point_group.name

            point_group_links = PointGroupLink.select(forUpdate = select_for_update)
            for point_group_link in point_group_links:
                point_group_link_msg = msg.point_group_link.add()
                point_group_link_msg.id = point_group_link.id
                point_group_link_msg.point_id = point_group_link.point.id
                point_group_link_msg.point_group_id = point_group_link.point_group.id

            users = User.select(forUpdate = select_for_update)
            for user in users:
                user_msg = msg.user.add()

                user_msg.id = user.id
                if user.name: user_msg.name = user.name
                if user.surname: user_msg.surname = user.surname
                if user.patronymic: user_msg.patronymic = user.patronymic
                if user.gender: user_msg.gender = user.gender

            em_marine_cards = EmMarineCard.select(forUpdate = select_for_update)
            for em_marine_card in em_marine_cards:
                em_marine_card_msg = msg.em_marine_card.add()

                em_marine_card_msg.id = em_marine_card.id
                em_marine_card_msg.code = em_marine_card.code
                em_marine_card_msg.user_id = em_marine_card.user.id

            user_groups = UserGroup.select(forUpdate = select_for_update)
            for user_group in user_groups:
                user_group_msg = msg.user_group.add()

                user_group_msg.id = user_group.id
                user_group_msg.name = user_group.name

            user_group_links = UserGroupLink.select(forUpdate = select_for_update)
            for user_group_link in user_group_links:
                user_group_link_msg = msg.user_group_link.add()

                user_group_link_msg.id = user_group_link.id
                user_group_link_msg.user_id = user_group_link.user.id
                user_group_link_msg.user_group_id = user_group_link.user_group.id

            scripts = Script.select(forUpdate = select_for_update)
            for script in scripts:
                script_msg = msg.script.add()

                script_msg.id = script.id
                script_msg.condition_code = script.condition_code

            accesses = Access.select(forUpdate = select_for_update)
            for access in accesses:
                access_msg = msg.access.add()

                access_msg.id = access.id
                access_msg.script_id = access.script.id
                access_msg.point_group_id = access.point_group.id
                access_msg.user_group_id = access.user_group.id

            return msg

        except Exception:
            logger().error('failed to get sync data from database to proto message')
            raise
 def stop(self):
     self._tcp_net.shutdown()
     log.logger().info("Node stopped.")