virt-manager/virtManager/libvirtenummap.py

201 lines
8.3 KiB
Python

# Copyright (C) 2018 Red Hat, Inc.
#
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
import logging
import re
import libvirt
if not hasattr(libvirt, "VIR_DOMAIN_PMSUSPENDED"):
setattr(libvirt, "VIR_DOMAIN_PMSUSPENDED", 7)
class _LibvirtEnumMap(object):
"""
Helper for mapping libvirt event int values to their API names
"""
# Some values we define to distinguish between API objects
(DOMAIN_EVENT,
DOMAIN_AGENT_EVENT,
NETWORK_EVENT,
STORAGE_EVENT,
NODEDEV_EVENT) = range(1, 6)
# Regex map for naming all event types depending on the API object
_EVENT_PREFIX = {
DOMAIN_EVENT: "VIR_DOMAIN_EVENT_ID_",
DOMAIN_AGENT_EVENT: "VIR_DOMAIN_EVENT_ID_AGENT_",
NETWORK_EVENT: "VIR_NETWORK_EVENT_ID_",
STORAGE_EVENT: "VIR_STORAGE_POOL_EVENT_ID_",
NODEDEV_EVENT: "VIR_NODE_DEVICE_EVENT_ID_",
}
# Regex map for 'state' values returned from lifecycle and other events
_DETAIL1_PREFIX = {
"VIR_DOMAIN_EVENT_ID_LIFECYCLE": "VIR_DOMAIN_EVENT_[^_]+$",
"VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE": _("VIR_CONNECT_DOMAIN_EVENT_AGENT"
"_LIFECYCLE_STATE_[^_]+$"),
"VIR_NETWORK_EVENT_ID_LIFECYCLE": "VIR_NETWORK_EVENT_[^_]+$",
"VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE": "VIR_STORAGE_POOL_EVENT_[^_]+$",
"VIR_NODE_DEVICE_EVENT_ID_LIFECYCLE": "VIR_NODE_DEVICE_EVENT_[^_]+$",
}
# Regex map for 'reason' values returned from lifecycle and other events
_DETAIL2_PREFIX = {
"VIR_DOMAIN_EVENT_DEFINED": "VIR_DOMAIN_EVENT_DEFINED_",
"VIR_DOMAIN_EVENT_UNDEFINED": "VIR_DOMAIN_EVENT_UNDEFINED_",
"VIR_DOMAIN_EVENT_STARTED": "VIR_DOMAIN_EVENT_STARTED_",
"VIR_DOMAIN_EVENT_SUSPENDED": "VIR_DOMAIN_EVENT_SUSPENDED_",
"VIR_DOMAIN_EVENT_RESUMED": "VIR_DOMAIN_EVENT_RESUMED_",
"VIR_DOMAIN_EVENT_STOPPED": "VIR_DOMAIN_EVENT_STOPPED_",
"VIR_DOMAIN_EVENT_SHUTDOWN": "VIR_DOMAIN_EVENT_SHUTDOWN_",
"VIR_DOMAIN_EVENT_PMSUSPENDED": "VIR_DOMAIN_EVENT_PMSUSPENDED_",
"VIR_DOMAIN_EVENT_CRASHED": "VIR_DOMAIN_EVENT_CRASHED_",
}
VM_STATUS_ICONS = {
libvirt.VIR_DOMAIN_BLOCKED: "state_running",
libvirt.VIR_DOMAIN_CRASHED: "state_shutoff",
libvirt.VIR_DOMAIN_PAUSED: "state_paused",
libvirt.VIR_DOMAIN_RUNNING: "state_running",
libvirt.VIR_DOMAIN_SHUTDOWN: "state_shutoff",
libvirt.VIR_DOMAIN_SHUTOFF: "state_shutoff",
libvirt.VIR_DOMAIN_NOSTATE: "state_running",
libvirt.VIR_DOMAIN_PMSUSPENDED: "state_paused",
}
@staticmethod
def pretty_run_status(status, has_managed_save):
if status == libvirt.VIR_DOMAIN_RUNNING:
return _("Running")
elif status == libvirt.VIR_DOMAIN_PAUSED:
return _("Paused")
elif status == libvirt.VIR_DOMAIN_SHUTDOWN:
return _("Shutting Down")
elif status == libvirt.VIR_DOMAIN_SHUTOFF:
if has_managed_save:
return _("Saved")
else:
return _("Shutoff")
elif status == libvirt.VIR_DOMAIN_CRASHED:
return _("Crashed")
elif status == libvirt.VIR_DOMAIN_PMSUSPENDED:
return _("Suspended")
logging.debug("Unknown status %s, returning 'Unknown'", status)
return _("Unknown")
@staticmethod
def pretty_status_reason(status, reason):
def key(x, y):
return getattr(libvirt, "VIR_DOMAIN_" + x, y)
reasons = {
libvirt.VIR_DOMAIN_RUNNING: {
key("RUNNING_BOOTED", 1): _("Booted"),
key("RUNNING_MIGRATED", 2): _("Migrated"),
key("RUNNING_RESTORED", 3): _("Restored"),
key("RUNNING_FROM_SNAPSHOT", 4): _("From snapshot"),
key("RUNNING_UNPAUSED", 5): _("Unpaused"),
key("RUNNING_MIGRATION_CANCELED", 6): _("Migration canceled"),
key("RUNNING_SAVE_CANCELED", 7): _("Save canceled"),
key("RUNNING_WAKEUP", 8): _("Event wakeup"),
key("RUNNING_CRASHED", 9): _("Crashed"),
},
libvirt.VIR_DOMAIN_PAUSED: {
key("PAUSED_USER", 1): _("User"),
key("PAUSED_MIGRATION", 2): _("Migrating"),
key("PAUSED_SAVE", 3): _("Saving"),
key("PAUSED_DUMP", 4): _("Dumping"),
key("PAUSED_IOERROR", 5): _("I/O error"),
key("PAUSED_WATCHDOG", 6): _("Watchdog"),
key("PAUSED_FROM_SNAPSHOT", 7): _("From snapshot"),
key("PAUSED_SHUTTING_DOWN", 8): _("Shutting down"),
key("PAUSED_SNAPSHOT", 9): _("Creating snapshot"),
key("PAUSED_CRASHED", 10): _("Crashed"),
},
libvirt.VIR_DOMAIN_SHUTDOWN: {
key("SHUTDOWN_USER", 1): _("User"),
},
libvirt.VIR_DOMAIN_SHUTOFF: {
key("SHUTOFF_SHUTDOWN", 1): _("Shut Down"),
key("SHUTOFF_DESTROYED", 2): _("Destroyed"),
key("SHUTOFF_CRASHED", 3): _("Crashed"),
key("SHUTOFF_MIGRATED", 4): _("Migrated"),
key("SHUTOFF_SAVED", 5): _("Saved"),
key("SHUTOFF_FAILED", 6): _("Failed"),
key("SHUTOFF_FROM_SNAPSHOT", 7): _("From snapshot"),
},
libvirt.VIR_DOMAIN_CRASHED: {
key("CRASHED_PANICKED", 1): _("Panicked"),
}
}
return reasons.get(status) and reasons[status].get(reason)
def __init__(self):
self._mapping = {}
def _make_map(self, regex):
# Run the passed regex over dir(libvirt) output
ret = {}
for key in [a for a in dir(libvirt) if re.match(regex, a)]:
val = getattr(libvirt, key)
if type(val) is not int:
logging.debug("libvirt regex=%s key=%s val=%s "
"isn't an integer", regex, key, val)
continue
if val in ret:
logging.debug("libvirt regex=%s key=%s val=%s is already "
"in dict as key=%s", regex, key, val, regex[val])
continue
ret[val] = key
return ret
def _get_map(self, key, regex):
if regex is None:
return {}
if key not in self._mapping:
self._mapping[key] = self._make_map(regex)
return self._mapping[key]
def _make_strs(self, api, event, detail1, detail2):
eventstr = str(event)
detail1str = str(detail1)
detail2str = str(detail2)
eventmap = self._get_map(api, self._EVENT_PREFIX[api])
if eventmap:
if event not in eventmap:
event = next(iter(eventmap))
eventstr = eventmap[event]
detail1map = self._get_map(eventstr,
self._DETAIL1_PREFIX.get(eventstr))
if detail1 in detail1map:
detail1str = detail1map[detail1]
detail2map = self._get_map(detail1str,
self._DETAIL2_PREFIX.get(detail1str))
if detail2 in detail2map:
detail2str = detail2map[detail2]
return eventstr, detail1str, detail2str
def _state_str(self, api, detail1, detail2):
ignore, d1str, d2str = self._make_strs(api, 0,
detail1, detail2)
return "state=%s reason=%s" % (d1str, d2str)
def domain_lifecycle_str(self, detail1, detail2):
return self._state_str(self.DOMAIN_EVENT, detail1, detail2)
def network_lifecycle_str(self, detail1, detail2):
return self._state_str(self.NETWORK_EVENT, detail1, detail2)
def storage_lifecycle_str(self, detail1, detail2):
return self._state_str(self.STORAGE_EVENT, detail1, detail2)
def nodedev_lifecycle_str(self, detail1, detail2):
return self._state_str(self.NODEDEV_EVENT, detail1, detail2)
def domain_agent_lifecycle_str(self, detail1, detail2):
return self._state_str(self.DOMAIN_AGENT_EVENT, detail1, detail2)
LibvirtEnumMap = _LibvirtEnumMap()