mirror of
https://github.com/dkmstr/openuds.git
synced 2024-12-22 13:34:04 +03:00
oVirt connector SHOULD work fine right now (but needs more testing... :P).
Have the "volPath" problem (inside vsdm/clientIF.py) at this time, solved by patching my installation, but i have to find a definitive solution. Will do also tests with "real" vms (not just small 1Gb with no os to test platform), but this should work fine. (we will see..)
This commit is contained in:
parent
0eea8a33b5
commit
830e1b2e6f
@ -38,7 +38,7 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
opCreate, opStart, opStop, opSuspend, opRemove, opWait, opError, opFinish, opRetry = range(9)
|
||||
opCreate, opStart, opStop, opSuspend, opRemove, opWait, opError, opFinish, opRetry, opChangeMac = range(10)
|
||||
|
||||
class OVirtLinkedDeployment(UserDeployment):
|
||||
'''
|
||||
@ -203,14 +203,18 @@ class OVirtLinkedDeployment(UserDeployment):
|
||||
def __initQueueForDeploy(self, forLevel2 = False):
|
||||
|
||||
if forLevel2 is False:
|
||||
self._queue = [opCreate, opStart, opFinish]
|
||||
self._queue = [opCreate, opChangeMac, opStart, opFinish]
|
||||
else:
|
||||
self._queue = [opCreate, opStart, opWait, opSuspend, opFinish]
|
||||
self._queue = [opCreate, opChangeMac, 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 we want to check an state and machine does not exists (except in case that we whant to check this)
|
||||
if state == 'unknown' and chkState != 'unknown':
|
||||
return self.__error('Machine not found')
|
||||
|
||||
if state != chkState:
|
||||
return State.RUNNING
|
||||
|
||||
@ -249,7 +253,7 @@ class OVirtLinkedDeployment(UserDeployment):
|
||||
return State.ERROR
|
||||
|
||||
def __executeQueue(self):
|
||||
self.__debugQueue('executeQueue')
|
||||
self.__debug('executeQueue')
|
||||
op = self.__getCurrentOp()
|
||||
|
||||
if op == opError:
|
||||
@ -259,12 +263,13 @@ class OVirtLinkedDeployment(UserDeployment):
|
||||
return State.FINISHED
|
||||
|
||||
fncs = { opCreate: self.__create,
|
||||
opRetry: self.__retry,
|
||||
opRetry: self.__retry,
|
||||
opStart: self.__startMachine,
|
||||
opStop: self.__stopMachine,
|
||||
opSuspend: self.__suspendMachine,
|
||||
opWait: self.__wait,
|
||||
opRemove: self.__remove
|
||||
opRemove: self.__remove,
|
||||
opChangeMac: self.__changeMac
|
||||
}
|
||||
|
||||
try:
|
||||
@ -273,9 +278,9 @@ class OVirtLinkedDeployment(UserDeployment):
|
||||
if execFnc is None:
|
||||
return self.__error('Unknown operation found at execution queue ({0})'.format(op))
|
||||
|
||||
state = execFnc()
|
||||
execFnc()
|
||||
|
||||
return state
|
||||
return State.RUNNING
|
||||
except Exception as e:
|
||||
return self.__error(e)
|
||||
|
||||
@ -285,6 +290,8 @@ class OVirtLinkedDeployment(UserDeployment):
|
||||
Used to retry an operation
|
||||
In fact, this will not be never invoked, unless we push it twice, because
|
||||
checkState method will "pop" first item when a check operation returns State.FINISHED
|
||||
|
||||
At executeQueue this return value will be ignored, and it will only be used at checkState
|
||||
'''
|
||||
return State.FINISHED
|
||||
|
||||
@ -306,65 +313,76 @@ class OVirtLinkedDeployment(UserDeployment):
|
||||
if self._vmid is None:
|
||||
raise Exception('Can\'t create machine')
|
||||
|
||||
return State.RUNNING
|
||||
|
||||
def __remove(self):
|
||||
'''
|
||||
Removes a machine from system
|
||||
'''
|
||||
state = self.service().getMachineState(self._vmid)
|
||||
|
||||
if state == 'unknown':
|
||||
raise Exception('Machine not found')
|
||||
|
||||
if state != 'down' and state != 'suspended':
|
||||
self.__pushFrontOp(opStop)
|
||||
return State.RUNNING
|
||||
|
||||
self.service().removeMachine(self._vmid)
|
||||
return State.RUNNING
|
||||
else:
|
||||
self.service().removeMachine(self._vmid)
|
||||
|
||||
def __startMachine(self):
|
||||
'''
|
||||
Powers on the machine
|
||||
'''
|
||||
state = self.service().getMachineState(self._vmid)
|
||||
if state == 'up':
|
||||
return State.FINISHED
|
||||
|
||||
if state == 'unknown':
|
||||
raise Exception('Machine not found')
|
||||
|
||||
if state == 'up': # Already started, return
|
||||
return
|
||||
|
||||
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
|
||||
self.__pushFrontOp(opRetry) # Will call "check Retry", that will finish inmediatly and again call this one
|
||||
else:
|
||||
self.service().startMachine(self._vmid)
|
||||
|
||||
def __stopMachine(self):
|
||||
'''
|
||||
Powers off the machine
|
||||
'''
|
||||
state = self.service().getMachineState(self._vmid)
|
||||
if state == 'down':
|
||||
return State.FINISHED
|
||||
|
||||
if state == 'unknown':
|
||||
raise Exception('Machine not found')
|
||||
|
||||
if state == 'down': # Already stoped, return
|
||||
return
|
||||
|
||||
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
|
||||
self.__pushBackOp(opRetry) # Will call "check Retry", that will finish inmediatly and again call this one
|
||||
else:
|
||||
self.service().stopMachine(self._vmid)
|
||||
|
||||
def __suspendMachine(self):
|
||||
'''
|
||||
Suspends the machine
|
||||
'''
|
||||
state = self.service().getMachineState(self._vmid)
|
||||
if state == 'suspended':
|
||||
return State.FINISHED
|
||||
|
||||
if state == 'unknown':
|
||||
raise Exception('Machine not found')
|
||||
|
||||
if state == 'suspended': # Already suspended, return
|
||||
return
|
||||
|
||||
if state != 'up':
|
||||
self.__pushBackOp(opRetry) # Remember here, the return State.FINISH will make this retry be "poped" right ar return
|
||||
return State.FINISHED
|
||||
else:
|
||||
self.service().suspendMachine(self._vmid)
|
||||
|
||||
self.service().suspendMachine(self._vmid)
|
||||
return State.RUNNING
|
||||
def __changeMac(self):
|
||||
'''
|
||||
Changes the mac of the first nic
|
||||
'''
|
||||
self.service().updateMachineMac(self._vmid, self.getUniqueId())
|
||||
|
||||
# Check methods
|
||||
def __checkCreate(self):
|
||||
@ -397,11 +415,19 @@ class OVirtLinkedDeployment(UserDeployment):
|
||||
'''
|
||||
return self.__checkMachineState('unknown')
|
||||
|
||||
def __checkMac(self):
|
||||
'''
|
||||
Checks if change mac operation has finished.
|
||||
|
||||
Changing nic configuration es 1-step operation, so when we check it here, it is already done
|
||||
'''
|
||||
return State.FINISHED
|
||||
|
||||
def checkState(self):
|
||||
'''
|
||||
Check what operation is going on, and acts acordly to it
|
||||
'''
|
||||
self.__debugQueue('checkState')
|
||||
self.__debug('checkState')
|
||||
op = self.__getCurrentOp()
|
||||
|
||||
if op == opError:
|
||||
@ -416,7 +442,8 @@ class OVirtLinkedDeployment(UserDeployment):
|
||||
opStart: self.__checkStart,
|
||||
opStop: self.__checkStop,
|
||||
opSuspend: self.__checkSuspend,
|
||||
opRemove: self.__checkRemoved
|
||||
opRemove: self.__checkRemoved,
|
||||
opChangeMac: self.__checkMac
|
||||
}
|
||||
|
||||
try:
|
||||
@ -438,8 +465,8 @@ class OVirtLinkedDeployment(UserDeployment):
|
||||
'''
|
||||
Invoked when the core notices that the deployment of a service has finished.
|
||||
(No matter wether it is for cache or for an user)
|
||||
|
||||
'''
|
||||
self.__debug('finish')
|
||||
pass
|
||||
|
||||
def assignToUser(self, user):
|
||||
@ -483,16 +510,19 @@ class OVirtLinkedDeployment(UserDeployment):
|
||||
'''
|
||||
Invoked for destroying a deployed service
|
||||
'''
|
||||
|
||||
self.__debug('destroy')
|
||||
# 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()
|
||||
if op == opError:
|
||||
return self.__error('Machine is already in error state!')
|
||||
|
||||
self._queue = [op, opStop, opRemove]
|
||||
if op == opFinish or op == opWait:
|
||||
self._queue = [opStop, opRemove, opFinish]
|
||||
return self.__executeQueue()
|
||||
|
||||
self._queue = [op, opStop, opRemove, opFinish]
|
||||
# Do not execute anything.here, just continue normally
|
||||
return State.RUNNING
|
||||
|
||||
@ -519,9 +549,14 @@ class OVirtLinkedDeployment(UserDeployment):
|
||||
opWait: 'wait',
|
||||
opError: 'error',
|
||||
opFinish: 'finish',
|
||||
opRetry: 'retry'
|
||||
opRetry: 'retry',
|
||||
opChangeMac: 'changing mac'
|
||||
}.get(op, '????')
|
||||
|
||||
def __debugQueue(self, txt):
|
||||
def __debug(self, txt):
|
||||
logger.debug('_name {0}: {1}'.format(txt, self._name))
|
||||
logger.debug('_ip {0}: {1}'.format(txt, self._ip))
|
||||
logger.debug('_mac {0}: {1}'.format(txt, self._mac))
|
||||
logger.debug('_vmid {0}: {1}'.format(txt, self._vmid))
|
||||
logger.debug('Queue at {0}: {1}'.format(txt,[OVirtLinkedDeployment.__op2str(op) for op in self._queue ]))
|
||||
|
@ -112,6 +112,14 @@ class OVirtLinkedService(Service):
|
||||
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)
|
||||
|
||||
display = gui.ChoiceField(label = translatable('Display'), rdonly = False, order = 6,
|
||||
tooltip = translatable('Display type (only for administration pourposses)'),
|
||||
values = [ gui.choiceItem('spice', 'Spice'),
|
||||
gui.choiceItem('vnc', 'Vnc')
|
||||
],
|
||||
defvalue = '1' # Default value is the ID of the choicefield
|
||||
)
|
||||
|
||||
ov = gui.HiddenField()
|
||||
ev = gui.HiddenField() # We need to keep the env so we can instantiate the Provider
|
||||
|
||||
@ -169,7 +177,7 @@ class OVirtLinkedService(Service):
|
||||
|
||||
Raises an exception if operation fails.
|
||||
'''
|
||||
return self.parent().makeTemplate(name, comments, self.machine.value, self.cluster.value, self.datastore.value)
|
||||
return self.parent().makeTemplate(name, comments, self.machine.value, self.cluster.value, self.datastore.value, self.display.value)
|
||||
|
||||
def getTemplateState(self, templateId):
|
||||
'''
|
||||
@ -196,7 +204,7 @@ class OVirtLinkedService(Service):
|
||||
Returns:
|
||||
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, self.display.value)
|
||||
|
||||
def removeTemplate(self, templateId):
|
||||
'''
|
||||
@ -267,6 +275,12 @@ class OVirtLinkedService(Service):
|
||||
Returns:
|
||||
'''
|
||||
return self.parent().removeMachine(machineId)
|
||||
|
||||
def updateMachineMac(self, machineId, macAddres):
|
||||
'''
|
||||
Changes the mac address of first nic of the machine to the one specified
|
||||
'''
|
||||
return self.parent().updateMachineMac(machineId, macAddres)
|
||||
|
||||
def getMacRange(self):
|
||||
'''
|
||||
@ -286,4 +300,9 @@ class OVirtLinkedService(Service):
|
||||
'''
|
||||
return int(self.lenName.value)
|
||||
|
||||
def getDisplay(self):
|
||||
'''
|
||||
Returns the selected display type (for created machines, for administration
|
||||
'''
|
||||
return self.display.value
|
||||
|
||||
|
@ -233,21 +233,22 @@ class Provider(ServiceProvider):
|
||||
'''
|
||||
return self.__getApi().getStorageInfo(storageId, force)
|
||||
|
||||
def makeTemplate(self, name, comments, vmId, clusterId, storageId):
|
||||
def makeTemplate(self, name, comments, machineId, clusterId, storageId, displayType):
|
||||
'''
|
||||
Publish the machine (makes a template from it so we can create COWs) and returns the template id of
|
||||
the creating machine
|
||||
|
||||
Args:
|
||||
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
|
||||
storageId: id of the storage tuat will contain the publication AND linked clones
|
||||
displayType: type of display (for oVirt admin interface only)
|
||||
|
||||
Returns
|
||||
Raises an exception if operation could not be acomplished, or returns the id of the template being created.
|
||||
'''
|
||||
return self.__getApi().makeTemplate(name, comments, vmId, clusterId, storageId)
|
||||
return self.__getApi().makeTemplate(name, comments, machineId, clusterId, storageId, displayType)
|
||||
|
||||
def getTemplateState(self, templateId):
|
||||
'''
|
||||
@ -290,7 +291,7 @@ class Provider(ServiceProvider):
|
||||
'''
|
||||
return self.__getApi().removeTemplate(templateId)
|
||||
|
||||
def deployFromTemplate(self, name, comments, templateId, clusterId):
|
||||
def deployFromTemplate(self, name, comments, templateId, clusterId, displayType):
|
||||
'''
|
||||
Deploys a virtual machine on selected cluster from selected template
|
||||
|
||||
@ -303,7 +304,7 @@ class Provider(ServiceProvider):
|
||||
Returns:
|
||||
Id of the machine being created form template
|
||||
'''
|
||||
return self.__getApi().deployFromTemplate(name, comments, templateId, clusterId)
|
||||
return self.__getApi().deployFromTemplate(name, comments, templateId, clusterId, displayType)
|
||||
|
||||
def startMachine(self, machineId):
|
||||
'''
|
||||
@ -351,6 +352,12 @@ class Provider(ServiceProvider):
|
||||
'''
|
||||
return self.__getApi().removeMachine(machineId)
|
||||
|
||||
def updateMachineMac(self, machineId, macAddres):
|
||||
'''
|
||||
Changes the mac address of first nic of the machine to the one specified
|
||||
'''
|
||||
return self.__getApi().updateMachineMac(machineId, macAddres)
|
||||
|
||||
def getMacRange(self):
|
||||
return self.macsRange.value
|
||||
|
||||
|
@ -10,6 +10,7 @@ from ovirtsdk.api import API
|
||||
import threading
|
||||
import logging
|
||||
import ovirtsdk
|
||||
from roman import OutOfRangeError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -63,7 +64,7 @@ class Client(object):
|
||||
pass
|
||||
|
||||
cached_api_key = aKey
|
||||
cached_api = API(url='https://'+self._host, username=self._username, password=self._password, timeout=self._timeout, insecure=True, debug=False)
|
||||
cached_api = API(url='https://'+self._host, username=self._username, password=self._password, timeout=self._timeout, insecure=True, debug=True)
|
||||
return cached_api
|
||||
|
||||
def __init__(self, host, username, password, timeout, cache):
|
||||
@ -317,7 +318,7 @@ class Client(object):
|
||||
lock.release()
|
||||
|
||||
|
||||
def makeTemplate(self, name, comments, machineId, clusterId, storageId):
|
||||
def makeTemplate(self, name, comments, machineId, clusterId, storageId, displayType):
|
||||
'''
|
||||
Publish the machine (makes a template from it so we can create COWs) and returns the template id of
|
||||
the creating machine
|
||||
@ -327,19 +328,18 @@ class Client(object):
|
||||
machineId: id of the machine to be published
|
||||
clusterId: id of the cluster that will hold the machine
|
||||
storageId: id of the storage tuat will contain the publication AND linked clones
|
||||
displayType: type of display (for oVirt admin interface only)
|
||||
|
||||
Returns
|
||||
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, machineId, clusterId, storageId)
|
||||
logger.debug("n: {0}, c: {1}, vm: {2}, cl: {3}, st: {3}, dt: {4}".format(name, comments, machineId, clusterId, storageId, displayType))
|
||||
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
#storage = api.storagedomains.get(id=storageId)
|
||||
storage_domain = params.StorageDomain(id=storageId)
|
||||
|
||||
cluster = api.clusters.get(id=clusterId)
|
||||
vm = api.vms.get(id=machineId)
|
||||
@ -350,14 +350,27 @@ class Client(object):
|
||||
if cluster is None:
|
||||
raise Exception('Cluster not found')
|
||||
|
||||
|
||||
if vm.get_status().get_state() != 'down':
|
||||
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)
|
||||
# Create disks description to be created in specified storage domain, one for each disk
|
||||
sd = params.StorageDomains(storage_domain=[params.StorageDomain(id=storageId)])
|
||||
|
||||
dsks = []
|
||||
for dsk in vm.disks.list():
|
||||
dsks.append(params.Disk(id=dsk.get_id(), storage_domains=sd))
|
||||
|
||||
disks = params.Disks(disk=dsks)
|
||||
|
||||
# Create display description
|
||||
display = params.Display(type_=displayType)
|
||||
|
||||
template = params.Template(name=name, vm=params.VM(id=vm.get_id(), disks=disks),
|
||||
cluster=params.Cluster(id=cluster.get_id()), description=comments,
|
||||
display=display)
|
||||
|
||||
return api.templates.add(template).get_id()
|
||||
|
||||
|
||||
#return api.templates.get(name=name).get_id()
|
||||
finally:
|
||||
lock.release()
|
||||
@ -390,7 +403,7 @@ class Client(object):
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
def deployFromTemplate(self, name, comments, templateId, clusterId):
|
||||
def deployFromTemplate(self, name, comments, templateId, clusterId, displayType):
|
||||
'''
|
||||
Deploys a virtual machine on selected cluster from selected template
|
||||
|
||||
@ -410,16 +423,9 @@ class Client(object):
|
||||
|
||||
cluster = params.Cluster(id=clusterId)
|
||||
template = params.Template(id=templateId)
|
||||
display = params.Display(type_=displayType)
|
||||
|
||||
if cluster is None:
|
||||
raise Exception('Cluster not found')
|
||||
|
||||
if template is None:
|
||||
raise Exception('Template not found')
|
||||
|
||||
par = params.VM(name=name, cluster=cluster, template=template, description=comments)
|
||||
|
||||
params.Display()
|
||||
par = params.VM(name=name, cluster=cluster, template=template, description=comments, display=display)
|
||||
|
||||
return api.vms.add(par).get_id()
|
||||
|
||||
@ -550,7 +556,7 @@ class Client(object):
|
||||
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
|
||||
def removeMachine(self, machineId):
|
||||
'''
|
||||
Tries to delete a machine. No check is done, it is simply requested to oVirt
|
||||
@ -574,4 +580,30 @@ class Client(object):
|
||||
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
|
||||
def updateMachineMac(self, machineId, macAddres):
|
||||
'''
|
||||
Changes the mac address of first nic of the machine to the one specified
|
||||
'''
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
vm = api.vms.get(id=machineId)
|
||||
|
||||
if vm is None:
|
||||
raise Exception('Machine not found')
|
||||
|
||||
nic = vm.nics.list()[0] # If has no nic, will raise an exception (IndexError)
|
||||
|
||||
nic.get_mac().set_address(macAddres)
|
||||
|
||||
nic.update() # Updates the nic
|
||||
|
||||
except IndexError:
|
||||
raise Exception('Machine do not have network interfaces!!')
|
||||
|
||||
finally:
|
||||
lock.release()
|
||||
|
Loading…
Reference in New Issue
Block a user