Exemple #1
0
    def update_fields(self, model, filter_dict=None, **kwargs):
        """Update content in the server's DB.

        Args:
            model (type): Django model to apply changes on.
            filter_dict (dict): arguments to filter by.
            kwargs (dict): the additional arguments are the changes to apply on
                the filtered instances.
        """
        if filter_dict is None:
            filter_dict = {}

        descriptor = ResourceDescriptor(resource_type=model, **filter_dict)

        request_data = UpdateFieldsParamsModel({
            "resource_descriptor":
            descriptor.encode(),
            "changes":
            kwargs
        })
        response = self.requester.request(UpdateFields,
                                          data=request_data,
                                          method="put")

        if isinstance(response, FailureResponseModel):
            raise Exception(response.details)
Exemple #2
0
    def update_resources(self, test_item):
        """Inform the result server of locked resources of a test.

        Args:
            test_item (rotest.core.case.TestCase): the test to update about.
        """
        resources = []
        if test_item.locked_resources is not None:
            resources = [
                ResourceDescriptor(type(resource),
                                   name=resource.data.name).encode()
                for resource in test_item.locked_resources.itervalues()
            ]

        request_data = UpdateResourcesParamsModel({
            "test_details": {
                "test_id": test_item.identifier,
                "token": self.token
            },
            "descriptors": resources
        })
        response = self.requester.request(UpdateResources,
                                          data=request_data,
                                          method="post")

        if isinstance(response, FailureResponseModel):
            raise RuntimeError(response.details)
Exemple #3
0
    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)
Exemple #4
0
    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)
Exemple #5
0
    def update_resources(self, test_id, resources):
        """Update the resources list for a test data.

        Args:
            test_id (number): the identifier of the test.
            resources (list): the resources the test used.
        """
        test_data = self.all_tests[test_id]
        test_data.resources.clear()

        for resource_descriptor in resources:
            resource_dict = ResourceDescriptor.decode(resource_descriptor)
            test_data.resources.add(
                resource_dict.type.objects.get(**resource_dict.properties))

        test_data.save()
Exemple #6
0
    def update_resources(self, test_item):
        """Inform the result server of locked resources of a test.

        Args:
            test_item (rotest.core.case.TestCase): the test to update about.
        """
        resources = []
        if test_item.locked_resources is not None:
            resources = [ResourceDescriptor(type(resource),
                                            name=resource.data.name).encode()
                         for resource in
                         test_item.locked_resources.itervalues()]

        msg = messages.UpdateResources(test_id=test_item.identifier,
                                       resources=resources)
        self._request(msg)
Exemple #7
0
    def test_lock_resource_message(self):
        """Test encoding & decoding of LockResources message."""
        resource1 = ResourceDescriptor(DemoResource,
                                       name="my_resource1",
                                       ip_address="1.2.3.4",
                                       version=1)
        resource2 = ResourceDescriptor(DemoResource,
                                       name="my_resource2",
                                       ip_address="1.2.3.5",
                                       version=2)

        descriptors = [resource1.encode(), resource2.encode()]

        msg = LockResources(descriptors=descriptors,
                            timeout=self.LOCK_RESOURCES_TIMEOUT)
        self.validate(msg)
Exemple #8
0
    def query_resources(self, request):
        """Find and return the resources that answer the client's query.

        Args:
            request (Request): QueryResources request.

        Returns:
            ResourcesReply. a reply containing matching resources.
        """
        desc = ResourceDescriptor.decode(request.message.descriptors)
        self.logger.debug("Looking for resources with description %r", desc)

        # query for resources that are usable and match the descriptors
        query = (Q(is_usable=True, **desc.properties))
        matches = desc.type.objects.filter(query)

        if matches.count() == 0:
            raise ResourceDoesNotExistError("No existing resource meets "
                                            "the requirements: %r" % desc)

        query_result = [resource for resource in matches]

        return ResourcesReply(resources=query_result)
Exemple #9
0
    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))
