mirror of
https://github.com/virt-manager/virt-manager.git
synced 2024-12-22 13:34:07 +03:00
virtinst: move UI only functions into virtManager
These throw off code coverage testing. They are mostly: * pretty* device helpers * network + snapshot validation + creation routines
This commit is contained in:
parent
c9233aa6c3
commit
b5a664bd1b
@ -48,7 +48,6 @@ class TestNodeDev(unittest.TestCase):
|
||||
dev = NodeDevice(self.conn, funky_chars_xml)
|
||||
self.assertEqual(dev.name, "L3B2616")
|
||||
self.assertEqual(dev.device_type, "LENOVO")
|
||||
self.assertEqual(dev.pretty_name(), dev.name)
|
||||
|
||||
def testNetDevice(self):
|
||||
devname = "net_00_1c_25_10_b1_e4"
|
||||
@ -57,19 +56,8 @@ class TestNodeDev(unittest.TestCase):
|
||||
self.assertEqual(dev.parent, "pci_8086_1049")
|
||||
self.assertEqual(dev.device_type, "net")
|
||||
self.assertEqual(dev.interface, "eth0")
|
||||
self.assertEqual(dev.pretty_name(), "Interface eth0")
|
||||
|
||||
def testPCIDevice(self):
|
||||
devname = "pci_1180_592"
|
||||
dev = self._nodeDevFromName(devname)
|
||||
self.assertEqual(dev.pretty_name(),
|
||||
"0000:15:00:4 Ricoh Co Ltd R5C592 Memory Stick Bus Host Adapter")
|
||||
|
||||
devname = "pci_8086_1049"
|
||||
dev = self._nodeDevFromName(devname)
|
||||
self.assertEqual(dev.pretty_name(),
|
||||
"0000:00:19:0 Intel Corporation 82566MM Gigabit Network Connection")
|
||||
|
||||
nodename = "pci_8086_10fb"
|
||||
obj = self._nodeDevFromName(nodename)
|
||||
self.assertEqual(obj.is_pci_sriov(), True)
|
||||
@ -81,13 +69,8 @@ class TestNodeDev(unittest.TestCase):
|
||||
def testUSBDevDevice(self):
|
||||
devname = "usb_device_781_5151_2004453082054CA1BEEE"
|
||||
dev = self._nodeDevFromName(devname)
|
||||
self.assertEqual(dev.pretty_name(),
|
||||
"001:004 SanDisk Corp. Cruzer Micro 256/512MB Flash Drive")
|
||||
|
||||
devname = "usb_device_483_2016_noserial"
|
||||
dev = self._nodeDevFromName(devname)
|
||||
self.assertEqual(dev.pretty_name(),
|
||||
"003:002 SGS Thomson Microelectronics Fingerprint Reader")
|
||||
self.assertEqual(dev.vendor_name, "SanDisk Corp.")
|
||||
self.assertEqual(dev.product_name, "Cruzer Micro 256/512MB Flash Drive")
|
||||
|
||||
devname = "usb_device_1d6b_1_0000_00_1a_0"
|
||||
dev = self._nodeDevFromName(devname)
|
||||
@ -126,8 +109,6 @@ class TestNodeDev(unittest.TestCase):
|
||||
"/dev/dri/by-path/pci-0000:00:02.0-render")
|
||||
self.assertEqual(dev.devnodes[1].node_type, "link")
|
||||
self.assertEqual(dev.is_drm_render(), True)
|
||||
self.assertEqual(dev.pretty_name(),
|
||||
"0000:00:02:0 Intel Corporation HD Graphics 530 (render)")
|
||||
|
||||
|
||||
# NodeDevice 2 Device XML tests
|
||||
|
@ -280,7 +280,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
True, None)
|
||||
add_hw_option(_("RNG"), "system-run", PAGE_RNG, True, None)
|
||||
add_hw_option(_("Panic Notifier"), "system-run", PAGE_PANIC,
|
||||
bool(DevicePanic.get_models(self.vm.get_xmlobj().os)),
|
||||
bool(DevicePanic.get_models(self.vm.get_xmlobj())),
|
||||
_("Not supported for this hypervisor/libvirt/arch combination."))
|
||||
add_hw_option(_("Virtio VSOCK"), "network-idle", PAGE_VSOCK,
|
||||
self.vm.is_hvm(),
|
||||
@ -403,6 +403,295 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
return True
|
||||
|
||||
|
||||
#####################
|
||||
# Pretty UI helpers #
|
||||
#####################
|
||||
|
||||
@staticmethod
|
||||
def char_recommended_types(char_class):
|
||||
if char_class.XML_NAME == "console":
|
||||
return [DeviceSerial.TYPE_PTY]
|
||||
|
||||
ret = [DeviceSerial.TYPE_PTY,
|
||||
DeviceSerial.TYPE_FILE,
|
||||
DeviceSerial.TYPE_UNIX]
|
||||
if char_class.XML_NAME == "channel":
|
||||
ret = [DeviceSerial.TYPE_SPICEVMC,
|
||||
DeviceSerial.TYPE_SPICEPORT] + ret
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def char_pretty_channel_name(val):
|
||||
if val == DeviceChannel.CHANNEL_NAME_SPICE:
|
||||
return "spice"
|
||||
if val == DeviceChannel.CHANNEL_NAME_QEMUGA:
|
||||
return "qemu-ga"
|
||||
if val == DeviceChannel.CHANNEL_NAME_LIBGUESTFS:
|
||||
return "libguestfs"
|
||||
if val == DeviceChannel.CHANNEL_NAME_SPICE_WEBDAV:
|
||||
return "spice-webdav"
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def char_pretty_type(ctype):
|
||||
"""
|
||||
Return a human readable description of the passed char type
|
||||
"""
|
||||
if ctype == DeviceSerial.TYPE_PTY:
|
||||
return _("Pseudo TTY")
|
||||
elif ctype == DeviceSerial.TYPE_FILE:
|
||||
return _("Output to a file")
|
||||
elif ctype == DeviceSerial.TYPE_TCP:
|
||||
return _("TCP net console")
|
||||
elif ctype == DeviceSerial.TYPE_UDP:
|
||||
return _("UDP net console")
|
||||
elif ctype == DeviceSerial.TYPE_UNIX:
|
||||
return _("Unix socket")
|
||||
elif ctype == DeviceSerial.TYPE_SPICEVMC:
|
||||
return _("Spice agent")
|
||||
elif ctype == DeviceSerial.TYPE_SPICEPORT:
|
||||
return _("Spice port")
|
||||
return ctype
|
||||
|
||||
@staticmethod
|
||||
def controller_recommended_types():
|
||||
return [DeviceController.TYPE_SCSI,
|
||||
DeviceController.TYPE_USB,
|
||||
DeviceController.TYPE_VIRTIOSERIAL,
|
||||
DeviceController.TYPE_CCID]
|
||||
|
||||
@staticmethod
|
||||
def controller_pretty_type(ctype):
|
||||
pretty_mappings = {
|
||||
DeviceController.TYPE_IDE: "IDE",
|
||||
DeviceController.TYPE_FDC: _("Floppy"),
|
||||
DeviceController.TYPE_SCSI: "SCSI",
|
||||
DeviceController.TYPE_SATA: "SATA",
|
||||
DeviceController.TYPE_VIRTIOSERIAL: "VirtIO Serial",
|
||||
DeviceController.TYPE_USB: "USB",
|
||||
DeviceController.TYPE_PCI: "PCI",
|
||||
DeviceController.TYPE_CCID: "CCID",
|
||||
DeviceController.TYPE_XENBUS: "xenbus",
|
||||
}
|
||||
if ctype not in pretty_mappings:
|
||||
return ctype
|
||||
return pretty_mappings[ctype]
|
||||
|
||||
@staticmethod
|
||||
def controller_pretty_desc(dev):
|
||||
ret = vmmAddHardware.controller_pretty_type(dev.type)
|
||||
if dev.type == "scsi":
|
||||
if dev.model == "virtio-scsi":
|
||||
ret = "Virtio " + ret
|
||||
elif dev.address.type == "spapr-vio":
|
||||
ret = "sPAPR " + ret
|
||||
if dev.type == "pci" and dev.model == "pcie-root":
|
||||
ret = "PCIe"
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def disk_old_recommended_buses(guest):
|
||||
ret = []
|
||||
if guest.os.is_hvm() or guest.conn.is_test():
|
||||
if not guest.os.is_q35():
|
||||
ret.append("ide")
|
||||
ret.append("sata")
|
||||
ret.append("fdc")
|
||||
ret.append("scsi")
|
||||
ret.append("usb")
|
||||
|
||||
if guest.type in ["qemu", "kvm", "test"]:
|
||||
ret.append("sd")
|
||||
ret.append("virtio")
|
||||
if "scsi" not in ret:
|
||||
ret.append("scsi")
|
||||
|
||||
if guest.conn.is_xen() or guest.conn.is_test():
|
||||
ret.append("xen")
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def disk_recommended_buses(guest, domcaps, devtype):
|
||||
# try to get supported disk bus types from domain capabilities
|
||||
if "bus" in domcaps.devices.disk.enum_names():
|
||||
buses = domcaps.devices.disk.get_enum("bus").get_values()
|
||||
else:
|
||||
buses = vmmAddHardware.disk_old_recommended_buses(guest)
|
||||
|
||||
bus_map = {
|
||||
"disk": ["ide", "sata", "scsi", "sd", "usb", "virtio", "xen"],
|
||||
"floppy": ["fdc"],
|
||||
"cdrom": ["ide", "sata", "scsi"],
|
||||
"lun": ["scsi"],
|
||||
}
|
||||
return [bus for bus in buses if bus in bus_map.get(devtype, [])]
|
||||
|
||||
@staticmethod
|
||||
def disk_pretty_bus(bus):
|
||||
if bus in ["ide", "sata", "scsi", "usb", "sd"]:
|
||||
return bus.upper()
|
||||
if bus in ["xen"]:
|
||||
return bus.capitalize()
|
||||
if bus == "virtio":
|
||||
return "VirtIO"
|
||||
return bus
|
||||
|
||||
@staticmethod
|
||||
def tpm_pretty_type(tpm_type):
|
||||
if tpm_type == DeviceTpm.TYPE_PASSTHROUGH:
|
||||
return _("Passthrough device")
|
||||
if tpm_type == DeviceTpm.TYPE_EMULATOR:
|
||||
return _("Emulated device")
|
||||
return tpm_type
|
||||
|
||||
@staticmethod
|
||||
def tpm_pretty_model(tpm_model):
|
||||
if tpm_model == DeviceTpm.MODEL_TIS:
|
||||
return _("TIS")
|
||||
if tpm_model == DeviceTpm.MODEL_CRB:
|
||||
return _("CRB")
|
||||
return tpm_model
|
||||
|
||||
@staticmethod
|
||||
def panic_pretty_model(panic_model):
|
||||
if panic_model == DevicePanic.MODEL_ISA:
|
||||
return _("ISA")
|
||||
elif panic_model == DevicePanic.MODEL_PSERIES:
|
||||
return _("pSeries")
|
||||
elif panic_model == DevicePanic.MODEL_HYPERV:
|
||||
return _("Hyper-V")
|
||||
elif panic_model == DevicePanic.MODEL_S390:
|
||||
return _("s390")
|
||||
return panic_model
|
||||
|
||||
@staticmethod
|
||||
def rng_pretty_type(rng_type):
|
||||
if rng_type == DeviceRng.TYPE_RANDOM:
|
||||
return _("Random")
|
||||
if rng_type == DeviceRng.TYPE_EGD:
|
||||
return _("Entropy Gathering Daemon")
|
||||
return rng_type
|
||||
|
||||
@staticmethod
|
||||
def rng_pretty_backend_type(backend_type):
|
||||
return {"udp": "UDP",
|
||||
"tcp": "TCP"}.get(backend_type) or backend_type
|
||||
|
||||
@staticmethod
|
||||
def rng_pretty_mode(mode):
|
||||
return {"bind": _("Bind"),
|
||||
"connect": _("Connect")}.get(mode) or mode
|
||||
|
||||
@staticmethod
|
||||
def sound_recommended_models(_guest):
|
||||
return ["ich6", "ich9", "ac97"]
|
||||
|
||||
@staticmethod
|
||||
def sound_pretty_model(model):
|
||||
ret = model.upper()
|
||||
if model in ["ich6", "ich9"]:
|
||||
ret = "HDA (%s)" % model.upper()
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def watchdog_pretty_action(action):
|
||||
if action == DeviceWatchdog.ACTION_RESET:
|
||||
return _("Forcefully reset the guest")
|
||||
if action == DeviceWatchdog.ACTION_SHUTDOWN:
|
||||
return _("Gracefully shutdown the guest")
|
||||
if action == DeviceWatchdog.ACTION_POWEROFF:
|
||||
return _("Forcefully power off the guest")
|
||||
if action == DeviceWatchdog.ACTION_PAUSE:
|
||||
return _("Pause the guest")
|
||||
if action == DeviceWatchdog.ACTION_NONE:
|
||||
return _("No action")
|
||||
if action == DeviceWatchdog.ACTION_DUMP:
|
||||
return _("Dump guest memory core")
|
||||
return action
|
||||
|
||||
@staticmethod
|
||||
def input_pretty_name(typ, bus):
|
||||
if typ == "tablet" and bus == "usb":
|
||||
return _("EvTouch USB Graphics Tablet")
|
||||
|
||||
if bus in ["usb", "ps2"]:
|
||||
return _("Generic") + (" %s %s" %
|
||||
(bus.upper(), str(typ).capitalize()))
|
||||
return "%s %s" % (str(bus).capitalize(), str(typ).capitalize())
|
||||
|
||||
@staticmethod
|
||||
def interface_recommended_models(guest):
|
||||
if not guest.os.is_hvm():
|
||||
return []
|
||||
|
||||
ret = []
|
||||
if guest.type in ["kvm", "qemu", "vz", "test"]:
|
||||
ret.append("virtio")
|
||||
if guest.os.is_x86():
|
||||
if guest.os.is_q35():
|
||||
ret.append("e1000e")
|
||||
else:
|
||||
ret.append("rtl8139")
|
||||
ret.append("e1000")
|
||||
if guest.type in ["xen", "test"]:
|
||||
ret.append("netfront")
|
||||
|
||||
ret.sort()
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def redirdev_pretty_type(typ):
|
||||
if typ == "tcp":
|
||||
return "TCP"
|
||||
if typ == "spicevmc":
|
||||
return "SpiceVMC"
|
||||
return typ and typ.capitalize()
|
||||
|
||||
@staticmethod
|
||||
def video_recommended_models(guest):
|
||||
if guest.conn.is_xen():
|
||||
return ["xen", "vga"]
|
||||
if guest.conn.is_qemu() or guest.conn.is_test():
|
||||
return ["vga", "qxl", "virtio"]
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def video_pretty_model(model):
|
||||
if model in ["qxl", "vmvga", "vga"]:
|
||||
return model.upper()
|
||||
return model.capitalize()
|
||||
|
||||
@staticmethod
|
||||
def hostdev_pretty_name(hostdev):
|
||||
def dehex(val):
|
||||
if val.startswith("0x"):
|
||||
val = val[2:]
|
||||
return val
|
||||
|
||||
def safeint(val, fmt="%.3d"):
|
||||
try:
|
||||
int(val)
|
||||
except Exception:
|
||||
return str(val)
|
||||
return fmt % int(val)
|
||||
|
||||
label = hostdev.type.upper()
|
||||
|
||||
if hostdev.vendor and hostdev.product:
|
||||
label += " %s:%s" % (dehex(hostdev.vendor), dehex(hostdev.product))
|
||||
|
||||
elif hostdev.bus and hostdev.device:
|
||||
label += " %s:%s" % (safeint(hostdev.bus), safeint(hostdev.device))
|
||||
|
||||
elif (hostdev.bus and hostdev.slot and
|
||||
hostdev.function and hostdev.domain):
|
||||
label += (" %s:%s:%s.%s" %
|
||||
(dehex(hostdev.domain), dehex(hostdev.bus),
|
||||
dehex(hostdev.slot), dehex(hostdev.function)))
|
||||
|
||||
return label
|
||||
|
||||
|
||||
#########################
|
||||
# UI init/reset helpers #
|
||||
@ -467,11 +756,11 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
@staticmethod
|
||||
def populate_disk_bus_combo(vm, devtype, model):
|
||||
domcaps = vm.get_domain_capabilities()
|
||||
buses = DeviceDisk.get_recommended_buses(vm.xmlobj, domcaps, devtype)
|
||||
buses = vmmAddHardware.disk_recommended_buses(vm.xmlobj, domcaps, devtype)
|
||||
|
||||
model.clear()
|
||||
for bus in buses:
|
||||
model.append([bus, DeviceDisk.pretty_disk_bus(bus)])
|
||||
model.append([bus, vmmAddHardware.disk_pretty_bus(bus)])
|
||||
|
||||
|
||||
@staticmethod
|
||||
@ -481,7 +770,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
|
||||
# [xml value, label]
|
||||
model.append([None, _("Hypervisor default")])
|
||||
for netmodel in DeviceInterface.get_models(vm.xmlobj):
|
||||
for netmodel in vmmAddHardware.interface_recommended_models(vm.xmlobj):
|
||||
model.append([netmodel, netmodel])
|
||||
|
||||
uiutil.set_list_selection(
|
||||
@ -502,15 +791,16 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
(DeviceInput.TYPE_TABLET, DeviceInput.BUS_VIRTIO),
|
||||
]
|
||||
|
||||
cvals = [((t, b), DeviceInput.pretty_name(t, b)) for t, b in devices]
|
||||
cvals = [((t, b), vmmAddHardware.input_pretty_name(t, b))
|
||||
for t, b in devices]
|
||||
_build_combo(self.widget("input-type"), cvals)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def build_sound_combo(vm, combo):
|
||||
values = []
|
||||
for m in DeviceSound.get_recommended_models(vm.xmlobj):
|
||||
values.append([m, DeviceSound.pretty_model(m)])
|
||||
for m in vmmAddHardware.sound_recommended_models(vm.xmlobj):
|
||||
values.append([m, vmmAddHardware.sound_pretty_model(m)])
|
||||
|
||||
default = DeviceSound.default_model(vm.xmlobj)
|
||||
_build_combo(combo, values, default_value=default)
|
||||
@ -540,12 +830,12 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
continue
|
||||
if dev.xmlobj.is_pci_bridge():
|
||||
continue
|
||||
prettyname = dev.xmlobj.pretty_name()
|
||||
prettyname = dev.pretty_name()
|
||||
|
||||
if devtype == "pci":
|
||||
for subdev in netdevs:
|
||||
if dev.xmlobj.name == subdev.xmlobj.parent:
|
||||
prettyname += " (%s)" % subdev.xmlobj.pretty_name()
|
||||
prettyname += " (%s)" % subdev.pretty_name()
|
||||
|
||||
model.append([dev.xmlobj, prettyname])
|
||||
|
||||
@ -557,8 +847,8 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
@staticmethod
|
||||
def build_video_combo(vm, combo):
|
||||
values = []
|
||||
for m in DeviceVideo.get_recommended_models(vm.xmlobj):
|
||||
values.append([m, DeviceVideo.pretty_model(m)])
|
||||
for m in vmmAddHardware.video_recommended_models(vm.xmlobj):
|
||||
values.append([m, vmmAddHardware.video_pretty_model(m)])
|
||||
if not values:
|
||||
values.append([None, _("Hypervisor default")])
|
||||
default = DeviceVideo.default_model(vm.xmlobj)
|
||||
@ -584,8 +874,8 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
model = self.widget("char-device-type").get_model()
|
||||
model.clear()
|
||||
|
||||
for t in char_class.get_recommended_types(self.vm.xmlobj):
|
||||
model.append([t, char_class.pretty_type(t) + " (%s)" % t])
|
||||
for t in vmmAddHardware.char_recommended_types(char_class):
|
||||
model.append([t, vmmAddHardware.char_pretty_type(t) + " (%s)" % t])
|
||||
uiutil.set_list_selection(self.widget("char-device-type"), "pty")
|
||||
|
||||
|
||||
@ -600,7 +890,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
def build_watchdogaction_combo(_vm, combo):
|
||||
values = []
|
||||
for m in DeviceWatchdog.ACTIONS:
|
||||
values.append([m, DeviceWatchdog.get_action_desc(m)])
|
||||
values.append([m, vmmAddHardware.watchdog_pretty_action(m)])
|
||||
_build_combo(combo, values, default_value=DeviceWatchdog.ACTION_RESET)
|
||||
|
||||
|
||||
@ -621,11 +911,11 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
def _build_tpm_type_combo(self):
|
||||
values = []
|
||||
for t in DeviceTpm.TYPES:
|
||||
values.append([t, DeviceTpm.get_pretty_type(t)])
|
||||
values.append([t, vmmAddHardware.tpm_pretty_type(t)])
|
||||
_build_combo(self.widget("tpm-type"), values)
|
||||
values = []
|
||||
for t in DeviceTpm.MODELS:
|
||||
values.append([t, DeviceTpm.get_pretty_model(t)])
|
||||
values.append([t, vmmAddHardware.tpm_pretty_model(t)])
|
||||
_build_combo(self.widget("tpm-model"), values)
|
||||
values = []
|
||||
for t in DeviceTpm.VERSIONS:
|
||||
@ -650,7 +940,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
|
||||
mod_list = vmmAddHardware._get_tpm_model_list(vm, tpmversion)
|
||||
for m in mod_list:
|
||||
model.append([m, DeviceTpm.get_pretty_model(m)])
|
||||
model.append([m, vmmAddHardware.tpm_pretty_model(m)])
|
||||
combo.set_active(0)
|
||||
|
||||
@staticmethod
|
||||
@ -661,8 +951,8 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
|
||||
def _build_panic_model_combo(self):
|
||||
values = []
|
||||
for m in DevicePanic.get_models(self.vm.get_xmlobj().os):
|
||||
values.append([m, DevicePanic.get_pretty_model(m)])
|
||||
for m in DevicePanic.get_models(self.vm.get_xmlobj()):
|
||||
values.append([m, vmmAddHardware.panic_pretty_model(m)])
|
||||
|
||||
default = DevicePanic.get_default_model(self.vm.get_xmlobj())
|
||||
_build_combo(self.widget("panic-model"), values, default_value=default)
|
||||
@ -670,8 +960,8 @@ class vmmAddHardware(vmmGObjectUI):
|
||||
|
||||
def _build_controller_type_combo(self):
|
||||
values = []
|
||||
for t in DeviceController.get_recommended_types(self.vm.xmlobj):
|
||||
values.append([t, DeviceController.pretty_type(t)])
|
||||
for t in vmmAddHardware.controller_recommended_types():
|
||||
values.append([t, vmmAddHardware.controller_pretty_type(t)])
|
||||
|
||||
_build_combo(self.widget("controller-type"), values,
|
||||
default_value=DeviceController.TYPE_SCSI)
|
||||
|
@ -11,6 +11,9 @@ from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import Pango
|
||||
|
||||
import libvirt
|
||||
|
||||
from virtinst import generatename
|
||||
from virtinst import Network
|
||||
|
||||
from . import uiutil
|
||||
@ -110,8 +113,9 @@ class vmmCreateNetwork(vmmGObjectUI):
|
||||
mode_model.append(["hostdev", _("SR-IOV pool")])
|
||||
|
||||
def reset_state(self):
|
||||
default_name = Network.find_free_name(
|
||||
self.conn.get_backend(), "network")
|
||||
basename = "network"
|
||||
default_name = generatename.generate_name(
|
||||
basename, self.conn.get_backend().networkLookupByName)
|
||||
self.widget("net-name").set_text(default_name)
|
||||
|
||||
self.widget("net-dns-use-netname").set_active(True)
|
||||
@ -161,7 +165,7 @@ class vmmCreateNetwork(vmmGObjectUI):
|
||||
for pcidev in self.conn.filter_nodedevs("pci"):
|
||||
if not pcidev.xmlobj.is_pci_sriov():
|
||||
continue
|
||||
devdesc = pcidev.xmlobj.pretty_name()
|
||||
devdesc = pcidev.pretty_name()
|
||||
for netdev in self.conn.filter_nodedevs("net"):
|
||||
if pcidev.xmlobj.name != netdev.xmlobj.parent:
|
||||
continue
|
||||
@ -353,6 +357,15 @@ class vmmCreateNetwork(vmmGObjectUI):
|
||||
# XML build and install #
|
||||
#########################
|
||||
|
||||
def _validate(self, net):
|
||||
net.validate_generic_name(_("Network"), net.name)
|
||||
|
||||
try:
|
||||
net.conn.networkLookupByName(net.name)
|
||||
except libvirt.libvirtError:
|
||||
return
|
||||
raise ValueError(_("Name '%s' already in use by another network." %
|
||||
net.name))
|
||||
|
||||
def _build_xmlobj(self):
|
||||
net = Network(self.conn.get_backend())
|
||||
@ -418,12 +431,22 @@ class vmmCreateNetwork(vmmGObjectUI):
|
||||
|
||||
def _async_net_create(self, asyncjob, net):
|
||||
ignore = asyncjob
|
||||
net.install()
|
||||
xml = net.get_xml()
|
||||
logging.debug("Creating virtual network '%s' with xml:\n%s",
|
||||
net.name, xml)
|
||||
|
||||
netobj = self.conn.get_backend().networkDefineXML(xml)
|
||||
try:
|
||||
netobj.create()
|
||||
netobj.setAutostart(True)
|
||||
except Exception:
|
||||
netobj.undefine()
|
||||
raise
|
||||
|
||||
def finish(self, ignore):
|
||||
try:
|
||||
net = self._build_xmlobj()
|
||||
net.validate()
|
||||
self._validate(net)
|
||||
except Exception as e:
|
||||
self.err.show_err(_("Error generating network xml: %s") % str(e))
|
||||
return
|
||||
|
@ -173,7 +173,7 @@ def _label_for_device(dev):
|
||||
devtype = dev.DEVICE_TYPE
|
||||
|
||||
if devtype == "disk":
|
||||
busstr = virtinst.DeviceDisk.pretty_disk_bus(dev.bus) or ""
|
||||
busstr = vmmAddHardware.disk_pretty_bus(dev.bus) or ""
|
||||
|
||||
if dev.device == "floppy":
|
||||
devstr = _("Floppy")
|
||||
@ -220,28 +220,30 @@ def _label_for_device(dev):
|
||||
|
||||
if devtype == "channel":
|
||||
label = _("Channel")
|
||||
name = dev.pretty_channel_name(dev.target_name)
|
||||
name = vmmAddHardware.char_pretty_channel_name(dev.target_name)
|
||||
if not name:
|
||||
name = dev.pretty_type(dev.type)
|
||||
name = vmmAddHardware.char_pretty_type(dev.type)
|
||||
if name:
|
||||
label += " %s" % name
|
||||
return label
|
||||
|
||||
if devtype == "graphics":
|
||||
return _("Display %s") % dev.pretty_type_simple(dev.type)
|
||||
pretty = vmmGraphicsDetails.graphics_pretty_type_simple(dev.type)
|
||||
return _("Display %s") % pretty
|
||||
if devtype == "redirdev":
|
||||
return _("%s Redirector %s") % (dev.bus.upper(),
|
||||
dev.get_xml_idx() + 1)
|
||||
if devtype == "hostdev":
|
||||
return dev.pretty_name()
|
||||
return vmmAddHardware.hostdev_pretty_name(dev)
|
||||
if devtype == "sound":
|
||||
return _("Sound %s") % dev.model
|
||||
if devtype == "video":
|
||||
return _("Video %s") % dev.pretty_model(dev.model)
|
||||
return _("Video %s") % vmmAddHardware.video_pretty_model(dev.model)
|
||||
if devtype == "filesystem":
|
||||
return _("Filesystem %s") % dev.target[:8]
|
||||
if devtype == "controller":
|
||||
return _("Controller %s %s") % (dev.pretty_desc(), dev.index)
|
||||
return _("Controller %s %s") % (
|
||||
vmmAddHardware.controller_pretty_desc(dev), dev.index)
|
||||
if devtype == "rng":
|
||||
label = _("RNG")
|
||||
if dev.device:
|
||||
@ -2269,7 +2271,7 @@ class vmmDetails(vmmGObjectUI):
|
||||
self.netlist.set_dev(net)
|
||||
|
||||
def refresh_input_page(self, inp):
|
||||
dev = inp.pretty_name(inp.type, inp.bus)
|
||||
dev = vmmAddHardware.input_pretty_name(inp.type, inp.bus)
|
||||
|
||||
mode = None
|
||||
if inp.type == "tablet":
|
||||
@ -2302,7 +2304,8 @@ class vmmDetails(vmmGObjectUI):
|
||||
address = _("%s:%s") % (rd.source.host, rd.source.service)
|
||||
|
||||
self.widget("redir-title").set_markup(_label_for_device(rd))
|
||||
self.widget("redir-type").set_text(rd.pretty_type(rd.type))
|
||||
self.widget("redir-type").set_text(
|
||||
vmmAddHardware.redirdev_pretty_type(rd.type))
|
||||
|
||||
self.widget("redir-address").set_text(address or "")
|
||||
uiutil.set_grid_row_visible(
|
||||
@ -2316,7 +2319,7 @@ class vmmDetails(vmmGObjectUI):
|
||||
|
||||
dev_type = tpmdev.type
|
||||
self.widget("tpm-dev-type").set_text(
|
||||
virtinst.DeviceTpm.get_pretty_type(dev_type))
|
||||
vmmAddHardware.tpm_pretty_type(dev_type))
|
||||
|
||||
vmmAddHardware.populate_tpm_model_combo(
|
||||
self.vm, self.widget("tpm-model"), tpmdev.version)
|
||||
@ -2328,7 +2331,7 @@ class vmmDetails(vmmGObjectUI):
|
||||
|
||||
def refresh_panic_page(self, dev):
|
||||
model = dev.model or "isa"
|
||||
pmodel = virtinst.DevicePanic.get_pretty_model(model)
|
||||
pmodel = vmmAddHardware.panic_pretty_model(model)
|
||||
self.widget("panic-model").set_text(pmodel)
|
||||
|
||||
def refresh_rng_page(self, dev):
|
||||
@ -2336,7 +2339,7 @@ class vmmDetails(vmmGObjectUI):
|
||||
uiutil.set_grid_row_visible(self.widget("rng-device"), is_random)
|
||||
|
||||
self.widget("rng-type").set_text(
|
||||
dev.get_pretty_type(dev.backend_model))
|
||||
vmmAddHardware.rng_pretty_type(dev.backend_model))
|
||||
self.widget("rng-device").set_text(dev.device or "")
|
||||
|
||||
def refresh_vsock_page(self, dev):
|
||||
@ -2413,13 +2416,13 @@ class vmmDetails(vmmGObjectUI):
|
||||
nodedev = None
|
||||
for trydev in self.vm.conn.filter_nodedevs(devtype):
|
||||
if trydev.xmlobj.compare_to_hostdev(hostdev):
|
||||
nodedev = trydev.xmlobj
|
||||
nodedev = trydev
|
||||
|
||||
pretty_name = None
|
||||
if nodedev:
|
||||
pretty_name = nodedev.pretty_name()
|
||||
if not pretty_name:
|
||||
pretty_name = hostdev.pretty_name()
|
||||
pretty_name = vmmAddHardware.hostdev_pretty_name(hostdev)
|
||||
|
||||
uiutil.set_grid_row_visible(
|
||||
self.widget("hostdev-rombar"), hostdev.type == "pci")
|
||||
@ -2499,7 +2502,7 @@ class vmmDetails(vmmGObjectUI):
|
||||
_("Cannot remove controller while devices are attached."))
|
||||
break
|
||||
|
||||
type_label = controller.pretty_desc()
|
||||
type_label = vmmAddHardware.controller_pretty_desc(controller)
|
||||
self.widget("controller-type").set_text(type_label)
|
||||
|
||||
combo = self.widget("controller-model")
|
||||
|
@ -131,11 +131,28 @@ class vmmDomainSnapshot(vmmLibvirtObject):
|
||||
ignore = force
|
||||
self._backend.delete()
|
||||
|
||||
def _state_str_to_int(self):
|
||||
state = self.get_xmlobj().state
|
||||
statemap = {
|
||||
"nostate": libvirt.VIR_DOMAIN_NOSTATE,
|
||||
"running": libvirt.VIR_DOMAIN_RUNNING,
|
||||
"blocked": libvirt.VIR_DOMAIN_BLOCKED,
|
||||
"paused": libvirt.VIR_DOMAIN_PAUSED,
|
||||
"shutdown": libvirt.VIR_DOMAIN_SHUTDOWN,
|
||||
"shutoff": libvirt.VIR_DOMAIN_SHUTOFF,
|
||||
"crashed": libvirt.VIR_DOMAIN_CRASHED,
|
||||
"pmsuspended": getattr(libvirt, "VIR_DOMAIN_PMSUSPENDED", 7)
|
||||
}
|
||||
|
||||
if state == "disk-snapshot" or state not in statemap:
|
||||
state = "shutoff"
|
||||
return statemap.get(state, libvirt.VIR_DOMAIN_NOSTATE)
|
||||
|
||||
def run_status(self):
|
||||
status = DomainSnapshot.state_str_to_int(self.get_xmlobj().state)
|
||||
status = self._state_str_to_int()
|
||||
return LibvirtEnumMap.pretty_run_status(status, False)
|
||||
def run_status_icon_name(self):
|
||||
status = DomainSnapshot.state_str_to_int(self.get_xmlobj().state)
|
||||
status = self._state_str_to_int()
|
||||
if status not in LibvirtEnumMap.VM_STATUS_ICONS:
|
||||
logging.debug("Unknown status %d, using NOSTATE", status)
|
||||
status = libvirt.VIR_DOMAIN_NOSTATE
|
||||
|
@ -55,6 +55,20 @@ class vmmGraphicsDetails(vmmGObjectUI):
|
||||
self.vm = None
|
||||
self.conn = None
|
||||
|
||||
|
||||
#####################
|
||||
# Pretty UI helpers #
|
||||
#####################
|
||||
|
||||
@staticmethod
|
||||
def graphics_pretty_type_simple(gtype):
|
||||
if (gtype in [virtinst.DeviceGraphics.TYPE_VNC,
|
||||
virtinst.DeviceGraphics.TYPE_SDL,
|
||||
virtinst.DeviceGraphics.TYPE_RDP]):
|
||||
return str(gtype).upper()
|
||||
return str(gtype).capitalize()
|
||||
|
||||
|
||||
##########################
|
||||
# Initialization methods #
|
||||
##########################
|
||||
@ -109,7 +123,7 @@ class vmmGraphicsDetails(vmmGObjectUI):
|
||||
if not drm.is_drm_render():
|
||||
continue
|
||||
rendernode = drm.get_devnode().path
|
||||
model.append([rendernode, i.xmlobj.pretty_name()])
|
||||
model.append([rendernode, i.pretty_name()])
|
||||
|
||||
def _get_config_graphics_ports(self):
|
||||
port = uiutil.spin_get_helper(self.widget("graphics-port"))
|
||||
@ -193,8 +207,8 @@ class vmmGraphicsDetails(vmmGObjectUI):
|
||||
is_vnc = (gtype == "vnc")
|
||||
is_sdl = (gtype == "sdl")
|
||||
is_spice = (gtype == "spice")
|
||||
title = (_("%(graphicstype)s Server") %
|
||||
{"graphicstype": gfx.pretty_type_simple(gtype)})
|
||||
pretty_type = vmmGraphicsDetails.graphics_pretty_type_simple(gtype)
|
||||
title = (_("%(graphicstype)s Server") % {"graphicstype": pretty_type})
|
||||
|
||||
if is_vnc or is_spice:
|
||||
use_passwd = gfx.passwd is not None
|
||||
|
@ -275,8 +275,15 @@ class vmmHostNets(vmmGObjectUI):
|
||||
def _populate_qos_state(self, net):
|
||||
qos = net.get_qos()
|
||||
|
||||
self.widget("net-qos-inbound-enable").set_active(qos.is_inbound())
|
||||
self.widget("net-qos-outbound-enable").set_active(qos.is_outbound())
|
||||
def is_inbound():
|
||||
return bool(qos.inbound_average or qos.inbound_peak or
|
||||
qos.inbound_burst or qos.inbound_floor)
|
||||
def is_outbound():
|
||||
return bool(qos.outbound_average or qos.outbound_peak or
|
||||
qos.outbound_burst)
|
||||
|
||||
self.widget("net-qos-inbound-enable").set_active(is_inbound())
|
||||
self.widget("net-qos-outbound-enable").set_active(is_outbound())
|
||||
|
||||
self._update_qos_widgets()
|
||||
|
||||
|
@ -125,8 +125,6 @@ class vmmNetwork(vmmLibvirtObject):
|
||||
return self.get_xmlobj().ipv6
|
||||
def get_ipv4_forward_mode(self):
|
||||
return self.get_xmlobj().forward.mode
|
||||
def pretty_forward_mode(self):
|
||||
return self.get_xmlobj().forward.pretty_desc()
|
||||
def get_qos(self):
|
||||
return self.get_xmlobj().bandwidth
|
||||
|
||||
@ -200,3 +198,30 @@ class vmmNetwork(vmmLibvirtObject):
|
||||
pf_name = xmlobj.forward.pf[0].dev
|
||||
vfs = xmlobj.forward.vfs
|
||||
return (ret, pf_name, vfs)
|
||||
|
||||
def pretty_forward_mode(self):
|
||||
mode = self.xmlobj.forward.mode
|
||||
dev = self.xmlobj.forward.dev
|
||||
|
||||
if not mode:
|
||||
return _("Isolated network")
|
||||
|
||||
if mode == "nat":
|
||||
if dev:
|
||||
desc = _("NAT to %s") % dev
|
||||
else:
|
||||
desc = _("NAT")
|
||||
elif mode == "route":
|
||||
if dev:
|
||||
desc = _("Route to %s") % dev
|
||||
else:
|
||||
desc = _("Routed network")
|
||||
else:
|
||||
modestr = mode.capitalize()
|
||||
if dev:
|
||||
desc = (_("%(mode)s to %(device)s") %
|
||||
{"mode": modestr, "device": dev})
|
||||
else:
|
||||
desc = _("%s network") % modestr
|
||||
|
||||
return desc
|
||||
|
@ -9,6 +9,64 @@ from virtinst import NodeDevice
|
||||
from .libvirtobject import vmmLibvirtObject
|
||||
|
||||
|
||||
def _usb_pretty_name(xmlobj):
|
||||
# Hypervisor may return a rather sparse structure, missing
|
||||
# some ol all stringular descriptions of the device altogether.
|
||||
# Do our best to help user identify the device.
|
||||
|
||||
# Certain devices pad their vendor with trailing spaces,
|
||||
# such as "LENOVO ". It does not look well.
|
||||
product = str(xmlobj.product_name).strip()
|
||||
vendor = str(xmlobj.vendor_name).strip()
|
||||
|
||||
if product == "":
|
||||
product = str(xmlobj.product_id)
|
||||
if vendor == "":
|
||||
# No stringular descriptions altogether
|
||||
vendor = str(xmlobj.vendor_id)
|
||||
devstr = "%s:%s" % (vendor, product)
|
||||
else:
|
||||
# Only the vendor is known
|
||||
devstr = "%s %s" % (vendor, product)
|
||||
else:
|
||||
if vendor == "":
|
||||
# Sometimes vendor is left out empty, but product is
|
||||
# already descriptive enough or contains the vendor string:
|
||||
# "Lenovo USB Laser Mouse"
|
||||
devstr = product
|
||||
else:
|
||||
# We know everything. Perfect.
|
||||
devstr = "%s %s" % (vendor, product)
|
||||
|
||||
busstr = "%.3d:%.3d" % (int(xmlobj.bus), int(xmlobj.device))
|
||||
desc = "%s %s" % (busstr, devstr)
|
||||
return desc
|
||||
|
||||
|
||||
def _pretty_name(xmlobj):
|
||||
if xmlobj.device_type == "net":
|
||||
if xmlobj.interface:
|
||||
return _("Interface %s") % xmlobj.interface
|
||||
return xmlobj.name
|
||||
|
||||
if xmlobj.device_type == "pci":
|
||||
devstr = "%.4X:%.2X:%.2X:%X" % (int(xmlobj.domain),
|
||||
int(xmlobj.bus),
|
||||
int(xmlobj.slot),
|
||||
int(xmlobj.function))
|
||||
return "%s %s %s" % (devstr,
|
||||
xmlobj.vendor_name, xmlobj.product_name)
|
||||
if xmlobj.device_type == "usb_device":
|
||||
return _usb_pretty_name(xmlobj)
|
||||
|
||||
if xmlobj.device_type == "drm":
|
||||
parent = NodeDevice.lookupNodedevFromString(
|
||||
xmlobj.conn, xmlobj.parent)
|
||||
return "%s (%s)" % (_pretty_name(parent), xmlobj.drm_type)
|
||||
|
||||
return xmlobj.name
|
||||
|
||||
|
||||
class vmmNodeDevice(vmmLibvirtObject):
|
||||
def __init__(self, conn, backend, key):
|
||||
vmmLibvirtObject.__init__(self, conn, backend, key, NodeDevice)
|
||||
@ -34,3 +92,6 @@ class vmmNodeDevice(vmmLibvirtObject):
|
||||
ignore = stats_update
|
||||
def _init_libvirt_state(self):
|
||||
self.ensure_latest_xml()
|
||||
|
||||
def pretty_name(self):
|
||||
return _pretty_name(self.xmlobj)
|
||||
|
@ -16,6 +16,7 @@ from gi.repository import Gtk
|
||||
from gi.repository import Pango
|
||||
|
||||
from virtinst import DomainSnapshot
|
||||
from virtinst import generatename
|
||||
from virtinst import xmlutil
|
||||
|
||||
from . import uiutil
|
||||
@ -117,8 +118,11 @@ class vmmSnapshotNew(vmmGObjectUI):
|
||||
|
||||
def _reset_state(self):
|
||||
collidelist = [s.get_xmlobj().name for s in self.vm.list_snapshots()]
|
||||
default_name = DomainSnapshot.find_free_name(
|
||||
self.vm.get_backend(), collidelist)
|
||||
basename = "snapshot"
|
||||
cb = self.vm.get_backend().snapshotLookupByName
|
||||
default_name = generatename.generate_name(
|
||||
basename, cb, sep="", start_num=1, force_num=True,
|
||||
collidelist=collidelist)
|
||||
|
||||
self.widget("snapshot-new-name").set_text(default_name)
|
||||
self.widget("snapshot-new-name").emit("changed")
|
||||
@ -210,8 +214,8 @@ class vmmSnapshotNew(vmmGObjectUI):
|
||||
newsnap = DomainSnapshot(self.vm.conn.get_backend())
|
||||
newsnap.name = name
|
||||
newsnap.description = desc or None
|
||||
newsnap.validate()
|
||||
newsnap.get_xml()
|
||||
newsnap.validate_generic_name(_("Snapshot"), newsnap.name)
|
||||
return newsnap
|
||||
except Exception as e:
|
||||
return self.err.val_err(_("Error validating snapshot: %s") % e)
|
||||
|
@ -90,62 +90,6 @@ class _DeviceChar(Device):
|
||||
CHANNEL_NAME_LIBGUESTFS,
|
||||
CHANNEL_NAME_SPICE_WEBDAV]
|
||||
|
||||
@classmethod
|
||||
def get_recommended_types(cls, _guest):
|
||||
if cls.XML_NAME == "console":
|
||||
return [cls.TYPE_PTY]
|
||||
|
||||
ret = [cls.TYPE_PTY, cls.TYPE_FILE, cls.TYPE_UNIX]
|
||||
if cls.XML_NAME == "channel":
|
||||
ret = [cls.TYPE_SPICEVMC, cls.TYPE_SPICEPORT] + ret
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def pretty_channel_name(val):
|
||||
if val == _DeviceChar.CHANNEL_NAME_SPICE:
|
||||
return "spice"
|
||||
if val == _DeviceChar.CHANNEL_NAME_QEMUGA:
|
||||
return "qemu-ga"
|
||||
if val == _DeviceChar.CHANNEL_NAME_LIBGUESTFS:
|
||||
return "libguestfs"
|
||||
if val == _DeviceChar.CHANNEL_NAME_SPICE_WEBDAV:
|
||||
return "spice-webdav"
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def pretty_type(ctype):
|
||||
"""
|
||||
Return a human readable description of the passed char type
|
||||
"""
|
||||
desc = ""
|
||||
|
||||
if ctype == _DeviceChar.TYPE_PTY:
|
||||
desc = _("Pseudo TTY")
|
||||
elif ctype == _DeviceChar.TYPE_DEV:
|
||||
desc = _("Physical host character device")
|
||||
elif ctype == _DeviceChar.TYPE_STDIO:
|
||||
desc = _("Standard input/output")
|
||||
elif ctype == _DeviceChar.TYPE_PIPE:
|
||||
desc = _("Named pipe")
|
||||
elif ctype == _DeviceChar.TYPE_FILE:
|
||||
desc = _("Output to a file")
|
||||
elif ctype == _DeviceChar.TYPE_VC:
|
||||
desc = _("Virtual console")
|
||||
elif ctype == _DeviceChar.TYPE_NULL:
|
||||
desc = _("Null device")
|
||||
elif ctype == _DeviceChar.TYPE_TCP:
|
||||
desc = _("TCP net console")
|
||||
elif ctype == _DeviceChar.TYPE_UDP:
|
||||
desc = _("UDP net console")
|
||||
elif ctype == _DeviceChar.TYPE_UNIX:
|
||||
desc = _("Unix socket")
|
||||
elif ctype == _DeviceChar.TYPE_SPICEVMC:
|
||||
desc = _("Spice agent")
|
||||
elif ctype == _DeviceChar.TYPE_SPICEPORT:
|
||||
desc = _("Spice port")
|
||||
|
||||
return desc
|
||||
|
||||
def set_friendly_target(self, val):
|
||||
_set_host_helper(self, "target_address", "target_port", val)
|
||||
|
||||
|
@ -21,31 +21,6 @@ class DeviceController(Device):
|
||||
TYPE_CCID = "ccid"
|
||||
TYPE_XENBUS = "xenbus"
|
||||
|
||||
@staticmethod
|
||||
def get_recommended_types(_guest):
|
||||
return [DeviceController.TYPE_SCSI,
|
||||
DeviceController.TYPE_USB,
|
||||
DeviceController.TYPE_VIRTIOSERIAL,
|
||||
DeviceController.TYPE_CCID]
|
||||
|
||||
@staticmethod
|
||||
def pretty_type(ctype):
|
||||
pretty_mappings = {
|
||||
DeviceController.TYPE_IDE: "IDE",
|
||||
DeviceController.TYPE_FDC: _("Floppy"),
|
||||
DeviceController.TYPE_SCSI: "SCSI",
|
||||
DeviceController.TYPE_SATA: "SATA",
|
||||
DeviceController.TYPE_VIRTIOSERIAL: "VirtIO Serial",
|
||||
DeviceController.TYPE_USB: "USB",
|
||||
DeviceController.TYPE_PCI: "PCI",
|
||||
DeviceController.TYPE_CCID: "CCID",
|
||||
DeviceController.TYPE_XENBUS: "xenbus",
|
||||
}
|
||||
|
||||
if ctype not in pretty_mappings:
|
||||
return ctype
|
||||
return pretty_mappings[ctype]
|
||||
|
||||
@staticmethod
|
||||
def get_usb2_controllers(conn):
|
||||
ret = []
|
||||
@ -101,17 +76,6 @@ class DeviceController(Device):
|
||||
|
||||
index = XMLProperty("./@index", is_int=True)
|
||||
|
||||
def pretty_desc(self):
|
||||
ret = self.pretty_type(self.type)
|
||||
if self.type == "scsi":
|
||||
if self.model == "virtio-scsi":
|
||||
ret = "Virtio " + ret
|
||||
elif self.address.type == "spapr-vio":
|
||||
ret = "sPAPR " + ret
|
||||
if self.type == "pci" and self.model == "pcie-root":
|
||||
ret = "PCIe"
|
||||
return ret
|
||||
|
||||
|
||||
##################
|
||||
# Default config #
|
||||
|
@ -77,54 +77,6 @@ class DeviceDisk(Device):
|
||||
IO_MODE_THREADS = "threads"
|
||||
IO_MODES = [IO_MODE_NATIVE, IO_MODE_THREADS]
|
||||
|
||||
@staticmethod
|
||||
def get_old_recommended_buses(guest):
|
||||
ret = []
|
||||
if guest.os.is_hvm() or guest.conn.is_test():
|
||||
if not guest.os.is_q35():
|
||||
ret.append("ide")
|
||||
ret.append("sata")
|
||||
ret.append("fdc")
|
||||
ret.append("scsi")
|
||||
ret.append("usb")
|
||||
|
||||
if guest.type in ["qemu", "kvm", "test"]:
|
||||
ret.append("sd")
|
||||
ret.append("virtio")
|
||||
if "scsi" not in ret:
|
||||
ret.append("scsi")
|
||||
|
||||
if guest.conn.is_xen() or guest.conn.is_test():
|
||||
ret.append("xen")
|
||||
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def get_recommended_buses(guest, domcaps, devtype):
|
||||
# try to get supported disk bus types from domain capabilities
|
||||
if "bus" in domcaps.devices.disk.enum_names():
|
||||
buses = domcaps.devices.disk.get_enum("bus").get_values()
|
||||
else:
|
||||
buses = DeviceDisk.get_old_recommended_buses(guest)
|
||||
|
||||
bus_map = {
|
||||
"disk": ["ide", "sata", "scsi", "sd", "usb", "virtio", "xen"],
|
||||
"floppy": ["fdc"],
|
||||
"cdrom": ["ide", "sata", "scsi"],
|
||||
"lun": ["scsi"],
|
||||
}
|
||||
return [bus for bus in buses if bus in bus_map.get(devtype, [])]
|
||||
|
||||
@staticmethod
|
||||
def pretty_disk_bus(bus):
|
||||
if bus in ["ide", "sata", "scsi", "usb", "sd"]:
|
||||
return bus.upper()
|
||||
if bus in ["xen"]:
|
||||
return bus.capitalize()
|
||||
if bus == "virtio":
|
||||
return "VirtIO"
|
||||
return bus
|
||||
|
||||
@staticmethod
|
||||
def path_definitely_exists(conn, path):
|
||||
"""
|
||||
|
@ -72,15 +72,6 @@ class DeviceGraphics(Device):
|
||||
|
||||
return sort_list
|
||||
|
||||
@staticmethod
|
||||
def pretty_type_simple(gtype):
|
||||
if (gtype in [DeviceGraphics.TYPE_VNC,
|
||||
DeviceGraphics.TYPE_SDL,
|
||||
DeviceGraphics.TYPE_RDP]):
|
||||
return str(gtype).upper()
|
||||
|
||||
return str(gtype).capitalize()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
Device.__init__(self, *args, **kwargs)
|
||||
|
||||
|
@ -68,34 +68,6 @@ class DeviceHostdev(Device):
|
||||
else:
|
||||
raise ValueError(_("Unknown node device type %s") % nodedev)
|
||||
|
||||
def pretty_name(self):
|
||||
def dehex(val):
|
||||
if val.startswith("0x"):
|
||||
val = val[2:]
|
||||
return val
|
||||
|
||||
def safeint(val, fmt="%.3d"):
|
||||
try:
|
||||
int(val)
|
||||
except Exception:
|
||||
return str(val)
|
||||
return fmt % int(val)
|
||||
|
||||
label = self.type.upper()
|
||||
|
||||
if self.vendor and self.product:
|
||||
label += " %s:%s" % (dehex(self.vendor), dehex(self.product))
|
||||
|
||||
elif self.bus and self.device:
|
||||
label += " %s:%s" % (safeint(self.bus), safeint(self.device))
|
||||
|
||||
elif self.bus and self.slot and self.function and self.domain:
|
||||
label += (" %s:%s:%s.%s" %
|
||||
(dehex(self.domain), dehex(self.bus),
|
||||
dehex(self.slot), dehex(self.function)))
|
||||
|
||||
return label
|
||||
|
||||
|
||||
_XML_PROP_ORDER = ["mode", "type", "managed", "vendor", "product",
|
||||
"domain", "bus", "slot", "function"]
|
||||
|
@ -20,16 +20,6 @@ class DeviceInput(Device):
|
||||
BUS_VIRTIO = "virtio"
|
||||
BUS_XEN = "xen"
|
||||
|
||||
@staticmethod
|
||||
def pretty_name(typ, bus):
|
||||
if typ == "tablet" and bus == "usb":
|
||||
return _("EvTouch USB Graphics Tablet")
|
||||
|
||||
if bus in ["usb", "ps2"]:
|
||||
return _("Generic") + (" %s %s" %
|
||||
(bus.upper(), str(typ).capitalize()))
|
||||
return "%s %s" % (str(bus).capitalize(), str(typ).capitalize())
|
||||
|
||||
|
||||
type = XMLProperty("./@type")
|
||||
bus = XMLProperty("./@bus")
|
||||
|
@ -117,42 +117,6 @@ class DeviceInterface(Device):
|
||||
TYPE_ETHERNET = "ethernet"
|
||||
TYPE_DIRECT = "direct"
|
||||
|
||||
@staticmethod
|
||||
def get_models(guest):
|
||||
if not guest.os.is_hvm():
|
||||
return []
|
||||
|
||||
ret = []
|
||||
if guest.type in ["kvm", "qemu", "vz", "test"]:
|
||||
ret.append("virtio")
|
||||
if guest.os.is_x86():
|
||||
if guest.os.is_q35():
|
||||
ret.append("e1000e")
|
||||
else:
|
||||
ret.append("rtl8139")
|
||||
ret.append("e1000")
|
||||
if guest.type in ["xen", "test"]:
|
||||
ret.append("netfront")
|
||||
|
||||
ret.sort()
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def get_network_type_desc(net_type):
|
||||
"""
|
||||
Return human readable description for passed network type
|
||||
"""
|
||||
desc = net_type.capitalize()
|
||||
|
||||
if net_type == DeviceInterface.TYPE_BRIDGE:
|
||||
desc = _("Shared physical device")
|
||||
elif net_type == DeviceInterface.TYPE_VIRTUAL:
|
||||
desc = _("Virtual networking")
|
||||
elif net_type == DeviceInterface.TYPE_USER:
|
||||
desc = _("Usermode networking")
|
||||
|
||||
return desc
|
||||
|
||||
@staticmethod
|
||||
def generate_mac(conn):
|
||||
"""
|
||||
|
@ -17,29 +17,6 @@ class DevicePanic(Device):
|
||||
MODEL_HYPERV = "hyperv"
|
||||
MODEL_S390 = "s390"
|
||||
|
||||
@staticmethod
|
||||
def get_pretty_model(panic_model):
|
||||
if panic_model == DevicePanic.MODEL_ISA:
|
||||
return _("ISA")
|
||||
elif panic_model == DevicePanic.MODEL_PSERIES:
|
||||
return _("pSeries")
|
||||
elif panic_model == DevicePanic.MODEL_HYPERV:
|
||||
return _("Hyper-V")
|
||||
elif panic_model == DevicePanic.MODEL_S390:
|
||||
return _("s390")
|
||||
return panic_model
|
||||
|
||||
@staticmethod
|
||||
def get_models(os):
|
||||
if os.is_x86():
|
||||
return [DevicePanic.MODEL_ISA,
|
||||
DevicePanic.MODEL_HYPERV]
|
||||
elif os.is_pseries():
|
||||
return [DevicePanic.MODEL_PSERIES]
|
||||
elif os.is_s390x():
|
||||
return [DevicePanic.MODEL_S390]
|
||||
return []
|
||||
|
||||
model = XMLProperty("./@model")
|
||||
|
||||
|
||||
@ -47,9 +24,20 @@ class DevicePanic(Device):
|
||||
# Default config #
|
||||
##################
|
||||
|
||||
@staticmethod
|
||||
def get_models(guest):
|
||||
if guest.os.is_x86():
|
||||
return [DevicePanic.MODEL_ISA,
|
||||
DevicePanic.MODEL_HYPERV]
|
||||
elif guest.os.is_pseries():
|
||||
return [DevicePanic.MODEL_PSERIES]
|
||||
elif guest.os.is_s390x():
|
||||
return [DevicePanic.MODEL_S390]
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def get_default_model(guest):
|
||||
models = DevicePanic.get_models(guest.os)
|
||||
models = DevicePanic.get_models(guest)
|
||||
if models:
|
||||
return models[0]
|
||||
return None
|
||||
|
@ -12,14 +12,6 @@ from ..xmlbuilder import XMLChildProperty, XMLProperty
|
||||
class DeviceRedirdev(Device):
|
||||
XML_NAME = "redirdev"
|
||||
|
||||
@staticmethod
|
||||
def pretty_type(typ):
|
||||
if typ == "tcp":
|
||||
return "TCP"
|
||||
if typ == "spicevmc":
|
||||
return "SpiceVMC"
|
||||
return typ and typ.capitalize()
|
||||
|
||||
_XML_PROP_ORDER = ["bus", "type", "source"]
|
||||
|
||||
bus = XMLProperty("./@bus")
|
||||
|
@ -15,24 +15,6 @@ class DeviceRng(Device):
|
||||
TYPE_RANDOM = "random"
|
||||
TYPE_EGD = "egd"
|
||||
|
||||
@staticmethod
|
||||
def get_pretty_type(rng_type):
|
||||
if rng_type == DeviceRng.TYPE_RANDOM:
|
||||
return _("Random")
|
||||
if rng_type == DeviceRng.TYPE_EGD:
|
||||
return _("Entropy Gathering Daemon")
|
||||
return rng_type
|
||||
|
||||
@staticmethod
|
||||
def get_pretty_backend_type(backend_type):
|
||||
return {"udp": "UDP",
|
||||
"tcp": "TCP"}.get(backend_type) or backend_type
|
||||
|
||||
@staticmethod
|
||||
def get_pretty_mode(mode):
|
||||
return {"bind": _("Bind"),
|
||||
"connect": _("Connect")}.get(mode) or mode
|
||||
|
||||
model = XMLProperty("./@model")
|
||||
|
||||
backend_model = XMLProperty("./backend/@model")
|
||||
|
@ -20,18 +20,6 @@ class _Codec(XMLBuilder):
|
||||
class DeviceSound(Device):
|
||||
XML_NAME = "sound"
|
||||
|
||||
@staticmethod
|
||||
def get_recommended_models(_guest):
|
||||
return ["ich6", "ich9", "ac97"]
|
||||
|
||||
@staticmethod
|
||||
def pretty_model(model):
|
||||
ret = model.upper()
|
||||
if model in ["ich6", "ich9"]:
|
||||
ret = "HDA (%s)" % model.upper()
|
||||
return ret
|
||||
|
||||
|
||||
model = XMLProperty("./@model")
|
||||
codecs = XMLChildProperty(_Codec)
|
||||
|
||||
|
@ -24,22 +24,6 @@ class DeviceTpm(Device):
|
||||
MODEL_CRB = "tpm-crb"
|
||||
MODELS = [MODEL_TIS, MODEL_CRB]
|
||||
|
||||
@staticmethod
|
||||
def get_pretty_type(tpm_type):
|
||||
if tpm_type == DeviceTpm.TYPE_PASSTHROUGH:
|
||||
return _("Passthrough device")
|
||||
if tpm_type == DeviceTpm.TYPE_EMULATOR:
|
||||
return _("Emulated device")
|
||||
return tpm_type
|
||||
|
||||
@staticmethod
|
||||
def get_pretty_model(tpm_model):
|
||||
if tpm_model == DeviceTpm.MODEL_TIS:
|
||||
return _("TIS")
|
||||
if tpm_model == DeviceTpm.MODEL_CRB:
|
||||
return _("CRB")
|
||||
return tpm_model
|
||||
|
||||
type = XMLProperty("./backend/@type")
|
||||
version = XMLProperty("./backend/@version")
|
||||
model = XMLProperty("./@model")
|
||||
|
@ -11,20 +11,6 @@ from ..xmlbuilder import XMLProperty
|
||||
class DeviceVideo(Device):
|
||||
XML_NAME = "video"
|
||||
|
||||
@staticmethod
|
||||
def get_recommended_models(guest):
|
||||
if guest.conn.is_xen():
|
||||
return ["xen", "vga"]
|
||||
if guest.conn.is_qemu() or guest.conn.is_test():
|
||||
return ["vga", "qxl", "virtio"]
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def pretty_model(model):
|
||||
if model in ["qxl", "vmvga", "vga"]:
|
||||
return model.upper()
|
||||
return model.capitalize()
|
||||
|
||||
_XML_PROP_ORDER = ["model", "vram", "heads", "vgamem"]
|
||||
model = XMLProperty("./model/@type")
|
||||
vram = XMLProperty("./model/@vram", is_int=True)
|
||||
|
@ -26,22 +26,6 @@ class DeviceWatchdog(Device):
|
||||
ACTION_POWEROFF, ACTION_PAUSE,
|
||||
ACTION_DUMP, ACTION_NONE]
|
||||
|
||||
@staticmethod
|
||||
def get_action_desc(action):
|
||||
if action == DeviceWatchdog.ACTION_RESET:
|
||||
return _("Forcefully reset the guest")
|
||||
if action == DeviceWatchdog.ACTION_SHUTDOWN:
|
||||
return _("Gracefully shutdown the guest")
|
||||
if action == DeviceWatchdog.ACTION_POWEROFF:
|
||||
return _("Forcefully power off the guest")
|
||||
if action == DeviceWatchdog.ACTION_PAUSE:
|
||||
return _("Pause the guest")
|
||||
if action == DeviceWatchdog.ACTION_NONE:
|
||||
return _("No action")
|
||||
if action == DeviceWatchdog.ACTION_DUMP:
|
||||
return _("Dump guest memory core")
|
||||
return action
|
||||
|
||||
_XML_PROP_ORDER = ["model", "action"]
|
||||
model = XMLProperty("./@model")
|
||||
action = XMLProperty("./@action")
|
||||
|
@ -7,11 +7,6 @@
|
||||
Classes for building and installing libvirt <network> XML
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
import libvirt
|
||||
|
||||
from . import generatename
|
||||
from .xmlbuilder import XMLBuilder, XMLChildProperty, XMLProperty
|
||||
|
||||
|
||||
@ -77,9 +72,6 @@ class _NetworkForward(XMLBuilder):
|
||||
pf = XMLChildProperty(_NetworkForwardPf)
|
||||
vfs = XMLChildProperty(_NetworkForwardAddress)
|
||||
|
||||
def pretty_desc(self):
|
||||
return Network.pretty_forward_desc(self.mode, self.dev)
|
||||
|
||||
|
||||
class _NetworkBandwidth(XMLBuilder):
|
||||
XML_NAME = "bandwidth"
|
||||
@ -93,45 +85,6 @@ class _NetworkBandwidth(XMLBuilder):
|
||||
outbound_peak = XMLProperty("./outbound/@peak")
|
||||
outbound_burst = XMLProperty("./outbound/@burst")
|
||||
|
||||
def is_inbound(self):
|
||||
return bool(self.inbound_average or self.inbound_peak or
|
||||
self.inbound_burst or self.inbound_floor)
|
||||
|
||||
def is_outbound(self):
|
||||
return bool(self.outbound_average or self.outbound_peak or
|
||||
self.outbound_burst)
|
||||
|
||||
def pretty_desc(self, inbound=True, outbound=True):
|
||||
items_in = [(self.inbound_average, _("Average"), "KiB/s"),
|
||||
(self.inbound_peak, _("Peak"), "KiB"),
|
||||
(self.inbound_burst, _("Burst"), "KiB/s"),
|
||||
(self.inbound_floor, _("Floor"), "KiB/s")]
|
||||
|
||||
items_out = [(self.outbound_average, _("Average"), "KiB/s"),
|
||||
(self.outbound_peak, _("Peak"), "KiB"),
|
||||
(self.outbound_burst, _("Burst"), "KiB/s")]
|
||||
|
||||
def stringify_items(items):
|
||||
return ", ".join(["%s: %s %s" % (desc, val, unit)
|
||||
for val, desc, unit in items if val])
|
||||
|
||||
ret = ""
|
||||
show_name = inbound and outbound
|
||||
|
||||
if inbound:
|
||||
if show_name:
|
||||
ret += _("Inbound: ")
|
||||
ret += stringify_items(items_in)
|
||||
|
||||
if outbound:
|
||||
if ret:
|
||||
ret += "\n"
|
||||
if show_name:
|
||||
ret += _("Outbound: ")
|
||||
ret += stringify_items(items_out)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
class _NetworkPortgroup(XMLBuilder):
|
||||
XML_NAME = "portgroup"
|
||||
@ -144,70 +97,6 @@ class Network(XMLBuilder):
|
||||
"""
|
||||
Top level class for <network> object XML
|
||||
"""
|
||||
@staticmethod
|
||||
def find_free_name(conn, basename, **kwargs):
|
||||
cb = conn.networkLookupByName
|
||||
return generatename.generate_name(basename, cb, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
def pretty_forward_desc(mode, dev):
|
||||
if not mode:
|
||||
return _("Isolated network")
|
||||
|
||||
if mode == "nat":
|
||||
if dev:
|
||||
desc = _("NAT to %s") % dev
|
||||
else:
|
||||
desc = _("NAT")
|
||||
elif mode == "route":
|
||||
if dev:
|
||||
desc = _("Route to %s") % dev
|
||||
else:
|
||||
desc = _("Routed network")
|
||||
else:
|
||||
modestr = mode.capitalize()
|
||||
if dev:
|
||||
desc = (_("%(mode)s to %(device)s") %
|
||||
{"mode": modestr, "device": dev})
|
||||
else:
|
||||
desc = _("%s network") % modestr
|
||||
|
||||
return desc
|
||||
|
||||
|
||||
###################
|
||||
# Helper routines #
|
||||
###################
|
||||
|
||||
def can_pxe(self):
|
||||
forward = self.forward.mode
|
||||
if forward and forward != "nat":
|
||||
return True
|
||||
for ip in self.ips:
|
||||
if ip.bootp_file:
|
||||
return True
|
||||
return False
|
||||
|
||||
######################
|
||||
# Validation helpers #
|
||||
######################
|
||||
|
||||
@staticmethod
|
||||
def validate_name(conn, name):
|
||||
XMLBuilder.validate_generic_name(_("Network"), name)
|
||||
|
||||
try:
|
||||
conn.networkLookupByName(name)
|
||||
except libvirt.libvirtError:
|
||||
return
|
||||
raise ValueError(_("Name '%s' already in use by another network." %
|
||||
name))
|
||||
|
||||
|
||||
##################
|
||||
# XML properties #
|
||||
##################
|
||||
|
||||
XML_NAME = "network"
|
||||
_XML_PROP_ORDER = ["ipv6", "name", "uuid", "forward", "virtualport_type",
|
||||
"bridge", "stp", "delay", "domain_name",
|
||||
@ -235,23 +124,15 @@ class Network(XMLBuilder):
|
||||
bandwidth = XMLChildProperty(_NetworkBandwidth, is_single=True)
|
||||
|
||||
|
||||
##################
|
||||
# build routines #
|
||||
##################
|
||||
###################
|
||||
# Helper routines #
|
||||
###################
|
||||
|
||||
def install(self, start=True, autostart=True):
|
||||
xml = self.get_xml()
|
||||
logging.debug("Creating virtual network '%s' with xml:\n%s",
|
||||
self.name, xml)
|
||||
|
||||
net = self.conn.networkDefineXML(xml)
|
||||
try:
|
||||
if start:
|
||||
net.create()
|
||||
if autostart:
|
||||
net.setAutostart(autostart)
|
||||
except Exception:
|
||||
net.undefine()
|
||||
raise
|
||||
|
||||
return net
|
||||
def can_pxe(self):
|
||||
forward = self.forward.mode
|
||||
if forward and forward != "nat":
|
||||
return True
|
||||
for ip in self.ips:
|
||||
if ip.bootp_file:
|
||||
return True
|
||||
return False
|
||||
|
@ -106,68 +106,6 @@ class NodeDevice(XMLBuilder):
|
||||
|
||||
return False
|
||||
|
||||
def _usb_pretty_name(self):
|
||||
# Hypervisor may return a rather sparse structure, missing
|
||||
# some ol all stringular descriptions of the device altogether.
|
||||
# Do our best to help user identify the device.
|
||||
|
||||
# Certain devices pad their vendor with trailing spaces,
|
||||
# such as "LENOVO ". It does not look well.
|
||||
product = str(self._product_name).strip()
|
||||
vendor = str(self._vendor_name).strip()
|
||||
|
||||
if product == "":
|
||||
product = str(self.product_id)
|
||||
if vendor == "":
|
||||
# No stringular descriptions altogether
|
||||
vendor = str(self.vendor_id)
|
||||
devstr = "%s:%s" % (vendor, product)
|
||||
else:
|
||||
# Only the vendor is known
|
||||
devstr = "%s %s" % (vendor, product)
|
||||
else:
|
||||
if vendor == "":
|
||||
# Sometimes vendor is left out empty, but product is
|
||||
# already descriptive enough or contains the vendor string:
|
||||
# "Lenovo USB Laser Mouse"
|
||||
devstr = product
|
||||
else:
|
||||
# We know everything. Perfect.
|
||||
devstr = "%s %s" % (vendor, product)
|
||||
|
||||
busstr = "%.3d:%.3d" % (int(self.bus), int(self.device))
|
||||
desc = "%s %s" % (busstr, devstr)
|
||||
return desc
|
||||
|
||||
def pretty_name(self):
|
||||
"""
|
||||
Use device information to attempt to print a human readable device
|
||||
name.
|
||||
|
||||
:returns: Device description string
|
||||
"""
|
||||
if self.device_type == "net":
|
||||
if self.interface:
|
||||
return _("Interface %s") % self.interface
|
||||
return self.name
|
||||
|
||||
if self.device_type == "pci":
|
||||
devstr = "%.4X:%.2X:%.2X:%X" % (int(self.domain),
|
||||
int(self.bus),
|
||||
int(self.slot),
|
||||
int(self.function))
|
||||
return "%s %s %s" % (devstr,
|
||||
self._vendor_name, self._product_name)
|
||||
if self.device_type == "usb_device":
|
||||
return self._usb_pretty_name()
|
||||
|
||||
if self.device_type == "drm":
|
||||
parent = NodeDevice.lookupNodedevFromString(
|
||||
self.conn, self.parent)
|
||||
return "%s (%s)" % (parent.pretty_name(), self._drm_type)
|
||||
|
||||
return self.name
|
||||
|
||||
|
||||
########################
|
||||
# XML helper functions #
|
||||
@ -183,7 +121,7 @@ class NodeDevice(XMLBuilder):
|
||||
self.product_id in ["0x0001", "0x0002", "0x0003"])
|
||||
|
||||
def is_drm_render(self):
|
||||
return self.device_type == "drm" and self._drm_type == "render"
|
||||
return self.device_type == "drm" and self.drm_type == "render"
|
||||
|
||||
|
||||
##################
|
||||
@ -198,8 +136,8 @@ class NodeDevice(XMLBuilder):
|
||||
bus = XMLProperty("./capability/bus")
|
||||
slot = XMLProperty("./capability/slot")
|
||||
function = XMLProperty("./capability/function")
|
||||
_product_name = XMLProperty("./capability/product")
|
||||
_vendor_name = XMLProperty("./capability/vendor")
|
||||
product_name = XMLProperty("./capability/product")
|
||||
vendor_name = XMLProperty("./capability/vendor")
|
||||
_capability_type = XMLProperty("./capability/capability/@type")
|
||||
|
||||
# type='usb' options
|
||||
@ -223,7 +161,7 @@ class NodeDevice(XMLBuilder):
|
||||
is_int=True)
|
||||
|
||||
# type='drm' options
|
||||
_drm_type = XMLProperty("./capability/type")
|
||||
drm_type = XMLProperty("./capability/type")
|
||||
devnodes = XMLChildProperty(DevNode)
|
||||
|
||||
def get_devnode(self, parent="by-path"):
|
||||
|
@ -4,9 +4,6 @@
|
||||
# This work is licensed under the GNU GPLv2 or later.
|
||||
# See the COPYING file in the top-level directory.
|
||||
|
||||
import libvirt
|
||||
|
||||
from . import generatename
|
||||
from .xmlbuilder import XMLBuilder, XMLChildProperty, XMLProperty
|
||||
|
||||
|
||||
@ -17,30 +14,6 @@ class _SnapshotDisk(XMLBuilder):
|
||||
|
||||
|
||||
class DomainSnapshot(XMLBuilder):
|
||||
@staticmethod
|
||||
def find_free_name(vm, collidelist):
|
||||
return generatename.generate_name("snapshot", vm.snapshotLookupByName,
|
||||
sep="", start_num=1, force_num=True,
|
||||
collidelist=collidelist)
|
||||
|
||||
@staticmethod
|
||||
def state_str_to_int(state):
|
||||
statemap = {
|
||||
"nostate": libvirt.VIR_DOMAIN_NOSTATE,
|
||||
"running": libvirt.VIR_DOMAIN_RUNNING,
|
||||
"blocked": libvirt.VIR_DOMAIN_BLOCKED,
|
||||
"paused": libvirt.VIR_DOMAIN_PAUSED,
|
||||
"shutdown": libvirt.VIR_DOMAIN_SHUTDOWN,
|
||||
"shutoff": libvirt.VIR_DOMAIN_SHUTOFF,
|
||||
"crashed": libvirt.VIR_DOMAIN_CRASHED,
|
||||
"pmsuspended": getattr(libvirt, "VIR_DOMAIN_PMSUSPENDED", 7)
|
||||
}
|
||||
|
||||
if state == "disk-snapshot" or state not in statemap:
|
||||
state = "shutoff"
|
||||
return statemap.get(state, libvirt.VIR_DOMAIN_NOSTATE)
|
||||
|
||||
|
||||
XML_NAME = "domainsnapshot"
|
||||
_XML_PROP_ORDER = ["name", "description", "creationTime"]
|
||||
|
||||
@ -53,12 +26,3 @@ class DomainSnapshot(XMLBuilder):
|
||||
memory_type = XMLProperty("./memory/@snapshot")
|
||||
|
||||
disks = XMLChildProperty(_SnapshotDisk, relative_xpath="./disks")
|
||||
|
||||
|
||||
##################
|
||||
# Public helpers #
|
||||
##################
|
||||
|
||||
def validate(self):
|
||||
if not self.name:
|
||||
raise RuntimeError(_("A name must be specified."))
|
||||
|
Loading…
Reference in New Issue
Block a user