Exemple #1
0
    def visit_struct(self, typ):
        """
        Visit StructValue

        :type  typ: :class:`vmware.vapi.bindings.type.StructType`
        :param typ: Binding type of the value
        """
        in_value = self._in_value
        out_value = {}
        typ_field_names = typ.get_field_names()
        value_field_names = in_value.get_field_names()

        for field_name in typ_field_names:
            if typ.binding_class:
                pep_name = typ.binding_class._get_pep_name(field_name)  # pylint: disable=W0212
            else:
                pep_name = Converter.canonical_to_pep(field_name)
            field_type = typ.get_field(field_name)
            # When the request is converted from DataValue to Native value
            # on the server side:
            # - if the client - server version matches: we wont hit this case
            # - if new client talks to old server, runtime would have
            #   raised InvalidArgument error if there are unexpected optional
            #   fields
            # - if old client talks to new server, runtime adds the missing
            #   optional fields, so we wont hit this case
            #
            # When the response is converted from DataValue to Native value
            # on the client side:
            # - if the client - server version matches: we wont hit this case
            # - if new client talks to old server,  client bindings should
            #   tolerate the absence of expected optional properties. So,
            #   we have to set it to None!
            # - if old client talks to new server, we will visit all the known
            #   fields here and the unexpected fields are added to the
            #   VapiStruct object
            if ((isinstance(field_type, OptionalType)
                 or self._allow_skip_struct_fields)
                    and not in_value.has_field(field_name)):
                out_value[pep_name] = None
            else:
                out_value[pep_name] = self._visit_struct_field(
                    in_value.get_field(field_name), field_type)
        self._in_value = in_value

        struct_class = typ.binding_class
        if struct_class is not None:
            struct_class.validate_struct_value(self._in_value)
            self._out_value = struct_class(**out_value)

            # Fields present in struct value but not in struct binding type.
            extra_field_names = set(value_field_names) - set(typ_field_names)
            if extra_field_names:
                extra_fields = {}
                for field_name in extra_field_names:
                    extra_fields[field_name] = in_value.get_field(field_name)
                self._out_value._set_extra_fields(extra_fields)  # pylint: disable=E1103,W0212
        else:
            self._out_value = out_value
Exemple #2
0
    def _get_pep_name(cls, canonical_name):
        """
        Return the pep name for the provided canonical name

        :rtype: :class:`str`
        :return: Pep name used in the binding
        """
        if (cls._canonical_to_pep_names
                and canonical_name in cls._canonical_to_pep_names):
            return cls._canonical_to_pep_names[canonical_name]
        else:
            return Converter.canonical_to_pep(canonical_name)
Exemple #3
0
    def _pepify_args(meth_args):
        """
        Converts all the keys of given keyword arguments into PEP8 standard
        names

        :type  meth_args: :class:`dict`
        :param meth_args: The keyword arguments to be converted
        :rtype:  :class:`dict`
        :return: The converted keyword arguments
        """
        new_args = {}
        for k, v in six.iteritems(meth_args):
            new_args[Converter.canonical_to_pep(k)] = v
        return new_args
Exemple #4
0
    def _visit_python_dict(self, typ):
        """
        Visit an instance of Python native dictionary

        :type  typ: :class:`vmware.vapi.bindings.type.StructType`
        :param typ: Binding type of the value
        :rtype: :class:`vmware.vapi.data.value.DataValue`
        :return: vAPI Data value
        """
        in_value = self._in_value
        out_value = typ.definition.new_value()
        field_names = typ.get_field_names()
        for field_name in field_names:
            field_type = typ.get_field(field_name)
            try:
                if typ.binding_class:
                    # pylint: disable=W0212
                    pep_name = typ.binding_class._get_pep_name(field_name)
                else:
                    pep_name = Converter.canonical_to_pep(field_name)
                self._in_value = in_value[pep_name]
            except KeyError:
                if isinstance(field_type, OptionalType):
                    # If the field is optional, then tolerate
                    # the absence of it in the dictionary
                    self._in_value = None
                else:
                    msg = message_factory.get_message(
                        'vapi.bindings.typeconverter.dict.missing.key',
                        pep_name)
                    logger.debug(msg)
                    raise CoreException(msg)
            self.visit(field_type)
            out_value.set_field(field_name, self._out_value)
        self._in_value = in_value
        self._out_value = out_value
Exemple #5
0
    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