def post(self, request, sessions, *args, **kwargs): """Initialize the tests run data. Args: tests_tree (dict): contains the hierarchy of the tests in the run. run_data (dict): contains additional data about the run. """ try: run_data = RunData.objects.create(**request.model.run_data) except TypeError: raise BadRequest("Invalid run data provided!") all_tests = {} tests_tree = request.model.tests try: main_test = self._create_test_data(tests_tree, run_data, all_tests) except KeyError: raise BadRequest("Invalid tests tree provided!") run_data.main_test = main_test run_data.user_name = request.get_host() run_data.save() session = sessions[request.model.token] session.all_tests = all_tests session.run_data = run_data session.main_test = main_test return Response({}, status=httplib.NO_CONTENT)
def _get_available_resources(self, descriptor, username, groups): """Get the potential resources to be locked that fits the descriptor. Args: descriptor (ResourceDescriptor): a descriptor of the wanted resource. username (str): the user who wants to lock the resource. groups (list): list of the resource groups that the resource should be taken from. Raises: BadRequest. if the descriptor given is invalid or the are no resources to be locked. Returns: generator. generator of resources that can be locked and are available to the user who requested them. """ # query for resources that are usable and match the user's # preference, which are either belong groups he's in or # don't belong to any group. query = (Q(is_usable=True, **descriptor.properties) & (Q(group__isnull=True) | Q(group__in=groups))) try: matches = descriptor.type.objects.select_for_update() \ .filter(query).order_by('-reserved') except FieldError as e: raise BadRequest(e.message) if matches.count() == 0: raise BadRequest(INVALID_RESOURCES.format(descriptor)) return (resource for resource in matches if resource.is_available(username))
def get(self, request, sessions, *args, **kwargs): """Initialize the tests run data.""" parameters = {"test_name": request.model.test_name} if request.model.max_sample_size is not None: parameters["max_size"] = request.model.max_sample_size test_durations = collect_durations(**parameters) if len(test_durations) < 1: raise BadRequest("No test history found!") parameters = {"durations": test_durations} if request.model.min_duration_cut is not None: parameters["min_duration_cut"] = request.model.min_duration_cut if request.model.max_iterations is not None: parameters["max_iterations"] = request.model.max_iterations if request.model.acceptable_ratio is not None: parameters["acceptable_ratio"] = request.model.acceptable_ratio test_durations = clean_data(**parameters) if len(test_durations) < 1: raise BadRequest("Test history disparity too wide!") response = { "min": min(test_durations), "avg": sum(test_durations) / len(test_durations), "max": max(test_durations) } return Response(response, status=http_client.OK)
def post(self, request, *args, **kwargs): """Find and return the resources that answer the client's query. Args: request (Request): QueryResources request. Returns: ResourcesReply. a reply containing matching resources. """ try: descriptor = ResourceDescriptor.decode(request.model.obj) except ResourceTypeError as e: raise BadRequest(str(e)) # query for resources that are usable and match the descriptors query = (Q(is_usable=True, **descriptor.properties)) query_result = [] with transaction.atomic(): matches = descriptor.type.objects.select_for_update().filter(query) if matches.count() == 0: raise BadRequest("No existing resource meets " "the requirements: {!r}".format(descriptor)) encoder = JSONParser() query_result = [ encoder.recursive_encode(resource) for resource in matches ] return Response({"resource_descriptors": query_result}, status=http_client.OK)
def get(self, request, sessions, *args, **kwargs): """Check if the test passed in the last run according to results DB. Args: test_id (number): the identifier of the test. token (str): token of the session. """ session_token = request.model.token try: session_data = sessions[session_token] test_data = session_data.all_tests[request.model.test_id] except KeyError: raise BadRequest("Invalid token/test_id provided!") run_data = session_data.run_data test_should_skip = test_data.should_skip(test_name=test_data.name, run_data=run_data, exclude_pk=test_data.pk) reason = SKIP_DELTA_MESSAGE if test_should_skip else "" return Response({ "should_skip": test_should_skip, "reason": reason }, status=httplib.OK)
def post(self, request, sessions, *args, **kwargs): """Update the resources list for a test data. Args: test_id (number): the identifier of the test. descriptors (list): the resources the test used. """ session_token = request.model.test_details.token try: session_data = sessions[session_token] test_data = \ session_data.all_tests[request.model.test_details.test_id] except KeyError: raise BadRequest("Invalid token/test_id provided " "(Test timed out?)") test_data.resources.clear() for resource_descriptor in request.model.descriptors: resource_dict = ResourceDescriptor.decode(resource_descriptor) test_data.resources.add(resource_dict.type.objects.get( **resource_dict.properties)) test_data.save() return Response({}, status=http_client.NO_CONTENT)
def post(self, request, sessions, *args, **kwargs): """Lock the given resources one by one. Note: If one of the resources fails to lock, all the resources that has been locked until that resource will be released. """ username = get_username(request) session = sessions[request.model.token] descriptors = request.model.descriptors if not auth_models.User.objects.filter(username=username).exists(): raise BadRequest(USER_NOT_EXIST.format(username)) locked_resources = [] user = auth_models.User.objects.get(username=username) groups = list(user.groups.all()) with transaction.atomic(): for descriptor_dict in descriptors: locked_resources.append( self._try_to_lock_available_resource( username, groups, descriptor_dict)) for resource in locked_resources: session.resources.append(resource) encoder = JSONParser() response = [ encoder.encode(_resource) for _resource in locked_resources ] return Response({"resource_descriptors": response}, status=httplib.OK)
def _create_test_data(self, test_dict, run_data, all_tests): """Recursively create the test's datas and add them to 'all_tests'. Args: tests_tree (dict): contains the hierarchy of the tests in the run. Returns: GeneralData. the created test data object. """ parser = JSONParser() data_type = parser.decode(test_dict[TEST_CLASS_CODE_KEY]) try: test_data = data_type(name=test_dict[TEST_NAME_KEY]) except TypeError: raise BadRequest("Invalid type provided: {}".format(data_type)) test_data.run_data = run_data test_data.save() all_tests[test_dict[TEST_ID_KEY]] = test_data if TEST_SUBTESTS_KEY in test_dict: for sub_test_dict in test_dict[TEST_SUBTESTS_KEY]: sub_test = self._create_test_data(sub_test_dict, run_data, all_tests) test_data.add_sub_test_data(sub_test) sub_test.save() return test_data
def post(self, request, sessions, *args, **kwargs): """Initialize the tests run data.""" session_token = request.model.token try: session_data = sessions[session_token] except KeyError: raise BadRequest("Invalid token provided!") run_data = session_data.run_data RunData.objects.filter(pk=run_data.pk).update(**request.model.run_data) return Response({}, status=http_client.NO_CONTENT)
def _try_to_lock_available_resource(self, username, groups, descriptor_dict): """Try to lock one of the given available resources. Args: descriptor_dict (dict): a descriptor dict of the wanted resource. Example: { "type": "resourceData", "properties": {} } username (str): the user who wants to lock the resource. groups (list): list of the resource groups that the resource should be taken from. Returns: ResourceData. the locked resource. Raises: BadRequest. If there are no available resources. """ try: descriptor = ResourceDescriptor.decode(descriptor_dict) except ResourceTypeError as e: raise BadRequest(e.message) availables = self._get_available_resources(descriptor, username, groups) try: resource = availables.next() self._lock_resource(resource, username) return resource except StopIteration: raise BadRequest(UNAVAILABLE_RESOURCES.format(descriptor))
def post(self, request, sessions, *args, **kwargs): """Update the test data to 'in progress' state and set the start time. Args: test_id (number): the identifier of the test. """ session_token = request.model.token try: session_data = sessions[session_token] test_data = session_data.all_tests[request.model.test_id] except KeyError: raise BadRequest("Invalid token/test_id provided!") test_data.start() test_data.save() return Response({}, status=httplib.NO_CONTENT)
def post(self, request, sessions, *args, **kwargs): """End a test run. Args: request (Request): StopTest request. """ session_token = request.model.token try: session_data = sessions[session_token] test_data = session_data.all_tests[request.model.test_id] except KeyError: raise BadRequest("Invalid token/test_id provided!") test_data.end() test_data.save() return Response({}, status=httplib.NO_CONTENT)
def post(self, request, sessions, *args, **kwargs): """Save the composite test's data. Args: test_id (number): the identifier of the test. """ session_token = request.model.token try: session_data = sessions[session_token] test_data = session_data.all_tests[request.model.test_id] except KeyError: raise BadRequest("Invalid token/test_id provided!") has_succeeded = all(sub_test.success for sub_test in test_data) test_data.success = has_succeeded test_data.end() test_data.save() return Response({}, status=httplib.NO_CONTENT)
def post(self, request, sessions, *args, **kwargs): """Release the given resources one by one.""" try: session = sessions[request.model.token] except KeyError: raise BadRequest("Invalid token provided!") errors = {} username = get_username(request) with transaction.atomic(): for name in request.model.resources: try: resource_data = ResourceData.objects.select_for_update() \ .get(name=name) except ObjectDoesNotExist: errors[name] = (ResourceDoesNotExistError.ERROR_CODE, "Resource %r doesn't exist" % name) continue resource = get_sub_model(resource_data) try: self.release_resource(resource, username) session.resources.remove(resource) except ServerError as ex: errors[name] = (ex.ERROR_CODE, ex.get_error_content()) if len(errors) > 0: return Response( { "errors": errors, "details": "errors occurred while releasing resource" }, status=http_client.BAD_REQUEST) return Response({}, status=http_client.NO_CONTENT)
def post(self, request, sessions, *args, **kwargs): """Add a result to the test. Args: test_id (number): the identifier of the test. result_code (number): code of the result as defined in TestOutcome. info (str): additional info (traceback / end reason etc). """ session_token = request.model.test_details.token try: session_data = sessions[session_token] test_data = \ session_data.all_tests[request.model.test_details.test_id] except KeyError: raise BadRequest("Invalid token/test_id provided!") test_data.update_result(request.model.result.result_code, request.model.result.info) test_data.save() return Response({}, status=httplib.NO_CONTENT)