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.")