forked from shaba/openuds
sample provider moved to 3.7
This commit is contained in:
parent
d48e71cfd3
commit
a32bb87a78
@ -90,7 +90,7 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
Does nothing here also, all data are kept at environment storage
|
||||
"""
|
||||
|
||||
def getName(self):
|
||||
def getName(self) -> str:
|
||||
"""
|
||||
We override this to return a name to display. Default implementation
|
||||
(in base class), returns getUniqueIde() value
|
||||
@ -111,16 +111,15 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
a new unique name, so we keep the first generated name cached and don't
|
||||
generate more names. (Generator are simple utility classes)
|
||||
"""
|
||||
name = self.storage.readData('name')
|
||||
name: str = typing.cast(str, self.storage.readData('name'))
|
||||
if name is None:
|
||||
name = self.nameGenerator().get(self.service().getBaseName()
|
||||
+'-' + self.service().getColour(), 3)
|
||||
name = self.nameGenerator().get(self.service().getBaseName() + '-' + self.service().getColour(), 3)
|
||||
# Store value for persistence
|
||||
self.storage.saveData('name', name)
|
||||
|
||||
return name
|
||||
|
||||
def setIp(self, ip):
|
||||
def setIp(self, ip: str) -> None:
|
||||
"""
|
||||
In our case, there is no OS manager associated with this, so this method
|
||||
will never get called, but we put here as sample.
|
||||
@ -132,9 +131,9 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
:note: This IP is the IP of the "consumed service", so the transport can
|
||||
access it.
|
||||
"""
|
||||
self.storage.saveData('ip', str(ip))
|
||||
self.storage.saveData('ip', ip)
|
||||
|
||||
def getUniqueId(self):
|
||||
def getUniqueId(self) -> str:
|
||||
"""
|
||||
Return and unique identifier for this service.
|
||||
In our case, we will generate a mac name, that can be also as sample
|
||||
@ -144,13 +143,13 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
The get method of a mac generator takes one param, that is the mac range
|
||||
to use to get an unused mac.
|
||||
"""
|
||||
mac = self.storage.readData('mac')
|
||||
mac = typing.cast(str, self.storage.readData('mac'))
|
||||
if mac is None:
|
||||
mac = self.macGenerator().get('00:00:00:00:00:00-00:FF:FF:FF:FF:FF')
|
||||
self.storage.saveData('mac', mac)
|
||||
return mac
|
||||
|
||||
def getIp(self):
|
||||
def getIp(self) -> str:
|
||||
"""
|
||||
We need to implement this method, so we can return the IP for transports
|
||||
use. If no IP is known for this service, this must return None
|
||||
@ -168,12 +167,12 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
show the IP to the administrator, this method will get called
|
||||
|
||||
"""
|
||||
ip = self.storage.readData('ip')
|
||||
ip = typing.cast(str, self.storage.readData('ip'))
|
||||
if ip is None:
|
||||
ip = '192.168.0.34' # Sample IP for testing purposses only
|
||||
return ip
|
||||
|
||||
def setReady(self):
|
||||
def setReady(self) -> str:
|
||||
"""
|
||||
This is a task method. As that, the expected return values are
|
||||
State values RUNNING, FINISHED or ERROR.
|
||||
@ -206,7 +205,7 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
# In our case, the service is always ready
|
||||
return State.FINISHED
|
||||
|
||||
def deployForUser(self, user):
|
||||
def deployForUser(self, user: 'models.User') -> str:
|
||||
"""
|
||||
Deploys an service instance for an user.
|
||||
|
||||
@ -243,7 +242,7 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
|
||||
return State.RUNNING
|
||||
|
||||
def checkState(self):
|
||||
def checkState(self) -> str:
|
||||
"""
|
||||
Our deployForUser method will initiate the consumable service deployment,
|
||||
but will not finish it.
|
||||
@ -265,8 +264,10 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
destroying, and cancel will simply invoke destroy
|
||||
"""
|
||||
import random
|
||||
|
||||
count = int(self.storage.readData('count')) + 1
|
||||
countStr: typing.Optional[str] = typing.cast(str, self.storage.readData('count'))
|
||||
count: int = 0
|
||||
if countStr:
|
||||
count = int(countStr) + 1
|
||||
# Count is always a valid value, because this method will never get
|
||||
# called before deployForUser, deployForCache, destroy or cancel.
|
||||
# In our sample, we only use checkState in case of deployForUser,
|
||||
@ -282,7 +283,7 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
self.storage.saveData('count', str(count))
|
||||
return State.RUNNING
|
||||
|
||||
def finish(self):
|
||||
def finish(self) -> None:
|
||||
"""
|
||||
Invoked when the core notices that the deployment of a service has finished.
|
||||
(No matter wether it is for cache or for an user)
|
||||
@ -295,7 +296,7 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
# Note that this is not really needed, is just a sample of storage use
|
||||
self.storage.remove('count')
|
||||
|
||||
def userLoggedIn(self, user):
|
||||
def userLoggedIn(self, username: str) -> None:
|
||||
"""
|
||||
This method must be available so os managers can invoke it whenever
|
||||
an user get logged into a service.
|
||||
@ -310,9 +311,9 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
The user provided is just an string, that is provided by actor.
|
||||
"""
|
||||
# We store the value at storage, but never get used, just an example
|
||||
self.storage.saveData('user', user)
|
||||
self.storage.saveData('user', username)
|
||||
|
||||
def userLoggedOut(self, user):
|
||||
def userLoggedOut(self, username) -> None:
|
||||
"""
|
||||
This method must be available so os managers can invoke it whenever
|
||||
an user get logged out if a service.
|
||||
@ -329,7 +330,7 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
# We do nothing more that remove the user
|
||||
self.storage.remove('user')
|
||||
|
||||
def reasonOfError(self):
|
||||
def reasonOfError(self) -> str:
|
||||
"""
|
||||
Returns the reason of the error.
|
||||
|
||||
@ -337,9 +338,9 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
for it, and it will be asked everytime it's needed to be shown to the
|
||||
user (when the administation asks for it).
|
||||
"""
|
||||
return self.storage.readData('error') or 'No error'
|
||||
return typing.cast(str, self.storage.readData('error')) or 'No error'
|
||||
|
||||
def destroy(self):
|
||||
def destroy(self) -> str:
|
||||
"""
|
||||
This is a task method. As that, the excepted return values are
|
||||
State values RUNNING, FINISHED or ERROR.
|
||||
@ -350,7 +351,7 @@ class SampleUserDeploymentOne(services.UserDeployment):
|
||||
"""
|
||||
return State.FINISHED
|
||||
|
||||
def cancel(self):
|
||||
def cancel(self) -> str:
|
||||
"""
|
||||
This is a task method. As that, the excepted return values are
|
||||
State values RUNNING, FINISHED or ERROR.
|
||||
|
@ -77,7 +77,23 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
# : Recheck every five seconds by default (for task methods)
|
||||
suggestedTime = 2
|
||||
|
||||
def initialize(self):
|
||||
_name: str
|
||||
_ip: str
|
||||
_mac: str
|
||||
_error: str
|
||||
_count: int
|
||||
|
||||
# Utility overrides for type checking...
|
||||
def service(self) -> 'ServiceOne':
|
||||
return typing.cast('ServiceOne', super().service())
|
||||
|
||||
def publication(self) -> 'SamplePublication':
|
||||
pub = super().publication()
|
||||
if pub is None:
|
||||
raise Exception('No publication for this element!')
|
||||
return typing.cast('SamplePublication', pub)
|
||||
|
||||
def initialize(self) -> None:
|
||||
"""
|
||||
Initialize default attributes values here. We can do whatever we like,
|
||||
but for this sample this is just right...
|
||||
@ -89,7 +105,7 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
self._count = 0
|
||||
|
||||
# Serializable needed methods
|
||||
def marshal(self):
|
||||
def marshal(self) -> bytes:
|
||||
"""
|
||||
Marshal own data, in this sample we will marshal internal needed
|
||||
attributes.
|
||||
@ -105,21 +121,21 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
"""
|
||||
data = '\t'.join(['v1', self._name, self._ip, self._mac, self._error,
|
||||
str(self._count)])
|
||||
return codecs.encode(data.encode('utf8'), 'zip')
|
||||
return codecs.encode(data.encode(), encoding='zip') # type: ignore
|
||||
|
||||
def unmarshal(self, data):
|
||||
def unmarshal(self, data: bytes) -> None:
|
||||
"""
|
||||
We unmarshal the content.
|
||||
"""
|
||||
data = codecs.decode(data, 'zip').decode('utf8').split('\t')
|
||||
values: typing.List[str] = codecs.decode(data, 'zip').decode().split('\t') # type: ignore
|
||||
# Data Version check
|
||||
# If we include some new data at some point in a future, we can
|
||||
# add "default" values at v1 check, and load new values at 'v2' check.
|
||||
if data[0] == 'v1':
|
||||
self._name, self._ip, self._mac, self._error, count = data[1:]
|
||||
if values[0] == 'v1':
|
||||
self._name, self._ip, self._mac, self._error, count = values[1:]
|
||||
self._count = int(count)
|
||||
|
||||
def getName(self):
|
||||
def getName(self) -> str:
|
||||
"""
|
||||
We override this to return a name to display. Default implementation
|
||||
(in base class), returns getUniqueIde() value
|
||||
@ -141,12 +157,11 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
generate more names. (Generator are simple utility classes)
|
||||
"""
|
||||
if self._name == '':
|
||||
self._name = self.nameGenerator().get(self.publication().getBaseName(),
|
||||
3)
|
||||
self._name = self.nameGenerator().get(self.publication().getBaseName(), 3)
|
||||
# self._name will be stored when object is marshaled
|
||||
return self._name
|
||||
|
||||
def setIp(self, ip):
|
||||
def setIp(self, ip: str) -> None:
|
||||
"""
|
||||
In our case, there is no OS manager associated with this, so this method
|
||||
will never get called, but we put here as sample.
|
||||
@ -160,7 +175,7 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
"""
|
||||
self._ip = ip
|
||||
|
||||
def getUniqueId(self):
|
||||
def getUniqueId(self) -> str:
|
||||
"""
|
||||
Return and unique identifier for this service.
|
||||
In our case, we will generate a mac name, that can be also as sample
|
||||
@ -188,7 +203,7 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
self._mac = self.macGenerator().get('00:00:00:00:00:00-00:FF:FF:FF:FF:FF')
|
||||
return self._mac
|
||||
|
||||
def getIp(self):
|
||||
def getIp(self) -> str:
|
||||
"""
|
||||
We need to implement this method, so we can return the IP for transports
|
||||
use. If no IP is known for this service, this must return None
|
||||
@ -210,7 +225,7 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
return '192.168.0.34' # Sample IP for testing purposes only
|
||||
return self._ip
|
||||
|
||||
def setReady(self):
|
||||
def setReady(self) -> str:
|
||||
"""
|
||||
This is a task method. As that, the excepted return values are
|
||||
State values RUNNING, FINISHED or ERROR.
|
||||
@ -243,7 +258,7 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
# In our case, the service is always ready
|
||||
return State.FINISHED
|
||||
|
||||
def deployForUser(self, user):
|
||||
def deployForUser(self, user: 'models.User') -> str:
|
||||
"""
|
||||
Deploys an service instance for an user.
|
||||
|
||||
@ -282,7 +297,7 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
|
||||
return State.RUNNING
|
||||
|
||||
def deployForCache(self, cacheLevel):
|
||||
def deployForCache(self, cacheLevel: int) -> str:
|
||||
"""
|
||||
Deploys a user deployment as cache.
|
||||
|
||||
@ -301,37 +316,7 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
self._count = 0
|
||||
return State.RUNNING
|
||||
|
||||
def moveToCache(self, newLevel):
|
||||
"""
|
||||
This method is invoked whenever the core needs to move from the current
|
||||
cache level to a new cache level an user deployment.
|
||||
|
||||
This is a task method. As that, the expected return values are
|
||||
State values RUNNING, FINISHED or ERROR.
|
||||
|
||||
We only provide newLevel, because there is only two cache levels, so if
|
||||
newLevel is L1, the actual is L2, and if it is L2, the actual is L1.
|
||||
|
||||
Actually there is no possibility to move assigned services again back to
|
||||
cache. If some service needs that kind of functionallity, this must be
|
||||
provided at service level (for example, when doing publishing creating
|
||||
a number of services that will be used, released and reused by users).
|
||||
|
||||
Also, user deployments that are at cache level 2 will never get directly
|
||||
assigned to user. First, it will pass to L1 and then it will get assigned.
|
||||
|
||||
A good sample of a real implementation of this is moving a virtual machine
|
||||
from a "suspended" state to "running" state to assign it to an user.
|
||||
|
||||
In this sample, there is L2 cache also, but moving from L1 to L2 and
|
||||
from L2 to L1 is doing really nothing, so this method will do nothing.
|
||||
|
||||
In a real scenario, we will, for example, suspend or resume virtual machine
|
||||
and, return State.RUNNING and at checkState check if this task is completed.
|
||||
"""
|
||||
pass
|
||||
|
||||
def checkState(self):
|
||||
def checkState(self) -> str:
|
||||
"""
|
||||
Our deployForUser method will initiate the consumable service deployment,
|
||||
but will not finish it.
|
||||
@ -386,7 +371,7 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
# We set count to 0, not needed but for sample purposes
|
||||
self._count = 0
|
||||
|
||||
def userLoggedIn(self, user):
|
||||
def userLoggedIn(self, username: str) -> None:
|
||||
"""
|
||||
This method must be available so os managers can invoke it whenever
|
||||
an user get logged into a service.
|
||||
@ -401,9 +386,9 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
The user provided is just an string, that is provided by actors.
|
||||
"""
|
||||
# We store the value at storage, but never get used, just an example
|
||||
self.storage.saveData('user', user)
|
||||
self.storage.saveData('user', username)
|
||||
|
||||
def userLoggedOut(self, user):
|
||||
def userLoggedOut(self, username) -> None:
|
||||
"""
|
||||
This method must be available so os managers can invoke it whenever
|
||||
an user get logged out if a service.
|
||||
@ -420,7 +405,7 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
# We do nothing more that remove the user
|
||||
self.storage.remove('user')
|
||||
|
||||
def reasonOfError(self):
|
||||
def reasonOfError(self) -> str:
|
||||
"""
|
||||
Returns the reason of the error.
|
||||
|
||||
@ -435,7 +420,7 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
"""
|
||||
return self._error
|
||||
|
||||
def destroy(self):
|
||||
def destroy(self) -> str:
|
||||
"""
|
||||
This is a task method. As that, the excepted return values are
|
||||
State values RUNNING, FINISHED or ERROR.
|
||||
@ -446,7 +431,7 @@ class SampleUserDeploymentTwo(services.UserDeployment):
|
||||
"""
|
||||
return State.FINISHED
|
||||
|
||||
def cancel(self):
|
||||
def cancel(self) -> str:
|
||||
"""
|
||||
This is a task method. As that, the excepted return values are
|
||||
State values RUNNING, FINISHED or ERROR.
|
||||
|
@ -34,7 +34,7 @@ import logging
|
||||
import typing
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from uds.core.services import Publication
|
||||
from uds.core import services
|
||||
from uds.core.util.state import State
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -44,7 +44,7 @@ if typing.TYPE_CHECKING:
|
||||
from .service import ServiceOne, ServiceTwo
|
||||
|
||||
|
||||
class SamplePublication(Publication):
|
||||
class SamplePublication(services.Publication):
|
||||
"""
|
||||
This class shows how a publication is developed.
|
||||
|
||||
@ -87,7 +87,7 @@ class SamplePublication(Publication):
|
||||
_reason: str = ''
|
||||
_number: int = -1
|
||||
|
||||
def initialize(self):
|
||||
def initialize(self) -> None:
|
||||
"""
|
||||
This method will be invoked by default __init__ of base class, so it gives
|
||||
us the oportunity to initialize whataver we need here.
|
||||
@ -101,13 +101,13 @@ class SamplePublication(Publication):
|
||||
self._reason = '' # No error, no reason for it
|
||||
self._number = 1
|
||||
|
||||
def marshal(self):
|
||||
def marshal(self) -> bytes:
|
||||
"""
|
||||
returns data from an instance of Sample Publication serialized
|
||||
"""
|
||||
return '\t'.join([self._name, self._reason, str(self._number)]).encode('utf8')
|
||||
|
||||
def unmarshal(self, data):
|
||||
def unmarshal(self, data: bytes) -> None:
|
||||
"""
|
||||
deserializes the data and loads it inside instance.
|
||||
"""
|
||||
@ -118,7 +118,7 @@ class SamplePublication(Publication):
|
||||
self._reason = vals[1]
|
||||
self._number = int(vals[2])
|
||||
|
||||
def publish(self):
|
||||
def publish(self) -> str:
|
||||
"""
|
||||
This method is invoked whenever the administrator requests a new publication.
|
||||
|
||||
@ -175,7 +175,7 @@ class SamplePublication(Publication):
|
||||
self._reason = ''
|
||||
return State.RUNNING
|
||||
|
||||
def checkState(self):
|
||||
def checkState(self) -> str:
|
||||
"""
|
||||
Our publish method will initiate publication, but will not finish it.
|
||||
So in our sample, wi will only check if _number reaches 0, and if so
|
||||
@ -204,10 +204,9 @@ class SamplePublication(Publication):
|
||||
|
||||
if self._number <= 0:
|
||||
return State.FINISHED
|
||||
else:
|
||||
return State.RUNNING
|
||||
return State.RUNNING
|
||||
|
||||
def finish(self):
|
||||
def finish(self) -> None:
|
||||
"""
|
||||
Invoked when Publication manager noticed that the publication has finished.
|
||||
This give us the oportunity of cleaning up things (as stored vars, etc..),
|
||||
@ -221,7 +220,7 @@ class SamplePublication(Publication):
|
||||
# Make simply a random string
|
||||
self._name = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(10))
|
||||
|
||||
def reasonOfError(self):
|
||||
def reasonOfError(self) -> str:
|
||||
"""
|
||||
If a publication produces an error, here we must notify the reason why
|
||||
it happened. This will be called just after publish or checkState
|
||||
@ -231,7 +230,7 @@ class SamplePublication(Publication):
|
||||
"""
|
||||
return self._reason
|
||||
|
||||
def destroy(self):
|
||||
def destroy(self) -> str:
|
||||
"""
|
||||
This is called once a publication is no more needed.
|
||||
|
||||
@ -248,7 +247,7 @@ class SamplePublication(Publication):
|
||||
# We do not do anything else to destroy this instance of publication
|
||||
return State.FINISHED
|
||||
|
||||
def cancel(self):
|
||||
def cancel(self) -> str:
|
||||
"""
|
||||
Invoked for canceling the current operation.
|
||||
This can be invoked directly by an administration or by the clean up
|
||||
@ -268,7 +267,7 @@ class SamplePublication(Publication):
|
||||
# Methods provided below are specific for this publication
|
||||
# and will be used by user deployments that uses this kind of publication
|
||||
|
||||
def getBaseName(self):
|
||||
def getBaseName(self) -> str:
|
||||
"""
|
||||
This sample method (just for this sample publication), provides
|
||||
the name generater for this publication. This is just a sample, and
|
||||
|
@ -152,7 +152,7 @@ class ServiceOne(services.Service):
|
||||
defvalue='' # Default value is the ID of the choicefield
|
||||
)
|
||||
|
||||
def initialize(self, values):
|
||||
def initialize(self, values: 'Module.ValuesType') -> None:
|
||||
"""
|
||||
We check here form values to see if they are valid.
|
||||
|
||||
@ -163,7 +163,7 @@ class ServiceOne(services.Service):
|
||||
# We don't need to check anything, bat because this is a sample, we do
|
||||
# As in provider, we receive values only at new Service creation,
|
||||
# so we only need to validate params if values is not None
|
||||
if values is not None:
|
||||
if values:
|
||||
if self.colour.value == 'nonsense':
|
||||
raise services.Service.ValidationException('The selected colour is invalid!!!')
|
||||
|
||||
@ -178,7 +178,7 @@ class ServiceOne(services.Service):
|
||||
# From now onwards, we implement our own methods, that will be used by,
|
||||
# for example, services derived from this provider
|
||||
|
||||
def getColour(self):
|
||||
def getColour(self) -> str:
|
||||
"""
|
||||
Simply returns colour, for deployed user services.
|
||||
|
||||
@ -186,15 +186,13 @@ class ServiceOne(services.Service):
|
||||
"""
|
||||
return self.colour.value
|
||||
|
||||
def getPassw(self):
|
||||
def getPassw(self) -> str:
|
||||
"""
|
||||
Simply returns passwd, for deloyed user services
|
||||
"""
|
||||
return self.passw.value
|
||||
|
||||
def getBaseName(self):
|
||||
"""
|
||||
"""
|
||||
def getBaseName(self) -> str:
|
||||
return self.baseName.value
|
||||
|
||||
|
||||
@ -239,7 +237,7 @@ class ServiceTwo(services.Service):
|
||||
|
||||
# No checks here
|
||||
|
||||
def getNames(self):
|
||||
def getNames(self) -> str:
|
||||
"""
|
||||
For using at deployed services, really nothing
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user