mirror of
https://gitlab.com/libvirt/libvirt-python.git
synced 2024-10-26 07:55:06 +03:00
c8abe55d4c
Prepare for using buildWrappers to generate code for the QEMU / LXC APIs too. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
281 lines
9.8 KiB
Python
281 lines
9.8 KiB
Python
|
|
from types import TracebackType
|
|
from typing import Any, Callable, Dict, List, Optional, overload, Tuple, Type, TypeVar, Union
|
|
_T = TypeVar('_T')
|
|
_EventCB = Callable[[int, int, int, _T], None]
|
|
_EventAddHandleFunc = Callable[[int, int, _EventCB, _T], int]
|
|
_EventUpdateHandleFunc = Callable[[int, int], None]
|
|
_EventRemoveHandleFunc = Callable[[int], int]
|
|
_TimerCB = Callable[[int, _T], None]
|
|
_EventAddTimeoutFunc = Callable[[int, _TimerCB, _T], int]
|
|
_EventUpdateTimeoutFunc = Callable[[int, int], None]
|
|
_EventRemoveTimeoutFunc = Callable[[int], int]
|
|
_DomainCB = Callable[['virConnect', 'virDomain', int, int, _T], Optional[int]]
|
|
_BlkioParameter = Dict[str, Any]
|
|
_MemoryParameter = Dict[str, Any]
|
|
_SchedParameter = Dict[str, Any]
|
|
_TypedParameter = Dict[str, Any]
|
|
|
|
|
|
# The root of all libvirt errors.
|
|
class libvirtError(Exception):
|
|
def __init__(self, defmsg: str) -> None:
|
|
|
|
# Never call virConnGetLastError().
|
|
# virGetLastError() is now thread local
|
|
err = libvirtmod.virGetLastError() # type: Optional[Tuple[int, int, str, int, str, Optional[str], Optional[str], int, int]]
|
|
if err is None:
|
|
msg = defmsg
|
|
else:
|
|
msg = err[2]
|
|
|
|
Exception.__init__(self, msg)
|
|
|
|
self.err = err
|
|
|
|
def get_error_code(self) -> Optional[int]:
|
|
if self.err is None:
|
|
return None
|
|
return self.err[0]
|
|
|
|
def get_error_domain(self) -> Optional[int]:
|
|
if self.err is None:
|
|
return None
|
|
return self.err[1]
|
|
|
|
def get_error_message(self) -> Optional[str]:
|
|
if self.err is None:
|
|
return None
|
|
return self.err[2]
|
|
|
|
def get_error_level(self) -> Optional[int]:
|
|
if self.err is None:
|
|
return None
|
|
return self.err[3]
|
|
|
|
def get_str1(self) -> Optional[str]:
|
|
if self.err is None:
|
|
return None
|
|
return self.err[4]
|
|
|
|
def get_str2(self) -> Optional[str]:
|
|
if self.err is None:
|
|
return None
|
|
return self.err[5]
|
|
|
|
def get_str3(self) -> Optional[str]:
|
|
if self.err is None:
|
|
return None
|
|
return self.err[6]
|
|
|
|
def get_int1(self) -> Optional[int]:
|
|
if self.err is None:
|
|
return None
|
|
return self.err[7]
|
|
|
|
def get_int2(self) -> Optional[int]:
|
|
if self.err is None:
|
|
return None
|
|
return self.err[8]
|
|
|
|
|
|
#
|
|
# register the libvirt global error handler
|
|
#
|
|
def registerErrorHandler(f: Callable[[_T, List], None], ctx: _T) -> int:
|
|
"""Register a Python function for error reporting.
|
|
The function is called back as f(ctx, error), with error
|
|
being a list of information about the error being raised.
|
|
Returns 1 in case of success."""
|
|
return libvirtmod.virRegisterErrorHandler(f, ctx)
|
|
|
|
|
|
def openAuth(uri: str, auth: List, flags: int = 0) -> 'virConnect':
|
|
# TODO: The C code rquires a List and there is not *Mutable*Tuple for a better description such as
|
|
# auth: Tuple[List[int], Callable[[List[MutableTuple[int, str, str, str, Any]], _T], int], _T]
|
|
"""
|
|
This function should be called first to get a connection to the
|
|
Hypervisor. If necessary, authentication will be performed fetching
|
|
credentials via the callback.
|
|
|
|
See :py:func:`open` for notes about environment variables which can
|
|
have an effect on opening drivers and freeing the connection resources.
|
|
|
|
:param str uri: (Optional) connection URI, see https://libvirt.org/uri.html
|
|
:param auth: a list that contains 3 items:
|
|
- a list of supported credential types
|
|
- a callable that takes 2 arguments (credentials, user-data) and returns 0 on succcess and -1 on errors.
|
|
The credentials argument is a list of credentials that libvirt (actually
|
|
the ESX driver) would like to request. An element of this list is itself a
|
|
list containing 5 items (4 inputs, 1 output):
|
|
- the credential type, e.g. :py:const:`libvirt.VIR_CRED_AUTHNAME`
|
|
- a prompt to be displayed to the user
|
|
- a challenge, the ESX driver sets this to the hostname to allow automatic
|
|
distinction between requests for ESX and vCenter credentials
|
|
- a default result for the request
|
|
- a place to store the actual result for the request
|
|
- user data that will be passed to the callable as second argument
|
|
:param int flags: bitwise-OR of virConnectFlags
|
|
:returns: a :py:class:`virConnect` instance on success.
|
|
:raises libvirtError: on errors.
|
|
"""
|
|
ret = libvirtmod.virConnectOpenAuth(uri, auth, flags)
|
|
if ret is None:
|
|
raise libvirtError('virConnectOpenAuth() failed')
|
|
return virConnect(_obj=ret)
|
|
|
|
|
|
#
|
|
# Return library version.
|
|
#
|
|
def getVersion(name: Optional[str] = None) -> int:
|
|
"""If no name parameter is passed (or name is None) then the
|
|
version of the libvirt library is returned as an integer.
|
|
|
|
If a name is passed and it refers to a driver linked to the
|
|
libvirt library, then this returns a tuple of (library version,
|
|
driver version).
|
|
|
|
If the name passed refers to a non-existent driver, then you
|
|
will get the exception 'no support for hypervisor'.
|
|
|
|
Versions numbers are integers: 1000000*major + 1000*minor + release."""
|
|
if name is None:
|
|
ret = libvirtmod.virGetVersion()
|
|
else:
|
|
ret = libvirtmod.virGetVersion(name)
|
|
if ret is None:
|
|
raise libvirtError("virGetVersion() failed")
|
|
return ret
|
|
|
|
|
|
#
|
|
# Invoke an EventHandle callback
|
|
#
|
|
@overload
|
|
def _eventInvokeHandleCallback(watch: int, fd: int, event: int, opaque: Tuple[_EventCB, _T], opaquecompat: None = None) -> None: ... # noqa E704
|
|
@overload # noqa F811
|
|
def _eventInvokeHandleCallback(watch: int, fd: int, event: int, opaque: _EventCB, opaquecompat: _T = None) -> None: ... # noqa E704
|
|
def _eventInvokeHandleCallback(watch: int, fd: int, event: int, opaque: Union[Tuple[_EventCB, _T], _EventCB], opaquecompat: Optional[_T] = None) -> None: # noqa F811
|
|
"""
|
|
Invoke the Event Impl Handle Callback in C
|
|
"""
|
|
# libvirt 0.9.2 and earlier required custom event loops to know
|
|
# that opaque=(cb, original_opaque) and pass the values individually
|
|
# to this wrapper. This should handle the back compat case, and make
|
|
# future invocations match the virEventHandleCallback prototype
|
|
if opaquecompat:
|
|
callback = opaque
|
|
opaque_ = opaquecompat
|
|
else:
|
|
assert isinstance(opaque, tuple)
|
|
callback = opaque[0]
|
|
opaque_ = opaque[1]
|
|
|
|
libvirtmod.virEventInvokeHandleCallback(watch, fd, event, callback, opaque_)
|
|
|
|
|
|
#
|
|
# Invoke an EventTimeout callback
|
|
#
|
|
def _eventInvokeTimeoutCallback(timer: int, opaque: Union[Tuple[_TimerCB, _T], _TimerCB], opaquecompat: Optional[_T] = None) -> None:
|
|
"""
|
|
Invoke the Event Impl Timeout Callback in C
|
|
"""
|
|
# libvirt 0.9.2 and earlier required custom event loops to know
|
|
# that opaque=(cb, original_opaque) and pass the values individually
|
|
# to this wrapper. This should handle the back compat case, and make
|
|
# future invocations match the virEventTimeoutCallback prototype
|
|
if opaquecompat:
|
|
callback = opaque
|
|
opaque_ = opaquecompat
|
|
else:
|
|
assert isinstance(opaque, tuple)
|
|
callback = opaque[0]
|
|
opaque_ = opaque[1]
|
|
|
|
libvirtmod.virEventInvokeTimeoutCallback(timer, callback, opaque_)
|
|
|
|
|
|
def _dispatchEventHandleCallback(watch: int, fd: int, events: int, cbData: Dict[str, Any]) -> int:
|
|
cb = cbData["cb"]
|
|
opaque = cbData["opaque"]
|
|
|
|
cb(watch, fd, events, opaque)
|
|
return 0
|
|
|
|
|
|
def _dispatchEventTimeoutCallback(timer: int, cbData: Dict[str, Any]) -> int:
|
|
cb = cbData["cb"]
|
|
opaque = cbData["opaque"]
|
|
|
|
cb(timer, opaque)
|
|
return 0
|
|
|
|
|
|
def virEventAddHandle(fd: int, events: int, cb: _EventCB, opaque: _T) -> int:
|
|
"""
|
|
register a callback for monitoring file handle events
|
|
|
|
@fd: file handle to monitor for events
|
|
@events: bitset of events to watch from virEventHandleType constants
|
|
@cb: callback to invoke when an event occurs
|
|
@opaque: user data to pass to callback
|
|
|
|
Example callback prototype is:
|
|
def cb(watch, # int id of the handle
|
|
fd, # int file descriptor the event occurred on
|
|
events, # int bitmap of events that have occurred
|
|
opaque): # opaque data passed to eventAddHandle
|
|
"""
|
|
cbData = {"cb": cb, "opaque": opaque}
|
|
ret = libvirtmod.virEventAddHandle(fd, events, cbData)
|
|
if ret == -1:
|
|
raise libvirtError('virEventAddHandle() failed')
|
|
return ret
|
|
|
|
|
|
def virEventAddTimeout(timeout: int, cb: _TimerCB, opaque: _T) -> int:
|
|
"""
|
|
register a callback for a timer event
|
|
|
|
@timeout: time between events in milliseconds
|
|
@cb: callback to invoke when an event occurs
|
|
@opaque: user data to pass to callback
|
|
|
|
Setting timeout to -1 will disable the timer. Setting the timeout
|
|
to zero will cause it to fire on every event loop iteration.
|
|
|
|
Example callback prototype is:
|
|
def cb(timer, # int id of the timer
|
|
opaque): # opaque data passed to eventAddTimeout
|
|
"""
|
|
cbData = {"cb": cb, "opaque": opaque}
|
|
ret = libvirtmod.virEventAddTimeout(timeout, cbData)
|
|
if ret == -1:
|
|
raise libvirtError('virEventAddTimeout() failed')
|
|
return ret
|
|
|
|
|
|
#
|
|
# a caller for the ff callbacks for custom event loop implementations
|
|
#
|
|
|
|
def virEventInvokeFreeCallback(opaque: Any) -> None:
|
|
"""
|
|
Execute callback which frees the opaque buffer
|
|
|
|
@opaque: the opaque object passed to addHandle or addTimeout
|
|
|
|
WARNING: This function should not be called from any call by libvirt's
|
|
core. It will most probably cause deadlock in C-level libvirt code.
|
|
Instead it should be scheduled and called from implementation's stack.
|
|
|
|
See https://libvirt.org/html/libvirt-libvirt-event.html#virEventAddHandleFunc
|
|
for more information.
|
|
|
|
This function is not dependent on any event loop implementation.
|
|
"""
|
|
|
|
libvirtmod.virEventInvokeFreeCallback(opaque[2], opaque[1])
|