Example #1
0
 def _marshaled_single_dispatch(self, request):
     # TODO - Use the multiprocessing and skip the response if
     # it is a notification
     # Put in support for custom dispatcher here
     # (See SimpleXMLRPCServer._marshaled_dispatch)
     method = request.get('method')
     params = request.get('params')
     try:
         response = self._dispatch(method, params)
     except:
         exc_type, exc_value, exc_tb = sys.exc_info()
         fault = Fault(-32603, '%s:%s' % (exc_type, exc_value))
         return fault.response()
     if 'id' not in request.keys() or request['id'] == None:
         # It's a notification
         return None
     try:
         response = jsonrpclib.dumps(response,
                                     methodresponse=True,
                                     rpcid=request['id']
                                     )
         return response
     except:
         exc_type, exc_value, exc_tb = sys.exc_info()
         fault = Fault(-32603, '%s:%s' % (exc_type, exc_value))
         return fault.response()
Example #2
0
    def _dispatch(self, method, params, config=None):
        """
        Default method resolver and caller

        :param method: Name of the method to call
        :param params: List of arguments to give to the method
        :param config: Request-specific configuration
        :return: The result of the method
        """
        config = config or self.json_config

        func = None
        try:
            # Look into registered methods
            func = self.funcs[method]
        except KeyError:
            if self.instance is not None:
                # Try with the registered instance
                try:
                    # Instance has a custom dispatcher
                    return getattr(self.instance, '_dispatch')(method, params)
                except AttributeError:
                    # Resolve the method name in the instance
                    try:
                        func = xmlrpcserver.resolve_dotted_attribute(
                            self.instance, method, True)
                    except AttributeError:
                        # Unknown method
                        pass

        if func is not None:
            try:
                # Call the method
                if isinstance(params, utils.ListType):
                    return func(*params)
                else:
                    return func(**params)
            except TypeError as ex:
                # Maybe the parameters are wrong
                fault = Fault(-32602,
                              'Invalid parameters: {0}'.format(ex),
                              config=config)
                _logger.warning("Invalid call parameters: %s", fault)
                return fault
            except:
                # Method exception
                err_lines = traceback.format_exc().splitlines()
                trace_string = '{0} | {1}'.format(err_lines[-3], err_lines[-1])
                fault = Fault(-32603,
                              'Server error: {0}'.format(trace_string),
                              config=config)
                _logger.exception("Server-side exception: %s", fault)
                return fault
        else:
            # Unknown method
            fault = Fault(-32601,
                          'Method {0} not supported.'.format(method),
                          config=config)
            _logger.warning("Unknown method: %s", fault)
            return fault
    def _unmarshaled_dispatch(self, request, dispatch_method=None):
        """
        Loads the request dictionary (unmarshaled), calls the method(s)
        accordingly and returns a JSON-RPC dictionary (not marshaled)

        :param request: JSON-RPC request dictionary (or list of)
        :param dispatch_method: Custom dispatch method (for method resolution)
        :return: A JSON-RPC dictionary (or an array of) or None if the request
                 was a notification
        :raise NoMulticallResult: No result in batch
        """
        if not request:
            # Invalid request dictionary
            fault = Fault(-32600, 'Request invalid -- no request data.',
                          config=self.json_config)
            _logger.warning("Invalid request: %s", fault)
            return fault.dump()

        if isinstance(request, utils.ListType):
            # This SHOULD be a batch, by spec
            responses = []
            for req_entry in request:
                # Validate the request
                result = validate_request(req_entry, self.json_config)
                if isinstance(result, Fault):
                    responses.append(result.dump())
                    continue

                # Call the method
                resp_entry = self._marshaled_single_dispatch(req_entry,
                                                             dispatch_method)

                # Store its result
                if isinstance(resp_entry, Fault):
                    # pylint: disable=E1103
                    responses.append(resp_entry.dump())
                elif resp_entry is not None:
                    responses.append(resp_entry)

            if not responses:
                # No non-None result
                _logger.error("No result in Multicall")
                raise NoMulticallResult("No result")

            return responses

        else:
            # Single call
            result = validate_request(request, self.json_config)
            if isinstance(result, Fault):
                return result.dump()

            # Call the method
            response = self._marshaled_single_dispatch(request,
                                                       dispatch_method)
            if isinstance(response, Fault):
                # pylint: disable=E1103
                return response.dump()

            return response
