Ejemplo n.º 1
0
    def visit_enum(self, typ):
        """
        Visit a enum type python value

        :type  typ: :class:`vmware.vapi.bindings.type.EnumType`
        :param typ: Binding type of the value
        """
        # If the binding type is EnumType, we will accept either
        # a plain string (or) a class variable of
        # :class:`vmware.vapi.bindings.enum.Enum` type.
        # String will be sent when the user invoked an API call
        # by sending a plain dictionary object (deserialized
        # from a human readable JSON).
        # Enum will be sent when the user use a language binding type
        # to invoke an operation.
        if not isinstance(self._in_value, six.string_types):
            msg = message_factory.get_message(
                'vapi.bindings.typeconverter.unexpected.python.type', typ.name,
                type(self._in_value).__name__)
            logger.debug(msg)
            raise CoreException(msg)
        if isinstance(self._in_value, Enum):
            # Check if it is the expected enum class
            expected_name = typ.name
            actual_name = self._in_value.get_binding_type().name
            # TODO: compare the types instead of names.
            if expected_name != actual_name:
                msg = message_factory.get_message(
                    'vapi.bindings.typeconverter.unexpected.enum.type',
                    expected_name, actual_name)
                logger.debug(msg)
                raise CoreException(msg)
        # Convert from vmware.vapi.bindings.Enum instance to string value
        enum_string_value = str(self._in_value)
        self._out_value = typ.definition.new_value(enum_string_value)
Ejemplo n.º 2
0
    def target(self, definition):
        """
        Resolves the reference. An unresolved reference can be resolved exactly
        once. A resolved reference cannot be re-resolved.

        :type  definition: :class:`DataDefinition`
        :param definition: structure definition
        :raise: :class:`vmware.vapi.exception.CoreException`: if the reference is
            already resolved (already has) a target) or if the name of the
            reference does not match the name of the definition
        """
        if not definition:
            raise ValueError('StructDefinition may not be None')
        if self._definition:
            msg = message_factory.get_message(
                'vapi.data.structref.already.resolved', self.name)
            logger.debug(msg)
            raise CoreException(msg)
        if self.name != definition.name:
            msg = message_factory.get_message(
                'vapi.data.structref.resolve.type.mismatch', self.name,
                definition.name)
            logger.debug(msg)
            raise CoreException(msg)
        self._definition = definition
Ejemplo n.º 3
0
    def _visit_vapi_struct(self, typ):
        """
        Visit an instance of VapiStruct class

        :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
        """
        # Check if it is the expected struct class
        expected_name = typ.name
        actual_name = self._in_value.get_binding_type().name
        # TODO: compare the types instead of names.
        if expected_name != actual_name:
            msg = message_factory.get_message(
                'vapi.bindings.typeconverter.unexpected.struct.class',
                expected_name, actual_name)
            logger.debug(msg)
            raise CoreException(msg)
        in_value = self._in_value
        out_value = typ.definition.new_value()
        field_names = typ.get_field_names()
        for field in field_names:
            try:
                self._in_value = in_value.get_field(field)
                # If self._in_value is None and field type is not
                # optional, raise an error
                field_type = typ.get_field(field)
                if (not isinstance(field_type, OptionalType)
                        and self._in_value is None):
                    raise AttributeError
            except AttributeError:
                msg = message_factory.get_message(
                    'vapi.bindings.typeconverter.struct.missing.field', field,
                    typ.name)
                logger.debug(msg)
                raise CoreException(msg)

            try:
                self.visit(typ.get_field(field))
            except Exception as e:
                msg = message_factory.get_message(
                    'vapi.bindings.typeconverter.struct.invalid.field', field,
                    typ.name)
                logger.debug(msg)
                raise CoreException(msg, e)
            out_value.set_field(field, self._out_value)

        for k, v in six.iteritems(in_value._get_extra_fields()):  # pylint: disable=W0212
            out_value.set_field(k, v)
        self._in_value = in_value
        self._out_value = out_value
