예제 #1
0
 def __init__(self):
     self.pybird = PyBird()
     self.prev_md5s = LRU_cache(
         maxlen=5
     )  # store previous configs like: {'md5_key': bird_cfg_string }
     self._config_fragments = {'md5': None, 'frags': []}
     self.bird_methods = {
         'get_config': {
             'method_ptr': self.get_config,
             'is_command': False
         },
         'set_config': {
             'method_ptr': self.set_config,
             'is_command': True
         },
         'get_protocols_info': {
             'method_ptr': self.get_protocols_info,
             'is_command': False
         }
     }
     try:
         current_cfg = self.pybird.get_config().encode('utf-8')
         self._current_md5 = hashlib.md5(current_cfg).hexdigest()
         self.prev_md5s[self._current_md5] = current_cfg
     except Exception as e:
         print(
             "Error occurred while reading from bird current cfg in the first time: %s"
             % e)
         self._current_md5 = -1  # signify no md5 loaded
예제 #2
0
class BirdWrapper:

    def __init__(self):
        self.pybird = PyBird()
        self.prev_md5s = LRU_cache(maxlen=5)        # store previous configs like: {'md5_key': bird_cfg_string }
        self._config_fragments = {'md5': None, 'frags': []}
        self.bird_methods = {   'connect': {'method_ptr': self.connect, 'is_command': False},
                                'get_config': {'method_ptr': self.get_config, 'is_command': False},
                                'set_config': {'method_ptr': self.set_config, 'is_command': True},
                                'set_empty_config': {'method_ptr': self.set_empty_config, 'is_command': True},
                                'get_protocols_info': {'method_ptr': self.get_protocols_info, 'is_command': False},
                                'disconnect': {'method_ptr': self.disconnect, 'is_command': False},
                                }
        try:
            current_cfg = self.pybird.get_config().encode('utf-8')
            self._current_md5 = hashlib.md5(current_cfg).hexdigest()
            self.prev_md5s[self._current_md5] = current_cfg
        except Exception as e:
            print("Error occurred while reading from bird current cfg in the first time: %s" % e)
            self._current_md5 = -1  # signify no md5 loaded

    def __del__(self):
        self.logger.info('***IN BIRD WRAPPER DTOR***')
        self.execute('disconnect', [])

    def parse_req_msg(self, JSON_req):
        try:
            req = json.loads(JSON_req)
            req_id = 'null'
            if (type(req) != type({})):
                raise ParseException("Expected dictionary got: '%s' " % type(req))
            json_rpc_keys = {'jsonrpc', 'id', 'method'}
            if set(req.keys()) != json_rpc_keys and set(req.keys()) != json_rpc_keys.union({'params'}):
                if 'id' in req.keys():
                    req_id = req['id']
                raise InvalidRequest(req_id)
            req_id = req['id']
            if 'params' in req.keys():
                return req['method'], req['params'], req_id
            else:
                return req['method'], [], req_id
        except ValueError:
            raise ParseException(req_id)

    def connect(self, params):
        return self.pybird.connect()

    def disconnect(self, params):
        return self.pybird.disconnect()

    def get_config(self, params):
        return self.pybird.get_config()

    def get_protocols_info(self, params):
        return self.pybird.get_protocols_info()

    def set_config(self ,params):
        first, last = params.get('frag_first'), params.get('frag_last')
        fragment = params['fragment']
        md5 = params.get('md5')
        
        self._config_fragments['frags'].append(fragment)

        if first and last:
            return self._set_new_config(fragment)
        elif first:
            self._config_fragments['md5'] = md5
        elif last:
            all_cfg = ''.join(self._config_fragments['frags'])
            md5 = self._config_fragments['md5']
            return self._set_new_config(all_cfg, md5)
        return 'send_another_frag'  # middle fragment

    def set_empty_config(self, params):
        # In set_empty_config, we don't need to compare cache since
        # we are not uploading any long configuration file (unlike in set_config),
        # rather this is just an RPC call.
        # However, this changes the configuration, and as such self._current_md5 needs to be cleared.
        self._current_md5 = None
        return self.pybird.set_empty_config()

    def _set_new_config(self, config, md5=None):
        if md5 is None:
            if type(config) is str:
                config = config.encode('utf-8')
            md5 = hashlib.md5(config).hexdigest()

        self._config_fragments['frags'] = []       # reset fragments config
        self._config_fragments['md5'] = None
        cached = self._is_md5_cached(md5)

        if 'Already configured' in cached:
            return cached
        elif 'Found configuration in cache' in cached:
            self._current_md5 = md5
            return cached + self.pybird.set_config(self.prev_md5s[md5])
        else:
            res = self.pybird.set_config(config)  # return a string
            if 'Configured successfully' in res:
                self._current_md5 = md5
                self.prev_md5s[md5] = config           # new md5, cache it
            return res

    def _is_md5_cached(self, md5):
        if md5 == self._current_md5:
            return 'Already configured'
        if md5 in self.prev_md5s.keys():
            return 'Found configuration in cache. '
        return ''

    def create_error_response(self, error_code, error_msg, req_id):
        return {"jsonrpc": "2.0", "error": {"code": error_code, "message": error_msg}, "id": req_id}

    def create_success_response(self, result, req_id):
        return {"jsonrpc": "2.0", "result": result, "id": req_id}

    def get_exception(self):
        return sys.exc_info()

    def has_method(self, method):
        return method in self.bird_methods.keys()

    def execute(self, method, params):
        return self.bird_methods[method]['method_ptr'](params) 

    def is_command_method(self, method):
        return self.bird_methods[method]['is_command']

    def error_handler(self, e, req_id):
        response = {"jsonrpc": "2.0", "error": {"code": -32097, "message": str(e)}, "id": req_id}
        try:
            raise e
        except ParseException as e:
            response = self.create_error_response(-32700,
                                                  'Parse error ', req_id)
        except InvalidRequest as e:
            response = self.create_error_response(
                -32600, 'Invalid Request', req_id)
        except MethodNotFound as e:
            response = self.create_error_response(
                -32601, 'Method not found', req_id)
        except InvalidParams as e:
            response = self.create_error_response(
                -32603, 'Invalid params', req_id)
        except SyntaxError as e:
            response = self.create_error_response(-32097,
                                                  'SyntaxError', req_id)
        except Exception as e:
            if hasattr(e, 'strerror'):
                response = self.create_error_response(
                    -32099, 'Bird Server: '+str(e.strerror), req_id)  # TODO maybe other code?
            elif hasattr(e, 'message'):
                response = self.create_error_response(
                    -32098, 'Bird Server: '+str(e.message), req_id)
            elif (is_python(3)):
                response = self.create_error_response(
                    -32096, 'Bird Server: '+str(e), req_id)
            else:
                response = self.create_error_response(
                    -32096, 'Bird Server: Unknown Error', req_id)
        finally:
            return response