Example #4
0
 def _dispatch(self, method, params):
     func = None
     try:
         func = self.funcs[method]
     except KeyError:
         if self.instance is not None:
             if hasattr(self.instance, '_dispatch'):
                 return self.instance._dispatch(method, params)
             else:
                 try:
                     func = SimpleXMLRPCServer.resolve_dotted_attribute(
                         self.instance, method, True)
                 except AttributeError:
                     pass
     if func is not None:
         try:
             if type(params) is types.ListType:
                 response = func(*params)
             else:
                 response = func(**params)
             return response
         except TypeError:
             return Fault(-32602, 'Invalid parameters: ')
         except:
             err_lines = traceback.format_exc().splitlines()
             trace_string = '%s | %s' % (err_lines[-3], err_lines[-1])
             fault = jsonrpclib.Fault(-32603,
                                      'Server error: %s' % trace_string)
             return fault
     else:
         return Fault(-32601, 'Method %s not supported.' % method)
    def _marshaled_dispatch(self, data, dispatch_method=None, path=None):
        """
        Parses the request data (marshaled), calls method(s) and returns a
        JSON string (marshaled)

        :param data: A JSON request string
        :param dispatch_method: Custom dispatch method (for method resolution)
        :param path: Unused parameter, to keep compatibility with xmlrpclib
        :return: A JSON-RPC response string (marshaled)
        """
        # Parse the request
        try:
            request = jsonrpclib.loads(data, self.json_config)
        except Exception as ex:
            # Parsing/loading error
            fault = Fault(-32700, 'Request {0} invalid. ({1}:{2})'
                          .format(data, type(ex).__name__, ex),
                          config=self.json_config)
            _logger.warning("Error parsing request: %s", fault)
            return fault.response()

        # Get the response dictionary
        try:
            response = self._unmarshaled_dispatch(request, dispatch_method)
            if response is not None:
                # Compute the string representation of the dictionary/list
                return jsonrpclib.jdumps(response, self.encoding)
            else:
                # No result (notification)
                return ''
        except NoMulticallResult:
            # Return an empty string (jsonrpclib internal behaviour)
            return ''
Example #6
0
 def _marshaled_dispatch(self, data, dispatch_method=None):
     """Convert the data to a JSON RPC method request and dispatch it."""
     try:
         request = jsonrpclib.loads(data)
     except Exception as e:
         fault = Fault(-32700, "Request %s invalid. (%s)" % (data, e))
         response = fault.response()
         return response
     if not request:
         fault = Fault(-32600, "Request invalid -- no request data.")
         return fault.response()
     if isinstance(request, types.ListType):
         # batch of requests
         responses = []
         for req_entry in request:
             result = validate_request(req_entry)
             if type(result) is Fault:
                 responses.append(result.response())
                 continue
             resp_entry = self._marshaled_single_dispatch(req_entry)
             if resp_entry is not None:
                 responses.append(resp_entry)
         if len(responses) > 0:
             response = "[%s]" % ",".join(responses)
         else:
             response = ""
     else:
         # single request
         result = validate_request(request)
         if type(result) is Fault:
             return result.response()
         response = self._marshaled_single_dispatch(request)
     return response
Example #7
0
    def _unmarshaled_dispatch(self, request, dispatch_method=None):
        """
        Loads the request dictionary (unmarshaled), calls the method(s)
        accordingly and returns a JSON-RPC dictionary (not marshaled)

        :param request: JSON-RPC request dictionary (or list of)
        :param dispatch_method: Custom dispatch method (for method resolution)
        :return: A JSON-RPC dictionary (or an array of) or None if the request
                 was a notification
        :raise NoMulticallResult: No result in batch
        """
        if not request:
            # Invalid request dictionary
            fault = Fault(-32600, 'Request invalid -- no request data.',
                          config=self.json_config)
            _logger.warning("Invalid request: %s", fault)
            return fault.dump()

        if isinstance(request, utils.ListType):
            # This SHOULD be a batch, by spec
            responses = []
            for req_entry in request:
                # Validate the request
                result = validate_request(req_entry, self.json_config)
                if isinstance(result, Fault):
                    responses.append(result.dump())
                    continue

                # Call the method
                resp_entry = self._marshaled_single_dispatch(req_entry,
                                                             dispatch_method)

                # Store its result
                if isinstance(resp_entry, Fault):
                    # pylint: disable=E1103
                    responses.append(resp_entry.dump())
                elif resp_entry is not None:
                    responses.append(resp_entry)

            if not responses:
                # No non-None result
                _logger.error("No result in Multicall")
                raise NoMulticallResult("No result")

            return responses

        else:
            # Single call
            result = validate_request(request, self.json_config)
            if isinstance(result, Fault):
                return result.dump()

            # Call the method
            response = self._marshaled_single_dispatch(request,
                                                       dispatch_method)
            if isinstance(response, Fault):
                # pylint: disable=E1103
                return response.dump()

            return response
Example #8
0
    def _marshaled_dispatch(self, data, dispatch_method=None, path=None):
        """
        Parses the request data (marshaled), calls method(s) and returns a
        JSON string (marshaled)

        :param data: A JSON request string
        :param dispatch_method: Custom dispatch method (for method resolution)
        :param path: Unused parameter, to keep compatibility with xmlrpclib
        :return: A JSON-RPC response string (marshaled)
        """
        # Parse the request
        try:
            request = jsonrpclib.loads(data, self.json_config)
        except Exception as ex:
            # Parsing/loading error
            fault = Fault(-32700, 'Request {0} invalid. ({1}:{2})'
                          .format(data, type(ex).__name__, ex),
                          config=self.json_config)
            _logger.warning("Error parsing request: %s", fault)
            return fault.response()

        # Get the response dictionary
        try:
            response = self._unmarshaled_dispatch(request, dispatch_method)
            if response is not None:
                # Compute the string representation of the dictionary/list
                return jsonrpclib.jdumps(response, self.encoding)
            else:
                # No result (notification)
                return ''
        except NoMulticallResult:
            # Return an empty string (jsonrpclib internal behaviour)
            return ''
 def _marshaled_dispatch(self, session_id, data, dispatch_method=None):
     response = None
     try:
         request = jsonrpclib.loads(data)
     except Exception, e:
         fault = Fault(-32700, 'Request %s invalid. (%s)' % (data, e))
         response = fault.response()
         return response
 def _marshaled_dispatch(self, session_id, data, dispatch_method=None):
     response = None
     try:
         request = jsonrpclib.loads(data)
     except Exception, e:
         fault = Fault(-32700, 'Request %s invalid. (%s)' % (data, e))
         response = fault.response()
         return response
