Example #1
0
 def getItems(self, parent: models.ServicePool, item: typing.Optional[str]):
     # Extract provider
     try:
         if not item:
             return [
                 AssignedService.itemToDict(k)
                 for k in parent.assignedUserServices().all().
                 prefetch_related('properties', 'deployed_service',
                                  'publication', 'user')
             ]
         return AssignedService.itemToDict(
             parent.assignedUserServices().get(
                 processUuid(uuid=processUuid(item))))
     except Exception:
         logger.exception('getItems')
         raise self.invalidItemException()
Example #2
0
 def getExistingAssignationForUser(self, servicePool: ServicePool, user: User) -> typing.Optional[UserService]:
     existing = servicePool.assignedUserServices().filter(user=user, state__in=State.VALID_STATES)  # , deployed_service__visible=True
     lenExisting = existing.count()
     if lenExisting > 0:  # Already has 1 assigned
         logger.debug('Found assigned service from %s to user %s', servicePool, user.name)
         return existing[0]
     return None
Example #3
0
 def getLogs(self, parent: models.ServicePool,
             item: str) -> typing.List[typing.Any]:
     try:
         userService: models.UserService = parent.assignedUserServices(
         ).get(uuid=processUuid(item))
         logger.debug('Getting logs for %s', userService)
         return log.getLogs(userService)
     except Exception:
         raise self.invalidItemException()
Example #4
0
    def getAssignationForUser(
        self, servicePool: ServicePool, user: User
    ) -> typing.Optional[UserService]:  # pylint: disable=too-many-branches
        if servicePool.service.getInstance().spawnsNew is False:
            assignedUserService = self.getExistingAssignationForUser(
                servicePool, user)
        else:
            assignedUserService = None

        # If has an assigned user service, returns this without any more work
        if assignedUserService:
            return assignedUserService

        if servicePool.isRestrained():
            raise InvalidServiceException(
                _('The requested service is restrained'))

        cache: typing.Optional[UserService] = None
        # Now try to locate 1 from cache already "ready" (must be usable and at level 1)
        with transaction.atomic():
            caches = typing.cast(
                typing.List[UserService],
                servicePool.cachedUserServices().select_for_update().filter(
                    cache_level=services.UserDeployment.L1_CACHE,
                    state=State.USABLE,
                    os_state=State.USABLE)[:1])
            if caches:
                cache = caches[0]
                # Ensure element is reserved correctly on DB
                if servicePool.cachedUserServices().select_for_update().filter(
                        user=None, uuid=typing.cast(
                            UserService, cache).uuid).update(
                                user=user, cache_level=0) != 1:
                    cache = None
            else:
                cache = None

        # Out of previous atomic
        if not cache:
            with transaction.atomic():
                caches = typing.cast(
                    typing.List[UserService],
                    servicePool.cachedUserServices().select_for_update().
                    filter(cache_level=services.UserDeployment.L1_CACHE,
                           state=State.USABLE)[:1])
                if cache:
                    cache = caches[0]
                    if servicePool.cachedUserServices().select_for_update(
                    ).filter(user=None,
                             uuid=typing.cast(UserService, cache).uuid).update(
                                 user=user, cache_level=0) != 1:
                        cache = None
                else:
                    cache = None

        # Out of atomic transaction
        if cache:
            # Early assign
            cache.assignToUser(user)

            logger.debug(
                'Found a cached-ready service from %s for user %s, item %s',
                servicePool, user, cache)
            events.addEvent(servicePool,
                            events.ET_CACHE_HIT,
                            fld1=servicePool.cachedUserServices().filter(
                                cache_level=services.UserDeployment.L1_CACHE,
                                state=State.USABLE).count())
            return cache

        # Cache missed

        # Now find if there is a preparing one
        with transaction.atomic():
            caches = servicePool.cachedUserServices().select_for_update(
            ).filter(cache_level=services.UserDeployment.L1_CACHE,
                     state=State.PREPARING)[:1]
            if caches:
                cache = caches[0]
                if servicePool.cachedUserServices().select_for_update().filter(
                        user=None, uuid=typing.cast(
                            UserService, cache).uuid).update(
                                user=user, cache_level=0) != 1:
                    cache = None
            else:
                cache = None

        # Out of atomic transaction
        if cache:
            cache.assignToUser(user)

            logger.debug(
                'Found a cached-preparing service from %s for user %s, item %s',
                servicePool, user, cache)
            events.addEvent(servicePool,
                            events.ET_CACHE_MISS,
                            fld1=servicePool.cachedUserServices().filter(
                                cache_level=services.UserDeployment.L1_CACHE,
                                state=State.PREPARING).count())
            return cache

        # Can't assign directly from L2 cache... so we check if we can create e new service in the limits requested
        serviceType = servicePool.service.getType()
        if serviceType.usesCache:
            # inCacheL1 = ds.cachedUserServices().filter(UserServiceManager.getCacheStateFilter(services.UserDeployment.L1_CACHE)).count()
            inAssigned = servicePool.assignedUserServices().filter(
                UserServiceManager.getStateFilter()).count()
            # totalL1Assigned = inCacheL1 + inAssigned
            if inAssigned >= servicePool.max_srvs:  # cacheUpdater will drop unnecesary L1 machines, so it's not neccesary to check against inCacheL1
                log.doLog(
                    servicePool, log.WARN,
                    'Max number of services reached: {}'.format(
                        servicePool.max_srvs), log.INTERNAL)
                raise MaxServicesReachedError()

        # Can create new service, create it
        events.addEvent(servicePool, events.ET_CACHE_MISS, fld1=0)
        return self.createAssignedFor(servicePool, user)