diff --git a/tests/data/cli/compare/virt-xml-remove-console-dup.xml b/tests/data/cli/compare/virt-xml-remove-console-dup.xml new file mode 100644 index 000000000..909b3f34e --- /dev/null +++ b/tests/data/cli/compare/virt-xml-remove-console-dup.xml @@ -0,0 +1,15 @@ + 8294400 + 8294400 + 1 +- +- +- +- +- +- +- +- +- +- ++ + \ No newline at end of file diff --git a/tests/data/cli/virtxml/virtxml-console-dup.xml b/tests/data/cli/virtxml/virtxml-console-dup.xml new file mode 100644 index 000000000..bffe9d6e3 --- /dev/null +++ b/tests/data/cli/virtxml/virtxml-console-dup.xml @@ -0,0 +1,17 @@ + + test-char-dup-remove + 8294400 + 8294400 + 1 + + + + + + + + + + + + diff --git a/tests/test_cli.py b/tests/test_cli.py index d3d5c6726..a524e4702 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1186,6 +1186,7 @@ c.add_compare("--connect %(URI-KVM)s test-many-devices --build-xml --disk %(EXIS c.add_compare("4a64cc71-19c4-2fd0-2323-3050941ea3c3 --edit --boot network,cdrom", "edit-bootorder") # basic bootorder test, also using UUID lookup c.add_compare("--confirm 1 --edit --cpu host-passthrough", "prompt-response", input_text="yes") # prompt response, also using domid lookup c.add_compare("--edit --print-diff --qemu-commandline clearxml=yes", "edit-clearxml-qemu-commandline", input_file=(_VIRTXMLDIR + "virtxml-qemu-commandline-clear.xml")) +c.add_compare("--print-diff --remove-device --serial 1", "remove-console-dup", input_file=(_VIRTXMLDIR + "virtxml-console-dup.xml")) c.add_compare("--connect %(URI-KVM)s test-hyperv-uefi --edit --boot uefi", "hyperv-uefi-collision") c.add_compare("--connect %(URI-KVM)s test-many-devices --edit --cpu host-copy", "edit-cpu-host-copy") diff --git a/virtManager/object/domain.py b/virtManager/object/domain.py index f3af63fe7..101242ef8 100644 --- a/virtManager/object/domain.py +++ b/virtManager/object/domain.py @@ -10,6 +10,7 @@ import threading import libvirt +from virtinst import DeviceConsole from virtinst import DeviceController from virtinst import DeviceDisk from virtinst import DomainSnapshot @@ -1256,18 +1257,7 @@ class vmmDomain(vmmLibvirtObject): return xmlobj.devices.disk def serial_is_console_dup(self, serial): - if serial.DEVICE_TYPE != "serial": - return False - - consoles = self.xmlobj.devices.console - if not consoles: - return False # pragma: no cover - - console = consoles[0] - if (console.type == serial.type and - (console.target_type is None or console.target_type == "serial")): - return True - return False + return DeviceConsole.get_console_duplicate(self.xmlobj, serial) def can_use_device_boot_order(self): # Return 'True' if guest can use new style boot device ordering diff --git a/virtinst/devices/char.py b/virtinst/devices/char.py index dabfcde82..9547c649e 100644 --- a/virtinst/devices/char.py +++ b/virtinst/devices/char.py @@ -123,6 +123,24 @@ class _DeviceChar(Device): class DeviceConsole(_DeviceChar): + @staticmethod + def get_console_duplicate(guest, serial): + """ + Determine if the passed serial device has a duplicate + device in the passed Guest + """ + if serial.DEVICE_TYPE != "serial": + return + + consoles = guest.devices.console + if not consoles: + return # pragma: no cover + + console = consoles[0] + if (console.type == serial.type and + (console.target_type is None or console.target_type == "serial")): + return console + XML_NAME = "console" diff --git a/virtinst/virtxml.py b/virtinst/virtxml.py index a5ba74e02..b80a84db5 100644 --- a/virtinst/virtxml.py +++ b/virtinst/virtxml.py @@ -11,6 +11,7 @@ import libvirt from . import cli from .cli import fail, print_stdout, print_stderr +from .devices import DeviceConsole from .guest import Guest from .logger import log from . import xmlutil @@ -176,8 +177,15 @@ def action_remove_device(guest, options, parserclass): devs = _find_objects_to_edit(guest, "remove-device", getattr(options, parserclass.cli_arg_name)[-1], parserclass) - devs = xmlutil.listify(devs) + + # Check for console duplicate devices + for dev in devs[:]: + condup = DeviceConsole.get_console_duplicate(guest, dev) + if condup: + log.debug("Found duplicate console device:\n%s", condup.get_xml()) + devs.append(condup) + for dev in devs: guest.remove_device(dev) return devs