mirror of
https://github.com/dkmstr/openuds.git
synced 2024-12-25 23:21:41 +03:00
* Adding more type checking (pylance type checking works fin with theese new "checks")
* Removed redundant fields not used
This commit is contained in:
parent
8cd5437429
commit
1ab534c3aa
@ -100,7 +100,7 @@ class StatsManager:
|
||||
self,
|
||||
ownerType: int,
|
||||
counterType: int,
|
||||
ownerIds: typing.Union[typing.Iterable[int], int],
|
||||
ownerIds: typing.Union[typing.Iterable[int], int, None],
|
||||
since: datetime.datetime,
|
||||
to: datetime.datetime,
|
||||
interval: typing.Optional[int],
|
||||
|
@ -113,8 +113,7 @@ def getCounters(obj: CounterClass, counterType: int, **kwargs) -> typing.Generat
|
||||
owner_ids = None
|
||||
|
||||
for i in statsManager().getCounters(__transDict[type(obj)], counterType, owner_ids, since, to, kwargs.get('interval'), kwargs.get('max_intervals'), limit, use_max):
|
||||
val = (datetime.datetime.fromtimestamp(i.stamp), i.value)
|
||||
yield val
|
||||
yield (datetime.datetime.fromtimestamp(i.stamp), i.value)
|
||||
|
||||
|
||||
def getCounterTitle(counterType: int) -> str:
|
||||
|
@ -101,11 +101,11 @@ class StorageAsDict(MutableMapping):
|
||||
return DBStorage.objects
|
||||
|
||||
@property
|
||||
def _filtered(self) -> models.QuerySet:
|
||||
def _filtered(self) -> 'models.QuerySet[DBStorage]':
|
||||
fltr = self._db.filter(owner=self._owner)
|
||||
if self._group:
|
||||
fltr = fltr.filter(attr1=self._group)
|
||||
return fltr
|
||||
return typing.cast('models.QuerySet[DBStorage]', fltr)
|
||||
|
||||
def _key(self, key: str) -> str:
|
||||
if key[0] == '#':
|
||||
@ -120,7 +120,7 @@ class StorageAsDict(MutableMapping):
|
||||
dbk = self._key(key)
|
||||
logger.debug('Getitem: %s', dbk)
|
||||
try:
|
||||
c: DBStorage = self._db.get(pk=dbk)
|
||||
c: DBStorage = typing.cast(DBStorage, self._db.get(pk=dbk))
|
||||
return _decodeValue(dbk, c.data)[1] # Ignores original key
|
||||
except DBStorage.DoesNotExist:
|
||||
return None
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 3.1.2 on 2020-11-11 11:23
|
||||
# Generated by Django 3.1.2 on 2020-11-11 13:29
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
@ -14,6 +14,10 @@ class Migration(migrations.Migration):
|
||||
model_name='metapool',
|
||||
name='accessCalendars',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='metapool',
|
||||
name='pools',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='servicepool',
|
||||
name='accessCalendars',
|
@ -62,7 +62,7 @@ from .group import Group
|
||||
|
||||
# Provisioned services
|
||||
from .service_pool import ServicePool # New name
|
||||
from .meta_pool import MetaPool
|
||||
from .meta_pool import MetaPool, MetaPoolMember
|
||||
from .service_pool_group import ServicePoolGroup
|
||||
from .service_pool_publication import ServicePoolPublication
|
||||
from .user_service import UserService
|
||||
|
@ -56,7 +56,7 @@ class Group(UUIDModel):
|
||||
This class represents a group, associated with one authenticator
|
||||
"""
|
||||
# pylint: disable=model-missing-unicode
|
||||
manager: Authenticator = UnsavedForeignKey(Authenticator, on_delete=models.CASCADE, related_name='groups')
|
||||
manager: 'models.ForeignKey[Group, Authenticator]' = UnsavedForeignKey(Authenticator, on_delete=models.CASCADE, related_name='groups')
|
||||
name = models.CharField(max_length=128, db_index=True)
|
||||
state = models.CharField(max_length=1, default=State.ACTIVE, db_index=True)
|
||||
comments = models.CharField(max_length=256, default='')
|
||||
|
@ -49,11 +49,11 @@ from .image import Image
|
||||
from .service_pool_group import ServicePoolGroup
|
||||
from .service_pool import ServicePool
|
||||
from .group import Group
|
||||
from .calendar import Calendar
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
import datetime
|
||||
from .user import User
|
||||
from uds.models import User, CalendarAccessMeta
|
||||
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -87,11 +87,13 @@ class MetaPool(UUIDModel, TaggingMixin): # type: ignore
|
||||
# Default fallback action for access
|
||||
fallbackAccess = models.CharField(default=states.action.ALLOW, max_length=8)
|
||||
|
||||
pools = models.ManyToManyField(ServicePool, through='MetapoolMember', related_name='meta')
|
||||
|
||||
# Pool selection policy
|
||||
policy = models.SmallIntegerField(default=0)
|
||||
|
||||
# "fake" relations declarations for type checking
|
||||
calendarAccess: 'models.QuerySet[CalendarAccessMeta]'
|
||||
members: 'models.QuerySet[MetaPoolMember]'
|
||||
|
||||
class Meta(UUIDModel.Meta):
|
||||
"""
|
||||
Meta class to declare the name of the table at database
|
||||
@ -106,10 +108,10 @@ class MetaPool(UUIDModel, TaggingMixin): # type: ignore
|
||||
bool -- [description]
|
||||
"""
|
||||
total, maintenance = 0, 0
|
||||
p: ServicePool
|
||||
for p in self.pools.all():
|
||||
p: 'MetaPoolMember'
|
||||
for p in self.members.all():
|
||||
total += 1
|
||||
if p.isInMaintenance():
|
||||
if p.pool.isInMaintenance():
|
||||
maintenance += 1
|
||||
return total == maintenance
|
||||
|
||||
@ -137,7 +139,7 @@ class MetaPool(UUIDModel, TaggingMixin): # type: ignore
|
||||
return self.name
|
||||
|
||||
@staticmethod
|
||||
def getForGroups(groups: typing.Iterable['Group'], user: typing.Optional['User'] = None) -> QuerySet:
|
||||
def getForGroups(groups: typing.Iterable['Group'], user: typing.Optional['User'] = None) -> 'QuerySet[MetaPool]':
|
||||
"""
|
||||
Return deployed services with publications for the groups requested.
|
||||
|
||||
@ -157,12 +159,12 @@ class MetaPool(UUIDModel, TaggingMixin): # type: ignore
|
||||
'servicesPoolGroup__image',
|
||||
'assignedGroups',
|
||||
'assignedGroups',
|
||||
'pools',
|
||||
'pools__service',
|
||||
'pools__service__provider',
|
||||
'pools__image',
|
||||
'pools__transports',
|
||||
'pools__transports__networks',
|
||||
'members__pool',
|
||||
'members__pool__service',
|
||||
'members__pool__service__provider',
|
||||
'members__pool__image',
|
||||
'members__pool__transports',
|
||||
'members__pool__transports__networks',
|
||||
'calendarAccess',
|
||||
'calendarAccess__calendar',
|
||||
'calendarAccess__calendar__rules',
|
||||
@ -171,11 +173,11 @@ class MetaPool(UUIDModel, TaggingMixin): # type: ignore
|
||||
if user:
|
||||
meta = meta.annotate(
|
||||
number_in_use=models.Count(
|
||||
'pools__userServices',
|
||||
'members__pool__userServices',
|
||||
filter=models.Q(
|
||||
pools__userServices__user=user,
|
||||
pools__userServices__in_use=True,
|
||||
pools__userServices__state__in=states.userService.USABLE
|
||||
members__pool__userServices__user=user,
|
||||
members__pool__userServices__in_use=True,
|
||||
members__pool__userServices__state__in=states.userService.USABLE
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -204,7 +206,7 @@ class MetaPool(UUIDModel, TaggingMixin): # type: ignore
|
||||
|
||||
def __str__(self):
|
||||
return 'Meta pool: {}, no. pools: {}, visible: {}, policy: {}'.format(
|
||||
self.name, self.pools.all().count(), self.visible, self.policy
|
||||
self.name, self.members.all().count(), self.visible, self.policy
|
||||
)
|
||||
|
||||
|
||||
@ -213,8 +215,8 @@ signals.pre_delete.connect(MetaPool.beforeDelete, sender=MetaPool)
|
||||
|
||||
|
||||
class MetaPoolMember(UUIDModel):
|
||||
pool: ServicePool = models.ForeignKey(ServicePool, related_name='memberOfMeta', on_delete=models.CASCADE)
|
||||
meta_pool: MetaPool = models.ForeignKey(MetaPool, related_name='members', on_delete=models.CASCADE)
|
||||
pool: 'models.ForeignKey[MetaPoolMember, ServicePool]' = models.ForeignKey(ServicePool, related_name='memberOfMeta', on_delete=models.CASCADE)
|
||||
meta_pool: 'models.ForeignKey[MetaPoolMember, MetaPool]' = models.ForeignKey(MetaPool, related_name='members', on_delete=models.CASCADE)
|
||||
priority = models.PositiveIntegerField(default=0)
|
||||
enabled = models.BooleanField(default=True)
|
||||
|
||||
@ -225,5 +227,5 @@ class MetaPoolMember(UUIDModel):
|
||||
db_table = 'uds__meta_pool_member'
|
||||
app_label = 'uds'
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return '{}/{} {} {}'.format(self.pool.name, self.meta_pool.name, self.priority, self.enabled)
|
||||
|
@ -34,7 +34,6 @@ import logging
|
||||
import typing
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import signals
|
||||
|
||||
from uds.core.util import net
|
||||
|
||||
@ -123,11 +122,11 @@ class Network(UUIDModel, TaggingMixin): # type: ignore
|
||||
self.net_string = netRange
|
||||
self.save()
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return u'Network {} ({}) from {} to {}'.format(self.name, self.net_string, net.longToIp(self.net_start), net.longToIp(self.net_end))
|
||||
|
||||
@staticmethod
|
||||
def beforeDelete(sender, **kwargs):
|
||||
def beforeDelete(sender, **kwargs) -> None:
|
||||
from uds.core.util.permissions import clean
|
||||
toDelete = kwargs['instance']
|
||||
|
||||
@ -137,4 +136,4 @@ class Network(UUIDModel, TaggingMixin): # type: ignore
|
||||
clean(toDelete)
|
||||
|
||||
# Connects a pre deletion signal to Authenticator
|
||||
signals.pre_delete.connect(Network.beforeDelete, sender=Network)
|
||||
models.signals.pre_delete.connect(Network.beforeDelete, sender=Network)
|
||||
|
@ -33,8 +33,7 @@
|
||||
import logging
|
||||
import typing
|
||||
|
||||
from django.db import IntegrityError
|
||||
from django.db.models import signals
|
||||
from django.db import IntegrityError, models
|
||||
|
||||
from .managed_object_model import ManagedObjectModel
|
||||
from .tag import TaggingMixin
|
||||
@ -42,6 +41,7 @@ from .tag import TaggingMixin
|
||||
# Not imported at runtime, just for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from uds.core import osmanagers
|
||||
from uds.models import ServicePool
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -50,7 +50,9 @@ class OSManager(ManagedObjectModel, TaggingMixin): # type: ignore
|
||||
"""
|
||||
An OS Manager represents a manager for responding requests for agents inside services.
|
||||
"""
|
||||
# pylint: disable=model-missing-unicode
|
||||
|
||||
# "fake" relations declarations for type checking
|
||||
deployedServices: 'models.QuerySet[ServicePool]'
|
||||
|
||||
class Meta(ManagedObjectModel.Meta):
|
||||
"""
|
||||
@ -102,7 +104,7 @@ class OSManager(ManagedObjectModel, TaggingMixin): # type: ignore
|
||||
return "{0} of type {1} (id:{2})".format(self.name, self.data_type, self.id)
|
||||
|
||||
@staticmethod
|
||||
def beforeDelete(sender, **kwargs):
|
||||
def beforeDelete(sender, **kwargs) -> None:
|
||||
"""
|
||||
Used to invoke the Service class "Destroy" before deleting it from database.
|
||||
|
||||
@ -122,5 +124,6 @@ class OSManager(ManagedObjectModel, TaggingMixin): # type: ignore
|
||||
|
||||
logger.debug('Before delete os manager %s', toDelete)
|
||||
|
||||
|
||||
# : Connects a pre deletion signal to OS Manager
|
||||
signals.pre_delete.connect(OSManager.beforeDelete, sender=OSManager)
|
||||
models.signals.pre_delete.connect(OSManager.beforeDelete, sender=OSManager)
|
||||
|
@ -76,7 +76,7 @@ class Permissions(UUIDModel):
|
||||
}.get(perm, _('None'))
|
||||
|
||||
@staticmethod
|
||||
def addPermission(**kwargs):
|
||||
def addPermission(**kwargs) -> 'Permissions':
|
||||
"""
|
||||
Adds a permission to an object and an user or group
|
||||
"""
|
||||
@ -113,7 +113,7 @@ class Permissions(UUIDModel):
|
||||
object_type=object_type, object_id=object_id, permission=permission)
|
||||
|
||||
@staticmethod
|
||||
def getPermissions(**kwargs):
|
||||
def getPermissions(**kwargs) -> int:
|
||||
"""
|
||||
Retrieves the permission for a given object
|
||||
It's mandatory to include at least object_type param
|
||||
@ -149,29 +149,29 @@ class Permissions(UUIDModel):
|
||||
return Permissions.PERMISSION_NONE
|
||||
|
||||
@staticmethod
|
||||
def enumeratePermissions(object_type, object_id):
|
||||
def enumeratePermissions(object_type, object_id) -> 'models.QuerySet[Permissions]':
|
||||
"""
|
||||
Get users permissions over object
|
||||
"""
|
||||
return Permissions.objects.filter(object_type=object_type, object_id=object_id)
|
||||
|
||||
@staticmethod
|
||||
def cleanPermissions(object_type, object_id):
|
||||
def cleanPermissions(object_type, object_id) -> None:
|
||||
Permissions.objects.filter(object_type=object_type, object_id=object_id).delete()
|
||||
|
||||
@staticmethod
|
||||
def cleanUserPermissions(user):
|
||||
def cleanUserPermissions(user) -> None:
|
||||
Permissions.objects.filter(user=user).delete()
|
||||
|
||||
@staticmethod
|
||||
def cleanGroupPermissions(group):
|
||||
def cleanGroupPermissions(group) -> None:
|
||||
Permissions.objects.filter(group=group).delete()
|
||||
|
||||
@property
|
||||
def permission_as_string(self):
|
||||
def permission_as_string(self) -> str:
|
||||
return Permissions.permissionAsString(self.permission)
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return 'Permission {}, user {} group {} object_type {} object_id {} permission {}'.format(
|
||||
self.uuid, self.user, self.group, self.object_type, self.object_id, Permissions.permissionAsString(self.permission)
|
||||
)
|
||||
|
@ -86,11 +86,11 @@ class Provider(ManagedObjectModel, TaggingMixin): # type: ignore
|
||||
def isInMaintenance(self) -> bool:
|
||||
return self.maintenance_mode
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return '{} of type {} (id:{})'.format(self.name, self.data_type, self.id)
|
||||
|
||||
@staticmethod
|
||||
def beforeDelete(sender, **kwargs):
|
||||
def beforeDelete(sender, **kwargs) -> None:
|
||||
"""
|
||||
Used to invoke the Provider class "Destroy" before deleting it from database.
|
||||
|
||||
|
@ -105,5 +105,5 @@ class Proxy(UUIDModel, TaggingMixin): # type: ignore
|
||||
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return 'Proxy {} on {}:{} '.format(self.name, self.host, self.port)
|
||||
|
@ -71,6 +71,9 @@ class Scheduler(models.Model):
|
||||
owner_server = models.CharField(max_length=64, db_index=True, default='')
|
||||
state = models.CharField(max_length=1, default=State.FOR_EXECUTE, db_index=True)
|
||||
|
||||
# primary key id declaration (for type checking)
|
||||
id: int
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Meta class to declare default order and unique multiple field index
|
||||
|
@ -34,7 +34,6 @@ import logging
|
||||
import typing
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import signals
|
||||
|
||||
from uds.core.environment import Environment
|
||||
from uds.core.util import log
|
||||
@ -59,10 +58,10 @@ class Service(ManagedObjectModel, TaggingMixin): # type: ignore
|
||||
A Service represents an specidied type of service offered to final users, with it configuration (i.e. a KVM Base Machine for cloning
|
||||
or a Terminal Server configuration).
|
||||
"""
|
||||
provider: 'Provider' = models.ForeignKey(Provider, related_name='services', on_delete=models.CASCADE)
|
||||
provider: 'models.ForeignKey[Service, Provider]' = models.ForeignKey(Provider, related_name='services', on_delete=models.CASCADE)
|
||||
|
||||
# Proxy for this service
|
||||
proxy: typing.Optional['Proxy'] = models.ForeignKey(Proxy, null=True, blank=True, related_name='services', on_delete=models.CASCADE)
|
||||
proxy: 'models.ForeignKey[Service, Proxy]' = models.ForeignKey(Proxy, null=True, blank=True, related_name='services', on_delete=models.CASCADE)
|
||||
|
||||
token = models.CharField(max_length=32, default=None, null=True, blank=True, unique=True)
|
||||
|
||||
@ -182,4 +181,4 @@ class Service(ManagedObjectModel, TaggingMixin): # type: ignore
|
||||
clean(toDelete)
|
||||
|
||||
# : Connects a pre deletion signal to Service
|
||||
signals.pre_delete.connect(Service.beforeDelete, sender=Service)
|
||||
models.signals.pre_delete.connect(Service.beforeDelete, sender=Service)
|
||||
|
@ -34,9 +34,9 @@ import typing
|
||||
import logging
|
||||
import pickle
|
||||
from datetime import datetime, timedelta
|
||||
from uds.core.util.states import publication
|
||||
|
||||
from django.db import models, transaction
|
||||
from django.db.models import signals, QuerySet
|
||||
|
||||
from uds.core.environment import Environment
|
||||
from uds.core.util import log
|
||||
@ -53,7 +53,6 @@ from .transport import Transport
|
||||
from .group import Group
|
||||
from .image import Image
|
||||
from .service_pool_group import ServicePoolGroup
|
||||
from .calendar import Calendar
|
||||
from .account import Account
|
||||
|
||||
from .util import NEVER
|
||||
@ -62,9 +61,7 @@ from .util import getSqlDatetime
|
||||
|
||||
# Not imported at runtime, just for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from uds.models import UserService, ServicePoolPublication, User, Group, Proxy
|
||||
from django.db.models import QuerySet
|
||||
|
||||
from uds.models import UserService, ServicePoolPublication, User, Group, Proxy, MetaPoolMember, CalendarAccess
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -76,8 +73,8 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
name = models.CharField(max_length=128, default='')
|
||||
short_name = models.CharField(max_length=32, default='')
|
||||
comments = models.CharField(max_length=256, default='')
|
||||
service: Service = models.ForeignKey(Service, null=True, blank=True, related_name='deployedServices', on_delete=models.CASCADE)
|
||||
osmanager: typing.Optional[OSManager] = models.ForeignKey(OSManager, null=True, blank=True, related_name='deployedServices', on_delete=models.CASCADE)
|
||||
service: 'models.ForeignKey[ServicePool, Service]' = models.ForeignKey(Service, null=True, blank=True, related_name='deployedServices', on_delete=models.CASCADE)
|
||||
osmanager: 'models.ForeignKey[ServicePool, OSManager]' = models.ForeignKey(OSManager, null=True, blank=True, related_name='deployedServices', on_delete=models.CASCADE)
|
||||
transports = models.ManyToManyField(Transport, related_name='deployedServices', db_table='uds__ds_trans')
|
||||
assignedGroups = models.ManyToManyField(Group, related_name='deployedServices', db_table='uds__ds_grps')
|
||||
state = models.CharField(max_length=1, default=states.servicePool.ACTIVE, db_index=True)
|
||||
@ -89,17 +86,18 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
|
||||
ignores_unused = models.BooleanField(default=False)
|
||||
|
||||
image: typing.Optional[Image] = models.ForeignKey(Image, null=True, blank=True, related_name='deployedServices', on_delete=models.SET_NULL)
|
||||
image: 'models.ForeignKey[ServicePool, Image]' = models.ForeignKey(Image, null=True, blank=True, related_name='deployedServices', on_delete=models.SET_NULL)
|
||||
|
||||
servicesPoolGroup: typing.Optional[ServicePoolGroup] = models.ForeignKey(ServicePoolGroup, null=True, blank=True, related_name='servicesPools', on_delete=models.SET_NULL)
|
||||
servicesPoolGroup: 'models.ForeignKey[ServicePool, ServicePoolGroup]' = models.ForeignKey(ServicePoolGroup, null=True, blank=True, related_name='servicesPools', on_delete=models.SET_NULL)
|
||||
|
||||
# Message if access denied
|
||||
calendar_message = models.CharField(default='', max_length=256)
|
||||
# Default fallback action for access
|
||||
fallbackAccess = models.CharField(default=states.action.ALLOW, max_length=8)
|
||||
# actionsCalendars = models.ManyToManyField(Calendar, related_name='actionsSP', through='CalendarAction')
|
||||
|
||||
# Usage accounting
|
||||
account: typing.Optional[Account] = models.ForeignKey(Account, null=True, blank=True, related_name='servicesPools', on_delete=models.CASCADE)
|
||||
account: 'models.ForeignKey[ServicePool, Account]' = models.ForeignKey(Account, null=True, blank=True, related_name='servicesPools', on_delete=models.CASCADE)
|
||||
|
||||
initial_srvs = models.PositiveIntegerField(default=0)
|
||||
cache_l1_srvs = models.PositiveIntegerField(default=0)
|
||||
@ -107,6 +105,12 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
max_srvs = models.PositiveIntegerField(default=0)
|
||||
current_pub_revision = models.PositiveIntegerField(default=1)
|
||||
|
||||
# "fake" relations declarations for type checking
|
||||
publications: 'models.QuerySet[ServicePoolPublication]'
|
||||
memberOfMeta: 'models.QuerySet[MetaPoolMember]'
|
||||
userServices: 'models.QuerySet[UserService]'
|
||||
calendarAccess: 'models.QuerySet[CalendarAccess]'
|
||||
|
||||
# Meta service related
|
||||
# meta_pools = models.ManyToManyField('self', symmetrical=False)
|
||||
|
||||
@ -121,6 +125,9 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
"""
|
||||
Returns an environment valid for the record this object represents
|
||||
"""
|
||||
a = self.image
|
||||
|
||||
|
||||
return Environment.getEnvForTableElement(self._meta.verbose_name, self.id)
|
||||
|
||||
def activePublication(self) -> typing.Optional['ServicePoolPublication']:
|
||||
@ -133,7 +140,7 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
None if there is no valid publication for this deployed service.
|
||||
"""
|
||||
try:
|
||||
return self.publications.filter(state=states.publication.USABLE)[0]
|
||||
return typing.cast(ServicePoolPublication, self.publications.filter(state=states.publication.USABLE)[0])
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
@ -154,13 +161,13 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
return username, password
|
||||
|
||||
@staticmethod
|
||||
def getRestrainedsQuerySet() -> QuerySet:
|
||||
def getRestrainedsQuerySet() -> models.QuerySet:
|
||||
from uds.models.user_service import UserService # pylint: disable=redefined-outer-name
|
||||
from uds.core.util.config import GlobalConfig
|
||||
from django.db.models import Count
|
||||
|
||||
if GlobalConfig.RESTRAINT_TIME.getInt() <= 0:
|
||||
return [] # Do not perform any restraint check if we set the globalconfig to 0 (or less)
|
||||
return ServicePool.objects.none() # Do not perform any restraint check if we set the globalconfig to 0 (or less)
|
||||
|
||||
date = typing.cast(datetime, getSqlDatetime()) - timedelta(seconds=GlobalConfig.RESTRAINT_TIME.getInt())
|
||||
min_ = GlobalConfig.RESTRAINT_COUNT.getInt()
|
||||
@ -174,8 +181,8 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
return ServicePool.objects.filter(pk__in=res)
|
||||
|
||||
@staticmethod
|
||||
def getRestraineds() -> typing.Iterable['ServicePool']:
|
||||
return ServicePool.getRestrainedsQuerySet().iterator()
|
||||
def getRestraineds() -> typing.Iterator['ServicePool']:
|
||||
return typing.cast(typing.Iterator['ServicePool'], ServicePool.getRestrainedsQuerySet().iterator())
|
||||
|
||||
@property
|
||||
def is_meta(self) -> bool:
|
||||
@ -234,7 +241,8 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
|
||||
# Return the date
|
||||
try:
|
||||
if activePub and activePub.id != self.assignedUserServices().filter(user=forUser, state__in=states.userService.VALID_STATES)[0].publication.id:
|
||||
found = typing.cast('UserService', self.assignedUserServices().filter(user=forUser, state__in=states.userService.VALID_STATES)[0])
|
||||
if activePub and found.publication and activePub.id != found.publication.id:
|
||||
ret = self.recoverValue('toBeReplacedIn')
|
||||
if ret:
|
||||
return pickle.loads(ret)
|
||||
@ -499,7 +507,7 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
if pub:
|
||||
pub.unpublish()
|
||||
|
||||
def cachedUserServices(self) -> 'QuerySet':
|
||||
def cachedUserServices(self) -> 'models.QuerySet':
|
||||
"""
|
||||
':rtype uds.models.user_service.UserService'
|
||||
Utility method to access the cached user services (level 1 and 2)
|
||||
@ -509,7 +517,7 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
"""
|
||||
return self.userServices.exclude(cache_level=0)
|
||||
|
||||
def assignedUserServices(self) -> 'QuerySet':
|
||||
def assignedUserServices(self) -> 'models.QuerySet':
|
||||
"""
|
||||
Utility method to access the assigned user services
|
||||
|
||||
@ -518,7 +526,7 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
"""
|
||||
return self.userServices.filter(cache_level=0)
|
||||
|
||||
def erroneousUserServices(self) -> 'QuerySet':
|
||||
def erroneousUserServices(self) -> 'models.QuerySet':
|
||||
"""
|
||||
Utility method to locate invalid assigned user services.
|
||||
|
||||
@ -585,4 +593,4 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
|
||||
|
||||
|
||||
# Connects a pre deletion signal to Authenticator
|
||||
signals.pre_delete.connect(ServicePool.beforeDelete, sender=ServicePool)
|
||||
models.signals.pre_delete.connect(ServicePool.beforeDelete, sender=ServicePool)
|
||||
|
@ -53,7 +53,7 @@ class ServicePoolGroup(UUIDModel):
|
||||
name = models.CharField(max_length=128, default='', db_index=True, unique=True)
|
||||
comments = models.CharField(max_length=256, default='')
|
||||
priority = models.IntegerField(default=0, db_index=True)
|
||||
image: Image = models.ForeignKey(Image, null=True, blank=True, related_name='servicesPoolsGroup', on_delete=models.SET_NULL)
|
||||
image: 'models.ForeignKey[ServicePoolGroup, Image]' = models.ForeignKey(Image, null=True, blank=True, related_name='servicesPoolsGroup', on_delete=models.SET_NULL)
|
||||
|
||||
class Meta(UUIDModel.Meta):
|
||||
"""
|
||||
@ -63,7 +63,7 @@ class ServicePoolGroup(UUIDModel):
|
||||
app_label = 'uds'
|
||||
|
||||
def __str__(self):
|
||||
return 'Service Pool group {}({})'.format(self.name, self.comments)
|
||||
return 'Service Pool group {}({}): {}'.format(self.name, self.comments, self.image.name)
|
||||
|
||||
@property
|
||||
def as_dict(self) -> typing.Dict[str, typing.Any]:
|
||||
|
@ -35,7 +35,6 @@ import logging
|
||||
import typing
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import signals
|
||||
|
||||
from uds.core.util.state import State
|
||||
from uds.core.environment import Environment
|
||||
@ -48,12 +47,13 @@ from .uuid_model import UUIDModel
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from uds.core import services
|
||||
from uds.models import UserService
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ServicePoolPublicationChangelog(models.Model):
|
||||
publication: ServicePool = models.ForeignKey(ServicePool, on_delete=models.CASCADE, related_name='changelog')
|
||||
publication: 'models.ForeignKey[ServicePoolPublication, ServicePool]' = models.ForeignKey(ServicePool, on_delete=models.CASCADE, related_name='changelog')
|
||||
stamp = models.DateTimeField()
|
||||
revision = models.PositiveIntegerField(default=1)
|
||||
log = models.TextField(default='')
|
||||
@ -72,7 +72,7 @@ class ServicePoolPublication(UUIDModel):
|
||||
"""
|
||||
A deployed service publication keep track of data needed by services that needs "preparation". (i.e. Virtual machine --> base machine --> children of base machines)
|
||||
"""
|
||||
deployed_service: ServicePool = models.ForeignKey(ServicePool, on_delete=models.CASCADE, related_name='publications')
|
||||
deployed_service: 'models.ForeignKey[ServicePoolPublication, ServicePool]' = models.ForeignKey(ServicePool, on_delete=models.CASCADE, related_name='publications')
|
||||
publish_date = models.DateTimeField(db_index=True)
|
||||
# data_type = models.CharField(max_length=128) # The data type is specified by the service itself
|
||||
data = models.TextField(default='')
|
||||
@ -87,6 +87,10 @@ class ServicePoolPublication(UUIDModel):
|
||||
state_date = models.DateTimeField()
|
||||
revision = models.PositiveIntegerField(default=1)
|
||||
|
||||
# "fake" relations declarations for type checking
|
||||
userServices: 'models.QuerySet[UserService]'
|
||||
|
||||
|
||||
class Meta(UUIDModel.Meta):
|
||||
"""
|
||||
Meta class to declare default order and unique multiple field index
|
||||
@ -207,4 +211,4 @@ class ServicePoolPublication(UUIDModel):
|
||||
return 'Publication {}, rev {}, state {}'.format(self.deployed_service.name, self.revision, State.toString(self.state))
|
||||
|
||||
# Connects a pre deletion signal to Authenticator
|
||||
signals.pre_delete.connect(ServicePoolPublication.beforeDelete, sender=ServicePoolPublication)
|
||||
models.signals.pre_delete.connect(ServicePoolPublication.beforeDelete, sender=ServicePoolPublication)
|
||||
|
@ -63,7 +63,7 @@ class StatsCounters(models.Model):
|
||||
app_label = 'uds'
|
||||
|
||||
@staticmethod
|
||||
def get_grouped(owner_type: typing.Union[int, typing.Iterable[int]], counter_type: int, **kwargs) -> typing.Iterable: # pylint: disable=too-many-locals
|
||||
def get_grouped(owner_type: typing.Union[int, typing.Iterable[int]], counter_type: int, **kwargs) -> 'models.QuerySet[StatsCounters]': # pylint: disable=too-many-locals
|
||||
"""
|
||||
Returns the average stats grouped by interval for owner_type and owner_id (optional)
|
||||
|
||||
@ -146,7 +146,7 @@ class StatsCounters(models.Model):
|
||||
logger.debug('Stats query: %s', query)
|
||||
|
||||
# We use result as an iterator
|
||||
return StatsCounters.objects.raw(query)
|
||||
return typing.cast('models.QuerySet[StatsCounters]', StatsCounters.objects.raw(query))
|
||||
|
||||
def __str__(self):
|
||||
return u"Counter of {}({}): {} - {} - {}".format(self.owner_type, self.owner_id, self.stamp, self.counter_type, self.value)
|
||||
|
@ -67,9 +67,9 @@ class StatsEvents(models.Model):
|
||||
app_label = 'uds'
|
||||
|
||||
@staticmethod
|
||||
def get_stats(owner_type: typing.Union[int, typing.Iterable[int]], event_type: typing.Union[int, typing.Iterable[int]], **kwargs) -> models.QuerySet:
|
||||
def get_stats(owner_type: typing.Union[int, typing.Iterable[int]], event_type: typing.Union[int, typing.Iterable[int]], **kwargs) -> 'models.QuerySet[StatsEvents]':
|
||||
"""
|
||||
Returns the average stats grouped by interval for owner_type and owner_id (optional)
|
||||
Returns a queryset with the average stats grouped by interval for owner_type and owner_id (optional)
|
||||
|
||||
Note: if someone cant get this more optimized, please, contribute it!
|
||||
"""
|
||||
|
@ -56,4 +56,4 @@ class Storage(models.Model):
|
||||
app_label = 'uds'
|
||||
|
||||
def __str__(self):
|
||||
return '{} {} = {}, {}'.format(self.owner, self.key, self.data, '/'.join([self.attr1]))
|
||||
return '{} {} > str= {}, {}'.format(self.owner, self.key, self.data, '/'.join([self.attr1]))
|
||||
|
@ -57,10 +57,10 @@ class Tag(UUIDModel):
|
||||
app_label = 'uds'
|
||||
|
||||
@property
|
||||
def vtag(self):
|
||||
def vtag(self) -> str:
|
||||
return self.tag.capitalize()
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return 'Tag: {} {}'.format(self.uuid, self.tag)
|
||||
|
||||
|
||||
|
@ -102,7 +102,7 @@ class TicketStore(UUIDModel):
|
||||
data: str,
|
||||
validatorFnc: typing.Optional[ValidatorType] = None,
|
||||
validity: int = DEFAULT_VALIDITY,
|
||||
owner: typing.Optional[str] = owner,
|
||||
owner: typing.Optional[str] = None,
|
||||
secure: bool = False
|
||||
) -> None:
|
||||
"""
|
||||
@ -119,6 +119,7 @@ class TicketStore(UUIDModel):
|
||||
t.data = pickle.dumps(data)
|
||||
t.stamp = getSqlDatetime()
|
||||
t.validity = validity
|
||||
t.owner = owner
|
||||
t.save()
|
||||
except TicketStore.DoesNotExist:
|
||||
TicketStore.objects.create(uuid=uuid, stamp=getSqlDatetime(), data=pickle.dumps(data), validator=validator, validity=validity)
|
||||
|
@ -34,7 +34,6 @@ import logging
|
||||
import typing
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import signals
|
||||
|
||||
from uds.core import transports
|
||||
|
||||
@ -43,6 +42,10 @@ from uds.core.util import net
|
||||
from .managed_object_model import ManagedObjectModel
|
||||
from .tag import TaggingMixin
|
||||
|
||||
# Not imported at runtime, just for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from uds.models import Network
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -59,6 +62,10 @@ class Transport(ManagedObjectModel, TaggingMixin):
|
||||
# We store allowed oss as a comma-separated list
|
||||
allowed_oss = models.CharField(max_length=255, default='')
|
||||
|
||||
# "fake" relations declarations for type checking
|
||||
networks: 'models.QuerySet[Network]'
|
||||
|
||||
|
||||
class Meta(ManagedObjectModel.Meta):
|
||||
"""
|
||||
Meta class to declare default order
|
||||
@ -69,7 +76,7 @@ class Transport(ManagedObjectModel, TaggingMixin):
|
||||
def getInstance(self, values: typing.Optional[typing.Dict[str, str]] = None) -> 'transports.Transport':
|
||||
return typing.cast('transports.Transport', super().getInstance(values=values))
|
||||
|
||||
def getType(self) -> typing.Type['transports.Transport']:
|
||||
def getType(self) -> 'typing.Type[transports.Transport]':
|
||||
"""
|
||||
Get the type of the object this record represents.
|
||||
|
||||
@ -121,7 +128,7 @@ class Transport(ManagedObjectModel, TaggingMixin):
|
||||
return True
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return '{} of type {} (id:{})'.format(self.name, self.data_type, self.id)
|
||||
|
||||
@staticmethod
|
||||
@ -148,4 +155,4 @@ class Transport(ManagedObjectModel, TaggingMixin):
|
||||
clean(toDelete)
|
||||
|
||||
# : Connects a pre deletion signal to OS Manager
|
||||
signals.pre_delete.connect(Transport.beforeDelete, sender=Transport)
|
||||
models.signals.pre_delete.connect(Transport.beforeDelete, sender=Transport)
|
||||
|
@ -56,5 +56,5 @@ class UniqueId(models.Model):
|
||||
ordering = ('-seq',)
|
||||
app_label = 'uds'
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return u"{0} {1}.{2}, assigned is {3}".format(self.owner, self.basename, self.seq, self.assigned)
|
||||
|
@ -70,6 +70,9 @@ class User(UUIDModel):
|
||||
parent = models.CharField(max_length=50, default=None, null=True)
|
||||
created = models.DateTimeField(default=getSqlDatetime, blank=True)
|
||||
|
||||
# "fake" relations declarations for type checking
|
||||
groups: 'models.QuerySet[Group]'
|
||||
|
||||
class Meta(UUIDModel.Meta):
|
||||
"""
|
||||
Meta class to declare default order and unique multiple field index
|
||||
@ -154,7 +157,7 @@ class User(UUIDModel):
|
||||
usr = self
|
||||
|
||||
grps: typing.List[int] = []
|
||||
g: 'Group'
|
||||
|
||||
for g in usr.groups.filter(is_meta=False):
|
||||
grps.append(g.id)
|
||||
yield g
|
||||
@ -164,17 +167,18 @@ class User(UUIDModel):
|
||||
.annotate(number_groups=Count('groups')) # g.groups.count()
|
||||
.annotate(number_belongs_meta=Count('groups', filter=Q(groups__id__in=grps))) # g.groups.filter(id__in=grps).count()
|
||||
):
|
||||
numberGroupsBelongingInMeta: int = g.number_belongs_meta
|
||||
numberGroupsBelongingInMeta: int = g.number_belongs_meta
|
||||
|
||||
logger.debug('gn = %s', numberGroupsBelongingInMeta)
|
||||
logger.debug('groups count: %s', g.number_groups)
|
||||
logger.debug('groups count: %s', g.number_groups)
|
||||
|
||||
if g.meta_if_any is True and numberGroupsBelongingInMeta > 0:
|
||||
numberGroupsBelongingInMeta = g.number_groups
|
||||
|
||||
logger.debug('gn after = %s', numberGroupsBelongingInMeta)
|
||||
|
||||
if numberGroupsBelongingInMeta == g.number_groups: # If a meta group is empty, all users belongs to it. we can use gn != 0 to check that if it is empty, is not valid
|
||||
# If a meta group is empty, all users belongs to it. we can use gn != 0 to check that if it is empty, is not valid
|
||||
if numberGroupsBelongingInMeta == g.number_groups:
|
||||
# This group matches
|
||||
yield g
|
||||
|
||||
|
@ -52,5 +52,5 @@ class UserPreference(models.Model):
|
||||
class Meta:
|
||||
app_label = 'uds'
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return '{}.{} = "{}" for user {}'.format(self.module, self.name, self.value, self.user)
|
||||
|
@ -65,8 +65,9 @@ class UserService(UUIDModel): # pylint: disable=too-many-public-methods
|
||||
|
||||
# The reference to deployed service is used to accelerate the queries for different methods, in fact its redundant cause we can access to the deployed service
|
||||
# through publication, but queries are much more simple
|
||||
deployed_service: ServicePool = models.ForeignKey(ServicePool, on_delete=models.CASCADE, related_name='userServices')
|
||||
publication: typing.Optional[ServicePoolPublication] = models.ForeignKey(ServicePoolPublication, on_delete=models.CASCADE, null=True, blank=True, related_name='userServices')
|
||||
deployed_service: 'models.ForeignKey[UserService, ServicePool]' = models.ForeignKey(ServicePool, on_delete=models.CASCADE, related_name='userServices')
|
||||
publication: 'models.ForeignKey[UserService, ServicePoolPublication]' = models.ForeignKey(
|
||||
ServicePoolPublication, on_delete=models.CASCADE, null=True, blank=True, related_name='userServices')
|
||||
|
||||
unique_id = models.CharField(max_length=128, default='', db_index=True) # User by agents to locate machine
|
||||
friendly_name = models.CharField(max_length=128, default='')
|
||||
@ -76,7 +77,8 @@ class UserService(UUIDModel): # pylint: disable=too-many-public-methods
|
||||
state_date = models.DateTimeField(db_index=True)
|
||||
creation_date = models.DateTimeField(db_index=True)
|
||||
data = models.TextField(default='')
|
||||
user: User = models.ForeignKey(User, on_delete=models.CASCADE, related_name='userServices', null=True, blank=True, default=None)
|
||||
user: 'models.ForeignKey[UserService, User]' = models.ForeignKey(
|
||||
User, on_delete=models.CASCADE, related_name='userServices', null=True, blank=True, default=None)
|
||||
in_use = models.BooleanField(default=False)
|
||||
in_use_date = models.DateTimeField(default=NEVER)
|
||||
cache_level = models.PositiveSmallIntegerField(db_index=True, default=0) # Cache level must be 1 for L1 or 2 for L2, 0 if it is not cached service
|
||||
@ -86,6 +88,8 @@ class UserService(UUIDModel): # pylint: disable=too-many-public-methods
|
||||
|
||||
cluster_node = models.CharField(max_length=128, default=None, blank=True, null=True, db_index=True)
|
||||
|
||||
# "fake" relations declarations for type checking
|
||||
properties: 'models.QuerySet[UserServiceProperty]'
|
||||
|
||||
class Meta(UUIDModel.Meta):
|
||||
"""
|
||||
@ -163,7 +167,8 @@ class UserService(UUIDModel): # pylint: disable=too-many-public-methods
|
||||
logger.exception('Got exception at getInstance of an userService %s (seems that publication does not exists!)', self)
|
||||
if serviceInstance.deployedType is None:
|
||||
raise Exception('Class {0} needs deployedType but it is not defined!!!'.format(serviceInstance.__class__.__name__))
|
||||
us = serviceInstance.deployedType(self.getEnvironment(), service=serviceInstance, publication=publicationInstance, osmanager=osmanagerInstance, dbservice=self)
|
||||
us = serviceInstance.deployedType(self.getEnvironment(), service=serviceInstance,
|
||||
publication=publicationInstance, osmanager=osmanagerInstance, dbservice=self)
|
||||
if self.data != '' and self.data is not None:
|
||||
try:
|
||||
us.unserialize(self.data)
|
||||
@ -376,7 +381,8 @@ class UserService(UUIDModel): # pylint: disable=too-many-public-methods
|
||||
# 1.- If do not have any account associated, do nothing
|
||||
# 2.- If called but already accounting, do nothing
|
||||
# 3.- If called and not accounting, start accounting
|
||||
if self.deployed_service.account is None or hasattr(self, 'accounting'): # accounting comes from AccountUsage, and is a OneToOneRelation with UserService
|
||||
# accounting comes from AccountUsage, and is a OneToOneRelation with UserService
|
||||
if self.deployed_service.account is None or hasattr(self, 'accounting'):
|
||||
return
|
||||
|
||||
self.deployed_service.account.startUsageAccounting(self)
|
||||
|
@ -57,5 +57,5 @@ class UserServiceProperty(models.Model): # pylint: disable=too-many-public-meth
|
||||
unique_together = (('name', 'user_service'),)
|
||||
app_label = 'uds'
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return "Property of {}. {}={}".format(self.user_service.pk, self.name, self.value)
|
||||
|
@ -45,6 +45,9 @@ class UUIDModel(models.Model):
|
||||
"""
|
||||
uuid = models.CharField(max_length=50, default=None, null=True, unique=True)
|
||||
|
||||
# Automatic field from Model without a defined specific primary_key
|
||||
id: int
|
||||
|
||||
class Meta: # pylint: disable=too-few-public-methods
|
||||
abstract = True
|
||||
|
||||
|
@ -43,17 +43,18 @@ from uds.core.managers import userServiceManager
|
||||
|
||||
# Not imported at runtime, just for type checking
|
||||
if typing.TYPE_CHECKING:
|
||||
from django.http import HttpRequest # pylint: disable=ungrouped-imports
|
||||
from uds.core.util.request import ExtendedHttpRequest
|
||||
from uds.core.util.tools import DictAsObj
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def getServicesData(request: 'HttpRequest') -> typing.Dict[str, typing.Any]: # pylint: disable=too-many-locals, too-many-branches, too-many-statements
|
||||
def getServicesData(request: 'ExtendedHttpRequest') -> typing.Dict[str, typing.Any]: # pylint: disable=too-many-locals, too-many-branches, too-many-statements
|
||||
"""Obtains the service data dictionary will all available services for this request
|
||||
|
||||
Arguments:
|
||||
request {HttpRequest} -- request from where to xtract credentials
|
||||
request {ExtendedHttpRequest} -- request from where to xtract credentials
|
||||
|
||||
Returns:
|
||||
typing.Dict[str, typing.Any] -- Keys has this:
|
||||
@ -65,7 +66,9 @@ def getServicesData(request: 'HttpRequest') -> typing.Dict[str, typing.Any]: #
|
||||
|
||||
"""
|
||||
# Session data
|
||||
os: typing.Dict[str, str] = request.os
|
||||
os: 'DictAsObj' = request.os
|
||||
if not request.user:
|
||||
return {}
|
||||
|
||||
# We look for services for this authenticator groups. User is logged in in just 1 authenticator, so his groups must coincide with those assigned to ds
|
||||
groups = list(request.user.getGroups())
|
||||
|
Loading…
Reference in New Issue
Block a user