Exemple #10
0
    def request_resources(self, requests,
                          config=None,
                          skip_init=False,
                          save_state=False,
                          use_previous=True,
                          enable_debug=False,
                          force_initialize=False,
                          base_work_dir=ROTEST_WORK_DIR):
        """Lock the required resources and prepare them for work.

        * Requests the resources from the manager server.
        * Iterates over the locked resources to try to prepare them for work.
        * The locked and initialized resources then returned as an AttrDict.

        Args:
            requests (tuple): List of the ResourceRequest.
            config (dict): run configuration dictionary.
            skip_init (bool): True to skip resources initialize and validation.
            save_state (bool): Determine if storing state is required.
            use_previous (bool): whether to use previously locked resources and
                release the unused ones.
            enable_debug (bool): True to wrap the resource's method with debug.
            force_initialize (bool): determines if the resources will be
                initialized even if their validation succeeds.
            base_work_dir (str): base work directory path.

        Returns:
            AttrDict. resources AttrDict {name: BaseResource}.

        Raises:
            ServerError. resource manager failed to lock resources.
        """
        requests = list(requests)
        descriptors = [ResourceDescriptor(request.type, **request.kwargs)
                       for request in requests]

        initialized_resources = AttrDict()

        if use_previous:
            # Find matches in previously locked resources
            initialized_resources = self._retrieve_previous(requests,
                                                            descriptors)

        self.logger.debug("Requesting resources from resource manager")
        locked_resources = self._lock_resources(descriptors)
        self.logger.info("Locked resources %s", locked_resources)

        try:
            self.logger.debug("Setting up the locked resources")

            for name, resource in self._setup_resources(requests,
                                                        locked_resources,
                                                        save_state,
                                                        force_initialize,
                                                        base_work_dir,
                                                        config,
                                                        enable_debug,
                                                        skip_init):

                initialized_resources[name] = resource

                if self.keep_resources:
                    self.locked_resources.append(resource)

            return initialized_resources

        except Exception:
            self._cleanup_resources(initialized_resources)
            self._release_resources(locked_resources)
            raise
Exemple #11
0
    def lock_resources(self, request):
        """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.

        Args:
            request (Request): LockResources request.

        Returns:
            ResourcesReply. a reply containing requested resources.

        Raises:
            ResourceDoesNotExistError. at least one of the requested resources
                doesn't exist.
            ResourceUnavailableError. when the requested resources are not
                available.
            UnknownUserError. when unknown user has tried to lock a resource.
        """
        locked_resources = []

        client = request.worker.name
        user_name, _ = client.split(":")  # splitting <user_name>:<port>

        if not auth_models.User.objects.filter(username=user_name).exists():
            raise UnknownUserError("User %r has no matching object in the DB" %
                                   user_name)

        user = auth_models.User.objects.get(username=user_name)

        groups = list(user.groups.all())

        for descriptor_dict in request.message.descriptors:

            desc = ResourceDescriptor.decode(descriptor_dict)
            self.logger.debug("Locking %r resource", desc)

            # query for resources that are usable and match the user's
            # preference, which are either belong to a group he's in or
            # don't belong to any group.
            query = (Q(is_usable=True, **desc.properties) &
                     (Q(group__isnull=True) | Q(group__in=groups)))
            matches = desc.type.objects.filter(query).order_by('-reserved')

            if matches.count() == 0:
                raise ResourceDoesNotExistError("No existing resource meets "
                                                "the requirements: %r" % desc)

            availables = (resource for resource in matches
                          if resource.is_available(client))

            try:
                resource = availables.next()

                self._lock_resource(resource, client)
                locked_resources.append(resource)
                self.logger.debug("Resource %r locked successfully", desc)

            except StopIteration:
                timeout = request.message.timeout
                waiting_time = time.time() - request.creation_time
                if timeout is not None and waiting_time > timeout:
                    raise ResourceUnavailableError("No available resource "
                                                   "meets the requirements: "
                                                   "%r" % desc)

                raise _WaitingForResourceException(
                    "Resource %r is unavailable"
                    ", waiting for it to be "
                    "released", desc)

        return ResourcesReply(resources=locked_resources)