def generate_primitive_value(self, typ): output = StructValue(Introspection.DATA_DEFINITION) output.set_field('type', StringValue(typ)) output.set_field('fields', OptionalValue()) output.set_field('name', OptionalValue()) output.set_field('element_definition', OptionalValue()) return output
def test_invoke(self): ctx = ExecutionContext() input_ = StructValue(method_name) input_.set_field('message', StringValue('hello')) input_.set_field('throw', BooleanValue(False)) actual_method_result = self.provider.invoke(interface_name, method_name, input_, ctx) expected_method_result = MethodResult(output=StringValue('hello')) self.assertEqual(actual_method_result.output, expected_method_result.output) self.assertEqual(actual_method_result.error, expected_method_result.error)
def test_struct_ref_to_value(self): actual_output = convert_data_def_to_data_value( StructRefDefinition('mock')) expected_output = StructValue(Introspection.DATA_DEFINITION) expected_output.set_field('type', StringValue('STRUCTURE_REF')) expected_output.set_field('fields', OptionalValue()) expected_output.set_field('name', OptionalValue(StringValue('mock'))) expected_output.set_field('element_definition', OptionalValue()) self.assertEqual(actual_output, expected_output)
def serialize_input(input_value, rest_metadata): """ Serialize the input value :type input_value: :class:`vmware.vapi.data.value.StructValue` :param input_value: method input parameters :type rest_metadata: :class:`vmware.vapi.lib.rest.OperationRestMetadata` :param rest_metadata: Rest request metadata :rtype :class:`tuple` :return: Tuple of URL path, HTTP headers and request body """ if rest_metadata is not None: path_variable_field_names = \ rest_metadata.get_path_variable_field_names() query_param_field_names = \ rest_metadata.get_query_parameter_field_names() request_body_param = rest_metadata.request_body_parameter else: path_variable_field_names = [] query_param_field_names = [] request_body_param = None if request_body_param is not None: request_body_input_value = input_value.get_field( request_body_param) else: request_body_input_value = StructValue(name=input_value.name) path_variable_fields = {} query_param_fields = {} for (field_name, field_val) in input_value.get_fields(): if field_name in path_variable_field_names: field_str = RequestSerializer._convert_to_string(field_val) if field_str is not None: path_variable_fields[field_name] = field_str elif field_name in query_param_field_names: field_str = RequestSerializer._convert_to_string(field_val) if field_str is not None: query_param_fields[field_name] = field_str elif request_body_param is None: request_body_input_value.set_field(field_name, field_val) url_path = rest_metadata.get_url_path( path_variable_fields, query_param_fields) if rest_metadata else None return (url_path, {}, DataValueConverter.convert_to_json(request_body_input_value))
def visit_map(self, typ): """ Visit a python dict :type typ: :class:`vmware.vapi.bindings.type.MapType` :param typ: Binding type of the value """ in_value = self._in_value out_value = StructValue(MAP_STRUCT) for k, v in six.iteritems(in_value): self._in_value = k self.visit(typ.key_type) key_value = self._out_value.value self._in_value = v self.visit(typ.value_type) out_value.set_field(key_value, self._out_value) self._in_value = in_value self._out_value = out_value
def test_generic_def_to_value(self): for typ_def, typ in [(OptionalDefinition, 'OPTIONAL'), (ListDefinition, 'LIST')]: typ_def = typ_def(StringDefinition()) actual_output = convert_data_def_to_data_value(typ_def) expected_output = StructValue(Introspection.DATA_DEFINITION) element_value = self.generate_primitive_value('STRING') expected_output.set_field('type', StringValue(typ)) expected_output.set_field('fields', OptionalValue()) expected_output.set_field('name', OptionalValue()) expected_output.set_field('element_definition', OptionalValue(element_value)) self.assertEqual(actual_output, expected_output)
def test_invoke_long_running(self): ctx = ExecutionContext() input_ = StructValue(method_name) input_.set_field('message', StringValue('hello')) input_.set_field('throw', BooleanValue(False)) actual_method_result = self.provider.invoke(interface_name, '%s$task' % task_method_name, input_, ctx) expected_method_result = MethodResult(output=StringValue('hello')) try: id_split = actual_method_result.output.value.split(':') uuid.UUID(id_split[0], version=4) uuid.UUID(id_split[1], version=4) except ValueError: # There's no assertNotRaises so explicitly fail assert # in case a ValueError is thrown for invalid uuid. self.assertTrue(False) self.assertEqual(actual_method_result.error, expected_method_result.error)
def test_publish(self): info = self.task_handle.get_info() progress = Progress() progress.total = 100 progress.completed = 42 progress.message = self.progress_msg desc2 = LocalizableMessage(id='msg2', default_message='task1', args=[]) info.description = desc2 info.cancelable = False info.status = 'RUNNING' info.start_time = datetime.utcnow() info.progress = progress self.task_handle.publish() result = self.task_manager.get_info(self.task_id) self.assertEqual(result.get_field('status'), StringValue('RUNNING')) progress_val = StructValue('com.vmware.cis.task.progress') progress_val.set_field('total', IntegerValue(100)) progress_val.set_field('completed', IntegerValue(42)) progress_val.set_field( 'message', TypeConverter.convert_to_vapi( self.progress_msg, LocalizableMessage.get_binding_type())) self.assertEqual(result.get_field('progress'), OptionalValue(progress_val)) self.assertEqual(result.get_field('cancelable'), BooleanValue(False))
def visit_user_defined(self, type_info, json_value): """ Deserialize a user defined value :type type_info: :class:`com.vmware.vapi.metadata.metamodel_client.Type` :param type_info: Metamodel type information :type json_value: :class:`object` :param json_value: Value to be visited :rtype: :class:`vmware.vapi.data.value.StructValue` or :class:`vmware.vapi.data.value.StringValue` :return: DataValue created using the input """ user_defined_type_info = type_info.user_defined_type if user_defined_type_info.resource_type == Enumeration.RESOURCE_TYPE: return StringValue(json_value) elif user_defined_type_info.resource_type == Structure.RESOURCE_TYPE: structure_info = self._metadata.structure_map[ user_defined_type_info.resource_id] struct_value = StructValue(name=user_defined_type_info.resource_id) for field_name, field_value in six.iteritems(json_value): try: field_info = structure_info[str(field_name)] field_data_value = self.visit(field_info.type, field_value) struct_value.set_field(field_name, field_data_value) except KeyError: msg = 'Unexpected field \'%s\' in request' % field_name logger.error(msg) raise werkzeug.exceptions.BadRequest(msg) return struct_value else: msg = ('Could not process the request,' 'user defined type %s is not supported' % user_defined_type_info.resource_type) logger.error(msg) raise werkzeug.exceptions.InternalServerError(msg)
def augment_method_result_with_errors(service_id, operation_id, method_result, errors_to_augment): """ Returns a new method result that is identical to `method_result` except that the `errors_definition` field in the `output` (which is of type Operation.Info from Introspection service) contains the errors from the Info structure in `method_result` plus the errors in `errors_to_augment`. This code will be executed only for "get" operation in vAPI Operation Introspection service. :type service_id: :class:`str` :param service_id: Service identifier :type operation_id: :class:`str` :param operation_id: Operation identifier :type method_result: :class:`vmware.vapi.core.MethodResult` :param method_result: Operation result :type errors_to_augment: :class:`list` of :class:`vmware.vapi.data.value.StructValue` :param errors_to_augment: Errors to augment. These are struct values of type com.vmware.vapi.std.introspection.Operation.DataDefinition whose `type` field has the value ERROR to the DataDefinition type in Introspection service IDL. :rtype: :class:`vmware.vapi.data.value.DataValue` :return: Output data value """ if method_result.success(): if (service_id == Introspection.OPERATION_SVC and operation_id == 'get'): output = method_result.output augmented_output = StructValue( 'com.vmware.vapi.std.introspection.operation.info') augmented_output.set_field('input_definition', output.get_field('input_definition')) augmented_output.set_field('output_definition', output.get_field('output_definition')) errors = ListValue() error_names = [] for error_def in output.get_field('error_definitions'): errors.add(error_def) error_names.append(error_def.get_field('name').value.value) for error_def in errors_to_augment: if error_def.get_field('name').value.value not in error_names: errors.add(error_def) augmented_output.set_field('error_definitions', errors) return MethodResult(output=augmented_output) return method_result
def test_error_value_as_data_value(self): ev = make_error_value_from_msgs(self.error_def, *self.multiple_messages) self.assertTrue(isinstance(ev, StructValue)) self.assertEqual(self.error_name, ev.name) self.assertFalse(ev.get_field_names() is None) self.assertEqual(2, len(ev.get_field_names())) self.assertTrue('messages' in ev.get_field_names()) msg_struct1 = StructValue('localizable_message') msg_struct1.set_field('id', StringValue(self.message1.id)) msg_struct1.set_field('default_message', StringValue(self.message1.def_msg)) args_list = ListValue() args_list.add_all((StringValue(s) for s in self.message1.args)) msg_struct1.set_field('args', args_list) msg_struct2 = StructValue('localizable_message') msg_struct2.set_field('id', StringValue(self.message2.id)) msg_struct2.set_field('default_message', StringValue(self.message2.def_msg)) msg_struct2.set_field('args', ListValue()) msg_struct3 = StructValue('localizable_message') msg_struct3.set_field('id', StringValue(self.message3.id)) msg_struct3.set_field('default_message', StringValue(self.message3.def_msg)) msg_struct3.set_field('args', ListValue()) messages = ListValue() messages.add_all([msg_struct1, msg_struct2, msg_struct3]) expected_data_value = ev = make_error_value_from_msgs(self.error_def) expected_data_value.set_field('messages', messages) self.assertEqual(expected_data_value, ev)
def _invoke(self, raise_error=False): ctx = ExecutionContext() input_ = StructValue('input') input_.set_field('raise', BooleanValue(raise_error)) return self.provider.invoke(interface_name, mock_method_name, input_, ctx)
def test_value_to_struct_ref_def(self): struct_value = StructValue(Introspection.DATA_DEFINITION) struct_value.set_field('type', StringValue('STRUCTURE')) struct_value.set_field('name', OptionalValue(StringValue('mock'))) struct_value.set_field('element_definition', OptionalValue()) field_value = self.generate_primitive_value('STRUCTURE_REF') field_value.set_field('name', OptionalValue(StringValue('mock'))) field_entry = StructValue(MAP_ENTRY) field_entry.set_field('key', StringValue('field1')) field_entry.set_field('value', field_value) field_values = ListValue() field_values.add(field_entry) struct_value.set_field('fields', OptionalValue(field_values)) actual_output = convert_data_value_to_data_def(struct_value) expected_output = StructDefinition( 'mock', [('field1', StructRefDefinition('mock'))]) self.assertEqual(actual_output, expected_output) # Check the circular reference as well self.assertEqual( actual_output.get_field('field1').target, expected_output)
def convert_data_def_to_data_value(data_def): """ Convert :class:`vmware.vapi.data.definition.DataDefinition` object to :class:`vmware.vapi.data.value.DataValue` object. The type of the object returned is a struct value that corresponds to DataDefinition VMODL2 type present in introspection service. :type data_def: :class:`vmware.vapi.data.definition.DataDefinition` :param data_def: Data definition :rtype: :class:`vmware.vapi.data.value.DataValue` :return: Data value representing the data definition object """ result = StructValue(Introspection.DATA_DEFINITION) result.set_field('type', StringValue(data_type_map.get(data_def.type))) if (data_def.type == Type.STRUCTURE or data_def.type == Type.STRUCTURE_REF or data_def.type == Type.ERROR): result.set_field('name', OptionalValue(StringValue(data_def.name))) else: result.set_field('name', OptionalValue()) if (data_def.type == Type.OPTIONAL or data_def.type == Type.LIST): element_definition = data_def.element_type element_value = convert_data_def_to_data_value(element_definition) result.set_field('element_definition', OptionalValue(element_value)) else: result.set_field('element_definition', OptionalValue()) if (data_def.type == Type.STRUCTURE or data_def.type == Type.ERROR): fields = ListValue() for field_name in data_def.get_field_names(): element_definition = data_def.get_field(field_name) field_pair = StructValue(MAP_ENTRY) field_pair.set_field('key', StringValue(field_name)) field_pair.set_field( 'value', convert_data_def_to_data_value(element_definition)) fields.add(field_pair) result.set_field('fields', OptionalValue(fields)) else: result.set_field('fields', OptionalValue()) return result
def create_task(self, provider_id, description, service_id, operation_id, cancelable, id_=None): """ Creates a task in task manager. :type provider_id: :class:`str` :param provider_id: Service UUID :type description: :class:`com.vmware.vapi.std.LocalizableMessage` :param description: Task description. :type service_id: :class:`str` :param service_id: Service Id. :type operation_id: :class:`str` :param operation_id: Operation Id. :type cancelable: :class:`bool` :param cancelable: Is the task cancelable. :type id_: :class:`str` :param id_: Base task id """ task_info = StructValue() if description is not None: task_info.set_field( 'description', TypeConverter.convert_to_vapi( description, LocalizableMessage.get_binding_type())) else: desc_value = StructValue() desc_value.set_field('id', StringValue()) desc_value.set_field('default_message', StringValue()) desc_value.set_field('args', ListValue()) task_info.set_field('description', desc_value) task_info.set_field('service', StringValue(service_id)) task_info.set_field('operation', StringValue(operation_id)) task_info.set_field('cancelable', BooleanValue(True if cancelable else False)) task_info.set_field('status', StringValue('PENDING')) base_id = id_ if id_ is not None else str(uuid.uuid4()) task_id = self._create_task_id(base_id, provider_id) with self.lock: self.task_map.setdefault(task_id, task_info) self._remove_expired_task() return task_id
def test_error_to_value(self): struct_def = ErrorDefinition('mock', [('field1', StringDefinition())]) actual_output = convert_data_def_to_data_value(struct_def) expected_output = StructValue(Introspection.DATA_DEFINITION) expected_output.set_field('type', StringValue('ERROR')) expected_output.set_field('name', OptionalValue(StringValue('mock'))) expected_output.set_field('element_definition', OptionalValue()) field_value = self.generate_primitive_value('STRING') field_entry = StructValue(MAP_ENTRY) field_entry.set_field('key', StringValue('field1')) field_entry.set_field('value', field_value) field_values = ListValue() field_values.add(field_entry) expected_output.set_field('fields', OptionalValue(field_values)) self.assertEqual(actual_output, expected_output)
def build_data_value(py_value, data_def): """ Converts a native python value to data value using the provided data definition :type py_value: :class:`object` :param py_value: Python native value :type data_def: :class:`vmware.vapi.data.definition.DataDefinition` :param data_def: Data definition :rtype: :class:`vmware.vapi.data.value.DataValue` :return: Data value """ output_val = None if data_def.type == Type.OPTIONAL: output_val = data_def.new_value() if py_value is not None: output_val.value = build_data_value(py_value, data_def.element_type) elif data_def.type == Type.LIST: output_val = data_def.new_value() if py_value: for output in py_value: output_val.add(build_data_value(output, data_def.element_type)) elif data_def.type in (Type.STRUCTURE, Type.ERROR): output_val = data_def.new_value() for field in data_def.get_field_names(): field_def = data_def.get_field(field) if py_value is None: if field_def.type == Type.OPTIONAL: output_val.set_field(field, OptionalValue()) else: msg = message_factory.get_message( 'vapi.data.structure.field.missing', data_def.name, field) raise CoreException(msg) else: if isinstance(py_value, dict): value = py_value.get(field) elif isinstance(py_value, VapiStruct): # If Class used in python bindings is the struct value = py_value.get_field(field) else: msg = message_factory.get_message( 'vapi.data.structure.field.invalid', field) raise CoreException(msg) output_val.set_field( field, build_data_value(value, data_def.get_field(field))) elif data_def.type == Type.DYNAMIC_STRUCTURE: output_val = StructValue(DYNAMIC_STRUCTURE) if isinstance(py_value, dict): for key, val in six.iteritems(py_value): if val is None: field_data_def = OptionalDefinition(StringDefinition()) elif isinstance(val, list): if len(val) == 0: # empty list field_data_def = ListDefinition(StringDefinition()) else: # at least one element field_data_def = ListDefinition( _py_to_data_def_map.get(type(val[0]))()) elif isinstance(val, dict): field_data_def = DynamicStructDefinition() else: try: # Field is probably a primitive/atomic type field_data_def_type = _py_to_data_def_map[type(val)] field_data_def = field_data_def_type() except KeyError: msg = message_factory.get_message( 'vapi.data.serializers.python.unsupported.' 'python.type', type(val), key) raise CoreException(msg) output_val.set_field(key, build_data_value(val, field_data_def)) elif data_def.type == Type.VOID: output_val = data_def.new_value() elif data_def.type == Type.OPAQUE: output_val = py_value # Primitive type Integer/Double/String/Boolean/Secret else: output_val = data_def.new_value(py_value) return output_val
def get_struct_value(self): struct_value = StructValue('struct0') struct_value.set_field('int', IntegerValue(7)) struct_value.set_field('optional', OptionalValue(StringValue("123"))) struct_value.set_field('optional1', OptionalValue()) return struct_value
def test_introspection_operation_get(self): ctx = ExecutionContext() input_val = StructValue(OPERATION_INPUT) input_val.set_field('service_id', StringValue('mockup_interface')) input_val.set_field('operation_id', StringValue('mock')) actual_output = self.local_provider.invoke( 'com.vmware.vapi.std.introspection.operation', 'get', input_val, ctx) expected_output = StructValue( name='com.vmware.vapi.std.introspection.operation.info') input_def_value = StructValue( 'com.vmware.vapi.std.introspection.operation.data_definition') input_def_value.set_field('fields', OptionalValue(ListValue(values=[]))) input_def_value.set_field('element_definition', OptionalValue()) input_def_value.set_field('type', StringValue('STRUCTURE')) input_def_value.set_field('name', OptionalValue(StringValue(OPERATION_INPUT))) expected_output.set_field('input_definition', input_def_value) output_def_value = StructValue( 'com.vmware.vapi.std.introspection.operation.data_definition') output_def_value.set_field('fields', OptionalValue()) output_def_value.set_field('element_definition', OptionalValue()) output_def_value.set_field('type', StringValue('VOID')) output_def_value.set_field('name', OptionalValue()) expected_output.set_field('output_definition', output_def_value) expected_output.set_field('error_definitions', error_values) self.assertEqual(actual_output.output, expected_output)
def create_task(self, description, service_id, operation_id, cancelable, error_types, id_=None): """ Creates a task in task manager. :type description: :class:`com.vmware.vapi.std.LocalizableMessage` :param description: Task description. :type service_id: :class:`str` :param service_id: Service Id. :type operation_id: :class:`str` :param operation_id: Operation Id. :type cancelable: :class:`bool` :param cancelable: Is the task cancelable. :type error_types: :class:`list` of :class:`vmware.vapi.bindings.type.ReferenceType` :param error_types: Error definitions describing the errors this operation can report :type id_: :class:`str` :param id_: Base task id """ task_info = StructValue() if description is not None: task_info.set_field( 'description', TypeConverter.convert_to_vapi( description, LocalizableMessage.get_binding_type())) else: desc_value = StructValue() desc_value.set_field('id', StringValue()) desc_value.set_field('default_message', StringValue()) desc_value.set_field('args', ListValue()) task_info.set_field('description', desc_value) user = self._get_user_from_sec_ctx() if user is not None: task_info.set_field('user', StringValue(user)) task_info.set_field('service', StringValue(service_id)) task_info.set_field('operation', StringValue(operation_id)) task_info.set_field('cancelable', BooleanValue(True if cancelable else False)) task_info.set_field('status', PENDING_STRING_VALUE) base_id = id_ if id_ is not None else str(uuid.uuid4()) task_id = self._create_task_id(base_id, service_id) task_summary = TaskSummary(task_info, error_types) with self.lock: self.task_map.setdefault(task_id, task_summary) self._remove_expired_task() return task_id