Ejemplo n.º 4
0
    def _convert_to_string(data_value):
        """
        Serialize data value to string for use in Request URL

        :type  data_value: :class:`vmware.vapi.data.value.DataValue`
        :param data_value: Data value
        :rtype   :class:`str` or :class:`NoneType`
        :return: Serialized string for use in Request URL or None
        """
        if isinstance(data_value, OptionalValue):
            if data_value.is_set():
                return RequestSerializer._convert_to_string(data_value.value)
            else:
                return None
        elif isinstance(data_value, BooleanValue):
            return DataValueConverter.convert_to_json(data_value)
        elif isinstance(data_value, StringValue):
            return data_value.value
        elif isinstance(data_value, IntegerValue):
            return str(data_value.value)
        else:
            msg = message_factory.get_message(
                'vapi.data.serializers.rest.unsupported_data_value',
                data_value.type)
            raise CoreException(msg)
Ejemplo n.º 5
0
    def visit_map(self, typ):
        """
        Visit a List Value. This ListValue must represent a map. Each element
        of the ListValue is a StructValue with two fields, namely 'key' and
        'value'. The 'key' field represents the key of the map and the 'value'
        field represents the value of the map. Also, since this represents a
        map, there should not be duplicate keys.

        :type  typ: :class:`vmware.vapi.bindings.type.MapType`
        :param typ: Binding type of the value
        """
        in_value = self._in_value
        key_typ = typ.key_type
        value_typ = typ.value_type
        out_value = {}
        for elt_value in in_value:
            key = self._visit_struct_field(elt_value.get_field(MAP_KEY_FIELD),
                                           key_typ)
            if key in out_value:
                msg = message_factory.get_message(
                    'vapi.bindings.typeconverter.map.duplicate.key', key)
                logger.debug(msg)
                raise CoreException(msg)
            value = self._visit_struct_field(
                elt_value.get_field(MAP_VALUE_FIELD), value_typ)
            out_value[key] = value
        self._out_value = out_value
        self._in_value = in_value
Ejemplo n.º 6
0
def raise_core_exception(msg_list):
    """
    Create and raise a CoreException from a list of messages

    :type msg_list: :class:`vmware.vapi.message.Message`
    :param msg_list: List of messages

    :raise: CoreException if msg list is not empty
    """
    exception = None
    if msg_list:
        for msg in reversed(msg_list):
            if exception:
                exception = CoreException(msg, cause=exception)
            else:
                exception = CoreException(msg)
    if exception is not None:
        raise exception  # pylint: disable-msg=E0702
Ejemplo n.º 7
0
 def check_resolved(self):
     """
     Check if the reference is resolved or not
     """
     if self._definition is None:
         msg = message_factory.get_message(
             'vapi.data.structref.not.resolved', self.name)
         logger.debug(msg)
         raise CoreException(msg)