Example #11
0
def validate_request(request, json_config):
    """
    Validates the format of a request dictionary

    :param request: A request dictionary
    :param json_config: A JSONRPClib Config instance
    :return: True if the dictionary is valid, else a Fault object
    """
    if not isinstance(request, utils.DictType):
        # Invalid request type
        fault = Fault(
            -32600,
            "Request must be a dict, not {0}".format(type(request).__name__),
            config=json_config,
        )
        _logger.warning("Invalid request content: %s", fault)
        return fault

    # Get the request ID
    rpcid = request.get("id", None)

    # Check request version
    version = get_version(request)
    if not version:
        fault = Fault(
            -32600,
            "Request {0} invalid.".format(request),
            rpcid=rpcid,
            config=json_config,
        )
        _logger.warning("No version in request: %s", fault)
        return fault

    # Default parameters: empty list
    request.setdefault("params", [])

    # Check parameters
    method = request.get("method", None)
    params = request.get("params")
    param_types = (utils.ListType, utils.DictType, utils.TupleType)

    if (not method or not isinstance(method, utils.STRING_TYPES)
            or not isinstance(params, param_types)):
        # Invalid type of method name or parameters
        fault = Fault(
            -32600,
            "Invalid request parameters or method.",
            rpcid=rpcid,
            config=json_config,
        )
        _logger.warning("Invalid request content: %s", fault)
        return fault

    # Valid request
    return True
Example #12
0
    def _marshaled_single_dispatch(self, request, dispatch_method=None):
        """
        Dispatches a single method call

        :param request: A validated request dictionary
        :param dispatch_method: Custom dispatch method (for method resolution)
        :return: A JSON-RPC response dictionary, or None if it was a
                 notification request
        """
        # TODO - Use the multiprocessing and skip the response if
        # it is a notification
        method = request.get('method')
        params = request.get('params')

        # Prepare a request-specific configuration
        if 'jsonrpc' not in request and self.json_config.version >= 2:
            # JSON-RPC 1.0 request on a JSON-RPC 2.0
            # => compatibility needed
            config = self.json_config.copy()
            config.version = 1.0
        else:
            # Keep server configuration as is
            config = self.json_config

        try:
            # Call the method
            if dispatch_method is not None:
                response = dispatch_method(method, params)
            else:
                response = self._dispatch(method, params, config)

        except:
            # Return a fault
            exc_type, exc_value, _ = sys.exc_info()
            fault = Fault(-32603, '{0}:{1}'.format(exc_type, exc_value),
                          config=config)
            return fault.dump()

        if 'id' not in request or request['id'] in (None, ''):
            # It's a notification, no result needed
            # Do not use 'not id' as it might be the integer 0
            return None

        # Prepare a JSON-RPC dictionary
        try:
            # TODO: use a copy of the configuration, to JSON-RPC version
            return jsonrpclib.dump(response, rpcid=request['id'],
                                   is_response=True, config=config)

        except:
            # JSON conversion exception
            exc_type, exc_value, _ = sys.exc_info()
            fault = Fault(-32603, '{0}:{1}'.format(exc_type, exc_value),
                          config=config)
            return fault.dump()
Example #13
0
 def _marshaled_dispatch(self, data, client_ip=None):
     response = None
     try:
         request = jsonrpclib.loads(data)
         if not request.has_key('params'):
             request['params'] = {}
         request['params']['client_ip'] = client_ip
         
     except Exception, e:
         fault = Fault(-32700, 'Request %s invalid. (%s)' % (data, e))
         response = fault.response()
         return response
Example #14
0
    def _marshaled_dispatch(self, data, client_ip=None):
        response = None
        try:
            request = jsonrpclib.loads(data)
            if not request.has_key("params"):
                request["params"] = {}
            request["params"]["client_ip"] = client_ip

        except Exception, e:
            fault = Fault(-32700, "Request %s invalid. (%s)" % (data, e))
            response = fault.response()
            return response
Example #15
0
 def get_running_info (self):
     if self.status == TRexStatus.Running:
         return self.get_latest_dump()
     else:
         logger.info("TRex isn't running. Running information isn't available.")
         if self.status == TRexStatus.Idle:
             if self.errcode is not None:    # some error occured
                 logger.info("TRex is in Idle state, with errors. returning fault")
                 return Fault(self.errcode, self.verbose_status)               # raise at client relevant exception, depending on the reason the error occured
             else:
                 logger.info("TRex is in Idle state, no errors. returning {}")
                 return u'{}'    
             
         return Fault(-12, self.verbose_status)                                # raise at client TRexWarning, indicating TRex is back to Idle state or still in Starting state
