forked from shaba/openuds
Backport for ovirt 4.0
This commit is contained in:
parent
efc59c0124
commit
f924604217
@ -41,7 +41,7 @@ from uds.core.ui import gui
|
||||
|
||||
import logging
|
||||
|
||||
__updated__ = '2016-06-04'
|
||||
__updated__ = '2016-09-11'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -171,7 +171,7 @@ class OVirtLinkedService(Service):
|
||||
values=[
|
||||
gui.choiceItem('disabled', 'disabled'),
|
||||
gui.choiceItem('native', 'native'),
|
||||
gui.choiceItem('legacy', 'legacy')
|
||||
gui.choiceItem('legacy', 'legacy (deprecated)')
|
||||
],
|
||||
defvalue='1' # Default value is the ID of the choicefield
|
||||
)
|
||||
|
@ -41,11 +41,11 @@ from uds.core.util import validators
|
||||
|
||||
from .OVirtLinkedService import OVirtLinkedService
|
||||
|
||||
from .client import oVirtClient
|
||||
from . import client
|
||||
|
||||
import logging
|
||||
|
||||
__updated__ = '2016-06-04'
|
||||
__updated__ = '2016-09-11'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -93,7 +93,20 @@ class Provider(ServiceProvider):
|
||||
# but used for sample purposes
|
||||
# If we don't indicate an order, the output order of fields will be
|
||||
# "random"
|
||||
host = gui.TextField(length=64, label=_('Host'), order=1, tooltip=_('oVirt Server IP or Hostname'), required=True)
|
||||
ovirtVersion = gui.ChoiceField(order=1,
|
||||
label=_('oVirt Version'),
|
||||
tooltip=_('oVirt Server Version'),
|
||||
# In this case, the choice can have none value selected by default
|
||||
required=True,
|
||||
rdonly=False,
|
||||
values=[
|
||||
gui.choiceItem('3', '3.x'),
|
||||
gui.choiceItem('4', '4.x'),
|
||||
],
|
||||
defvalue='4' # Default value is the ID of the choicefield
|
||||
)
|
||||
|
||||
host = gui.TextField(length=64, label=_('Host'), order=2, tooltip=_('oVirt Server IP or Hostname'), required=True)
|
||||
username = gui.TextField(length=32, label=_('Username'), order=3, tooltip=_('User with valid privileges on oVirt, (use "user@domain" form)'), required=True, defvalue='admin@internal')
|
||||
password = gui.PasswordField(lenth=32, label=_('Password'), order=4, tooltip=_('Password of the user of oVirt'), required=True)
|
||||
|
||||
@ -116,7 +129,8 @@ class Provider(ServiceProvider):
|
||||
Returns the connection API object for oVirt (using ovirtsdk)
|
||||
'''
|
||||
if self._api is None:
|
||||
self._api = oVirtClient.Client(self.host.value, self.username.value, self.password.value, self.timeout.value, self.cache)
|
||||
APIClass = self._api = client.getClient(self.ovirtVersion.value)
|
||||
self._api = APIClass(self.host.value, self.username.value, self.password.value, self.timeout.value, self.cache)
|
||||
return self._api
|
||||
|
||||
# There is more fields type, but not here the best place to cover it
|
||||
|
@ -0,0 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2016 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from . import oVirtClient3;
|
||||
from . import oVirtClient4;
|
||||
|
||||
import logging
|
||||
|
||||
__updated__ = '2016-09-11'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def getClient(forVersion):
|
||||
logger.debug('For Version: {}'.format(forVersion))
|
||||
if forVersion == '3':
|
||||
return oVirtClient3.Client;
|
||||
else:
|
||||
return oVirtClient4.Client;
|
||||
|
@ -11,7 +11,7 @@ import threading
|
||||
import logging
|
||||
import re
|
||||
|
||||
__updated__ = '2016-06-04'
|
||||
__updated__ = '2016-09-11'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
695
server/src/uds/services/OVirt/client/oVirtClient4.py
Normal file
695
server/src/uds/services/OVirt/client/oVirtClient4.py
Normal file
@ -0,0 +1,695 @@
|
||||
'''
|
||||
Created on Nov 14, 2012
|
||||
|
||||
@author: dkmaster
|
||||
'''
|
||||
|
||||
import ovirtsdk4 as ovirt
|
||||
import ovirtsdk4.types
|
||||
|
||||
import threading
|
||||
import logging
|
||||
import re
|
||||
|
||||
__updated__ = '2016-09-11'
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
lock = threading.Lock()
|
||||
|
||||
cached_api = None
|
||||
cached_api_key = None
|
||||
|
||||
|
||||
class Client(object):
|
||||
'''
|
||||
Module to manage oVirt connections using ovirtsdk.
|
||||
|
||||
Due to the fact that we can't create two proxy connections at same time, we serialize all access to ovirt platform.
|
||||
Only one request and one live connection can exists at a time.
|
||||
|
||||
This can waste a lot of time, so use of cache here is more than important to achieve aceptable performance.
|
||||
|
||||
'''
|
||||
|
||||
CACHE_TIME_LOW = 60 * 5 # Cache time for requests are 5 minutes by default
|
||||
CACHE_TIME_HIGH = 60 * 30 # Cache time for requests that are less probable to change (as cluster perteinance of a machine)
|
||||
|
||||
def __getKey(self, prefix=''):
|
||||
'''
|
||||
Creates a key for the cache, using the prefix indicated as part of it
|
||||
|
||||
Returns:
|
||||
The cache key, taking into consideration the prefix
|
||||
'''
|
||||
return prefix + self._host + self._username + self._password + str(self._timeout)
|
||||
|
||||
def __getApi(self):
|
||||
'''
|
||||
Gets the api connection.
|
||||
|
||||
Again, due to the fact that ovirtsdk don't allow (at this moment, but it's on the "TODO" list) concurrent access to
|
||||
more than one server, we keep only one opened connection.
|
||||
|
||||
Must be accesed "locked", so we can safely alter cached_api and cached_api_key
|
||||
'''
|
||||
global cached_api, cached_api_key
|
||||
aKey = self.__getKey('o-host')
|
||||
# if cached_api_key == aKey:
|
||||
# return cached_api
|
||||
|
||||
if cached_api is not None:
|
||||
try:
|
||||
cached_api.close()
|
||||
except:
|
||||
# Nothing happens, may it was already disconnected
|
||||
pass
|
||||
try:
|
||||
cached_api_key = aKey
|
||||
cached_api = ovirt.Connection(url='https://' + self._host + '/ovirt-engine/api', username=self._username, password=self._password, timeout=self._timeout, insecure=True, debug=True)
|
||||
return cached_api
|
||||
except:
|
||||
logger.exception('Exception connection ovirt at {0}'.format(self._host))
|
||||
cached_api_key = None
|
||||
raise Exception("Can't connet to server at {0}".format(self._host))
|
||||
return None
|
||||
|
||||
def __init__(self, host, username, password, timeout, cache):
|
||||
self._host = host
|
||||
self._username = username
|
||||
self._password = password
|
||||
self._timeout = int(timeout)
|
||||
self._cache = cache
|
||||
|
||||
def test(self):
|
||||
try:
|
||||
lock.acquire(True)
|
||||
return self.__getApi().test()
|
||||
except Exception as e:
|
||||
logger.error('Testing Server failed: {0}'.format(e))
|
||||
return False
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
|
||||
def isFullyFunctionalVersion(self):
|
||||
'''
|
||||
'4.0 version is always functional (right now...)
|
||||
'''
|
||||
return [True, 'Test successfully passed']
|
||||
|
||||
def getVms(self, force=False):
|
||||
'''
|
||||
Obtains the list of machines inside ovirt that do aren't part of uds
|
||||
|
||||
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'
|
||||
|
||||
'''
|
||||
vmsKey = self.__getKey('o-vms')
|
||||
val = self._cache.get(vmsKey)
|
||||
|
||||
if val is not None and force is False:
|
||||
return val
|
||||
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
vms = api.system_service().vms_service().list()
|
||||
|
||||
logger.debug('oVirt VMS: {}'.format(vms))
|
||||
|
||||
res = []
|
||||
|
||||
for vm in vms:
|
||||
try:
|
||||
pair = [vm.usb.enabled, vm.usb.type.value]
|
||||
except:
|
||||
pair = [False, '']
|
||||
res.append({'name': vm.name, 'id': vm.id, 'cluster_id': vm.cluster.id, 'usb': pair })
|
||||
|
||||
self._cache.put(vmsKey, res, Client.CACHE_TIME_LOW)
|
||||
|
||||
return res
|
||||
|
||||
finally:
|
||||
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.system_service().clusters_service().list()
|
||||
|
||||
res = []
|
||||
|
||||
for cluster in clusters:
|
||||
dc = cluster.data_center
|
||||
|
||||
if dc is not None:
|
||||
dc = dc.id
|
||||
|
||||
val = {'name': cluster.name, 'id': cluster.id, 'datacenter_id': dc}
|
||||
|
||||
# Updates cache info for every single cluster
|
||||
clKey = self.__getKey('o-cluster' + cluster.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):
|
||||
'''
|
||||
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'
|
||||
'''
|
||||
clKey = self.__getKey('o-cluster' + clusterId)
|
||||
val = self._cache.get(clKey)
|
||||
|
||||
if val is not None and force is False:
|
||||
return val
|
||||
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
c = api.system_service().clusters_service().service(clusterId).get()
|
||||
|
||||
dc = c.data_center
|
||||
|
||||
if dc is not None:
|
||||
dc = dc.id
|
||||
|
||||
res = {'name': c.name, 'id': c.id, 'datacenter_id': dc}
|
||||
self._cache.put(clKey, res, Client.CACHE_TIME_HIGH)
|
||||
return res
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
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
|
||||
|
||||
'''
|
||||
dcKey = self.__getKey('o-dc' + datacenterId)
|
||||
val = self._cache.get(dcKey)
|
||||
|
||||
if val is not None and force is False:
|
||||
return val
|
||||
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
datacenter_service = api.system_service().data_centers_service().service(datacenterId)
|
||||
d = datacenter_service.get()
|
||||
|
||||
storage = []
|
||||
for dd in datacenter_service.storage_domains_service().list():
|
||||
try:
|
||||
active = dd.status.value
|
||||
except:
|
||||
active = 'inactive'
|
||||
|
||||
storage.append({'id': dd.id, 'name': dd.name, 'type': dd.type.value,
|
||||
'available': dd.available, 'used': dd.used,
|
||||
'active': active == 'active'})
|
||||
|
||||
res = {'name': d.name, 'id': d.id, 'storage_type': d.local and 'local' or 'shared',
|
||||
'storage_format': d.storage_format.value, 'description': d.description,
|
||||
'storage': storage}
|
||||
|
||||
self._cache.put(dcKey, res, Client.CACHE_TIME_HIGH)
|
||||
return res
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
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)
|
||||
|
||||
'''
|
||||
sdKey = self.__getKey('o-sd' + storageId)
|
||||
val = self._cache.get(sdKey)
|
||||
|
||||
if val is not None and force is False:
|
||||
return val
|
||||
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
dd = api.system_service().storage_domains_service().service(storageId).get()
|
||||
|
||||
res = {
|
||||
'id': dd.id,
|
||||
'name': dd.name,
|
||||
'type': dd.type.value,
|
||||
'available': dd.available,
|
||||
'used': dd.used
|
||||
}
|
||||
|
||||
self._cache.put(sdKey, res, Client.CACHE_TIME_LOW)
|
||||
return res
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
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!!!)
|
||||
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.
|
||||
'''
|
||||
logger.debug("n: {0}, c: {1}, vm: {2}, cl: {3}, st: {4}, dt: {5}".format(name, comments, machineId, clusterId, storageId, displayType))
|
||||
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
# cluster = ov.clusters_service().service('00000002-0002-0002-0002-0000000002e4') # .get()
|
||||
# vm = ov.vms_service().service('e7ff4e00-b175-4e80-9c1f-e50a5e76d347') # .get()
|
||||
|
||||
vms = api.system_service().vms_service().service(machineId)
|
||||
|
||||
cluster = api.system_service().clusters_service().service(clusterId).get()
|
||||
vm = vms.get()
|
||||
|
||||
if vm is None:
|
||||
raise Exception('Machine not found')
|
||||
|
||||
if cluster is None:
|
||||
raise Exception('Cluster not found')
|
||||
|
||||
if vm.status.value != 'down':
|
||||
raise Exception('Machine must be in down state to publish it')
|
||||
|
||||
# sd = [ovirt.types.StorageDomain(id=storageId)]
|
||||
# dsks = []
|
||||
# for dsk in vms.disk_attachments_service().list():
|
||||
# dsks = None
|
||||
# dsks.append(params.Disk(id=dsk.get_id(), storage_domains=sd, alias=dsk.get_alias()))
|
||||
# dsks.append(dsk)
|
||||
|
||||
tvm = ovirt.types.Vm(id=vm.id)
|
||||
tcluster = ovirt.types.Cluster(id=cluster.id)
|
||||
|
||||
template = ovirt.types.Template(
|
||||
name=name,
|
||||
vm=tvm,
|
||||
cluster=tcluster,
|
||||
description=comments
|
||||
)
|
||||
|
||||
# display=display)
|
||||
|
||||
return api.system_service().templates_service().add(template).id
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
def getTemplateState(self, templateId):
|
||||
'''
|
||||
Returns current template state.
|
||||
This method do not uses cache at all (it always tries to get template state from oVirt server)
|
||||
|
||||
Returned values could be:
|
||||
ok
|
||||
locked
|
||||
removed
|
||||
|
||||
(don't know if ovirt returns something more right now, will test what happens when template can't be published)
|
||||
'''
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
template = api.system_service().templates_service().service(templateId).get()
|
||||
|
||||
if template is None:
|
||||
return 'removed'
|
||||
|
||||
return template.status.value
|
||||
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
def deployFromTemplate(self, name, comments, templateId, clusterId, displayType, usbType, memoryMB, guaranteedMB):
|
||||
'''
|
||||
Deploys a virtual machine on selected cluster from selected template
|
||||
|
||||
Args:
|
||||
name: Name (sanitized) of the machine
|
||||
comments: Comments for machine
|
||||
templateId: Id of the template to deploy from
|
||||
clusterId: Id of the cluster to deploy to
|
||||
displayType: 'vnc' or 'spice'. Display to use ad oVirt admin interface
|
||||
memoryMB: Memory requested for machine, in MB
|
||||
guaranteedMB: Minimum memory guaranteed for this machine
|
||||
|
||||
Returns:
|
||||
Id of the machine being created form template
|
||||
'''
|
||||
logger.debug('Deploying machine with name "{0}" from template {1} at cluster {2} with display {3} and usb {4}, memory {5} and guaranteed {6}'.format(
|
||||
name, templateId, clusterId, displayType, usbType, memoryMB, guaranteedMB))
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
logger.debug('Deploying machine {0}'.format(name))
|
||||
|
||||
cluster = ovirt.types.Cluster(id=clusterId)
|
||||
template = ovirt.types.Template(id=templateId)
|
||||
if usbType in ('native', 'legacy'):
|
||||
usb = ovirt.types.Usb(enabled=True, type=ovirt.types.UsbType.NATIVE if usbType == 'native' else ovirt.types.UsbType.LEGACY)
|
||||
else:
|
||||
usb = ovirt.types.Usb(enabled=False)
|
||||
|
||||
memoryPolicy = ovirt.types.MemoryPolicy(guaranteed=guaranteedMB * 1024 * 1024)
|
||||
par = ovirt.types.Vm(name=name, cluster=cluster, template=template, description=comments,
|
||||
type=ovirt.types.VmType.DESKTOP, memory=memoryMB * 1024 * 1024, memory_policy=memoryPolicy,
|
||||
usb=usb) # display=display,
|
||||
|
||||
return api.system_service().vms_service().add(par).id
|
||||
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
def removeTemplate(self, templateId):
|
||||
'''
|
||||
Removes a template from ovirt server
|
||||
|
||||
Returns nothing, and raises an Exception if it fails
|
||||
'''
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
api.system_service().templates_service().service(templateId).remove()
|
||||
# This returns nothing, if it fails it raises an exception
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
def getMachineState(self, machineId):
|
||||
'''
|
||||
Returns current state of a machine (running, suspended, ...).
|
||||
This method do not uses cache at all (it always tries to get machine state from oVirt server)
|
||||
|
||||
Args:
|
||||
machineId: Id of the machine to get status
|
||||
|
||||
Returns:
|
||||
one of this values:
|
||||
unassigned, down, up, powering_up, powered_down,
|
||||
paused, migrating_from, migrating_to, unknown, not_responding,
|
||||
wait_for_launch, reboot_in_progress, saving_state, restoring_state,
|
||||
suspended, image_illegal, image_locked or powering_down
|
||||
Also can return'unknown' if Machine is not known
|
||||
'''
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
vm = api.system_service().vms_service().service(machineId).get()
|
||||
|
||||
if vm is None or vm.status is None:
|
||||
return 'unknown'
|
||||
|
||||
return vm.status.value
|
||||
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
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:
|
||||
'''
|
||||
try:
|
||||
lock.acquire(True)
|
||||
|
||||
api = self.__getApi()
|
||||
|
||||
|
||||
vmService = api.system_service().vms_service().service(machineId)
|
||||
|
||||
if vmService.get() is None:
|
||||
raise Exception('Machine not found')
|
||||
|
||||
vmService.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()
|
||||
|
||||
vmService = api.system_service().vms_service().service(machineId)
|
||||
|
||||
if vmService.get() is None:
|
||||
raise Exception('Machine not found')
|
||||
|
||||
vmService.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()
|
||||
|
||||
vmService = api.system_service().vms_service().service(machineId)
|
||||
|
||||
if vmService.get() is None:
|
||||
raise Exception('Machine not found')
|
||||
|
||||
vmService.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()
|
||||
|
||||
vmService = api.system_service().vms_service().service(machineId)
|
||||
|
||||
if vmService.get() is None:
|
||||
raise Exception('Machine not found')
|
||||
|
||||
vmService.remove()
|
||||
|
||||
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()
|
||||
|
||||
vmService = api.system_service().vms_service().service(machineId)
|
||||
|
||||
if vmService.get() is None:
|
||||
raise Exception('Machine not found')
|
||||
|
||||
nic = vmService.nics_service().list()[0] # If has no nic, will raise an exception (IndexError)
|
||||
nic.mac.address = macAddres
|
||||
nicService = vmService.nics_service().service(nic.id)
|
||||
nicService.update(nic)
|
||||
except IndexError:
|
||||
raise Exception('Machine do not have network interfaces!!')
|
||||
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
def getConsoleConnection(self, machineId):
|
||||
'''
|
||||
Gets the connetion info for the specified machine
|
||||
'''
|
||||
try:
|
||||
lock.acquire(True)
|
||||
api = self.__getApi()
|
||||
|
||||
vmService = api.system_service().vms_service().service(machineId)
|
||||
vm = vmService.get()
|
||||
|
||||
if vm is None:
|
||||
raise Exception('Machine not found')
|
||||
|
||||
display = vm.display
|
||||
ticket = vmService.ticket()
|
||||
|
||||
# Get host subject
|
||||
cert_subject = ''
|
||||
if display.certificate != None:
|
||||
cert_subject = display.certificate.subject
|
||||
else:
|
||||
for i in api.system_service().hosts_service().list():
|
||||
for k in api.system_service().hosts_service().service(i.id).nics_service().list():
|
||||
if k.ip.address == display.address:
|
||||
cert_subject = i.certificate.subject
|
||||
break
|
||||
# If found
|
||||
if cert_subject != '':
|
||||
break
|
||||
|
||||
return {
|
||||
'type': display.type.value,
|
||||
'address': display.address,
|
||||
'port': display.port,
|
||||
'secure_port': display.secure_port,
|
||||
'monitors': display.monitors,
|
||||
'cert_subject': cert_subject,
|
||||
'ticket': {
|
||||
'value': ticket.value,
|
||||
'expiry': ticket.expiry
|
||||
}
|
||||
}
|
||||
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
def desktopLogin(self, machineId, username, password, domain):
|
||||
pass
|
Loading…
Reference in New Issue
Block a user