Ejemplo n.º 8
0
def _convert_data_value_to_data_def_int(data_value, ctx):
    """
    Convert :class:`vmware.vapi.data.value.DataValue` object that
    corresponds to DataDefinition structure in introspection VMODL2 into
    :class:`vmware.vapi.data.definition.DataDefinition` object using the
    ReferenceResolver context.

    ReferenceResolver is used to resolve any STRUCTURE_REF objects present in
    the input value. This function registers all the STRUCTURE and
    STRUCTURE_REF objects with ReferenceResolver. The caller of this function
    must call "resolve()" on the ReferenceResolver to resolve the
    StructDefinition references in StructRefDefinition

    :type  data_value: :class:`vmware.vapi.data.value.DataValue`
    :param data_value: Data value representing the data definition object
    :type  ctx: :class:`vmware.vapi.data.definition.ReferenceResolver`
    :param ctx: Context to resolve structure reference definitions
    :rtype: :class:`vmware.vapi.data.definition.DataDefinition`
    :return: Data definition
    """
    type_name = data_value.get_field('type').value
    data_def_class = reverse_data_type_map.get(type_name)
    # Primitive types
    if type_name in [
            'VOID', 'LONG', 'DOUBLE', 'STRING', 'OPAQUE', 'BOOLEAN', 'SECRET',
            'BINARY', 'DYNAMIC_STRUCTURE', 'ANY_ERROR'
    ]:
        return data_def_class()
    # Generic types
    elif type_name in ['OPTIONAL', 'LIST']:
        element_type_def = _convert_data_value_to_data_def_int(
            data_value.get_field('element_definition').value, ctx)
        return data_def_class(element_type_def)
    # Struct Ref definition
    elif type_name == 'STRUCTURE_REF':
        data_def = data_def_class(data_value.get_field('name').value.value)
        ctx.add_reference(data_def)
        return data_def
    # Structure and Error types
    elif type_name in ['STRUCTURE', 'ERROR']:
        name = data_value.get_field('name').value.value
        field_defs = []
        fields = data_value.get_field('fields').value
        for field_info in fields:
            field_name = field_info.get_field('key').value
            field_def = _convert_data_value_to_data_def_int(
                field_info.get_field('value'), ctx)
            field_defs.append((field_name, field_def))
        data_def = data_def_class(name, field_defs)
        ctx.add_definition(data_def)
        return data_def
    else:
        msg = message_factory.get_message('vapi.introspection.invalid.type',
                                          type_name)
        logger.debug(msg)
        raise CoreException(msg)
Ejemplo n.º 9
0
 def __init__(self, values=None):
     """
     Initialize ListValue
     """
     DataValue.__init__(self, Type.LIST)
     if values is not None and not isinstance(values, list):
         msg = message_factory.get_message("vapi.data.invalid", self.type,
                                           type(values).__name__)
         logger.debug(msg)
         raise CoreException(msg)
     self._list_val = values if values is not None else []
Ejemplo n.º 10
0
    def visit_void(self, typ):
        """
        Visit a void value (i.e. None)

        :type  typ: :class:`vmware.vapi.bindings.type.VoidType`
        :param typ: Binding type of the value
        """
        if self._in_value is not None:
            msg = message_factory.get_message(
                'vapi.bindings.typeconverter.voiddef.expect.null',
                type(self._in_value).__name__)
            logger.debug(msg)
            raise CoreException(msg)
        self._out_value = typ.definition.new_value()
Ejemplo n.º 11
0
 def resolve(self):
     """
     Traverses all references and resolves the unresolved ones.
     """
     for reference in self._references:
         if reference.target is None:
             definition = self._definitions.get(reference.name)
             if definition is None:
                 msg = message_factory.get_message(
                     'vapi.data.structref.structure.not.defined',
                     reference.name)
                 logger.debug(msg)
                 raise CoreException(msg)
             reference.target = definition
Ejemplo n.º 12
0
    def __init__(self, value=""):
        """
        Initialize StringValue

        :type  value: :class:`str`
        :kwarg value: String value to be initialized
        """
        PrimitiveDataValue.__init__(self, Type.SECRET)
        ComparableValueMixin.__init__(self)
        if not isinstance(value, six.string_types):
            msg = message_factory.get_message("vapi.data.invalid", self.type,
                                              type(value).__name__)
            raise CoreException(msg)
        self.value = value
Ejemplo n.º 13
0
    def visit_set(self, typ):
        """
        Visit a python set

        :type  typ: :class:`vmware.vapi.bindings.type.SetType`
        :param typ: Binding type of the value
        """
        if not isinstance(self._in_value, (set, frozenset)):
            msg = message_factory.get_message(
                'vapi.bindings.typeconverter.invalid', 'set',
                type(self._in_value))
            logger.debug(msg)
            raise CoreException(msg)
        self.visit_list(typ)
Ejemplo n.º 14
0
    def __init__(self, value=b''):
        """
        Initialize BooleanValue

        :type value: :class:`str` for Python 2 and :class:`bytes` for Python 3
        :kwarg value: Binary value to be initialized
        """
        PrimitiveDataValue.__init__(self, Type.BLOB)
        ComparableValueMixin.__init__(self)
        if not isinstance(value, six.binary_type):
            msg = message_factory.get_message("vapi.data.invalid", self.type,
                                              type(value).__name__)
            logger.debug(msg)
            raise CoreException(msg)
        self.value = value
