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 visit_map(self, type_info, json_value): """ Deserialize a map 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` :return: DataValue created using the input """ if not isinstance(json_value, list): msg = 'Excepted list, but got %s' % type(json_value).__name__ logger.error(msg) raise werkzeug.exceptions.BadRequest(msg) try: return ListValue([ StructValue(name=MAP_ENTRY, values={ 'key': self.visit(type_info.map_key_type, value['key']), 'value': self.visit(type_info.map_value_type, value['value']) }) for value in json_value ]) except KeyError as e: msg = 'Invalid Map input, missing %s' % e logger.error(msg) raise werkzeug.exceptions.BadRequest(msg)
def test_list(self): input_val = '["val1","val2"]' expected_val = ListValue( values=[StringValue('val1'), StringValue('val2')]) actual_val = DataValueConverter.convert_to_data_value(input_val) self.assertEqual(expected_val, actual_val)
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 _convert_method_def_to_data_value(method_def): """ Converts a :class:`vmware.vapi.core.MethodDefinition` object to :class:`vmware.vapi.data.value.DataValue` object :type method_def: :class:`vmware.vapi.core.MethodDefinition` :param method_def: Method definition :rtype: :class:`vmware.vapi.data.value.DataValue` :return: Data value object representing method definition """ output = StructValue( name='com.vmware.vapi.std.introspection.operation.info', values={ 'input_definition': convert_data_def_to_data_value( method_def.get_input_definition()), 'output_definition': convert_data_def_to_data_value( method_def.get_output_definition()), 'error_definitions': ListValue(values=[ convert_data_def_to_data_value(error_def) for error_def in method_def.get_error_definitions() ]) }) return output
def get_data_values(self): # Data values list_value = ListValue() list_value.add_all([IntegerValue(val) for val in range(1,15)]) data_values = [ VoidValue(), IntegerValue(3), DoubleValue(decimal.Decimal('7.2')), StringValue('blah'), SecretValue(), BooleanValue(True), BlobValue(b"a blob"), BlobValue(b"0\x82\x04\x00"), list_value, OptionalValue(), OptionalValue(IntegerValue(7)), StructValue('name'), self.get_struct_value(), self.get_error_value(), ] struct_value = StructValue('struct') for idx, data_val in enumerate(data_values): struct_value.set_field(str(idx), data_val) data_values.append(struct_value) return data_values
def test_list_value(self): input_val = ListValue( values=[StringValue('val1'), StringValue('val2')]) actual_val = DataValueConverter.convert_to_json(input_val) expected_val = '["val1","val2"]' self.assertEqual(expected_val, actual_val) # Verify json is valid json.loads(actual_val)
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
def _visit_list(self, obj): """ Visit python list object :type obj: :class:`list` :param obj: Python list object :rtype: :class:`vmware.vapi.data.value.ListValue` :return: List value """ list_val = [self._visit(o) for o in obj] return ListValue(list_val)
def get_operations(self, service_id): service_info = self._service_data.get(service_id) if service_info: method_ids = service_info.get_definition().get_method_identifiers() return MethodResult(output=ListValue(values=[ StringValue(method_id.get_name()) for method_id in method_ids ])) else: msg = message_factory.get_message( 'vapi.introspection.operation.service.not_found', service_id) error_value = make_error_value_from_msgs(not_found_def, msg) return MethodResult(error=error_value)
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_not_found_error_value(self): input_status = 404 input_response = '{"type":"com.vmware.vapi.std.errors.not_found","value":{"messages":[{"args":["datacenter-21"],"default_message":"Datacenter with identifier \'datacenter-21\' does not exist.","id":"com.vmware.api.vcenter.datacenter.not_found"}]}}' msg_val = StructValue( values={ 'id': StringValue('com.vmware.api.vcenter.datacenter.not_found'), 'default_message': StringValue( 'Datacenter with identifier \'datacenter-21\' does not exist.' ), 'args': ListValue([StringValue('datacenter-21')]) }) error_val = ErrorValue('com.vmware.vapi.std.errors.not_found', {'messages': ListValue([msg_val])}) expected_result = MethodResult(error=error_val) logging.debug(expected_result) actual_result = RestSerializer.deserialize_response( status=input_status, response_str=input_response, is_vapi_rest=True) self.assertEqual(expected_result.output, actual_result.output) self.assertEqual(expected_result.error, actual_result.error)
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 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 deserialize_response(status, response_str, is_vapi_rest): """ Deserialize the REST response :type status: :class:`int` :param status: HTTP response status code :type response_str: :class:`str` :param response_str: HTTP response body :type is_vapi_rest: :class:`bool` :param is_vapi_rest: Whether the Rest json message format is VAPI Rest or not :rtype :class:`vmware.vapi.core.MethodResult` :return: VAPI MethodResult """ output, error = None, None if response_str is not None and response_str != '': response_value = DataValueConverter.convert_to_data_value( response_str) if status in successful_status_codes: # Successful response, create output # Skyscraper uses 202 for returning tasks if is_vapi_rest: # VAPI REST output has a value wrapper output = response_value.get_field('value') else: output = response_value else: # Create error if is_vapi_rest: # VAPI REST error has specific format name = response_value.get_field('type').value values = dict( response_value.get_field('value').get_fields()) error = ErrorValue(name=name, values=values) else: # For other REST APIs create generic error for now error = ErrorValue(name=http_to_vapi_error_map[status], values={ 'messages': ListValue(), 'data': response_value, }) else: # No response body if status == 200: output = VoidValue() return MethodResult(output=output, error=error)
def visit_list(self, type_info, json_value): """ Deserialize a list 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.ListValue` :return: DataValue created using the input """ if not isinstance(json_value, list): msg = 'Excepted list, but got %s' % type(json_value).__name__ logger.error(msg) raise werkzeug.exceptions.BadRequest(msg) return ListValue([ self.visit(type_info.element_type, value) for value in json_value ])
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 test_invalid_query_params(self): input_val = StructValue(name='operation-input', values={ 'string_val': StringValue('string1'), 'action1_val': OptionalValue(value=StringValue('start')), 'action2_val': ListValue([]) }) rest_metadata = OperationRestMetadata(http_method='POST', url_template='/foo/bar', query_parameters={ 'action1_val': 'action1', 'action2_val': 'action2' }) self.assertRaises(CoreException, RestSerializer.serialize_request, input_value=input_val, ctx=None, rest_metadata=rest_metadata, is_vapi_rest=True)
input_def = StructDefinition('input', [ ('service_name', StringDefinition()), ('operation_name', StringDefinition()), ('operation_input', OpaqueDefinition()), ]) mock_input_def = StructDefinition('input', [('raise', BooleanDefinition())]) not_found_error_def = make_std_error_def( 'com.vmware.vapi.std.errors.not_found') errors = [ 'com.vmware.vapi.std.errors.not_found', 'com.vmware.vapi.std.errors.internal_server_error', 'com.vmware.vapi.std.errors.invalid_argument', 'com.vmware.vapi.std.errors.operation_not_found', ] error_defs = [make_std_error_def(error) for error in errors] error_values = ListValue( [convert_data_def_to_data_value(error_def) for error_def in error_defs]) class MockupApiInterface(ApiInterface): def __init__(self, interface_id): self._interface_id = interface_id self.counters = {} for name in [ mock_method_name, pre_method_name, post_method_name, veto_method_name ]: self.counters[name] = 0 def get_identifier(self): return self._interface_id
raise_python_exception: raise_python_exception_id, return_invalid_output: return_invalid_output_id, } internal_server_error_def = make_std_error_def( 'com.vmware.vapi.std.errors.internal_server_error') invalid_argument_def = make_std_error_def( 'com.vmware.vapi.std.errors.invalid_argument') not_found_error_def = make_std_error_def( 'com.vmware.vapi.std.errors.not_found') operation_not_found_def = make_std_error_def( 'com.vmware.vapi.std.errors.operation_not_found') error_values = ListValue([ convert_data_def_to_data_value(internal_server_error_def), convert_data_def_to_data_value(invalid_argument_def), convert_data_def_to_data_value(operation_not_found_def) ]) _msg = Message('mockup.message.id', 'mockup error message') not_found_error = make_error_value_from_msgs(not_found_error_def, _msg) param_name = 'param' class MockupApiInterface(ApiInterface): def __init__(self): pass def get_identifier(self): return interface_id
def test_empty_list(self): input_val = '[]' expected_val = ListValue() actual_val = DataValueConverter.convert_to_data_value(input_val) self.assertEqual(expected_val, actual_val)