def test_resources_reply_message(self): """Test encoding & decoding of ResourcesReply message.""" data = DemoResourceData(name='demo1', version=1, ip_address="1.2.3.4") data.save() msg = ResourcesReply(request_id=0, resources=[data]) self.validate(msg)
def test_complex_resources_reply_message(self): """Test encoding & decoding of ResourcesReply message.""" data1 = DemoResourceData(name='demo1', version=1, ip_address="1.2.3.4") data2 = DemoResourceData(name='demo2', version=2, ip_address="1.2.3.5") data1.save() data2.save() resource_data = DemoComplexResourceData(name="complex", demo1=data1, demo2=data2) resource_data.save() msg = ResourcesReply(request_id=0, resources=[resource_data]) self.validate(msg)
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)
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)