Ejemplo n.º 15
0
    def __init__(self, value=False):
        """
        Initialize BooleanValue

        :type  value: :class:`bool`
        :kwarg value: Bool value to be initialized
        """
        PrimitiveDataValue.__init__(self, Type.BOOLEAN)
        ComparableValueMixin.__init__(self)
        if not isinstance(value, bool):
            msg = message_factory.get_message("vapi.data.invalid", self.type,
                                              type(value).__name__)
            logger.debug(msg)
            raise CoreException(msg)
        self.value = value
Ejemplo n.º 16
0
    def _process_error(msg_id, *args):
        """
        Helper method to process error condition. It creates a localizable
        message, logs it in debug mode and raises a CoreException.

        :type  msg_id: :class:`str`
        :param msg_id: The unique message identifier
        :type  args: :class:`list` of :class:`object`
        :param args: Arguments for the message
        :raise CoreException: Raise the CoreException with the localizable
            message
        """
        msg = message_factory.get_message(msg_id, *args)
        logger.debug(msg)
        raise CoreException(msg)
Ejemplo n.º 17
0
    def visit_error(self, typ):
        """
        Visit an error value

        :type  typ: :class:`vmware.vapi.bindings.type.ErrorType`
        :param typ: Binding type of the value
        """
        if isinstance(self._in_value, VapiError):
            self._visit_vapi_struct(typ)
        else:
            msg = message_factory.get_message(
                'vapi.bindings.typeconverter.unexpected.error.type',
                type(self._in_value).__name__)
            logger.debug(msg)
            raise CoreException(msg)
Ejemplo n.º 18
0
    def _visit(self, obj):
        """
        Visit json object

        :type  obj: :class:`object`
        :param obj: Python object
        :rtype: :class:`vmware.vapi.data.value.DataValue`
        :return: Data value
        """
        obj_type = type(obj)
        if obj_type not in self._dispatch_map:
            msg = message_factory.get_message(
                'vapi.data.serializers.invalid.type', obj_type)
            raise CoreException(msg)
        return self._dispatch_map.get(type(obj))(obj)
Ejemplo n.º 19
0
    def __init__(self, value=0):
        """
        Initialize IntegerValue

        :type  value: :class:`int`
        :kwarg value: Integer value to be initialized
        """
        PrimitiveDataValue.__init__(self, Type.INTEGER)
        ComparableValueMixin.__init__(self)
        if not isinstance(value, six.integer_types):
            msg = message_factory.get_message("vapi.data.invalid", self.type,
                                              type(value).__name__)
            logger.debug(msg)
            raise CoreException(msg)
        self.value = value
Ejemplo n.º 20
0
    def visit_opaque(self, typ):
        """
        Visit an opaque value. Don't do any conversion.

        :type  typ: :class:`vmware.vapi.bindings.type.OpaqueType`
        :param typ: Binding type of the value
        """
        if not isinstance(self._in_value, DataValue):
            msg = message_factory.get_message(
                'vapi.bindings.typeconverter.unexpected.python.type',
                DataValue.__name__,
                type(self._in_value).__name__)
            logger.debug(msg)
            raise CoreException(msg)
        self._out_value = self._in_value
Ejemplo n.º 21
0
    def __init__(self, value=0.0):
        """
        Initialize DoubleValue

        :type  value: :class:`float` or :class:`decimal.Decimal`
        :kwarg value: Float or decimal.Decimal value to be initialized
        """
        PrimitiveDataValue.__init__(self, Type.DOUBLE)
        ComparableValueMixin.__init__(self)
        if not isinstance(value, float) and not isinstance(value, Decimal):
            msg = message_factory.get_message('vapi.data.invalid', self.type,
                                              type(value).__name__)
            logger.debug(msg)
            raise CoreException(msg)
        # Accept floats, but store as decimal
        if isinstance(value, float):
            value = Decimal(str(value))
        if isinstance(value, Decimal):
            if math.isinf(float(value)):
                msg = message_factory.get_message(
                    'vapi.data.invalid.double.inf', value)
                logger.debug(msg)
                raise CoreException(msg)
        self.value = value