Example #16
0
def validate_request(request):
    if not isinstance(request, types.DictType):
        return Fault(-32600, 'Request must be {}, not %s.' % type(request))
    rpcid = request.get('id', None)
    version = get_version(request)
    if not version:
        return Fault(-32600, 'Request %s invalid.' % request, rpcid=rpcid)
    request.setdefault('params', [])
    method = request.get('method', None)
    params = request.get('params')
    param_types = (types.ListType, types.DictType, types.TupleType)
    if not method or type(method) not in types.StringTypes or type(params) not in param_types:
        return Fault(-32600, 'Invalid request parameters or method.', rpcid=rpcid)
    return True
Example #17
0
    def cancel_reservation(self, user):
        with self.start_lock:
            logger.info("Processing cancel_reservation() command.")
            if self.is_reserved():
                if self.__reservation['user'] == user:
                    logger.info(
                        "TRex reservation to {res_user} has been canceled successfully."
                        .format(res_user=self.__reservation['user']))
                    self.__reservation = None
                    return True
                else:
                    logger.warning(
                        "TRex is reserved to different user than the provided one. Reservation wasn't canceled."
                    )
                    return Fault(
                        -33,
                        "Cancel reservation request is available to the user that holds the reservation. Request denied"
                    )  # raise at client TRexRequestDenied

            else:
                logger.info(
                    "TRex is not reserved to anyone. No need to cancel anything"
                )
                assert (self.__reservation is None)
                return False
Example #18
0
 def get_trex_config_metadata(self):
     logger.info("Processing get_trex_config_metadata() command.")
     metadata_json_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'config_metadata.json'))
     try:
         with open(metadata_json_path) as f:
             return json.load(f)
     except Exception as e:
         return Fault(-33, "Can't load config metadata contents: %s" % e)
Example #19
0
    def start_trex(self, trex_cmd_options, user, block_to_success = True, timeout = 40, stateless = False, debug_image = False, trex_args = ''):
        self.trex.zmq_error = None
        self.assert_zmq_ok()
        with self.start_lock:
            logger.info("Processing start_trex() command.")
            if self.is_reserved():
                # check if this is not the user to which TRex is reserved
                if self.__reservation['user'] != user:  
                    logger.info("TRex is reserved to another user ({res_user}). Only that user is allowed to initiate new runs.".format(res_user = self.__reservation['user']))
                    return Fault(-33, "TRex is reserved to another user ({res_user}). Only that user is allowed to initiate new runs.".format(res_user = self.__reservation['user']))  # raise at client TRexRequestDenied
            elif self.trex.get_status() != TRexStatus.Idle:
                err = 'TRex is already taken, cannot create another run until done.'
                logger.info(err)
                return Fault(-13, err) # raise at client TRexInUseError

            try:
                server_cmd_data = self.generate_run_cmd(stateless = stateless, debug_image = debug_image, trex_args = trex_args, **trex_cmd_options)
                self.zmq_monitor.first_dump = True
                self.trex.start_trex(self.TREX_PATH, server_cmd_data)
                logger.info("TRex session has been successfully initiated.")
                if block_to_success:
                    # delay server response until TRex is at 'Running' state.
                    start_time = time.time()
                    trex_state = None
                    while (time.time() - start_time) < timeout :
                        trex_state = self.trex.get_status()
                        if trex_state != TRexStatus.Starting:
                            break
                        else:
                            time.sleep(0.5)
                            self.assert_zmq_ok()

                    # check for TRex run started normally
                    if trex_state == TRexStatus.Starting:   # reached timeout
                        logger.warning("TimeoutError: TRex initiation outcome could not be obtained, since TRex stays at Starting state beyond defined timeout.")
                        return Fault(-12, 'TimeoutError: TRex initiation outcome could not be obtained, since TRex stays at Starting state beyond defined timeout.') # raise at client TRexWarning
                    elif trex_state == TRexStatus.Idle:
                        return Fault(-11, self.trex.get_verbose_status())   # raise at client TRexError
                
                # reach here only if TRex is at 'Running' state
                self.trex.gen_seq()
                return self.trex.get_seq()          # return unique seq number to client
                        
            except TypeError as e:
                logger.error("TRex command generation failed, probably because either -f (traffic generation .yaml file) and -c (num of cores) was not specified correctly.\nReceived params: {params}".format( params = trex_cmd_options) )
                raise TypeError('TRex -f (traffic generation .yaml file) and -c (num of cores) must be specified. %s' % e)
Example #20
0
 def _pull_file(filepath):
     try:
         with open(filepath, 'rb') as f:
             file_content = f.read()
             return binascii.b2a_base64(file_content).decode(errors='replace')
     except Exception as e:
         err_str = "Can't get requested file %s: %s" % (filepath, e)
         logger.error(err_str)
         return Fault(-33, err_str)
