forked from shaba/openuds
Fixed Xen to work correctly with 3.7
This commit is contained in:
parent
d7ac1f590a
commit
083b1f21fd
@ -14,7 +14,6 @@ paramiko
|
|||||||
defusedxml
|
defusedxml
|
||||||
python-dateutil
|
python-dateutil
|
||||||
requests
|
requests
|
||||||
XenAPI
|
|
||||||
WeasyPrint
|
WeasyPrint
|
||||||
webencodings
|
webencodings
|
||||||
xml-marshaller
|
xml-marshaller
|
||||||
|
@ -95,6 +95,7 @@ class XenLinkedDeployment(UserDeployment):
|
|||||||
Does nothing here also, all data are keeped at environment storage
|
Does nothing here also, all data are keeped at environment storage
|
||||||
"""
|
"""
|
||||||
vals = str_.split(b'\1')
|
vals = str_.split(b'\1')
|
||||||
|
logger.debug('Values: %s', vals)
|
||||||
if vals[0] == b'v1':
|
if vals[0] == b'v1':
|
||||||
self._name = vals[1].decode('utf8')
|
self._name = vals[1].decode('utf8')
|
||||||
self._ip = vals[2].decode('utf8')
|
self._ip = vals[2].decode('utf8')
|
||||||
|
264
server/src/uds/services/Xen/xen_client/XenAPI.py
Normal file
264
server/src/uds/services/Xen/xen_client/XenAPI.py
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
# Copyright (c) Citrix Systems, Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are
|
||||||
|
# met:
|
||||||
|
#
|
||||||
|
# 1) Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# 2) 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.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
# --------------------------------------------------------------------
|
||||||
|
# Parts of this file are based upon xmlrpclib.py, the XML-RPC client
|
||||||
|
# interface included in the Python distribution.
|
||||||
|
#
|
||||||
|
# Copyright (c) 1999-2002 by Secret Labs AB
|
||||||
|
# Copyright (c) 1999-2002 by Fredrik Lundh
|
||||||
|
#
|
||||||
|
# By obtaining, using, and/or copying this software and/or its
|
||||||
|
# associated documentation, you agree that you have read, understood,
|
||||||
|
# and will comply with the following terms and conditions:
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and distribute this software and
|
||||||
|
# its associated documentation for any purpose and without fee is
|
||||||
|
# hereby granted, provided that the above copyright notice appears in
|
||||||
|
# all copies, and that both that copyright notice and this permission
|
||||||
|
# notice appear in supporting documentation, and that the name of
|
||||||
|
# Secret Labs AB or the author not be used in advertising or publicity
|
||||||
|
# pertaining to distribution of the software without specific, written
|
||||||
|
# prior permission.
|
||||||
|
#
|
||||||
|
# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||||
|
# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
|
||||||
|
# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
|
||||||
|
# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
|
||||||
|
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||||
|
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
# OF THIS SOFTWARE.
|
||||||
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
|
import gettext
|
||||||
|
import six.moves.xmlrpc_client as xmlrpclib
|
||||||
|
import six.moves.http_client as httplib
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
|
||||||
|
translation = gettext.translation('xen-xm', fallback = True)
|
||||||
|
|
||||||
|
API_VERSION_1_1 = '1.1'
|
||||||
|
API_VERSION_1_2 = '1.2'
|
||||||
|
|
||||||
|
class Failure(Exception):
|
||||||
|
def __init__(self, details):
|
||||||
|
self.details = details
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
try:
|
||||||
|
return str(self.details)
|
||||||
|
except Exception as exn:
|
||||||
|
msg = "Xen-API failure: %s" % exn
|
||||||
|
sys.stderr.write(msg)
|
||||||
|
return msg
|
||||||
|
|
||||||
|
def _details_map(self):
|
||||||
|
return dict([(str(i), self.details[i])
|
||||||
|
for i in range(len(self.details))])
|
||||||
|
|
||||||
|
|
||||||
|
# Just a "constant" that we use to decide whether to retry the RPC
|
||||||
|
_RECONNECT_AND_RETRY = object()
|
||||||
|
|
||||||
|
class UDSHTTPConnection(httplib.HTTPConnection):
|
||||||
|
"""HTTPConnection subclass to allow HTTP over Unix domain sockets. """
|
||||||
|
def connect(self):
|
||||||
|
path = self.host.replace("_", "/")
|
||||||
|
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
|
self.sock.connect(path)
|
||||||
|
|
||||||
|
class UDSHTTP(httplib.HTTPConnection):
|
||||||
|
_connection_class = UDSHTTPConnection
|
||||||
|
|
||||||
|
class UDSTransport(xmlrpclib.Transport):
|
||||||
|
def __init__(self, use_datetime=0):
|
||||||
|
self._use_datetime = use_datetime
|
||||||
|
self._extra_headers=[]
|
||||||
|
self._connection = (None, None)
|
||||||
|
def add_extra_header(self, key, value):
|
||||||
|
self._extra_headers += [ (key,value) ]
|
||||||
|
def make_connection(self, host):
|
||||||
|
# Python 2.4 compatibility
|
||||||
|
if sys.version_info[0] <= 2 and sys.version_info[1] < 7:
|
||||||
|
return UDSHTTP(host)
|
||||||
|
else:
|
||||||
|
return UDSHTTPConnection(host)
|
||||||
|
def send_request(self, connection, handler, request_body):
|
||||||
|
connection.putrequest("POST", handler)
|
||||||
|
for key, value in self._extra_headers:
|
||||||
|
connection.putheader(key, value)
|
||||||
|
|
||||||
|
class Session(xmlrpclib.ServerProxy):
|
||||||
|
"""A server proxy and session manager for communicating with xapi using
|
||||||
|
the Xen-API.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
session = Session('http://localhost/')
|
||||||
|
session.login_with_password('me', 'mypassword', '1.0', 'xen-api-scripts-xenapi.py')
|
||||||
|
session.xenapi.VM.start(vm_uuid)
|
||||||
|
session.xenapi.session.logout()
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, uri, transport=None, encoding=None, verbose=0,
|
||||||
|
allow_none=1, ignore_ssl=False):
|
||||||
|
|
||||||
|
# Fix for CA-172901 (+ Python 2.4 compatibility)
|
||||||
|
# Fix for context=ctx ( < Python 2.7.9 compatibility)
|
||||||
|
if not (sys.version_info[0] <= 2 and sys.version_info[1] <= 7 and sys.version_info[2] <= 9 ) \
|
||||||
|
and ignore_ssl:
|
||||||
|
import ssl
|
||||||
|
ctx = ssl._create_unverified_context()
|
||||||
|
xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
|
||||||
|
verbose, allow_none, context=ctx)
|
||||||
|
else:
|
||||||
|
xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
|
||||||
|
verbose, allow_none)
|
||||||
|
self.transport = transport
|
||||||
|
self._session = None
|
||||||
|
self.last_login_method = None
|
||||||
|
self.last_login_params = None
|
||||||
|
self.API_version = API_VERSION_1_1
|
||||||
|
|
||||||
|
|
||||||
|
def xenapi_request(self, methodname, params):
|
||||||
|
if methodname.startswith('login'):
|
||||||
|
self._login(methodname, params)
|
||||||
|
return None
|
||||||
|
elif methodname == 'logout' or methodname == 'session.logout':
|
||||||
|
self._logout()
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
retry_count = 0
|
||||||
|
while retry_count < 3:
|
||||||
|
full_params = (self._session,) + params
|
||||||
|
result = _parse_result(getattr(self, methodname)(*full_params))
|
||||||
|
if result is _RECONNECT_AND_RETRY:
|
||||||
|
retry_count += 1
|
||||||
|
if self.last_login_method:
|
||||||
|
self._login(self.last_login_method,
|
||||||
|
self.last_login_params)
|
||||||
|
else:
|
||||||
|
raise xmlrpclib.Fault(401, 'You must log in')
|
||||||
|
else:
|
||||||
|
return result
|
||||||
|
raise xmlrpclib.Fault(
|
||||||
|
500, 'Tried 3 times to get a valid session, but failed')
|
||||||
|
|
||||||
|
def _login(self, method, params):
|
||||||
|
try:
|
||||||
|
result = _parse_result(
|
||||||
|
getattr(self, 'session.%s' % method)(*params))
|
||||||
|
if result is _RECONNECT_AND_RETRY:
|
||||||
|
raise xmlrpclib.Fault(
|
||||||
|
500, 'Received SESSION_INVALID when logging in')
|
||||||
|
self._session = result
|
||||||
|
self.last_login_method = method
|
||||||
|
self.last_login_params = params
|
||||||
|
self.API_version = self._get_api_version()
|
||||||
|
except socket.error as e:
|
||||||
|
if e.errno == socket.errno.ETIMEDOUT:
|
||||||
|
raise xmlrpclib.Fault(504, 'The connection timed out')
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def _logout(self):
|
||||||
|
try:
|
||||||
|
if self.last_login_method.startswith("slave_local"):
|
||||||
|
return _parse_result(self.session.local_logout(self._session))
|
||||||
|
else:
|
||||||
|
return _parse_result(self.session.logout(self._session))
|
||||||
|
finally:
|
||||||
|
self._session = None
|
||||||
|
self.last_login_method = None
|
||||||
|
self.last_login_params = None
|
||||||
|
self.API_version = API_VERSION_1_1
|
||||||
|
|
||||||
|
def _get_api_version(self):
|
||||||
|
pool = self.xenapi.pool.get_all()[0]
|
||||||
|
host = self.xenapi.pool.get_master(pool)
|
||||||
|
major = self.xenapi.host.get_API_version_major(host)
|
||||||
|
minor = self.xenapi.host.get_API_version_minor(host)
|
||||||
|
return "%s.%s"%(major,minor)
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
if name == 'handle':
|
||||||
|
return self._session
|
||||||
|
elif name == 'xenapi':
|
||||||
|
return _Dispatcher(self.API_version, self.xenapi_request, None)
|
||||||
|
elif name.startswith('login') or name.startswith('slave_local'):
|
||||||
|
return lambda *params: self._login(name, params)
|
||||||
|
elif name == 'logout':
|
||||||
|
return _Dispatcher(self.API_version, self.xenapi_request, "logout")
|
||||||
|
else:
|
||||||
|
return xmlrpclib.ServerProxy.__getattr__(self, name)
|
||||||
|
|
||||||
|
def xapi_local():
|
||||||
|
return Session("http://_var_lib_xcp_xapi/", transport=UDSTransport())
|
||||||
|
|
||||||
|
def _parse_result(result):
|
||||||
|
if type(result) != dict or 'Status' not in result:
|
||||||
|
raise xmlrpclib.Fault(500, 'Missing Status in response from server' + result)
|
||||||
|
if result['Status'] == 'Success':
|
||||||
|
if 'Value' in result:
|
||||||
|
return result['Value']
|
||||||
|
else:
|
||||||
|
raise xmlrpclib.Fault(500,
|
||||||
|
'Missing Value in response from server')
|
||||||
|
else:
|
||||||
|
if 'ErrorDescription' in result:
|
||||||
|
if result['ErrorDescription'][0] == 'SESSION_INVALID':
|
||||||
|
return _RECONNECT_AND_RETRY
|
||||||
|
else:
|
||||||
|
raise Failure(result['ErrorDescription'])
|
||||||
|
else:
|
||||||
|
raise xmlrpclib.Fault(
|
||||||
|
500, 'Missing ErrorDescription in response from server')
|
||||||
|
|
||||||
|
|
||||||
|
# Based upon _Method from xmlrpclib.
|
||||||
|
class _Dispatcher:
|
||||||
|
def __init__(self, API_version, send, name):
|
||||||
|
self.__API_version = API_version
|
||||||
|
self.__send = send
|
||||||
|
self.__name = name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if self.__name:
|
||||||
|
return '<XenAPI._Dispatcher for %s>' % self.__name
|
||||||
|
else:
|
||||||
|
return '<XenAPI._Dispatcher>'
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
if self.__name is None:
|
||||||
|
return _Dispatcher(self.__API_version, self.__send, name)
|
||||||
|
else:
|
||||||
|
return _Dispatcher(self.__API_version, self.__send, "%s.%s" % (self.__name, name))
|
||||||
|
|
||||||
|
def __call__(self, *args):
|
||||||
|
return self.__send(self.__name, args)
|
@ -28,8 +28,8 @@
|
|||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import six
|
import xmlrpc.client
|
||||||
import XenAPI # From PIP, will remove this when dropped Python 2.7 support
|
from . import XenAPI # From PIP, will remove this when dropped Python 2.7 support
|
||||||
|
|
||||||
import ssl
|
import ssl
|
||||||
|
|
||||||
@ -40,7 +40,6 @@ logger = logging.getLogger(__name__)
|
|||||||
TAG_TEMPLATE = "uds-template"
|
TAG_TEMPLATE = "uds-template"
|
||||||
TAG_MACHINE = "uds-machine"
|
TAG_MACHINE = "uds-machine"
|
||||||
|
|
||||||
|
|
||||||
class XenFault(Exception):
|
class XenFault(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -105,7 +104,7 @@ class XenServer(object):
|
|||||||
|
|
||||||
def __init__(self, host, port, username, password, useSSL=False, verifySSL=False):
|
def __init__(self, host, port, username, password, useSSL=False, verifySSL=False):
|
||||||
self._originalHost = self._host = host
|
self._originalHost = self._host = host
|
||||||
self._port = six.text_type(port)
|
self._port = str(port)
|
||||||
self._useSSL = useSSL and True or False
|
self._useSSL = useSSL and True or False
|
||||||
self._verifySSL = verifySSL and True or False
|
self._verifySSL = verifySSL and True or False
|
||||||
self._protocol = 'http' + (self._useSSL and 's' or '') + '://'
|
self._protocol = 'http' + (self._useSSL and 's' or '') + '://'
|
||||||
@ -131,7 +130,7 @@ class XenServer(object):
|
|||||||
return getattr(self._session.xenapi, prop)
|
return getattr(self._session.xenapi, prop)
|
||||||
|
|
||||||
# Properties to fast access XenApi classes
|
# Properties to fast access XenApi classes
|
||||||
asnc = property(lambda self: self.getXenapiProperty('asnc'))
|
Async = property(lambda self: self.getXenapiProperty('Async'))
|
||||||
task = property(lambda self: self.getXenapiProperty('task'))
|
task = property(lambda self: self.getXenapiProperty('task'))
|
||||||
VM = property(lambda self: self.getXenapiProperty('VM'))
|
VM = property(lambda self: self.getXenapiProperty('VM'))
|
||||||
SR = property(lambda self: self.getXenapiProperty('SR'))
|
SR = property(lambda self: self.getXenapiProperty('SR'))
|
||||||
@ -155,19 +154,19 @@ class XenServer(object):
|
|||||||
def login(self, switchToMaster=False):
|
def login(self, switchToMaster=False):
|
||||||
try:
|
try:
|
||||||
self._url = self._protocol + self._host + ':' + self._port
|
self._url = self._protocol + self._host + ':' + self._port
|
||||||
# On python 2.7.9, HTTPS is verified by default,
|
# On modern python's, HTTPS is verified by default,
|
||||||
if self._useSSL and self._verifySSL is False:
|
if self._useSSL:
|
||||||
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) # @UndefinedVariable
|
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
|
||||||
context.verify_mode = ssl.CERT_NONE
|
if self._verifySSL is False:
|
||||||
transport = six.moves.xmlrpc_client.SafeTransport(context=context)
|
context.verify_mode = ssl.CERT_NONE
|
||||||
else:
|
transport = xmlrpc.client.SafeTransport(context=context)
|
||||||
transport = None
|
logger.debug('Transport: %s', transport)
|
||||||
|
|
||||||
self._session = XenAPI.Session(self._url, transport=transport)
|
self._session = XenAPI.Session(self._url, transport=transport)
|
||||||
self._session.xenapi.login_with_password(self._username, self._password)
|
self._session.xenapi.login_with_password(self._username, self._password)
|
||||||
self._loggedIn = True
|
self._loggedIn = True
|
||||||
self._apiVersion = self._session.API_version
|
self._apiVersion = self._session.API_version
|
||||||
self._poolName = six.text_type(self.getPoolName())
|
self._poolName = str(self.getPoolName())
|
||||||
except XenAPI.Failure as e: # XenAPI.Failure: ['HOST_IS_SLAVE', '172.27.0.29'] indicates that this host is an slave of 172.27.0.29, connect to it...
|
except XenAPI.Failure as e: # XenAPI.Failure: ['HOST_IS_SLAVE', '172.27.0.29'] indicates that this host is an slave of 172.27.0.29, connect to it...
|
||||||
if switchToMaster and e.details[0] == 'HOST_IS_SLAVE':
|
if switchToMaster and e.details[0] == 'HOST_IS_SLAVE':
|
||||||
logger.info('{0} is an Slave, connecting to master at {1} cause switchToMaster is True'.format(self._host, e.details[1]))
|
logger.info('{0} is an Slave, connecting to master at {1} cause switchToMaster is True'.format(self._host, e.details[1]))
|
||||||
@ -175,6 +174,9 @@ class XenServer(object):
|
|||||||
self.login()
|
self.login()
|
||||||
else:
|
else:
|
||||||
raise XenFailure(e.details)
|
raise XenFailure(e.details)
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception('Unrecognized xenapi exception')
|
||||||
|
raise
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
self.login(False)
|
self.login(False)
|
||||||
@ -219,7 +221,7 @@ class XenServer(object):
|
|||||||
status = 'failure'
|
status = 'failure'
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception('Unexpected exception!')
|
logger.exception('Unexpected exception!')
|
||||||
result = six.text_type(e)
|
result = str(e)
|
||||||
status = 'failure'
|
status = 'failure'
|
||||||
|
|
||||||
# Removes <value></value> if present
|
# Removes <value></value> if present
|
||||||
@ -230,9 +232,9 @@ class XenServer(object):
|
|||||||
try:
|
try:
|
||||||
self.task.destroy(task)
|
self.task.destroy(task)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.info('Task {0} returned error {1}'.format(task, six.text_type(e)))
|
logger.info('Task {0} returned error {1}'.format(task, str(e)))
|
||||||
|
|
||||||
return {'result': result, 'progress': progress, 'status': six.text_type(status)}
|
return {'result': result, 'progress': progress, 'status':str(status)}
|
||||||
|
|
||||||
def getSRs(self):
|
def getSRs(self):
|
||||||
for srId in self.SR.get_all():
|
for srId in self.SR.get_all():
|
||||||
@ -296,7 +298,7 @@ class XenServer(object):
|
|||||||
except XenAPI.Failure as e:
|
except XenAPI.Failure as e:
|
||||||
raise XenFailure(e.details)
|
raise XenFailure(e.details)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise XenException(six.text_type(e))
|
raise XenException(str(e))
|
||||||
|
|
||||||
def getVMPowerState(self, vmId):
|
def getVMPowerState(self, vmId):
|
||||||
try:
|
try:
|
||||||
@ -321,7 +323,7 @@ class XenServer(object):
|
|||||||
return self.resumeVM(vmId, asnc)
|
return self.resumeVM(vmId, asnc)
|
||||||
|
|
||||||
if asnc:
|
if asnc:
|
||||||
return self.asnc.VM.start(vmId, False, False)
|
return self.Async.VM.start(vmId, False, False)
|
||||||
return self.VM.start(vmId, False, False)
|
return self.VM.start(vmId, False, False)
|
||||||
|
|
||||||
def stopVM(self, vmId, asnc=True):
|
def stopVM(self, vmId, asnc=True):
|
||||||
@ -329,7 +331,7 @@ class XenServer(object):
|
|||||||
if vmState in (XenPowerState.suspended, XenPowerState.halted):
|
if vmState in (XenPowerState.suspended, XenPowerState.halted):
|
||||||
return None # Already powered off
|
return None # Already powered off
|
||||||
if asnc:
|
if asnc:
|
||||||
return self.asnc.VM.hard_shutdown(vmId)
|
return self.Async.VM.hard_shutdown(vmId)
|
||||||
return self.VM.hard_shutdown(vmId)
|
return self.VM.hard_shutdown(vmId)
|
||||||
|
|
||||||
def resetVM(self, vmId, asnc=True):
|
def resetVM(self, vmId, asnc=True):
|
||||||
@ -337,7 +339,7 @@ class XenServer(object):
|
|||||||
if vmState in (XenPowerState.suspended, XenPowerState.halted):
|
if vmState in (XenPowerState.suspended, XenPowerState.halted):
|
||||||
return None # Already powered off
|
return None # Already powered off
|
||||||
if asnc:
|
if asnc:
|
||||||
return self.asnc.VM.hard_reboot(vmId)
|
return self.Async.VM.hard_reboot(vmId)
|
||||||
return self.VM.hard_reboot(vmId)
|
return self.VM.hard_reboot(vmId)
|
||||||
|
|
||||||
def canSuspendVM(self, vmId):
|
def canSuspendVM(self, vmId):
|
||||||
@ -350,7 +352,7 @@ class XenServer(object):
|
|||||||
if vmState == XenPowerState.suspended:
|
if vmState == XenPowerState.suspended:
|
||||||
return None
|
return None
|
||||||
if asnc:
|
if asnc:
|
||||||
return self.asnc.VM.suspend(vmId)
|
return self.Async.VM.suspend(vmId)
|
||||||
return self.VM.suspend(vmId)
|
return self.VM.suspend(vmId)
|
||||||
|
|
||||||
def resumeVM(self, vmId, asnc=True):
|
def resumeVM(self, vmId, asnc=True):
|
||||||
@ -358,7 +360,7 @@ class XenServer(object):
|
|||||||
if vmState != XenPowerState.suspended:
|
if vmState != XenPowerState.suspended:
|
||||||
return None
|
return None
|
||||||
if asnc:
|
if asnc:
|
||||||
return self.asnc.VM.resume(vmId, False, False)
|
return self.Async.VM.resume(vmId, False, False)
|
||||||
return self.VM.resume(vmId, False, False)
|
return self.VM.resume(vmId, False, False)
|
||||||
|
|
||||||
def cloneVM(self, vmId, targetName, targetSR=None):
|
def cloneVM(self, vmId, targetName, targetSR=None):
|
||||||
@ -382,11 +384,11 @@ class XenServer(object):
|
|||||||
if targetSR:
|
if targetSR:
|
||||||
if 'copy' not in operations:
|
if 'copy' not in operations:
|
||||||
raise XenException('Copy is not supported for this machine')
|
raise XenException('Copy is not supported for this machine')
|
||||||
task = self.asnc.VM.copy(vmId, targetName, targetSR)
|
task = self.Async.VM.copy(vmId, targetName, targetSR)
|
||||||
else:
|
else:
|
||||||
if 'clone' not in operations:
|
if 'clone' not in operations:
|
||||||
raise XenException('Clone is not supported for this machine')
|
raise XenException('Clone is not supported for this machine')
|
||||||
task = self.asnc.VM.clone(vmId, targetName)
|
task = self.Async.VM.clone(vmId, targetName)
|
||||||
return task
|
return task
|
||||||
except XenAPI.Failure as e:
|
except XenAPI.Failure as e:
|
||||||
raise XenFailure(e.details)
|
raise XenFailure(e.details)
|
||||||
@ -446,7 +448,7 @@ class XenServer(object):
|
|||||||
if memory is not None:
|
if memory is not None:
|
||||||
logger.debug('Setting up memory to {0} MB'.format(memory))
|
logger.debug('Setting up memory to {0} MB'.format(memory))
|
||||||
# Convert memory to MB
|
# Convert memory to MB
|
||||||
memory = six.text_type(int(memory) * 1024 * 1024)
|
memory = str(int(memory) * 1024 * 1024)
|
||||||
self.VM.set_memory_limits(vmId, memory, memory, memory, memory)
|
self.VM.set_memory_limits(vmId, memory, memory, memory, memory)
|
||||||
except XenAPI.Failure as e:
|
except XenAPI.Failure as e:
|
||||||
raise XenFailure(e.details)
|
raise XenFailure(e.details)
|
||||||
@ -461,7 +463,7 @@ class XenServer(object):
|
|||||||
self.VM.set_tags(vmId, tags)
|
self.VM.set_tags(vmId, tags)
|
||||||
|
|
||||||
if kwargs.get('asnc', True) is True:
|
if kwargs.get('asnc', True) is True:
|
||||||
return self.asnc.VM.provision(vmId)
|
return self.Async.VM.provision(vmId)
|
||||||
return self.VM.provision(vmId)
|
return self.VM.provision(vmId)
|
||||||
|
|
||||||
def convertToTemplate(self, vmId, shadowMultiplier=4):
|
def convertToTemplate(self, vmId, shadowMultiplier=4):
|
||||||
|
@ -357,9 +357,6 @@ MIT
|
|||||||
@angular/router
|
@angular/router
|
||||||
MIT
|
MIT
|
||||||
|
|
||||||
@angular/animations
|
|
||||||
MIT
|
|
||||||
|
|
||||||
@angular/cdk
|
@angular/cdk
|
||||||
MIT
|
MIT
|
||||||
The MIT License
|
The MIT License
|
||||||
@ -385,10 +382,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
@angular/material/menu
|
@angular/animations
|
||||||
|
MIT
|
||||||
|
|
||||||
@angular/material/button
|
@angular/material/button
|
||||||
|
|
||||||
|
@angular/material/menu
|
||||||
|
|
||||||
@angular/material/sort
|
@angular/material/sort
|
||||||
|
|
||||||
@angular/material/table
|
@angular/material/table
|
||||||
|
File diff suppressed because one or more lines are too long
@ -2,6 +2,10 @@
|
|||||||
// Typescript
|
// Typescript
|
||||||
gettext("yes");
|
gettext("yes");
|
||||||
gettext("no");
|
gettext("no");
|
||||||
|
gettext("$USERS users, $GROUPS groups");
|
||||||
|
gettext("$POOLS service pools");
|
||||||
|
gettext("$SERVICES user services");
|
||||||
|
gettext("$RESTRAINED restrained services!");
|
||||||
gettext("New Network");
|
gettext("New Network");
|
||||||
gettext("Edit Network");
|
gettext("Edit Network");
|
||||||
gettext("Delete Network");
|
gettext("Delete Network");
|
||||||
@ -255,6 +259,15 @@ gettext("No");
|
|||||||
gettext("(hidden)");
|
gettext("(hidden)");
|
||||||
gettext("Selected items :");
|
gettext("Selected items :");
|
||||||
// HTML
|
// HTML
|
||||||
|
gettext("Dashboard");
|
||||||
|
gettext("View authenticators");
|
||||||
|
gettext("View service pools");
|
||||||
|
gettext("View service pools");
|
||||||
|
gettext("View service pools");
|
||||||
|
gettext("You are accessing UDS Administration as staff member.");
|
||||||
|
gettext("This means that you have restricted access to elements.");
|
||||||
|
gettext("In order to increase your access privileges, please contact your local UDS administrator.");
|
||||||
|
gettext("Thank you.");
|
||||||
gettext("Summary");
|
gettext("Summary");
|
||||||
gettext("Services");
|
gettext("Services");
|
||||||
gettext("Usage");
|
gettext("Usage");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user