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