def validate_request(request, json_config):
    """
    Validates the format of a request dictionary

    :param request: A request dictionary
    :param json_config: A JSONRPClib Config instance
    :return: True if the dictionary is valid, else a Fault object
    """
    if not isinstance(request, utils.DictType):
        # Invalid request type
        return Fault(-32600,
                     'Request must be a dict, not {0}'.format(
                         type(request).__name__),
                     config=json_config)

    # Get the request ID
    rpcid = request.get('id', None)

    # Check request version
    version = get_version(request)
    if not version:
        return Fault(-32600,
                     'Request {0} invalid.'.format(request),
                     rpcid=rpcid,
                     config=json_config)

    # Default parameters: empty list
    request.setdefault('params', [])

    # Check parameters
    method = request.get('method', None)
    params = request.get('params')
    param_types = (utils.ListType, utils.DictType, utils.TupleType)

    if not method or not isinstance(method, utils.string_types) or \
            not isinstance(params, param_types):
        # Invalid type of method name or parameters
        return Fault(-32600,
                     'Invalid request parameters or method.',
                     rpcid=rpcid,
                     config=json_config)

    # Valid request
    return True
def validate_request(request):
    if not isinstance(request, dict):
        fault = Fault(-32600, 'Request must be {}, not %s.' % type(request))
        return fault
    rpcid = request.get('id', None)
    version = get_version(request)
    if not version:
        fault = Fault(-32600, 'Request %s invalid.' % request, rpcid=rpcid)
        return fault
    request.setdefault('params', [])
    method = request.get('method', None)
    params = request.get('params')
    if not method or not isinstance(method, basestring) or \
            not isinstance(params, (list, dict, tuple)):
        fault = Fault(-32600,
                      'Invalid request parameters or method.',
                      rpcid=rpcid)
        return fault
    return True
Example #23
0
 def wait_until_kickoff_finish (self, timeout = 40):
     # block until T-Rex exits Starting state
     logger.info("Processing wait_until_kickoff_finish() command.")
     trex_state = None
     start_time = time.time()
     while (time.time() - start_time) < timeout :
         trex_state = self.trex.get_status()
         if trex_state != TRexStatus.Starting:
             return
     return Fault(-12, 'TimeoutError: T-Rex initiation outcome could not be obtained, since T-Rex stays at Starting state beyond defined timeout.') # raise at client TRexWarning
Example #24
0
 def get_devices_info(self):
     logger.info("Processing get_devices_info() command.")
     try:
         args = [os.path.join(self.TREX_PATH, 'dpdk_nic_bind.py'), '-s', '--json']
         result = subprocess.check_output(args, cwd=self.TREX_PATH, universal_newlines=True)
         return json.loads(result)
     except Exception as e:
         err_str = "Error processing get_devices_info(): %s" % e
         logger.error(e)
         return Fault(-33, err_str)
Example #25
0
 def get_file(self, filepath):
     try:
         logger.info("Processing get_file() command.")
         if not self._check_path_under_TRex_or_temp(filepath):
             raise Exception('Given path should be under current TRex package or /tmp/trex_files')
         return self._pull_file(filepath)
     except Exception as e:
         err_str = "Can't get requested file %s: %s" % (filepath, e)
         logger.error(err_str)
         return Fault(-33, err_str)
Example #26
0
    def reserve_trex(self, user):
        if user == "":
            logger.info(
                "TRex reservation cannot apply to empty string user. Request denied."
            )
            return Fault(
                -33,
                "TRex reservation cannot apply to empty string user. Request denied."
            )

        with self.start_lock:
            logger.info("Processing reserve_trex() command.")
            if self.is_reserved():
                if user == self.__reservation['user']:
                    # return True is the same user is asking and already has the resrvation
                    logger.info(
                        "the same user is asking and already has the resrvation. Re-reserving TRex."
                    )
                    return True

                logger.info(
                    "TRex is already reserved to another user ({res_user}), cannot reserve to another user."
                    .format(res_user=self.__reservation['user']))
                return Fault(
                    -33,
                    "TRex is already reserved to another user ({res_user}). Please make sure TRex is free before reserving it."
                    .format(res_user=self.__reservation['user']
                            ))  # raise at client TRexInUseError
            elif self.trex.get_status() != TRexStatus.Idle:
                logger.info(
                    "TRex is currently running, cannot reserve TRex unless in Idle state."
                )
                return Fault(
                    -13,
                    'TRex is currently running, cannot reserve TRex unless in Idle state. Please try again when TRex run finished.'
                )  # raise at client TRexInUseError
            else:
                logger.info(
                    "TRex is now reserved for user ({res_user}).".format(
                        res_user=user))
                self.__reservation = {'user': user, 'since': time.ctime()}
                logger.debug("Reservation details: " + str(self.__reservation))
                return True
Example #27
0
 def _pull_file(filepath):
     try:
         with open(filepath, 'rb') as f:
             file_content = f.read()
             return binascii.b2a_base64(file_content)
     except Exception as e:
         err_str = "Can't get requested file: {0}, possibly due to TRex that did not run".format(
             filepath)
         logger.error('{0}, error: {1}'.format(err_str, e))
         return Fault(-33, err_str)
