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,
'must_assign_manually': info.mustAssignManually,
'can_reset': info.canReset,
'can_list_assignables': info.canAssign()
}
@staticmethod

View File

@ -34,7 +34,7 @@ import logging
import typing
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 (
CALENDAR_ACTION_INITIAL,
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, ....
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]:
summary = 'summarize' in self._params
@ -438,7 +444,7 @@ class ServicesPools(ModelHandler):
return item.fallbackAccess
# 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, ...] = ()
itemInfo = item.service.getType()
if itemInfo.usesCache is True:
@ -452,3 +458,16 @@ class ServicesPools(ModelHandler):
# Transport & groups actions
validActions += (CALENDAR_ACTION_ADD_TRANSPORT, CALENDAR_ACTION_DEL_TRANSPORT, CALENDAR_ACTION_ADD_GROUP, CALENDAR_ACTION_DEL_GROUP)
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
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:
"""
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 uds.core import Module
from uds.core.transports import protocols
from uds.core.util.state import State
from . import types
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_mac_generator import UniqueMacGenerator
from uds.core.util.unique_gid_generator import UniqueGIDGenerator
from uds.models import ServicePoolPublication
from uds.models import ServicePoolPublication, User
class Service(Module):
@ -253,6 +254,37 @@ class Service(Module):
"""
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):
"""
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..)
"""
# pylint: disable=model-missing-unicode
name = models.CharField(max_length=128, default='')
short_name = models.CharField(max_length=32, default='')
comments = models.CharField(max_length=256, default='')
@ -383,7 +382,7 @@ class ServicePool(UUIDModel, TaggingMixin): # type: ignore
"""
from uds.core import auths
if not set(groups) & set(self.assignedGroups.all()):
raise auths.Exceptions.InvalidUserException()
raise auths.exceptions.InvalidUserException()
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)
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:
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.services import types as serviceTypes
from uds.core.util.state import State
from .deployment import IPMachineDeployed
from .service_base import IPServiceBase
# Not imported at runtime, just for type checking
if typing.TYPE_CHECKING:
from uds import models
from uds.core import Module
from uds.core import services
logger = logging.getLogger(__name__)
@ -120,3 +123,11 @@ class IPMachinesService(IPServiceBase):
self.storage.remove(ip)
except Exception:
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("Launch now");
gettext("Change owner");
gettext("Assign service");
gettext("Cancel");
gettext("Changelog");
gettext("Delete assigned service");
@ -189,6 +190,8 @@ gettext("Execute scheduled action right now?");
gettext("Scheduled action executed");
gettext("dismiss");
gettext("Delete calendar access rule");
gettext("Error");
gettext("Please, select a valid user");
gettext("(This service does not requires an OS Manager)");
gettext("New service Pool");
gettext("Publish on creation");
@ -409,6 +412,12 @@ gettext("Logs of");
gettext("Ok");
gettext("Changelog of");
gettext("Ok");
gettext("Assign service to user manually");
gettext("Service");
gettext("Authenticator");
gettext("User");
gettext("Cancel");
gettext("Ok");
gettext("Priority");
gettext("Calendar");
gettext("Action");

View File

@ -92,6 +92,6 @@
</svg>
</div>
</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>