Adding "manual assignements" for UDS

This commit is contained in:
Adolfo Gómez García 2019-11-11 13:27:33 +01:00
parent 928360444b
commit eb2ad9da19
10 changed files with 124 additions and 8 deletions

View File

@ -81,6 +81,7 @@ class Services(DetailHandler): # pylint: disable=too-many-public-methods
'servicesTypeProvided': info.servicesTypeProvided, 'servicesTypeProvided': info.servicesTypeProvided,
'must_assign_manually': info.mustAssignManually, 'must_assign_manually': info.mustAssignManually,
'can_reset': info.canReset, 'can_reset': info.canReset,
'can_list_assignables': info.canAssign()
} }
@staticmethod @staticmethod

View File

@ -34,7 +34,7 @@ import logging
import typing import typing
from django.utils.translation import ugettext, ugettext_lazy as _ from django.utils.translation import ugettext, ugettext_lazy as _
from uds.models import ServicePool, OSManager, Service, Image, ServicePoolGroup, Account from uds.models import ServicePool, OSManager, Service, Image, ServicePoolGroup, Account, User
from uds.models.calendar_action import ( from uds.models.calendar_action import (
CALENDAR_ACTION_INITIAL, CALENDAR_ACTION_INITIAL,
CALENDAR_ACTION_MAX, CALENDAR_ACTION_MAX,
@ -105,7 +105,13 @@ class ServicesPools(ModelHandler):
# Field from where to get "class" and prefix for that class, so this will generate "row-state-A, row-state-X, .... # Field from where to get "class" and prefix for that class, so this will generate "row-state-A, row-state-X, ....
table_row_style = {'field': 'state', 'prefix': 'row-state-'} table_row_style = {'field': 'state', 'prefix': 'row-state-'}
custom_methods = [('setFallbackAccess', True), ('getFallbackAccess', True), ('actionsList', True)] custom_methods = [
('setFallbackAccess', True),
('getFallbackAccess', True),
('actionsList', True),
('listAssignables', True),
('createFromAssignable', True),
]
def item_as_dict(self, item: ServicePool) -> typing.Dict[str, typing.Any]: def item_as_dict(self, item: ServicePool) -> typing.Dict[str, typing.Any]:
summary = 'summarize' in self._params summary = 'summarize' in self._params
@ -438,7 +444,7 @@ class ServicesPools(ModelHandler):
return item.fallbackAccess return item.fallbackAccess
# Returns the action list based on current element, for calendar # Returns the action list based on current element, for calendar
def actionsList(self, item: ServicePool): def actionsList(self, item: ServicePool) -> typing.Any:
validActions: typing.Tuple[typing.Dict, ...] = () validActions: typing.Tuple[typing.Dict, ...] = ()
itemInfo = item.service.getType() itemInfo = item.service.getType()
if itemInfo.usesCache is True: if itemInfo.usesCache is True:
@ -452,3 +458,16 @@ class ServicesPools(ModelHandler):
# Transport & groups actions # Transport & groups actions
validActions += (CALENDAR_ACTION_ADD_TRANSPORT, CALENDAR_ACTION_DEL_TRANSPORT, CALENDAR_ACTION_ADD_GROUP, CALENDAR_ACTION_DEL_GROUP) validActions += (CALENDAR_ACTION_ADD_TRANSPORT, CALENDAR_ACTION_DEL_TRANSPORT, CALENDAR_ACTION_ADD_GROUP, CALENDAR_ACTION_DEL_GROUP)
return validActions return validActions
def listAssignables(self, item: ServicePool) -> typing.Any:
service = item.service.getInstance()
return [gui.choiceItem(i[0], i[1]) for i in service.listAssignables()]
def createFromAssignable(self, item: ServicePool) ->typing.Any:
if 'user_id' not in self._params or 'assignable_id' not in self._params:
return self.invalidRequestException('Invalid parameters')
logger.debug('Creating from assignable: %s', self._params)
userServiceManager().createFromAssignable(item, User.objects.get(uuid=processUuid(self._params['user_id'])), self._params['assignable_id'])
return True

View File

@ -192,6 +192,34 @@ class UserServiceManager:
return assigned return assigned
def createFromAssignable(self, servicePool: ServicePool, user: User, assignableId: str) -> UserService:
"""
Creates an assigned service from an "assignable" id
"""
serviceInstance = servicePool.service.getInstance()
if not serviceInstance.canAssign():
raise Exception('This service type cannot assign asignables')
if servicePool.service.getType().publicationType is not None:
publication = servicePool.activePublication()
logger.debug('Creating an assigned element from assignable %s for user %s por publication %s', user, assignableId, publication)
if publication:
assigned = self.__createAssignedAtDb(publication, user)
else:
raise Exception('Invalid publication creating service assignation: {} {}'.format(servicePool, user))
else:
logger.debug('Creating an assigned element from assignable %s for user %s', assignableId, user)
assigned = self.__createAssignedAtDbForNoPublication(servicePool, user)
# Now, get from serviceInstance the data
assignedInstance = assigned.getInstance()
state = serviceInstance.assignFromAssignables(assignableId, user, assignedInstance)
# assigned.updateData(assignedInstance)
UserServiceOpChecker.makeUnique(assigned, assignedInstance, state)
return assigned
def moveToLevel(self, cache: UserService, cacheLevel: int) -> None: def moveToLevel(self, cache: UserService, cacheLevel: int) -> None:
""" """
Moves a cache element from one level to another Moves a cache element from one level to another

View File

@ -36,6 +36,7 @@ import typing
from django.utils.translation import ugettext_noop as _ from django.utils.translation import ugettext_noop as _
from uds.core import Module from uds.core import Module
from uds.core.transports import protocols from uds.core.transports import protocols
from uds.core.util.state import State
from . import types from . import types
from .publication import Publication from .publication import Publication
@ -48,7 +49,7 @@ if typing.TYPE_CHECKING:
from uds.core.util.unique_name_generator import UniqueNameGenerator from uds.core.util.unique_name_generator import UniqueNameGenerator
from uds.core.util.unique_mac_generator import UniqueMacGenerator from uds.core.util.unique_mac_generator import UniqueMacGenerator
from uds.core.util.unique_gid_generator import UniqueGIDGenerator from uds.core.util.unique_gid_generator import UniqueGIDGenerator
from uds.models import ServicePoolPublication from uds.models import ServicePoolPublication, User
class Service(Module): class Service(Module):
@ -253,6 +254,37 @@ class Service(Module):
""" """
return typing.cast('UniqueNameGenerator', self.idGenerators('name')) return typing.cast('UniqueNameGenerator', self.idGenerators('name'))
def listAssignables(self) -> typing.Iterable[typing.Tuple[str, str]]:
"""
If overrided, will provide list of assignables elements, so we can "add" an element manually to the list of assigned user services
If not overriden, means that it cannot assign manually
Returns:
typing.List[typing.Tuple[str, str]] -- List of asignables services, first element is id, second is name of the element
"""
return []
def assignFromAssignables(self, assignableId: str, user: 'User', userDeployment: UserDeployment) -> str:
"""
Assigns from it internal assignable list to an user
Arguments:
assignableId {str} -- [description]
user {[type]} -- [description]
userDeployment {UserDeployment} -- [description]
Returns:
str -- State
"""
return State.FINISHED
@classmethod
def canAssign(cls) -> bool:
"""
Helper to query if a class is custom (implements getJavascript method)
"""
return cls.listAssignables != Service.listAssignables and cls.assignFromAssignables != Service.assignFromAssignables
def __str__(self): def __str__(self):
""" """
String method, mainly used for debugging purposes String method, mainly used for debugging purposes

View File

@ -72,7 +72,6 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
""" """
A deployed service is the Service produced element that is assigned finally to an user (i.e. a Virtual Machine, etc..) A deployed service is the Service produced element that is assigned finally to an user (i.e. a Virtual Machine, etc..)
""" """
# pylint: disable=model-missing-unicode
name = models.CharField(max_length=128, default='') name = models.CharField(max_length=128, default='')
short_name = models.CharField(max_length=32, default='') short_name = models.CharField(max_length=32, default='')
comments = models.CharField(max_length=256, default='') comments = models.CharField(max_length=256, default='')
@ -383,7 +382,7 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
""" """
from uds.core import auths from uds.core import auths
if not set(groups) & set(self.assignedGroups.all()): if not set(groups) & set(self.assignedGroups.all()):
raise auths.Exceptions.InvalidUserException() raise auths.exceptions.InvalidUserException()
def validatePublication(self) -> None: def validatePublication(self) -> None:
""" """

View File

@ -97,6 +97,23 @@ class IPMachineDeployed(services.UserDeployment, AutoAttributes):
logger.debug("Starting deploy of %s for user %s", self._ip, user) logger.debug("Starting deploy of %s for user %s", self._ip, user)
return self.__deploy() return self.__deploy()
def assign(self, ip: str) -> str:
logger.debug('Assigning from assignable with ip %s', ip)
self._ip = ip
self._state = State.FINISHED
dbService = self.dbservice()
if dbService:
dbService.setInUse(True)
dbService.save()
return self._state
def error(self, reason: str) -> str:
self._state = State.ERROR
self._ip = ''
self._reason = reason
return self._state
def checkState(self) -> str: def checkState(self) -> str:
return self._state return self._state

View File

@ -38,13 +38,16 @@ from django.utils.translation import ugettext_lazy as _
from uds.core.ui import gui from uds.core.ui import gui
from uds.core.services import types as serviceTypes from uds.core.services import types as serviceTypes
from uds.core.util.state import State
from .deployment import IPMachineDeployed from .deployment import IPMachineDeployed
from .service_base import IPServiceBase from .service_base import IPServiceBase
# Not imported at runtime, just for type checking # Not imported at runtime, just for type checking
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from uds import models
from uds.core import Module from uds.core import Module
from uds.core import services
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -120,3 +123,11 @@ class IPMachinesService(IPServiceBase):
self.storage.remove(ip) self.storage.remove(ip)
except Exception: except Exception:
logger.exception("Exception at getUnassignedMachine") logger.exception("Exception at getUnassignedMachine")
def listAssignables(self):
return [(ip, ip.split('~')[0]) for ip in self._ips]
def assignFromAssignables(self, assignableId: str, user: 'models.User', userDeployment: 'services.UserDeployment') -> str:
userServiceInstance = typing.cast(IPMachineDeployed, userDeployment)
return userServiceInstance.assign(assignableId)

File diff suppressed because one or more lines are too long

View File

@ -173,6 +173,7 @@ gettext("Please, select a valid group");
gettext("Logs"); gettext("Logs");
gettext("Launch now"); gettext("Launch now");
gettext("Change owner"); gettext("Change owner");
gettext("Assign service");
gettext("Cancel"); gettext("Cancel");
gettext("Changelog"); gettext("Changelog");
gettext("Delete assigned service"); gettext("Delete assigned service");
@ -189,6 +190,8 @@ gettext("Execute scheduled action right now?");
gettext("Scheduled action executed"); gettext("Scheduled action executed");
gettext("dismiss"); gettext("dismiss");
gettext("Delete calendar access rule"); gettext("Delete calendar access rule");
gettext("Error");
gettext("Please, select a valid user");
gettext("(This service does not requires an OS Manager)"); gettext("(This service does not requires an OS Manager)");
gettext("New service Pool"); gettext("New service Pool");
gettext("Publish on creation"); gettext("Publish on creation");
@ -409,6 +412,12 @@ gettext("Logs of");
gettext("Ok"); gettext("Ok");
gettext("Changelog of"); gettext("Changelog of");
gettext("Ok"); gettext("Ok");
gettext("Assign service to user manually");
gettext("Service");
gettext("Authenticator");
gettext("User");
gettext("Cancel");
gettext("Ok");
gettext("Priority"); gettext("Priority");
gettext("Calendar"); gettext("Calendar");
gettext("Action"); gettext("Action");

View File

@ -92,6 +92,6 @@
</svg> </svg>
</div> </div>
</uds-root> </uds-root>
<script src="/uds/res/admin/runtime.js?stamp=1572244247" defer></script><script src="/uds/res/admin/polyfills-es5.js?stamp=1572244247" nomodule defer></script><script src="/uds/res/admin/polyfills.js?stamp=1572244247" defer></script><script src="/uds/res/admin/main.js?stamp=1572244247" defer></script></body> <script src="/uds/res/admin/runtime.js?stamp=1573474523" defer></script><script src="/uds/res/admin/polyfills-es5.js?stamp=1573474523" nomodule defer></script><script src="/uds/res/admin/polyfills.js?stamp=1573474523" defer></script><script src="/uds/res/admin/main.js?stamp=1573474523" defer></script></body>
</html> </html>