Example #28
0
 def get_files_list(self, path):
     try:
         logger.info("Processing get_files_list() command, given path: %s" % path)
         if not self._check_path_under_TRex_or_temp(path):
             raise Exception('Given path should be under current TRex package or /tmp/trex_files')
         return os.walk(path).next()[1:3]
     except Exception as e:
         err_str = "Error processing get_files_list(): %s" % e
         logger.error(err_str)
         return Fault(-33, err_str)
Example #29
0
    def do_POST(self):
        """
        HTTP POST method processor.
        """

        if not self.is_rpc_path_valid():
            logger.warning("[Response] HTTP 404 - The path requested is not " "a  valid address.")
            self.report_404()
            return

        try:
            size_remaining = int(self.headers["content-length"])
            L = []
            while size_remaining:
                chunk_size = min(size_remaining, self.MAX_CHUNK_SIZE)
                L.append(self.rfile.read(chunk_size))
                size_remaining -= len(L[-1])
            data = "".join(L)
            c_ip, c_port = self.client_address
            logger.info("[Request] Client %s:%s method POST: %s" % (c_ip, c_port, data))
            response = self.server._marshaled_dispatch(data)
            status = 200
            message = "Request accepted."
        except Exception:
            logger.exception("Exception processing request:")
            status = 500
            message = "Internal Server Error."
            err_lines = traceback.format_exc().splitlines()
            trace_string = "%s | %s" % (err_lines[-3], err_lines[-1])
            fault = Fault(-32603, "Server error: %s" % trace_string)
            response = fault.response()
        finally:
            logger.info("[Response] HTTP %d - %s" % (status, message))
            self.send_response(status)

        logger.info("[Response] Content: %s" % repr(response))
        self.send_header("Content-type", "application/json-rpc")
        self.send_header("Content-length", str(len(response)))
        self.end_headers()
        self.wfile.write(response)
        self.wfile.flush()
        self.connection.shutdown(1)
Example #30
0
 def prepare_astf_profile(self, filepath):
     logger.info("Processing prepare_astf_profile() command.")
     try:
         if not self._check_path_under_TRex_or_temp(filepath):
             raise Exception('Given path should be under current TRex package or /tmp/trex_files')
         profile = ASTFProfile.load(filepath)
         return ASTFProfile.to_json(profile)
     except Exception as e:
         err_str = "Error processing prepare_astf_profile(): %s" % e
         logger.error(err_str)
         return Fault(-33, err_str)
Example #31
0
    def _marshaled_dispatch(self, session_id, data, dispatch_method=None):
        response = None
        try:
            request = jsonrpclib.loads(data)
        except Exception as e:
            fault = Fault(-32700, 'Request %s invalid. (%s)' % (data, e))
            response = fault.response()
            return response

        session = self.dispatcher.get_session_by_address(session_id)
        if not session:
            return 'Error: session not found'
        session.time = time.time()

        responses = []
        if not isinstance(request, types.ListType):
            request = [request]

        for req_entry in request:
            result = validate_request(req_entry)
            if type(result) is Fault:
                responses.append(result.response())
                continue

            self.dispatcher.do_dispatch(session, req_entry)

            if req_entry['method'] == 'server.stop':
                return json.dumps({'result': 'ok'})

        r = self.poll_session(session)
        for item in r:
            responses.append(json.dumps(item))

        if len(responses) > 1:
            response = '[%s]' % ','.join(responses)
        elif len(responses) == 1:
            response = responses[0]
        else:
            response = ''

        return response
    def _marshaled_single_dispatch(self, request, dispatch_method=None):
        """
        Dispatches a single method call
        
        :param request: A validated request dictionary
        :param dispatch_method: Custom dispatch method (for method resolution)
        :return: A JSON-RPC response dictionary, or None if it was a
                 notification request
        """
        # TODO - Use the multiprocessing and skip the response if
        # it is a notification
        method = request.get('method')
        params = request.get('params')
        try:
            # Call the method
            if dispatch_method is not None:
                response = dispatch_method(method, params)
            else:
                response = self._dispatch(method, params)

        except:
            # Return a fault
            exc_type, exc_value, _ = sys.exc_info()
            fault = Fault(-32603, '{0}:{1}'.format(exc_type, exc_value))
            return fault.dump()

        if 'id' not in request or request['id'] in (None, ''):
            # It's a notification, no result needed
            # Do not use 'not id' as it might be the integer 0
            return None

        # Prepare a JSON-RPC dictionary
        try:
            return jsonrpclib.dump(response, rpcid=request['id'],
                                   is_response=True)

        except:
            # JSON conversion exception
            exc_type, exc_value, _ = sys.exc_info()
            fault = Fault(-32603, '{0}:{1}'.format(exc_type, exc_value))
            return fault.dump()
Example #33
0
    def stop_trex(self, seq):
        logger.info("Processing stop_trex() command.")
        if self.trex.get_seq()== seq:
            logger.debug("Abort request legit since seq# match")
            return self.trex.stop_trex()
        else:
            if self.trex.get_status() != TRexStatus.Idle:
                logger.warning("Abort request is only allowed to process initiated the run. Request denied.")

                return Fault(-33, 'Abort request is only allowed to process initiated the run. Request denied.')  # raise at client TRexRequestDenied
            else:
                return False
