mirror of
https://github.com/dkmstr/openuds.git
synced 2025-01-18 06:03:54 +03:00
Using again XenAPI pip package
This commit is contained in:
parent
bed57c4133
commit
73cd338325
@ -1,293 +0,0 @@
|
||||
# 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.
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
# Fixes and adaption by agomez@virtualcable.net
|
||||
|
||||
import ssl
|
||||
import gettext
|
||||
import xmlrpc.client as xmlrpclib
|
||||
import http.client as httplib
|
||||
import socket
|
||||
import sys
|
||||
import typing
|
||||
|
||||
translation = gettext.translation('xen-xm', fallback=True)
|
||||
|
||||
API_VERSION_1_1 = '1.1'
|
||||
API_VERSION_1_2 = '1.2'
|
||||
|
||||
|
||||
class Failure(Exception):
|
||||
details: typing.List[typing.Any]
|
||||
|
||||
def __init__(self, details: typing.List[typing.Any]):
|
||||
super().__init__()
|
||||
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):
|
||||
# dict([(str(i), self.details[i]) for i in range(len(self.details))])
|
||||
return {str(i): d for i, d in enumerate(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):
|
||||
_use_datetime: bool
|
||||
_extra_headers: typing.List[typing.Tuple[str, str]]
|
||||
_connection: typing.Tuple[typing.Any, typing.Any]
|
||||
|
||||
def __init__(self, use_datetime: bool = False):
|
||||
super().__init__()
|
||||
self._use_datetime = use_datetime
|
||||
self._extra_headers = []
|
||||
self._connection = (None, None)
|
||||
|
||||
def add_extra_header(self, key: str, value: str) -> None:
|
||||
self._extra_headers += [(key, value)]
|
||||
|
||||
def make_connection(self, host: str) -> httplib.HTTPConnection: # type: ignore # In our case, host is always an string
|
||||
return UDSHTTPConnection(host)
|
||||
|
||||
def send_request(
|
||||
self, connection, handler, request_body, debug
|
||||
): # pylint: disable=arguments-differ
|
||||
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
|
||||
):
|
||||
ctx = ssl._create_unverified_context() # nosec: Xen Server will not have a valid cert
|
||||
xmlrpclib.ServerProxy.__init__(
|
||||
self, uri, transport, encoding, bool(verbose), bool(allow_none), context=ctx
|
||||
)
|
||||
else:
|
||||
xmlrpclib.ServerProxy.__init__(
|
||||
self, uri, transport, encoding, bool(verbose), bool(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 TimeoutError as e:
|
||||
raise xmlrpclib.Fault(504, 'The connection timed out')
|
||||
except socket.error:
|
||||
raise
|
||||
|
||||
def _logout(self):
|
||||
try:
|
||||
if self.last_login_method.startswith("slave_local"): # type: ignore
|
||||
return _parse_result(self.session.local_logout(self._session)) # type: ignore
|
||||
else:
|
||||
return _parse_result(self.session.logout(self._session)) # type: ignore
|
||||
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] # type: ignore
|
||||
host = self.xenapi.pool.get_master(pool) # type: ignore
|
||||
major = self.xenapi.host.get_API_version_major(host) # type: ignore
|
||||
minor = self.xenapi.host.get_API_version_minor(host) # type: ignore
|
||||
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 not isinstance(result, dict) or 'Status' not in result:
|
||||
raise xmlrpclib.Fault(
|
||||
500, 'Missing Status in response from server: {}'.format(result)
|
||||
)
|
||||
if result['Status'] == 'Success':
|
||||
if 'Value' in result:
|
||||
return result['Value']
|
||||
raise xmlrpclib.Fault(500, 'Missing Value in response from server')
|
||||
|
||||
if 'ErrorDescription' in result:
|
||||
if result['ErrorDescription'][0] == 'SESSION_INVALID':
|
||||
return _RECONNECT_AND_RETRY
|
||||
raise Failure(result['ErrorDescription'])
|
||||
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
|
||||
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)
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014-2019 Virtual Cable S.L.
|
||||
# Copyright (c) 2014-2023 Virtual Cable S.L.U.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -30,7 +30,8 @@ import xmlrpc.client
|
||||
import logging
|
||||
import typing
|
||||
|
||||
from . import XenAPI
|
||||
import XenAPI
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -193,7 +194,9 @@ class XenServer: # pylint: disable=too-many-public-methods
|
||||
self._loggedIn = True
|
||||
self._apiVersion = self._session.API_version
|
||||
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':
|
||||
logger.info(
|
||||
'%s is an Slave, connecting to master at %s',
|
||||
@ -259,11 +262,7 @@ class XenServer: # pylint: disable=too-many-public-methods
|
||||
status = 'failure'
|
||||
|
||||
# Removes <value></value> if present
|
||||
if (
|
||||
result
|
||||
and not isinstance(result, XenFailure)
|
||||
and result.startswith('<value>')
|
||||
):
|
||||
if result and not isinstance(result, XenFailure) and result.startswith('<value>'):
|
||||
result = result[7:-8]
|
||||
|
||||
if destroyTask:
|
||||
@ -279,11 +278,7 @@ class XenServer: # pylint: disable=too-many-public-methods
|
||||
# Only valid SR shared, non iso
|
||||
name_label = self.SR.get_name_label(srId)
|
||||
# Skip non valid...
|
||||
if (
|
||||
self.SR.get_content_type(srId) == 'iso'
|
||||
or self.SR.get_shared(srId) is False
|
||||
or name_label == ''
|
||||
):
|
||||
if self.SR.get_content_type(srId) == 'iso' or self.SR.get_shared(srId) is False or name_label == '':
|
||||
continue
|
||||
|
||||
valid = True
|
||||
@ -310,12 +305,7 @@ class XenServer: # pylint: disable=too-many-public-methods
|
||||
|
||||
def getNetworks(self) -> typing.Iterable[typing.MutableMapping[str, typing.Any]]:
|
||||
for netId in self.network.get_all():
|
||||
if (
|
||||
self.network.get_other_config(netId).get(
|
||||
'is_host_internal_management_network', False
|
||||
)
|
||||
is False
|
||||
):
|
||||
if self.network.get_other_config(netId).get('is_host_internal_management_network', False) is False:
|
||||
yield {
|
||||
'id': netId,
|
||||
'name': self.network.get_name_label(netId),
|
||||
@ -408,9 +398,7 @@ class XenServer: # pylint: disable=too-many-public-methods
|
||||
return self.Async.VM.resume(vmId, False, False)
|
||||
return self.VM.resume(vmId, False, False)
|
||||
|
||||
def cloneVM(
|
||||
self, vmId: str, targetName: str, targetSR: typing.Optional[str] = None
|
||||
) -> str:
|
||||
def cloneVM(self, vmId: str, targetName: str, targetSR: typing.Optional[str] = None) -> str:
|
||||
"""
|
||||
If targetSR is NONE:
|
||||
Clones the specified VM, making a new VM.
|
||||
@ -430,15 +418,11 @@ class XenServer: # pylint: disable=too-many-public-methods
|
||||
try:
|
||||
if targetSR:
|
||||
if 'copy' not in operations:
|
||||
raise XenException(
|
||||
'Copy is not supported for this machine (maybe it\'s powered on?)'
|
||||
)
|
||||
raise XenException('Copy is not supported for this machine (maybe it\'s powered on?)')
|
||||
task = self.Async.VM.copy(vmId, targetName, targetSR)
|
||||
else:
|
||||
if 'clone' not in operations:
|
||||
raise XenException(
|
||||
'Clone is not supported for this machine (maybe it\'s powered on?)'
|
||||
)
|
||||
raise XenException('Clone is not supported for this machine (maybe it\'s powered on?)')
|
||||
task = self.Async.VM.clone(vmId, targetName)
|
||||
return task
|
||||
except XenAPI.Failure as e:
|
||||
@ -528,9 +512,7 @@ class XenServer: # pylint: disable=too-many-public-methods
|
||||
operations = self.VM.get_allowed_operations(vmId)
|
||||
logger.debug('Allowed operations: %s', operations)
|
||||
if 'make_into_template' not in operations:
|
||||
raise XenException(
|
||||
'Convert in template is not supported for this machine'
|
||||
)
|
||||
raise XenException('Convert in template is not supported for this machine')
|
||||
self.VM.set_is_a_template(vmId, True)
|
||||
|
||||
# Apply that is an "UDS Template" taggint it
|
||||
@ -546,7 +528,7 @@ class XenServer: # pylint: disable=too-many-public-methods
|
||||
try:
|
||||
self.VM.set_HVM_shadow_multiplier(vmId, float(shadowMultiplier))
|
||||
except Exception: # nosec: Can't set shadowMultiplier, nothing happens
|
||||
pass
|
||||
pass
|
||||
except XenAPI.Failure as e:
|
||||
raise XenFailure(e.details)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user