Ejemplo n.º 22
0
    def get_field(self, field):
        """
        Returns the field value of the field present in the StructValue

        :type  field: :class:`str`
        :param field: Name of the field
        :rtype: :class:`DataValue`
        :return: Returns the field value of the field present in the StructValue
        """
        value = self._fields.get(field)
        if value is None:
            msg = message_factory.get_message(
                "vapi.data.structure.getfield.unknown", field)
            logger.debug(msg)
            raise CoreException(msg)
        return value
Ejemplo n.º 23
0
    def __init__(self, value=""):
        """
        Initialize StringValue

        :type  value: :class:`str` or :class:`unicode` for Python 2 and
                      :class:`str` for Python 3
        :kwarg value: String value to be initialized
        """
        PrimitiveDataValue.__init__(self, Type.STRING)
        ComparableValueMixin.__init__(self)
        if not isinstance(value, six.string_types):
            msg = message_factory.get_message("vapi.data.invalid", self.type,
                                              type(value).__name__)
            logger.debug(msg)
            raise CoreException(msg)
        self.value = value
Ejemplo n.º 24
0
    def set_field(self, field, value):
        """
        Set the field value for the field name passed in the argument

        :type  field: :class:`str`
        :param field: Name of the field
        :type  field: :class:`str`
        :param field: Name of the field to be set
        :type  value: :class:`DataValue`
        :param value: DataValue to be used for the field
        """
        if value is None:
            msg = message_factory.get_message(
                "vapi.data.structure.setfield.null", field)
            logger.debug(msg)
            raise CoreException(msg)

        self._fields[field] = value
Ejemplo n.º 25
0
    def visit_any_error(self, typ):
        """
        Visit any error value

        :type  typ: :class:`vmware.vapi.bindings.type.AnyErrorType`
        :param typ: Binding type of the value
        """
        if isinstance(self._in_value, UnresolvedError):
            self._out_value = self._in_value.get_error_value()
        elif isinstance(self._in_value, VapiError):
            self._visit_vapi_struct(self._in_value.get_binding_type())
        else:

            msg = message_factory.get_message(
                'vapi.bindings.typeconverter.unexpected.python.type',
                VapiError.__name__,
                type(self._in_value).__name__)
            logger.debug(msg)
            raise CoreException(msg)
Ejemplo n.º 26
0
    def publish(self, accept=False):
        """
        Publish the temporary task info into task manager

        :type  accept: :class:`bool`
        :param accept: Accept task and return task id to client
        """
        published_info = self.task_manager.get_info(self.task_id)

        # Override the common info fields which can't be modified by providers
        self._override_api_info(published_info)

        if self.info.result is not None:
            # Check if result type is Opaque or actual type
            res_type = self.info_type.get_binding_type().get_field('result')
            if isinstance(res_type.element_type.definition, OpaqueDefinition):
                result = None
                try:
                    result = TypeConverter.convert_to_vapi(
                        self.info.result, self.result_type.get_binding_type())
                except AttributeError:
                    result = TypeConverter.convert_to_vapi(
                        self.info.result, self.result_type)
                self.info.result = result

        info = TypeConverter.convert_to_vapi(self.info,
                                             self.info_type.get_binding_type())
        self.task_manager.set_info(self.task_id, info)

        if accept:
            event = get_event()
            event.set()
            clear_event()
            # Validate that description is set while accepting the task
            if (self.info.description is None
                    or (not self.info.description.id
                        and not self.info.description.default_message)):
                msg = message_factory.get_message(
                    'vapi.data.structure.field.missing', self.info_type,
                    'description')
                logger.debug(msg)
                raise CoreException(msg)