Example #34
0
 def stop_trex(self):
     if self.status == TRexStatus.Idle:
         # TRex isn't running, nothing to abort
         logger.info("TRex isn't running. No need to stop anything.")
         if self.errcode is not None:    # some error occurred, notify client despite TRex already stopped
                 return Fault(self.errcode, self.verbose_status)               # raise at client relevant exception, depending on the reason the error occured
         return False
     else:
         # handle stopping TRex's run
         self.session.join()
         logger.info("TRex session has been successfully aborted.")
         return True
Example #35
0
 def _marshaled_single_dispatch(self, request):
     # TODO - Use the multiprocessing and skip the response if
     # it is a notification
     # Put in support for custom dispatcher here
     # (See SimpleXMLRPCServer._marshaled_dispatch)
     method = request.get('method')
     params = request.get('params')
     try:
         response = self._dispatch(method, params)
     except:
         exc_type, exc_value, exc_tb = sys.exc_info()
         fault = Fault(-32603, '%s:%s' % (exc_type, exc_value))
         return fault.response()
     if 'id' not in request.keys() or request['id'] == None:
         # It's a notification
         return None
     try:
         response = jsonrpclib.dumps(response,
                                     methodresponse=True,
                                     rpcid=request['id'])
         return response
     except:
         exc_type, exc_value, exc_tb = sys.exc_info()
         fault = Fault(-32603, '%s:%s' % (exc_type, exc_value))
         return fault.response()
 def _marshaled_dispatch(self, data, dispatch_method=None):
     response = None
     try:
         request = jsonrpclib.loads(data)
     except Exception as e:
         fault = Fault(-32700, 'Request %s invalid. (%s)' % (data, e))
         response = fault.response()
         return response
     if not request:
         fault = Fault(-32600, 'Request invalid -- no request data.')
         return fault.response()
     if isinstance(request, list):
         # This SHOULD be a batch, by spec
         responses = []
         for req_entry in request:
             result = validate_request(req_entry)
             if type(result) is Fault:
                 responses.append(result.response())
                 continue
             resp_entry = self._marshaled_single_dispatch(req_entry)
             if resp_entry is not None:
                 responses.append(resp_entry)
         if len(responses) > 0:
             response = '[%s]' % ','.join(responses)
         else:
             response = ''
     else:
         result = validate_request(request)
         if type(result) is Fault:
             return result.response()
         response = self._marshaled_single_dispatch(request)
     return response
    def _marshaled_single_dispatch(self, request, dispatch_method=None):
        """
        Dispatches a single method call

        :param request: A validated request dictionary
        :param dispatch_method: Custom dispatch method (for method resolution)
        :return: A JSON-RPC response dictionary, or None if it was a
                 notification request
        """
        method = request.get('method')
        params = request.get('params')

        # Prepare a request-specific configuration
        if 'jsonrpc' not in request and self.json_config.version >= 2:
            # JSON-RPC 1.0 request on a JSON-RPC 2.0
            # => compatibility needed
            config = self.json_config.copy()
            config.version = 1.0
        else:
            # Keep server configuration as is
            config = self.json_config

        try:
            # TODO - Use the multiprocessing if it is a notification
            # Call the method
            if dispatch_method is not None:
                response = dispatch_method(method, params)
            else:
                response = self._dispatch(method, params, config)

        except:
            # Return a fault
            exc_type, exc_value, _ = sys.exc_info()
            fault = Fault(-32603,
                          '{0}:{1}'.format(exc_type, exc_value),
                          config=config)
            return fault.dump()

        if 'id' not in request or request['id'] in (None, ''):
            # It's a notification, no result needed
            # Do not use 'not id' as it might be the integer 0
            return None

        # Prepare a JSON-RPC dictionary
        try:
            return jsonrpclib.dump(response,
                                   rpcid=request['id'],
                                   is_response=True,
                                   config=config)
        except:
            # JSON conversion exception
            exc_type, exc_value, _ = sys.exc_info()
            fault = Fault(-32603,
                          '{0}:{1}'.format(exc_type, exc_value),
                          config=config)
            return fault.dump()
Example #38
0
 def _marshaled_dispatch(self, data, dispatch_method = None):
     response = None
     try:
         request = jsonrpclib.loads(data)
     except:
         fault = Fault(-32600, 'Request %s invalid.' % data)
         response = fault.response()
         return response
     version = get_version(request)
     if not version:
         fault = Fault(-32600, 'Request %s invalid.' % data)
         response = fault.response()
         return response
     if type(request) is types.ListType:
         # This SHOULD be a batch, by spec
         responses = []
         for req_entry in request:
             resp_entry = self._marshaled_single_dispatch(req_entry)
             if resp_entry is not None:
                 responses.append(resp_entry)
         response = '[%s]' % ','.join(responses)
     else:
         response = self._marshaled_single_dispatch(request)
     return response
