mirror of
https://github.com/dkmstr/openuds.git
synced 2024-12-22 13:34:04 +03:00
Done oVirt engine connector. Now the hard part, test it and fix it (it isn't already usable!!!)
This commit is contained in:
parent
400ac892f0
commit
0eea8a33b5
@ -134,6 +134,7 @@ encoding//src/uds/services/Vmware/client/Exceptions.py=utf-8
|
|||||||
encoding//src/uds/services/Vmware/client/Server.py=utf-8
|
encoding//src/uds/services/Vmware/client/Server.py=utf-8
|
||||||
encoding//src/uds/services/Vmware/client/Task.py=utf-8
|
encoding//src/uds/services/Vmware/client/Task.py=utf-8
|
||||||
encoding//src/uds/services/Vmware/client/ws/VimService_types.py=utf-8
|
encoding//src/uds/services/Vmware/client/ws/VimService_types.py=utf-8
|
||||||
|
encoding//src/uds/services/Vmware_enterprise/Helpers.py=utf-8
|
||||||
encoding//src/uds/services/Vmware_enterprise/PublicationVC.py=utf-8
|
encoding//src/uds/services/Vmware_enterprise/PublicationVC.py=utf-8
|
||||||
encoding//src/uds/services/Vmware_enterprise/ServiceProviderVC.py=utf-8
|
encoding//src/uds/services/Vmware_enterprise/ServiceProviderVC.py=utf-8
|
||||||
encoding//src/uds/services/Vmware_enterprise/VCLinkedCloneDeployed.py=utf-8
|
encoding//src/uds/services/Vmware_enterprise/VCLinkedCloneDeployed.py=utf-8
|
||||||
|
@ -33,11 +33,12 @@
|
|||||||
|
|
||||||
from uds.core.services import UserDeployment
|
from uds.core.services import UserDeployment
|
||||||
from uds.core.util.State import State
|
from uds.core.util.State import State
|
||||||
|
import cPickle
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
opCreate, opStart, opStop, opSuspend, opWait, opError, opFinish, opRetry = range(8)
|
opCreate, opStart, opStop, opSuspend, opRemove, opWait, opError, opFinish, opRetry = range(9)
|
||||||
|
|
||||||
class OVirtLinkedDeployment(UserDeployment):
|
class OVirtLinkedDeployment(UserDeployment):
|
||||||
'''
|
'''
|
||||||
@ -57,24 +58,27 @@ class OVirtLinkedDeployment(UserDeployment):
|
|||||||
def initialize(self):
|
def initialize(self):
|
||||||
self._name = ''
|
self._name = ''
|
||||||
self._ip = ''
|
self._ip = ''
|
||||||
|
self._mac = ''
|
||||||
self._vmid = ''
|
self._vmid = ''
|
||||||
self._reason = ''
|
self._reason = ''
|
||||||
self._queue = []
|
self._queue = []
|
||||||
self._destroyAfter = 'f'
|
|
||||||
|
|
||||||
# Serializable needed methods
|
# Serializable needed methods
|
||||||
def marshal(self):
|
def marshal(self):
|
||||||
'''
|
'''
|
||||||
Does nothing right here, we will use envoronment storage in this sample
|
Does nothing right here, we will use envoronment storage in this sample
|
||||||
'''
|
'''
|
||||||
return ''
|
return '\1'.join( ['v1', self._name, self._ip, self._mac, self._vmid, self._reason, cPickle.dumps(self._queue)] )
|
||||||
|
|
||||||
def unmarshal(self, str_):
|
def unmarshal(self, str_):
|
||||||
'''
|
'''
|
||||||
Does nothing here also, all data are keeped at environment storage
|
Does nothing here also, all data are keeped at environment storage
|
||||||
'''
|
'''
|
||||||
pass
|
logger.debug('Data: {0}'.format(str_))
|
||||||
|
vals = str_.split('\1')
|
||||||
|
if vals[0] == 'v1':
|
||||||
|
self._name, self._ip, self._mac, self._vmid, self._reason, queue = vals[1:]
|
||||||
|
self._queue = cPickle.loads(queue)
|
||||||
|
|
||||||
def getName(self):
|
def getName(self):
|
||||||
'''
|
'''
|
||||||
@ -165,7 +169,8 @@ class OVirtLinkedDeployment(UserDeployment):
|
|||||||
return self.__error('Machine is not available anymore')
|
return self.__error('Machine is not available anymore')
|
||||||
|
|
||||||
if state not in ('up', 'powering_up', 'restoring_state'):
|
if state not in ('up', 'powering_up', 'restoring_state'):
|
||||||
return self.__powerOn()
|
self._queue = [ opStart, opFinish ]
|
||||||
|
return self.__executeQueue()
|
||||||
|
|
||||||
self.cache().put('ready', '1')
|
self.cache().put('ready', '1')
|
||||||
return State.FINISHED
|
return State.FINISHED
|
||||||
@ -177,30 +182,39 @@ class OVirtLinkedDeployment(UserDeployment):
|
|||||||
logger.debug('Machine is ready. Moving to level 2')
|
logger.debug('Machine is ready. Moving to level 2')
|
||||||
self.__popCurrentOp() # Remove current state
|
self.__popCurrentOp() # Remove current state
|
||||||
return self.__executeQueue()
|
return self.__executeQueue()
|
||||||
|
# Do not need to go to level 2 (opWait is in fact "waiting for moving machine to cache level 2)
|
||||||
#if self._squeue.getCurrent() == stWaitReady:
|
|
||||||
# logger.debug('Move to level 2, suspending machine')
|
|
||||||
# return self.moveToCache(self.L2_CACHE)
|
|
||||||
return State.FINISHED
|
return State.FINISHED
|
||||||
|
|
||||||
|
def deployForUser(self, user):
|
||||||
|
'''
|
||||||
|
Deploys an service instance for an user.
|
||||||
|
'''
|
||||||
|
logger.debug('Deploying for user')
|
||||||
|
self.__initQueueForDeploy(False)
|
||||||
|
return self.__executeQueue()
|
||||||
|
|
||||||
def __executeQueue(self):
|
def deployForCache(self, cacheLevel):
|
||||||
op = self.__getCurrentOp()
|
'''
|
||||||
|
Deploys an service instance for cache
|
||||||
if op == opError:
|
'''
|
||||||
return State.ERROR
|
self.__initQueueForDeploy(cacheLevel == self.L2_CACHE)
|
||||||
|
return self.__executeQueue()
|
||||||
if op == opFinish:
|
|
||||||
return State.FINISHED
|
|
||||||
|
|
||||||
if op == opCreate:
|
|
||||||
return self.__create()
|
|
||||||
|
|
||||||
def __initQueueForDeploy(self, forLevel2 = False):
|
def __initQueueForDeploy(self, forLevel2 = False):
|
||||||
|
|
||||||
if forLevel2 is False:
|
if forLevel2 is False:
|
||||||
self._queue = [opCreate, opStart, opFinish]
|
self._queue = [opCreate, opStart, opFinish]
|
||||||
else:
|
else:
|
||||||
self._queue = [opCreate, opStart, opWait, opSuspend, opFinish]
|
self._queue = [opCreate, opStart, opWait, opSuspend, opFinish]
|
||||||
|
|
||||||
|
def __checkMachineState(self, chkState):
|
||||||
|
logger.debug('Checking that state of machine {0} is {1}'.format(self._vmid, chkState))
|
||||||
|
state = self.service().getMachineState(self._vmid)
|
||||||
|
|
||||||
|
if state != chkState:
|
||||||
|
return State.RUNNING
|
||||||
|
|
||||||
|
return State.FINISHED
|
||||||
|
|
||||||
def __getCurrentOp(self):
|
def __getCurrentOp(self):
|
||||||
if len(self._queue) == 0:
|
if len(self._queue) == 0:
|
||||||
@ -228,10 +242,43 @@ class OVirtLinkedDeployment(UserDeployment):
|
|||||||
Returns:
|
Returns:
|
||||||
State.ERROR, so we can do "return self.__error(reason)"
|
State.ERROR, so we can do "return self.__error(reason)"
|
||||||
'''
|
'''
|
||||||
|
logger.debug('Setting error state, reason: {0}'.format(reason))
|
||||||
|
|
||||||
self._queue = [opError]
|
self._queue = [opError]
|
||||||
self._reason = str(reason)
|
self._reason = str(reason)
|
||||||
return State.ERROR
|
return State.ERROR
|
||||||
|
|
||||||
|
def __executeQueue(self):
|
||||||
|
self.__debugQueue('executeQueue')
|
||||||
|
op = self.__getCurrentOp()
|
||||||
|
|
||||||
|
if op == opError:
|
||||||
|
return State.ERROR
|
||||||
|
|
||||||
|
if op == opFinish:
|
||||||
|
return State.FINISHED
|
||||||
|
|
||||||
|
fncs = { opCreate: self.__create,
|
||||||
|
opRetry: self.__retry,
|
||||||
|
opStart: self.__startMachine,
|
||||||
|
opStop: self.__stopMachine,
|
||||||
|
opSuspend: self.__suspendMachine,
|
||||||
|
opWait: self.__wait,
|
||||||
|
opRemove: self.__remove
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
execFnc = fncs.get(op, None)
|
||||||
|
|
||||||
|
if execFnc is None:
|
||||||
|
return self.__error('Unknown operation found at execution queue ({0})'.format(op))
|
||||||
|
|
||||||
|
state = execFnc()
|
||||||
|
|
||||||
|
return state
|
||||||
|
except Exception as e:
|
||||||
|
return self.__error(e)
|
||||||
|
|
||||||
# Queue execution methods
|
# Queue execution methods
|
||||||
def __retry(self):
|
def __retry(self):
|
||||||
'''
|
'''
|
||||||
@ -241,6 +288,12 @@ class OVirtLinkedDeployment(UserDeployment):
|
|||||||
'''
|
'''
|
||||||
return State.FINISHED
|
return State.FINISHED
|
||||||
|
|
||||||
|
def __wait(self):
|
||||||
|
'''
|
||||||
|
Executes opWait, it simply waits something "external" to end
|
||||||
|
'''
|
||||||
|
return State.RUNNING
|
||||||
|
|
||||||
def __create(self):
|
def __create(self):
|
||||||
'''
|
'''
|
||||||
Deploys a machine from template for user/cache
|
Deploys a machine from template for user/cache
|
||||||
@ -249,56 +302,106 @@ class OVirtLinkedDeployment(UserDeployment):
|
|||||||
name = self.service().sanitizeVmName('UDS service ' + self.getName())
|
name = self.service().sanitizeVmName('UDS service ' + self.getName())
|
||||||
comments = 'UDS Linked clone for'
|
comments = 'UDS Linked clone for'
|
||||||
|
|
||||||
try:
|
self._vmid = self.service().deployFromTemplate(name, comments, templateId)
|
||||||
self._vmid = self.service().deployFromTemplate(name, comments, templateId)
|
if self._vmid is None:
|
||||||
if self._vmid is None:
|
raise Exception('Can\'t create machine')
|
||||||
raise Exception('Can\'t create machine')
|
|
||||||
except Exception as e:
|
|
||||||
return self.__error(e)
|
|
||||||
|
|
||||||
return State.RUNNING
|
return State.RUNNING
|
||||||
|
|
||||||
def __powerOn(self):
|
def __remove(self):
|
||||||
|
'''
|
||||||
|
Removes a machine from system
|
||||||
|
'''
|
||||||
|
state = self.service().getMachineState(self._vmid)
|
||||||
|
|
||||||
|
if state != 'down' and state != 'suspended':
|
||||||
|
self.__pushFrontOp(opStop)
|
||||||
|
return State.RUNNING
|
||||||
|
|
||||||
|
self.service().removeMachine(self._vmid)
|
||||||
|
return State.RUNNING
|
||||||
|
|
||||||
|
def __startMachine(self):
|
||||||
'''
|
'''
|
||||||
Powers on the machine
|
Powers on the machine
|
||||||
'''
|
'''
|
||||||
state = self.service.getMachineState(self._vmid)
|
state = self.service().getMachineState(self._vmid)
|
||||||
if state == 'down':
|
if state == 'up':
|
||||||
pass
|
return State.FINISHED
|
||||||
|
|
||||||
def deployForUser(self, user):
|
if state != 'down':
|
||||||
|
self.__pushFrontOp(opRetry) # Remember here, the return State.FINISH will make this retry be "poped" right ar return
|
||||||
|
return State.FINISHED
|
||||||
|
|
||||||
|
self.service().startMachine(self._vmid)
|
||||||
|
return State.RUNNING
|
||||||
|
|
||||||
|
def __stopMachine(self):
|
||||||
'''
|
'''
|
||||||
Deploys an service instance for an user.
|
Powers off the machine
|
||||||
'''
|
'''
|
||||||
self.__initQueueForDeploy(False)
|
state = self.service().getMachineState(self._vmid)
|
||||||
return self.__executeQueue()
|
if state == 'down':
|
||||||
|
return State.FINISHED
|
||||||
|
|
||||||
|
if state != 'up':
|
||||||
|
self.__pushBackOp(opRetry) # Remember here, the return State.FINISH will make this retry be "poped" right ar return
|
||||||
|
return State.FINISHED
|
||||||
|
|
||||||
|
self.service().stopMachine(self._vmid)
|
||||||
|
return State.RUNNING
|
||||||
|
|
||||||
def deployForCache(self, cacheLevel):
|
def __suspendMachine(self):
|
||||||
'''
|
'''
|
||||||
Deploys an service instance for cache
|
Suspends the machine
|
||||||
'''
|
'''
|
||||||
forLevel2 = cacheLevel == self.L2_CACHE
|
state = self.service().getMachineState(self._vmid)
|
||||||
self.__initQueueForDeploy(forLevel2)
|
if state == 'suspended':
|
||||||
return self.__executeQueue()
|
return State.FINISHED
|
||||||
|
|
||||||
def __checkDeploy(self):
|
if state != 'up':
|
||||||
|
self.__pushBackOp(opRetry) # Remember here, the return State.FINISH will make this retry be "poped" right ar return
|
||||||
|
return State.FINISHED
|
||||||
|
|
||||||
|
self.service().suspendMachine(self._vmid)
|
||||||
|
return State.RUNNING
|
||||||
|
|
||||||
|
# Check methods
|
||||||
|
def __checkCreate(self):
|
||||||
'''
|
'''
|
||||||
Checks the state of a deploy for an user or cache
|
Checks the state of a deploy for an user or cache
|
||||||
'''
|
'''
|
||||||
try:
|
return self.__checkMachineState('down')
|
||||||
state = self.service().getMachineState(self._vmid)
|
|
||||||
if state != 'down':
|
def __checkStart(self):
|
||||||
return State.RUNNING
|
'''
|
||||||
except Exception as e:
|
Checks if machine has started
|
||||||
return self.__error(e)
|
'''
|
||||||
|
return self.__checkMachineState('up')
|
||||||
return State.FINISHED
|
|
||||||
|
def __checkStop(self):
|
||||||
|
'''
|
||||||
|
Checks if machine has stoped
|
||||||
|
'''
|
||||||
|
return self.__checkMachineState('down')
|
||||||
|
|
||||||
|
def __checkSuspend(self):
|
||||||
|
'''
|
||||||
|
Check if the machine has suspended
|
||||||
|
'''
|
||||||
|
return self.__checkMachineState('suspended')
|
||||||
|
|
||||||
|
def __checkRemoved(self):
|
||||||
|
'''
|
||||||
|
Checks if a machine has been removed
|
||||||
|
'''
|
||||||
|
return self.__checkMachineState('unknown')
|
||||||
|
|
||||||
def checkState(self):
|
def checkState(self):
|
||||||
'''
|
'''
|
||||||
Check what operation is going on, and acts acordly to it
|
Check what operation is going on, and acts acordly to it
|
||||||
'''
|
'''
|
||||||
|
self.__debugQueue('checkState')
|
||||||
op = self.__getCurrentOp()
|
op = self.__getCurrentOp()
|
||||||
|
|
||||||
if op == opError:
|
if op == opError:
|
||||||
@ -307,56 +410,43 @@ class OVirtLinkedDeployment(UserDeployment):
|
|||||||
if op == opFinish:
|
if op == opFinish:
|
||||||
return State.FINISHED
|
return State.FINISHED
|
||||||
|
|
||||||
res = None
|
fncs = { opCreate: self.__checkCreate,
|
||||||
|
opRetry: self.__retry,
|
||||||
|
opWait: self.__wait,
|
||||||
|
opStart: self.__checkStart,
|
||||||
|
opStop: self.__checkStop,
|
||||||
|
opSuspend: self.__checkSuspend,
|
||||||
|
opRemove: self.__checkRemoved
|
||||||
|
}
|
||||||
|
|
||||||
if op == opCreate:
|
try:
|
||||||
res = self.__checkDeploy()
|
chkFnc = fncs.get(op, None)
|
||||||
|
|
||||||
if op == opStart:
|
|
||||||
res = self.__checkPowerOn()
|
|
||||||
|
|
||||||
if op == opStop:
|
if chkFnc is None:
|
||||||
res = self.__checkPowerOff()
|
return self.__error('Unknown operation found at check queue ({0})'.format(op))
|
||||||
|
|
||||||
if op == opWait:
|
state = chkFnc()
|
||||||
res = State.RUNNING
|
if state == State.FINISHED:
|
||||||
|
self.__popCurrentOp() # Remove runing op
|
||||||
|
return self.__executeQueue()
|
||||||
|
|
||||||
if op == opSuspend:
|
return state
|
||||||
res = self.__checkSuspend()
|
except Exception as e:
|
||||||
|
return self.__error(e)
|
||||||
if res is None:
|
|
||||||
return self.__error('Unexpected operation found')
|
|
||||||
|
|
||||||
if res == State.FINISHED:
|
|
||||||
self.__popCurrentOp()
|
|
||||||
return State.RUNNING
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
'''
|
'''
|
||||||
Invoked when the core notices that the deployment of a service has finished.
|
Invoked when the core notices that the deployment of a service has finished.
|
||||||
(No matter wether it is for cache or for an user)
|
(No matter wether it is for cache or for an user)
|
||||||
|
|
||||||
This gives the oportunity to make something at that moment.
|
|
||||||
:note: You can also make these operations at checkState, this is really
|
|
||||||
not needed, but can be provided (default implementation of base class does
|
|
||||||
nothing)
|
|
||||||
'''
|
'''
|
||||||
# Note that this is not really needed, is just a sample of storage use
|
pass
|
||||||
self.storage().remove('count')
|
|
||||||
|
|
||||||
def assignToUser(self, user):
|
def assignToUser(self, user):
|
||||||
'''
|
'''
|
||||||
This method is invoked whenever a cache item gets assigned to an user.
|
This method is invoked whenever a cache item gets assigned to an user.
|
||||||
This gives the User Deployment an oportunity to do whatever actions
|
This gives the User Deployment an oportunity to do whatever actions
|
||||||
are required so the service puts at a correct state for using by a service.
|
are required so the service puts at a correct state for using by a service.
|
||||||
|
|
||||||
In our sample, the service is always ready, so this does nothing.
|
|
||||||
|
|
||||||
This is not a task method. All level 1 cache items can be diretly
|
|
||||||
assigned to an user with no more work needed, but, if something is needed,
|
|
||||||
here you can do whatever you need
|
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -364,35 +454,20 @@ class OVirtLinkedDeployment(UserDeployment):
|
|||||||
'''
|
'''
|
||||||
This method must be available so os managers can invoke it whenever
|
This method must be available so os managers can invoke it whenever
|
||||||
an user get logged into a service.
|
an user get logged into a service.
|
||||||
|
|
||||||
Default implementation does nothing, so if you are going to do nothing,
|
|
||||||
you don't need to implement it.
|
|
||||||
|
|
||||||
The responability of notifying it is of os manager actor, and it's
|
|
||||||
directly invoked by os managers (right now, linux os manager and windows
|
|
||||||
os manager)
|
|
||||||
|
|
||||||
The user provided is just an string, that is provided by actor.
|
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
|
# We store the value at storage, but never get used, just an example
|
||||||
self.storage().saveData('user', user)
|
pass
|
||||||
|
|
||||||
def userLoggedOut(self, user):
|
def userLoggedOut(self, user):
|
||||||
'''
|
'''
|
||||||
This method must be available so os managers can invoke it whenever
|
This method must be available so os managers can invoke it whenever
|
||||||
an user get logged out if a service.
|
an user get logged out if a service.
|
||||||
|
|
||||||
Default implementation does nothing, so if you are going to do nothing,
|
|
||||||
you don't need to implement it.
|
|
||||||
|
|
||||||
The responability of notifying it is of os manager actor, and it's
|
|
||||||
directly invoked by os managers (right now, linux os manager and windows
|
|
||||||
os manager)
|
|
||||||
|
|
||||||
The user provided is just an string, that is provided by actor.
|
The user provided is just an string, that is provided by actor.
|
||||||
'''
|
'''
|
||||||
# We do nothing more that remove the user
|
pass
|
||||||
self.storage().remove('user')
|
|
||||||
|
|
||||||
def reasonOfError(self):
|
def reasonOfError(self):
|
||||||
'''
|
'''
|
||||||
@ -402,18 +477,24 @@ class OVirtLinkedDeployment(UserDeployment):
|
|||||||
for it, and it will be asked everytime it's needed to be shown to the
|
for it, and it will be asked everytime it's needed to be shown to the
|
||||||
user (when the administation asks for it).
|
user (when the administation asks for it).
|
||||||
'''
|
'''
|
||||||
return self.storage().readData('error') or 'No error'
|
return self._reason
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
'''
|
'''
|
||||||
This is a task method. As that, the excepted return values are
|
|
||||||
State values RUNNING, FINISHED or ERROR.
|
|
||||||
|
|
||||||
Invoked for destroying a deployed service
|
Invoked for destroying a deployed service
|
||||||
Do whatever needed here, as deleting associated data if needed (i.e. a copy of the machine, snapshots, etc...)
|
|
||||||
@return: State.FINISHED if no more checks/steps for deployment are needed, State.RUNNING if more steps are needed (steps checked using checkState)
|
|
||||||
'''
|
'''
|
||||||
return State.FINISHED
|
|
||||||
|
# If executing something, wait until finished to remove it
|
||||||
|
# We simply replace the execution queue
|
||||||
|
op = self.__getCurrentOp()
|
||||||
|
|
||||||
|
if op == opFinish or op == opWait:
|
||||||
|
self._queue = [opStop, opRemove]
|
||||||
|
return self.__executeQueue()
|
||||||
|
|
||||||
|
self._queue = [op, opStop, opRemove]
|
||||||
|
# Do not execute anything.here, just continue normally
|
||||||
|
return State.RUNNING
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
'''
|
'''
|
||||||
@ -425,5 +506,22 @@ class OVirtLinkedDeployment(UserDeployment):
|
|||||||
When administrator requests it, the cancel is "delayed" and not
|
When administrator requests it, the cancel is "delayed" and not
|
||||||
invoked directly.
|
invoked directly.
|
||||||
'''
|
'''
|
||||||
return State.FINISHED
|
return self.destroy()
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __op2str(op):
|
||||||
|
return { opCreate: 'create',
|
||||||
|
opStart: 'start',
|
||||||
|
opStop: 'stop',
|
||||||
|
opSuspend: 'suspend',
|
||||||
|
opRemove: 'remove',
|
||||||
|
opWait: 'wait',
|
||||||
|
opError: 'error',
|
||||||
|
opFinish: 'finish',
|
||||||
|
opRetry: 'retry'
|
||||||
|
}.get(op, '????')
|
||||||
|
|
||||||
|
def __debugQueue(self, txt):
|
||||||
|
logger.debug('Queue at {0}: {1}'.format(txt,[OVirtLinkedDeployment.__op2str(op) for op in self._queue ]))
|
||||||
|
|
@ -77,7 +77,7 @@ class OVirtLinkedService(Service):
|
|||||||
cacheTooltip = translatable('Number of desired machines to keep running waiting for a user')
|
cacheTooltip = translatable('Number of desired machines to keep running waiting for a user')
|
||||||
#: If we need to generate a "Level 2" cache for this service (i.e., L1
|
#: If we need to generate a "Level 2" cache for this service (i.e., L1
|
||||||
#: could be running machines and L2 suspended machines)
|
#: could be running machines and L2 suspended machines)
|
||||||
usesCache_L2 = False
|
usesCache_L2 = True
|
||||||
#: Tooltip shown to user when this item is pointed at admin interface, None
|
#: Tooltip shown to user when this item is pointed at admin interface, None
|
||||||
#: also because we don't use it
|
#: also because we don't use it
|
||||||
cacheTooltip_L2 = translatable('Number of desired machines to keep suspended waiting for use')
|
cacheTooltip_L2 = translatable('Number of desired machines to keep suspended waiting for use')
|
||||||
@ -109,7 +109,7 @@ class OVirtLinkedService(Service):
|
|||||||
datastore = gui.ChoiceField(label = translatable("Datastore Domain"), rdonly = False, order = 3,
|
datastore = gui.ChoiceField(label = translatable("Datastore Domain"), rdonly = False, order = 3,
|
||||||
tooltip = translatable('Datastore domain where to publish and put incrementals'), required = True)
|
tooltip = translatable('Datastore domain where to publish and put incrementals'), required = True)
|
||||||
baseName = gui.TextField(label = translatable('Machine Names'), rdonly = False, order = 4, tooltip = ('Base name for clones from this machine'), required = True)
|
baseName = gui.TextField(label = translatable('Machine Names'), rdonly = False, order = 4, tooltip = ('Base name for clones from this machine'), required = True)
|
||||||
lenName = gui.NumericField(length = 1, label = translatable('Name Length'), defvalue = 3, order = 5,
|
lenName = gui.NumericField(length = 1, label = translatable('Name Length'), defvalue = 5, order = 5,
|
||||||
tooltip = translatable('Length of numeric part for the names of this machines (betwen 3 and 6'), required = True)
|
tooltip = translatable('Length of numeric part for the names of this machines (betwen 3 and 6'), required = True)
|
||||||
|
|
||||||
ov = gui.HiddenField()
|
ov = gui.HiddenField()
|
||||||
@ -197,6 +197,12 @@ class OVirtLinkedService(Service):
|
|||||||
Id of the machine being created form template
|
Id of the machine being created form template
|
||||||
'''
|
'''
|
||||||
return self.parent().deployFromTemplate(name, comments, templateId, self.cluster.value)
|
return self.parent().deployFromTemplate(name, comments, templateId, self.cluster.value)
|
||||||
|
|
||||||
|
def removeTemplate(self, templateId):
|
||||||
|
'''
|
||||||
|
invokes removeTemplate from parent provider
|
||||||
|
'''
|
||||||
|
return self.parent().removeTemplate(templateId)
|
||||||
|
|
||||||
def getMachineState(self, machineId):
|
def getMachineState(self, machineId):
|
||||||
'''
|
'''
|
||||||
@ -207,23 +213,77 @@ class OVirtLinkedService(Service):
|
|||||||
machineId: If of the machine to get state
|
machineId: If of the machine to get state
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
'down': Machine is not running
|
one of this values:
|
||||||
'unknown': Machine is not known
|
unassigned, down, up, powering_up, powered_down,
|
||||||
'powering_up': Machine is powering up
|
paused, migrating_from, migrating_to, unknown, not_responding,
|
||||||
'up': Machine is up and running
|
wait_for_launch, reboot_in_progress, saving_state, restoring_state,
|
||||||
'saving_state': Machine is "suspending"
|
suspended, image_illegal, image_locked or powering_down
|
||||||
'suspended': Machine is suspended
|
Also can return'unknown' if Machine is not known
|
||||||
'restoring_state': Machine is restoring state (unsuspending)
|
|
||||||
'powering_down': Machine is powering down
|
|
||||||
'image_locked': Machine is creating/cloning and is not usable
|
|
||||||
'''
|
'''
|
||||||
return self.parent().getMachineState(machineId)
|
return self.parent().getMachineState(machineId)
|
||||||
|
|
||||||
|
def startMachine(self, machineId):
|
||||||
|
'''
|
||||||
|
Tries to start a machine. No check is done, it is simply requested to oVirt.
|
||||||
|
|
||||||
|
This start also "resume" suspended/paused machines
|
||||||
|
|
||||||
|
Args:
|
||||||
|
machineId: Id of the machine
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
'''
|
||||||
|
return self.parent().startMachine(machineId)
|
||||||
|
|
||||||
def removeTemplate(self, templateId):
|
def stopMachine(self, machineId):
|
||||||
'''
|
'''
|
||||||
invokes removeTemplate from parent provider
|
Tries to start a machine. No check is done, it is simply requested to oVirt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
machineId: Id of the machine
|
||||||
|
|
||||||
|
Returns:
|
||||||
'''
|
'''
|
||||||
return self.parent().removeTemplate(templateId)
|
return self.parent().stopMachine(machineId)
|
||||||
|
|
||||||
|
def suspendMachine(self, machineId):
|
||||||
|
'''
|
||||||
|
Tries to start a machine. No check is done, it is simply requested to oVirt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
machineId: Id of the machine
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
'''
|
||||||
|
return self.parent().suspendMachine(machineId)
|
||||||
|
|
||||||
|
def removeMachine(self, machineId):
|
||||||
|
'''
|
||||||
|
Tries to delete a machine. No check is done, it is simply requested to oVirt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
machineId: Id of the machine
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
'''
|
||||||
|
return self.parent().removeMachine(machineId)
|
||||||
|
|
||||||
def getMacRange(self):
|
def getMacRange(self):
|
||||||
|
'''
|
||||||
|
Returns de selected mac range
|
||||||
|
'''
|
||||||
return self.parent().getMacRange()
|
return self.parent().getMacRange()
|
||||||
|
|
||||||
|
def getBaseName(self):
|
||||||
|
'''
|
||||||
|
Returns the base name
|
||||||
|
'''
|
||||||
|
return self.baseName.value
|
||||||
|
|
||||||
|
def getLenName(self):
|
||||||
|
'''
|
||||||
|
Returns the length of numbers part
|
||||||
|
'''
|
||||||
|
return int(self.lenName.value)
|
||||||
|
|
||||||
|
|
||||||
|
@ -271,15 +271,12 @@ class Provider(ServiceProvider):
|
|||||||
machineId: Id of the machine to get state
|
machineId: Id of the machine to get state
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
'down': Machine is not running
|
one of this values:
|
||||||
'unknown': Machine is not known
|
unassigned, down, up, powering_up, powered_down,
|
||||||
'powering_up': Machine is powering up
|
paused, migrating_from, migrating_to, unknown, not_responding,
|
||||||
'up': Machine is up and running
|
wait_for_launch, reboot_in_progress, saving_state, restoring_state,
|
||||||
'saving_state': Machine is "suspending"
|
suspended, image_illegal, image_locked or powering_down
|
||||||
'suspended': Machine is suspended
|
Also can return'unknown' if Machine is not known
|
||||||
'restoring_state': Machine is restoring state (unsuspending)
|
|
||||||
'powering_down': Machine is powering down
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
return self.__getApi().getMachineState(machineId)
|
return self.__getApi().getMachineState(machineId)
|
||||||
|
|
||||||
@ -308,6 +305,52 @@ class Provider(ServiceProvider):
|
|||||||
'''
|
'''
|
||||||
return self.__getApi().deployFromTemplate(name, comments, templateId, clusterId)
|
return self.__getApi().deployFromTemplate(name, comments, templateId, clusterId)
|
||||||
|
|
||||||
|
def startMachine(self, machineId):
|
||||||
|
'''
|
||||||
|
Tries to start a machine. No check is done, it is simply requested to oVirt.
|
||||||
|
|
||||||
|
This start also "resume" suspended/paused machines
|
||||||
|
|
||||||
|
Args:
|
||||||
|
machineId: Id of the machine
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
'''
|
||||||
|
return self.__getApi().startMachine(machineId)
|
||||||
|
|
||||||
|
def stopMachine(self, machineId):
|
||||||
|
'''
|
||||||
|
Tries to start a machine. No check is done, it is simply requested to oVirt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
machineId: Id of the machine
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
'''
|
||||||
|
return self.__getApi().stopMachine(machineId)
|
||||||
|
|
||||||
|
def suspendMachine(self, machineId):
|
||||||
|
'''
|
||||||
|
Tries to start a machine. No check is done, it is simply requested to oVirt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
machineId: Id of the machine
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
'''
|
||||||
|
return self.__getApi().suspendMachine(machineId)
|
||||||
|
|
||||||
|
def removeMachine(self, machineId):
|
||||||
|
'''
|
||||||
|
Tries to delete a machine. No check is done, it is simply requested to oVirt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
machineId: Id of the machine
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
'''
|
||||||
|
return self.__getApi().removeMachine(machineId)
|
||||||
|
|
||||||
def getMacRange(self):
|
def getMacRange(self):
|
||||||
return self.macsRange.value
|
return self.macsRange.value
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ from ovirtsdk.api import API
|
|||||||
|
|
||||||
import threading
|
import threading
|
||||||
import logging
|
import logging
|
||||||
|
import ovirtsdk
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -316,21 +317,21 @@ class Client(object):
|
|||||||
lock.release()
|
lock.release()
|
||||||
|
|
||||||
|
|
||||||
def makeTemplate(self, name, comments, vmId, clusterId, storageId):
|
def makeTemplate(self, name, comments, machineId, clusterId, storageId):
|
||||||
'''
|
'''
|
||||||
Publish the machine (makes a template from it so we can create COWs) and returns the template id of
|
Publish the machine (makes a template from it so we can create COWs) and returns the template id of
|
||||||
the creating machine
|
the creating machine
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
name: Name of the machine (care, only ascii characters and no spaces!!!)
|
name: Name of the machine (care, only ascii characters and no spaces!!!)
|
||||||
vmId: id of the machine to be published
|
machineId: id of the machine to be published
|
||||||
clusterId: id of the cluster that will hold the machine
|
clusterId: id of the cluster that will hold the machine
|
||||||
storageId: id of the storage tuat will contain the publication AND linked clones
|
storageId: id of the storage tuat will contain the publication AND linked clones
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
Raises an exception if operation could not be acomplished, or returns the id of the template being created.
|
Raises an exception if operation could not be acomplished, or returns the id of the template being created.
|
||||||
'''
|
'''
|
||||||
print "n: {0}, c: {1}, vm: {2}, cl: {3}, st: {3}".format(name, comments, vmId, clusterId, storageId)
|
print "n: {0}, c: {1}, vm: {2}, cl: {3}, st: {3}".format(name, comments, machineId, clusterId, storageId)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
lock.acquire(True)
|
lock.acquire(True)
|
||||||
@ -341,11 +342,18 @@ class Client(object):
|
|||||||
storage_domain = params.StorageDomain(id=storageId)
|
storage_domain = params.StorageDomain(id=storageId)
|
||||||
|
|
||||||
cluster = api.clusters.get(id=clusterId)
|
cluster = api.clusters.get(id=clusterId)
|
||||||
vm = api.vms.get(id=vmId)
|
vm = api.vms.get(id=machineId)
|
||||||
|
|
||||||
|
if vm is None:
|
||||||
|
raise Exception('Machine not found')
|
||||||
|
|
||||||
|
if cluster is None:
|
||||||
|
raise Exception('Cluster not found')
|
||||||
|
|
||||||
|
|
||||||
if vm.get_status().get_state() != 'down':
|
if vm.get_status().get_state() != 'down':
|
||||||
raise Exception('Machine must be in down state to publish it')
|
raise Exception('Machine must be in down state to publish it')
|
||||||
|
|
||||||
template = params.Template(name=name,storage_domain=storage_domain, vm=vm, cluster=cluster, description=comments)
|
template = params.Template(name=name,storage_domain=storage_domain, vm=vm, cluster=cluster, description=comments)
|
||||||
|
|
||||||
return api.templates.add(template).get_id()
|
return api.templates.add(template).get_id()
|
||||||
@ -400,8 +408,8 @@ class Client(object):
|
|||||||
|
|
||||||
api = self.__getApi()
|
api = self.__getApi()
|
||||||
|
|
||||||
cluster = api.clusters.get(id=clusterId)
|
cluster = params.Cluster(id=clusterId)
|
||||||
template = api.templates.get(id=templateId)
|
template = params.Template(id=templateId)
|
||||||
|
|
||||||
if cluster is None:
|
if cluster is None:
|
||||||
raise Exception('Cluster not found')
|
raise Exception('Cluster not found')
|
||||||
@ -437,7 +445,6 @@ class Client(object):
|
|||||||
# This returns nothing, if it fails it raises an exception
|
# This returns nothing, if it fails it raises an exception
|
||||||
finally:
|
finally:
|
||||||
lock.release()
|
lock.release()
|
||||||
|
|
||||||
|
|
||||||
def getMachineState(self, machineId):
|
def getMachineState(self, machineId):
|
||||||
'''
|
'''
|
||||||
@ -448,15 +455,12 @@ class Client(object):
|
|||||||
machineId: Id of the machine to get status
|
machineId: Id of the machine to get status
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
'down': Machine is not running
|
one of this values:
|
||||||
'unknown': Machine is not known
|
unassigned, down, up, powering_up, powered_down,
|
||||||
'powering_up': Machine is powering up
|
paused, migrating_from, migrating_to, unknown, not_responding,
|
||||||
'up': Machine is up and running
|
wait_for_launch, reboot_in_progress, saving_state, restoring_state,
|
||||||
'saving_state': Machine is "suspending"
|
suspended, image_illegal, image_locked or powering_down
|
||||||
'suspended': Machine is suspended
|
Also can return'unknown' if Machine is not known
|
||||||
'restoring_state': Machine is restoring state (unsuspending)
|
|
||||||
'powering_down': Machine is powering down
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
lock.acquire(True)
|
lock.acquire(True)
|
||||||
@ -472,16 +476,102 @@ class Client(object):
|
|||||||
|
|
||||||
finally:
|
finally:
|
||||||
lock.release()
|
lock.release()
|
||||||
|
|
||||||
|
|
||||||
def powerOnMachine(self, machineId):
|
def startMachine(self, machineId):
|
||||||
'''
|
'''
|
||||||
Tries to power on a machine. No check is done, it is simply requested to oVirt
|
Tries to start a machine. No check is done, it is simply requested to oVirt.
|
||||||
|
|
||||||
|
This start also "resume" suspended/paused machines
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
machineId: Id of the machine
|
machineId: Id of the machine
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
|
||||||
|
api = self.__getApi()
|
||||||
|
|
||||||
|
vm = api.vms.get(id=machineId)
|
||||||
|
|
||||||
|
if vm is None:
|
||||||
|
raise Exception('Machine not found')
|
||||||
|
|
||||||
|
vm.start()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
|
||||||
|
def stopMachine(self, machineId):
|
||||||
|
'''
|
||||||
|
Tries to start a machine. No check is done, it is simply requested to oVirt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
machineId: Id of the machine
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
|
||||||
|
api = self.__getApi()
|
||||||
|
|
||||||
|
vm = api.vms.get(id=machineId)
|
||||||
|
|
||||||
|
if vm is None:
|
||||||
|
raise Exception('Machine not found')
|
||||||
|
|
||||||
|
vm.stop()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
|
||||||
|
def suspendMachine(self, machineId):
|
||||||
|
'''
|
||||||
|
Tries to start a machine. No check is done, it is simply requested to oVirt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
machineId: Id of the machine
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
|
||||||
|
api = self.__getApi()
|
||||||
|
|
||||||
|
vm = api.vms.get(id=machineId)
|
||||||
|
|
||||||
|
if vm is None:
|
||||||
|
raise Exception('Machine not found')
|
||||||
|
|
||||||
|
vm.suspend()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
|
||||||
|
def removeMachine(self, machineId):
|
||||||
|
'''
|
||||||
|
Tries to delete a machine. No check is done, it is simply requested to oVirt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
machineId: Id of the machine
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
|
||||||
|
api = self.__getApi()
|
||||||
|
|
||||||
|
vm = api.vms.get(id=machineId)
|
||||||
|
|
||||||
|
if vm is None:
|
||||||
|
raise Exception('Machine not found')
|
||||||
|
|
||||||
|
vm.delete()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user