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:
Cole Robinson 2019-06-09 15:29:44 -04:00
parent c9233aa6c3
commit b5a664bd1b
27 changed files with 526 additions and 637 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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 #

View File

@ -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):
"""

View File

@ -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)

View File

@ -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"]

View File

@ -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")

View File

@ -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):
"""

View File

@ -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

View File

@ -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")

View File

@ -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")

View File

@ -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)

View File

@ -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")

View File

@ -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)

View File

@ -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")

View File

@ -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

View File

@ -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"):

View File

@ -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."))