def url(self, service_id, operation_id, operation_summary): """ Generate the mapping rule for an operation that has RequestMapping in the VMODL2 service definition. :type service_id: :class:`str` :param service_id: Service identifier :type operation_id: :class:`str` :param operation_id: Operation identifier :type operation_summary: :class:`vmware.vapi.server.rest_handler.MetadataStore.OperationSummary` :param operation_summary: Details of the operation :rtype: :class:`tuple` of :class:`str` and :class:`str` :return: Tuple that has URL and the HTTP method for the given operation. """ request_mapping = operation_summary.request_mapping_metadata http_method = request_mapping.elements[ RestAnnotations.METHOD_ELEMENT].string_value custom_url = request_mapping.elements[ RestAnnotations.VALUE_ELEMENT].string_value custom_url = custom_url.replace('{', '<') custom_url = custom_url.replace('}', '>') custom_url = '%s%s' % (self._rest_prefix, custom_url[1:]) # Get value of fixed query parameter 'action' if it exists if '?' in custom_url: (custom_url, param) = custom_url.split('?') (_, action_value) = param.split('=') self._validate_action_param(param, http_method) else: params = request_mapping.elements.get( RestAnnotations.PARAMS_ELEMENT) if params and params.list_value: action_value = None for param in params.list_value: param_split = param.split('=') if (len(param_split) == 2 and param_split[0] == RestAnnotations.ACTION_PARAM): action_value = param_split[1] self._validate_action_param(param, http_method) break else: action_value = None dispatch_info = DispatchInfo( mapping_type=RestAnnotationType.REQUEST, operation_id=get_non_task_operation_name(operation_id), action_value=action_value) return (custom_url, http_method, dispatch_info)
def url(self, service_id, operation_id, operation_summary): """ Generate the URL for the given operation :type service_id: :class:`str` :param service_id: Service identifier :type operation_id: :class:`str` :param operation_id: Operation identifier :type operation_summary: :class:`vmware.vapi.server.rest_handler.MetadataStore.OperationSummary` :param operation_summary: Details of the operation :type param_info_map: :class:`collections.OrderedDict` of :class:`str` and :class:`com.vmware.vapi.metadata.metamodel_client.FieldInfo` :return: Tuple that has URL and the HTTP method for the given operation. """ http_method, request_metadata = \ next(iter(operation_summary.verb_metadata.items())) custom_url = request_metadata.elements[ RestAnnotations.PATH_ELEMENT].string_value custom_url = custom_url.replace('{', '<') custom_url = custom_url.replace('}', '>') custom_url = '%s%s' % (self._rest_prefix, custom_url[1:]) dispatch_params = request_metadata.elements.get( RestAnnotations.PARAMS_ELEMENT) if dispatch_params is not None: dispatch_params = dispatch_params.list_value dispatch_headers = request_metadata.elements.get( RestAnnotations.HEADERS_ELEMENT) if dispatch_headers is not None: dispatch_headers = dispatch_headers.list_value dispatch_info = DispatchInfo( mapping_type=RestAnnotationType.VERB, operation_id=get_non_task_operation_name(operation_id), params=dispatch_params, headers=dispatch_headers ) return (custom_url, http_method, dispatch_info)
def url(self, service_id, operation_id, operation_summary): """ Generate the URL for the given operation :type service_id: :class:`str` :param service_id: Service identifier :type operation_id: :class:`str` :param operation_id: Operation identifier :type operation_summary: :class:`vmware.vapi.server.rest_handler.MetadataStore.OperationSummary` :param operation_summary: Details of the operation :rtype: :class:`tuple` of :class:`str` and :class:`str` :return: Tuple that has URL and the HTTP method for the given operation. """ service_url = self._generate_service_base_url(service_id) dispatch_info = DispatchInfo( mapping_type=RestAnnotationType.NONE, operation_id=get_non_task_operation_name(operation_id)) return (service_url, 'POST', dispatch_info)
def invoke(self, ctx, method_id, input_value): """ Invokes the specified method using the execution context and the input provided :type ctx: :class:`vmware.vapi.core.ExecutionContext` :param ctx: Execution context for this method :type input_value: :class:`vmware.vapi.data.value.StructValue` :param input_value: Method input parameters :rtype: :class:`vmware.vapi.core.MethodResult` :return: Result of the method invocation """ op_info = self._operations.get(method_id.get_name()) # Set execution context set_context(ctx) try: # input validators validators = op_info['input_value_validator_list'] input_type = op_info['input_type'] for validator in validators: msg_list = validator.validate(input_value, input_type) if msg_list: error_value = make_error_value_from_msgs( self._invalid_argument_def, *msg_list) return MethodResult(error=error_value) error_value = ApiInterfaceSkeleton.check_for_unknown_fields( input_type, input_value) if error_value: return MethodResult(error=error_value) try: meth_args = TypeConverter.convert_to_python( input_value, binding_type=input_type, resolver=self._resolver) except CoreException as e: error_value = make_error_value_from_msgs( self._invalid_argument_def, *e.messages) return MethodResult(error=error_value) method_name = Converter.canonical_to_pep( get_non_task_operation_name(method_id.get_name())) method = getattr(self._impl, method_name) # If it's a task method then create a new thread to run provider # impl and return task id or result depending upon type of # invocation. if op_info['task_type'] != TaskType.NONE: meth_output, task_accepted = self._invoke_task_operation( ctx, method_id, method, meth_args) if isinstance(meth_output, VapiError): raise meth_output # pylint: disable=raising-bad-type # In case of provider not accepting task throw an error. if task_accepted is False: msg_list = [message_factory.get_message( 'vapi.bindings.skeleton.task.invalidstate')] error_value = make_error_value_from_msgs( self._internal_server_error_def, *msg_list) return MethodResult(error=error_value) else: meth_output = method(**meth_args) output_type = op_info['output_type'] # output validators validators = op_info['output_validator_list'] output = TypeConverter.convert_to_vapi(meth_output, output_type) for validator in validators: msg_list = validator.validate(output, output_type) if msg_list: error_value = make_error_value_from_msgs( self._internal_server_error_def, *msg_list) return MethodResult(error=error_value) result = MethodResult(output=output) except CoreException as e: logger.exception("Error in invoking %s - %s", str(method_id), e) error_value = make_error_value_from_msgs( self._internal_server_error_def, *e.messages) result = MethodResult(error=error_value) except VapiError as e: exc_info = sys.exc_info() error_type = e.__class__.get_binding_type() try: error = TypeConverter.convert_to_vapi(e, error_type) except CoreException as ce: logger.error('Failed to convert %s to error type %s because %s', e, error_type.name, ' because '.join((e.def_msg for e in ce.messages)), exc_info=exc_info) raise result = MethodResult(error=error) finally: # Reset the execution context after the operation clear_context() return result