mirror of
https://github.com/dkmstr/openuds.git
synced 2025-01-18 06:03:54 +03:00
* Added more methods needed at oVirtClient
* Finished (need testing) oVirtLinkedService, so now we can add new oVirtLinkedServices, but can't publish it :-) * Added helpers methods to allow new oVirtLinkedServices
This commit is contained in:
parent
85dd9b0537
commit
0bb26cfae1
44
server/src/uds/services/OVirt/Helpers.py
Normal file
44
server/src/uds/services/OVirt/Helpers.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
'''
|
||||||
|
Created on Nov 15, 2012
|
||||||
|
|
||||||
|
@author: dkmaster
|
||||||
|
'''
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class oVirtHelpers(object):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getResources(parameters):
|
||||||
|
'''
|
||||||
|
This helper is designed as a callback for machine selector, so we can provide valid clusters and datastores domains based on it
|
||||||
|
'''
|
||||||
|
from OVirtProvider import Provider
|
||||||
|
from uds.core.Environment import Environment
|
||||||
|
logger.debug('Parameters received by getResources Helper: {0}'.format(parameters))
|
||||||
|
env = Environment(parameters['ev'])
|
||||||
|
provider = Provider(env)
|
||||||
|
provider.unserialize(parameters['ov'])
|
||||||
|
|
||||||
|
# Obtains datacenter from cluster
|
||||||
|
ci = provider.getClusterInfo(parameters['cluster'])
|
||||||
|
|
||||||
|
res = []
|
||||||
|
# Get storages for that datacenter
|
||||||
|
for storage in provider.getDatacenterInfo(ci['datacenter_id'])['storage']:
|
||||||
|
if storage['active'] is True and storage['type'] == 'data':
|
||||||
|
space, free = storage['available']/1024/1024/1024, (storage['available']-storage['used'])/1024/1024/1024
|
||||||
|
|
||||||
|
res.append( {'id': storage['id'], 'text': "%s (%4.2f Gb/%4.2f Gb)" % (storage['name'], space, free ) })
|
||||||
|
data = [{
|
||||||
|
'name' : 'datastore', 'values' : res
|
||||||
|
}]
|
||||||
|
|
||||||
|
logger.debug('return data: {0}'.format(data))
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -42,6 +42,8 @@ import logging
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
from Helpers import oVirtHelpers
|
||||||
|
|
||||||
class OVirtLinkedService(Service):
|
class OVirtLinkedService(Service):
|
||||||
'''
|
'''
|
||||||
oVirt Linked clones service. This is based on creating a template from selected vm, and then use it to
|
oVirt Linked clones service. This is based on creating a template from selected vm, and then use it to
|
||||||
@ -93,21 +95,25 @@ class OVirtLinkedService(Service):
|
|||||||
#: Types of deploys (services in cache and/or assigned to users)
|
#: Types of deploys (services in cache and/or assigned to users)
|
||||||
deployedType = OVirtLinkedDeployment
|
deployedType = OVirtLinkedDeployment
|
||||||
|
|
||||||
# Now the form part, this service will have only two "dummy" fields
|
# Now the form part
|
||||||
# If we don't indicate an order, the output order of fields will be
|
machine = gui.ChoiceField(label=translatable("Base Machine"), order = 1, tooltip = _('Service base machine'), required = True)
|
||||||
# "random"
|
cluster = gui.ChoiceField(label=translatable("Cluster"), order = 2,
|
||||||
|
fills = {
|
||||||
|
'callbackName' : 'ovFillResourcesFromCluster',
|
||||||
|
'function' : oVirtHelpers.getResources,
|
||||||
|
'parameters' : ['cluster', 'ov', 'ev']
|
||||||
|
},
|
||||||
|
tooltip = translatable("Cluster to contain services"), required = True
|
||||||
|
)
|
||||||
|
|
||||||
machine = gui.ChoiceField(label = _("Base Machine"), order = 6, tooltip = _('Base machine for this service'), required = True )
|
datastore = gui.ChoiceField(label = translatable("Datastore Domain"), rdonly = False, order = 3,
|
||||||
|
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)
|
||||||
|
lenName = gui.NumericField(length = 1, label = translatable('Name Length'), defvalue = 3, order = 5,
|
||||||
|
tooltip = translatable('Length of numeric part for the names of this machines (betwen 3 and 6'), required = True)
|
||||||
|
|
||||||
|
ov = gui.HiddenField()
|
||||||
|
ev = gui.HiddenField() # We need to keep the env so we can instantiate the Provider
|
||||||
baseName = gui.TextField(order = 3,
|
|
||||||
label = translatable('Services names'),
|
|
||||||
tooltip = translatable('Base name for this user services'),
|
|
||||||
# In this case, the choice can have none value selected by default
|
|
||||||
required = True,
|
|
||||||
defvalue = '' # Default value is the ID of the choicefield
|
|
||||||
)
|
|
||||||
|
|
||||||
def initialize(self, values):
|
def initialize(self, values):
|
||||||
'''
|
'''
|
||||||
@ -116,40 +122,27 @@ class OVirtLinkedService(Service):
|
|||||||
Note that we check them throught FROM variables, that already has been
|
Note that we check them throught FROM variables, that already has been
|
||||||
initialized by __init__ method of base class, before invoking this.
|
initialized by __init__ method of base class, before invoking this.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# 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 is not None:
|
||||||
if self.colour.value == 'nonsense':
|
length = int(self.lenName.value)
|
||||||
raise Service.ValidationException('The selected colour is invalid!!!')
|
if len(self.baseName.value) + length > 15:
|
||||||
|
raise Service.ValidationException(_('The length of basename plus length must not be greater than 15'))
|
||||||
|
if self.baseName.value.isdigit():
|
||||||
# Services itself are non testeable right now, so we don't even have
|
raise Service.ValidationException(_('The machine name can\'t be only numbers'))
|
||||||
# to provide one!!!
|
|
||||||
|
|
||||||
|
|
||||||
# Congratulations!!!, the needed part of your first simple service is done!
|
machines = self.parent().getMachines()
|
||||||
# Now you can go to administration panel, and check it
|
vals = []
|
||||||
#
|
for m in machines:
|
||||||
# From now onwards, we implement our own methods, that will be used by,
|
vals.append( gui.choiceItem( m['id'], m['name'] ))
|
||||||
# for example, services derived from this provider
|
self.machine.setValues(vals)
|
||||||
|
|
||||||
def getColour(self):
|
clusters = self.parent().getClusters()
|
||||||
'''
|
vals = []
|
||||||
Simply returns colour, for deployed user services.
|
for c in clusters:
|
||||||
|
vals.append( gui.choiceItem(c['id'], c['name'] ) )
|
||||||
|
self.cluster.setValues(vals)
|
||||||
|
|
||||||
|
|
||||||
|
def initGui(self):
|
||||||
|
self.ov.value = self.parent().serialize()
|
||||||
|
self.ev.value = self.parent().env().key()
|
||||||
|
|
||||||
Remember that choiceField.value returns the id part of the ChoiceItem
|
|
||||||
'''
|
|
||||||
return self.colour.value
|
|
||||||
|
|
||||||
def getPassw(self):
|
|
||||||
'''
|
|
||||||
Simply returns passwd, for deloyed user services
|
|
||||||
'''
|
|
||||||
return self.passw.value
|
|
||||||
|
|
||||||
def getBaseName(self):
|
|
||||||
'''
|
|
||||||
'''
|
|
||||||
return self.baseName.value
|
|
||||||
|
@ -118,9 +118,120 @@ class Provider(ServiceProvider):
|
|||||||
self._api = None
|
self._api = None
|
||||||
|
|
||||||
def testConnection(self):
|
def testConnection(self):
|
||||||
api = self.__getApi()
|
'''
|
||||||
return api.test()
|
Test that conection to oVirt server is fine
|
||||||
|
|
||||||
|
Returns
|
||||||
|
|
||||||
|
True if all went fine, false if id didn't
|
||||||
|
'''
|
||||||
|
|
||||||
|
return self.__getApi().test()
|
||||||
|
|
||||||
|
def getMachines(self, force = False):
|
||||||
|
'''
|
||||||
|
Obtains the list of machines inside oVirt.
|
||||||
|
Machines starting with UDS are filtered out
|
||||||
|
|
||||||
|
Args:
|
||||||
|
force: If true, force to update the cache, if false, tries to first
|
||||||
|
get data from cache and, if valid, return this.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
An array of dictionaries, containing:
|
||||||
|
'name'
|
||||||
|
'id'
|
||||||
|
'cluster_id'
|
||||||
|
'''
|
||||||
|
|
||||||
|
return self.__getApi().getVms(force)
|
||||||
|
|
||||||
|
def getClusters(self, force = False):
|
||||||
|
'''
|
||||||
|
Obtains the list of clusters inside oVirt.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
force: If true, force to update the cache, if false, tries to first
|
||||||
|
get data from cache and, if valid, return this.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
Filters out clusters not attached to any datacenter
|
||||||
|
An array of dictionaries, containing:
|
||||||
|
'name'
|
||||||
|
'id'
|
||||||
|
'datacenter_id'
|
||||||
|
'''
|
||||||
|
|
||||||
|
return self.__getApi().getClusters(force)
|
||||||
|
|
||||||
|
def getClusterInfo(self, clusterId, force = False):
|
||||||
|
'''
|
||||||
|
Obtains the cluster info
|
||||||
|
|
||||||
|
Args:
|
||||||
|
datacenterId: Id of the cluster to get information about it
|
||||||
|
force: If true, force to update the cache, if false, tries to first
|
||||||
|
get data from cache and, if valid, return this.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
|
||||||
|
A dictionary with following values
|
||||||
|
'name'
|
||||||
|
'id'
|
||||||
|
'datacenter_id'
|
||||||
|
'''
|
||||||
|
return self.__getApi().getClusterInfo(clusterId, force)
|
||||||
|
|
||||||
|
def getDatacenterInfo(self, datacenterId, force = False):
|
||||||
|
'''
|
||||||
|
Obtains the datacenter info
|
||||||
|
|
||||||
|
Args:
|
||||||
|
datacenterId: Id of the datacenter to get information about it
|
||||||
|
force: If true, force to update the cache, if false, tries to first
|
||||||
|
get data from cache and, if valid, return this.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
|
||||||
|
A dictionary with following values
|
||||||
|
'name'
|
||||||
|
'id'
|
||||||
|
'storage_type' -> ('isisi', 'nfs', ....)
|
||||||
|
'storage_format' -> ('v1', v2')
|
||||||
|
'description'
|
||||||
|
'storage' -> array of dictionaries, with:
|
||||||
|
'id' -> Storage id
|
||||||
|
'name' -> Storage name
|
||||||
|
'type' -> Storage type ('data', 'iso')
|
||||||
|
'available' -> Space available, in bytes
|
||||||
|
'used' -> Space used, in bytes
|
||||||
|
'active' -> True or False
|
||||||
|
|
||||||
|
'''
|
||||||
|
return self.__getApi().getDatacenterInfo(datacenterId, force)
|
||||||
|
|
||||||
|
def getStorageInfo(self, storageId, force = False):
|
||||||
|
'''
|
||||||
|
Obtains the datacenter info
|
||||||
|
|
||||||
|
Args:
|
||||||
|
datacenterId: Id of the datacenter to get information about it
|
||||||
|
force: If true, force to update the cache, if false, tries to first
|
||||||
|
get data from cache and, if valid, return this.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
|
||||||
|
A dictionary with following values
|
||||||
|
'id' -> Storage id
|
||||||
|
'name' -> Storage name
|
||||||
|
'type' -> Storage type ('data', 'iso')
|
||||||
|
'available' -> Space available, in bytes
|
||||||
|
'used' -> Space used, in bytes
|
||||||
|
# 'active' -> True or False --> This is not provided by api?? (api.storagedomains.get)
|
||||||
|
|
||||||
|
'''
|
||||||
|
return self.__getApi().getStorageInfo(storageId, force)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def test(env, data):
|
def test(env, data):
|
||||||
|
@ -92,7 +92,6 @@ class Client(object):
|
|||||||
get data from cache and, if valid, return this.
|
get data from cache and, if valid, return this.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
|
||||||
An array of dictionaries, containing:
|
An array of dictionaries, containing:
|
||||||
'name'
|
'name'
|
||||||
'id'
|
'id'
|
||||||
@ -124,6 +123,60 @@ class Client(object):
|
|||||||
finally:
|
finally:
|
||||||
lock.release()
|
lock.release()
|
||||||
|
|
||||||
|
def getClusters(self, force = False):
|
||||||
|
'''
|
||||||
|
Obtains the list of clusters inside ovirt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
force: If true, force to update the cache, if false, tries to first
|
||||||
|
get data from cache and, if valid, return this.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
Filters out clusters not attached to any datacenter
|
||||||
|
An array of dictionaries, containing:
|
||||||
|
'name'
|
||||||
|
'id'
|
||||||
|
'datacenter_id'
|
||||||
|
|
||||||
|
'''
|
||||||
|
clsKey = self.__getKey('o-clusters')
|
||||||
|
val = self._cache.get(clsKey)
|
||||||
|
|
||||||
|
if val is not None and force is False:
|
||||||
|
return val
|
||||||
|
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
|
||||||
|
api = self.__getApi()
|
||||||
|
|
||||||
|
clusters = api.clusters.list()
|
||||||
|
|
||||||
|
res = []
|
||||||
|
|
||||||
|
for cluster in clusters:
|
||||||
|
dc = cluster.get_data_center()
|
||||||
|
|
||||||
|
if dc is not None:
|
||||||
|
dc = dc.get_id()
|
||||||
|
|
||||||
|
val = { 'name' : cluster.get_name(), 'id' : cluster.get_id(), 'datacenter_id' : dc }
|
||||||
|
|
||||||
|
# Updates cache info for every single cluster
|
||||||
|
clKey = self.__getKey('o-cluster'+cluster.get_id())
|
||||||
|
self._cache.put(clKey, val)
|
||||||
|
|
||||||
|
if dc is not None:
|
||||||
|
res.append(val)
|
||||||
|
|
||||||
|
self._cache.put(clsKey, res, Client.CACHE_TIME_HIGH)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
|
||||||
|
|
||||||
def getClusterInfo(self, clusterId, force = False):
|
def getClusterInfo(self, clusterId, force = False):
|
||||||
'''
|
'''
|
||||||
Obtains the cluster info
|
Obtains the cluster info
|
||||||
@ -138,7 +191,6 @@ class Client(object):
|
|||||||
A dictionary with following values
|
A dictionary with following values
|
||||||
'name'
|
'name'
|
||||||
'id'
|
'id'
|
||||||
'description'
|
|
||||||
'datacenter_id'
|
'datacenter_id'
|
||||||
'''
|
'''
|
||||||
clKey = self.__getKey('o-cluster'+clusterId)
|
clKey = self.__getKey('o-cluster'+clusterId)
|
||||||
@ -154,7 +206,12 @@ class Client(object):
|
|||||||
|
|
||||||
c = api.clusters.get(id=clusterId)
|
c = api.clusters.get(id=clusterId)
|
||||||
|
|
||||||
res = { 'name' : c.get_name(), 'id' : c.get_id(), 'datacenter_id' : c.get_data_center().get_id() }
|
dc = c.get_data_center()
|
||||||
|
|
||||||
|
if dc is not None:
|
||||||
|
dc = dc.get_id()
|
||||||
|
|
||||||
|
res = { 'name' : c.get_name(), 'id' : c.get_id(), 'datacenter_id' : dc }
|
||||||
self._cache.put(clKey, res, Client.CACHE_TIME_HIGH)
|
self._cache.put(clKey, res, Client.CACHE_TIME_HIGH)
|
||||||
return res
|
return res
|
||||||
finally:
|
finally:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user