Ejemplo n.º 27
0
    def convert_from_datetime(datetime_obj):
        """
        Convert from Python native datetime object to the datetime format in
        vAPI Runtime i.e. YYYY-MM-DDThh:mm:ss.sssZ.

        datetime objects returned by datetime.now() or datetime.utcnow() does
        not contain any timezone information. The caller to this method should
        only pass datetime objects that have time in UTC timezone.

        datetime objects have microsecond precision but the vAPI datetime
        string format has millisecond precision. The method will truncate the
        microsecond to millisecond and won't do any rounding of the value.

        :type  datetime_obj: :class:`datetime.datetime`
        :param datetime_obj: Datetime object with UTC time
        :rtype: :class:`str`
        :return: String representation of the input datetime object
        """
        if datetime_obj.tzinfo:
            # If tzinfo object is present, it should be in UTC timezone
            # i.e. timedelta is 0
            if datetime_obj.tzinfo.utcoffset(datetime_obj) != \
                    datetime.timedelta(0):
                msg = message_factory.get_message(
                    'vapi.bindings.typeconverter.datetime.serialize.invalid.tz',
                    str(datetime_obj))
                logger.error(msg)
                raise CoreException(msg)

        # Since it is UTC timezone, replacing it with None
        # the output of isoformat() does not match vAPI runtime datetime string
        # format if tzinfo is present in the datetime object
        datetime_obj = datetime_obj.replace(tzinfo=None)

        iso_str = datetime_obj.isoformat()
        if datetime_obj.microsecond:
            # datetime prints microseconds, reducing precision to milliseconds
            iso_str = iso_str[:-3]
        else:
            # Python .isoformat does not print microsecond if it is 0
            iso_str = '%s.000' % iso_str
        return '%sZ' % iso_str  # Adding Z to indicate it is UTC timezone
Ejemplo n.º 28
0
    def _visit_session_security_context(security_context, is_vapi_rest):
        """
        Get the authorization headers for session security context. This is
        currently supported for vapi-rest format only

        :type  security_context: :class:`vmware.vapi.core.SecurityContext`
        :param security_context: Security context
        :type  is_vapi_rest: :class:`bool`
        :param is_vapi_rest: Whether the Rest json message format is VAPI Rest
            or not
        :rtype   :class:`tuple`
        :return: Tuple of HTTP headers and cookies
        """
        if not is_vapi_rest:
            msg = message_factory.get_message(
                'vapi.data.serializers.security_context.unsupported',
                security_context.get(SCHEME_ID))
            raise CoreException(msg)
        session_id = security_context.get(SESSION_ID)
        return ({REST_SESSION_ID_KEY: session_id}, None)
Ejemplo n.º 29
0
    def visit_optional(self, typ):
        """
        Visit OptionalValue

        :type  typ: :class:`vmware.vapi.bindings.type.OptionalType`
        :param typ: Binding type of the value
        """
        if isinstance(self._in_value, OptionalValue):
            if self._in_value.is_set():
                self._in_value = self._in_value.value
                self.visit(typ.element_type)
            else:
                self._out_value = None
        else:
            # Invalid data value
            msg = message_factory.get_message(
                'vapi.bindings.typeconverter.invalid', OptionalValue.__name__,
                type(self._in_value).__name__)
            logger.debug(msg)
            raise CoreException(msg)
Ejemplo n.º 30
0
    def _visit_oauth_security_context(security_context, is_vapi_rest):
        """
        Get the authorization headers for oauth security context. This is
        currently supported for skyscraper-rest format only

        :type  security_context: :class:`vmware.vapi.core.SecurityContext`
        :param security_context: Security context
        :type  is_vapi_rest: :class:`bool`
        :param is_vapi_rest: Whether the Rest json message format is VAPI Rest
            or not
        :rtype   :class:`tuple`
        :return: Tuple of HTTP headers and cookies
        """
        if is_vapi_rest:
            msg = message_factory.get_message(
                'vapi.data.serializers.security_context.unsupported',
                security_context.get(SCHEME_ID))
            raise CoreException(msg)
        oauth_token = security_context.get(ACCESS_TOKEN)
        return ({'csp-auth-token': oauth_token}, None)