forked from shaba/openuds
Adding "manual assignements" for UDS
This commit is contained in:
parent
928360444b
commit
eb2ad9da19
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
"""
|
"""
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
@ -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");
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user