Example #39
0
class SimpleJSONRPCDispatcher(SimpleXMLRPCServer.SimpleXMLRPCDispatcher):
    def __init__(self, encoding=None):
        SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self,
                                                           allow_none=True,
                                                           encoding=encoding)

    def _marshaled_dispatch(self,
                            data,
                            dispatch_method=None,
                            isNotification=[False]):
        response = None
        try:
            request = jsonrpclib.loads(data)
        except Exception, e:
            fault = Fault(-32700, 'Request %s invalid. (%s)' % (data, e))
            response = fault.response()
            return response
        if not request:
            fault = Fault(-32600, 'Request invalid -- no request data.')
            return fault.response()
        if type(request) is types.ListType:
            # This SHOULD be a batch, by spec
            responses = []
            for req_entry in request:
                result = validate_request(req_entry)
                if type(result) is Fault:
                    responses.append(result.response())
                    continue
                isNotification[0] = 'id' not in request.keys(
                ) or request['id'] == None
                resp_entry = self._marshaled_single_dispatch(
                    isNotification[0], req_entry)
                if resp_entry is not None:
                    responses.append(resp_entry)
            if len(responses) > 0:
                response = '[%s]' % ','.join(responses)
            else:
                response = ''
        else:
            result = validate_request(request)
            if type(result) is Fault:
                return result.response()
            isNotification[0] = 'id' not in request.keys(
            ) or request['id'] == None
            response = self._marshaled_single_dispatch(isNotification[0],
                                                       request)
        return response
Example #40
0
 def get_trex_version (self, base64 = True):
     try:
         logger.info("Processing get_trex_version() command.")
         if not self.trex_version:
             ret_code, stdout, stderr = run_command('./t-rex-64 --help', cwd = self.TREX_PATH)
             search_result = re.search('\n\s*(Version\s*:.+)', stdout, re.DOTALL)
             if not search_result:
                 raise Exception('Could not determine version from ./t-rex-64 --help')
             self.trex_version = binascii.b2a_base64(search_result.group(1).encode(errors='replace'))
         if base64:
             return self.trex_version.decode(errors='replace')
         else:
             return binascii.a2b_base64(self.trex_version).decode(errors='replace')
     except Exception as e:
         err_str = "Can't get trex version, error: %s" % e
         logger.error(err_str)
         return Fault(-33, err_str)
    def _marshaled_single_dispatch(self, request, dispatch_method=None):
        """
        Dispatches a single method call

        :param request: A validated request dictionary
        :param dispatch_method: Custom dispatch method (for method resolution)
        :return: A JSON-RPC response dictionary, or None if it was a
                 notification request
        """
        method = request.get('method')
        params = request.get('params')

        # Prepare a request-specific configuration
        if 'jsonrpc' not in request and self.json_config.version >= 2:
            # JSON-RPC 1.0 request on a JSON-RPC 2.0
            # => compatibility needed
            config = self.json_config.copy()
            config.version = 1.0
        else:
            # Keep server configuration as is
            config = self.json_config

        # Test if this is a notification request
        is_notification = 'id' not in request or request['id'] in (None, '')
        if is_notification and self.__notification_pool is not None:
            # Use the thread pool for notifications
            if dispatch_method is not None:
                self.__notification_pool.enqueue(dispatch_method,
                                                 method, params)
            else:
                self.__notification_pool.enqueue(self._dispatch,
                                                 method, params, config)

            # Return immediately
            return None
        else:
            # Synchronous call
            try:
                # Call the method
                if dispatch_method is not None:
                    response = dispatch_method(method, params)
                else:
                    response = self._dispatch(method, params, config)
            except Exception as ex:
                # Return a fault
                fault = Fault(-32603, '{0}:{1}'.format(type(ex).__name__, ex),
                              config=config)
                _logger.error("Error calling method %s: %s", method, fault)
                return fault.dump()

            if is_notification:
                # It's a notification, no result needed
                # Do not use 'not id' as it might be the integer 0
                return None

        # Prepare a JSON-RPC dictionary
        try:
            return jsonrpclib.dump(response, rpcid=request['id'],
                                   is_response=True, config=config)
        except Exception as ex:
            # JSON conversion exception
            fault = Fault(-32603, '{0}:{1}'.format(type(ex).__name__, ex),
                          config=config)
            _logger.error("Error preparing JSON-RPC result: %s", fault)
            return fault.dump()
Example #42
0
        return response

    def _marshaled_single_dispatch(self, request):
        # TODO - Use the multiprocessing and skip the response if
        # it is a notification
        # Put in support for custom dispatcher here
        # (See SimpleXMLRPCServer._marshaled_dispatch)
        method = request.get('method')
        params = request.get('params')
        try:
            response = self._dispatch(method, params)
        except Fault, fault:
            return fault.response()
        except:
            exc_type, exc_value, exc_tb = sys.exc_info()
            fault = Fault(-32603, '%s:%s' % (exc_type, exc_value))
            return fault.response()
        if 'id' not in request.keys() or request['id'] == None:
            # It's a notification
            return None
        try:
            response = jsonrpclib.dumps(response,
                                        methodresponse=True,
                                        rpcid=request['id']
                                        )
            return response
        except:
            exc_type, exc_value, exc_tb = sys.exc_info()
            fault = Fault(-32603, '%s:%s' % (exc_type, exc_value))
            return fault.response()