1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
|
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 requires 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])
|