diff --git a/nova/tests/unit/virt/libvirt/test_config.py b/nova/tests/unit/virt/libvirt/test_config.py
index 214f730744..015ec3a54d 100644
--- a/nova/tests/unit/virt/libvirt/test_config.py
+++ b/nova/tests/unit/virt/libvirt/test_config.py
@@ -1035,6 +1035,43 @@ class LibvirtConfigGuestConsoleTest(LibvirtConfigBaseTest):
self.assertXmlEqual(xml, """
""")
+ def test_config_target_type(self):
+ obj = config.LibvirtConfigGuestConsole()
+ obj.type = "pty"
+ obj.target_type = "sclp"
+
+ xml = obj.to_xml()
+ self.assertXmlEqual(xml, """
+
+
+
+ """)
+
+ def test_config_type_file_with_target_type(self):
+ obj = config.LibvirtConfigGuestConsole()
+ obj.type = "file"
+ obj.target_type = "sclplm"
+ obj.source_path = "/var/lib/nova/instances/uuid/console.log"
+
+ xml = obj.to_xml()
+ self.assertXmlEqual(xml, """
+
+
+
+
+ """)
+
+ def test_config_target_port(self):
+ obj = config.LibvirtConfigGuestConsole()
+ obj.target_port = 0
+
+ xml = obj.to_xml()
+ self.assertXmlEqual(xml, """
+
+
+
+ """)
+
class LibvirtConfigGuestChannelTest(LibvirtConfigBaseTest):
def test_config_spice_minimal(self):
diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py
index b69b1461a2..2a5b36ef37 100644
--- a/nova/tests/unit/virt/libvirt/test_driver.py
+++ b/nova/tests/unit/virt/libvirt/test_driver.py
@@ -2148,6 +2148,75 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.assertEqual(cfg.devices[3].type, "vnc")
self.assertEqual(cfg.devices[4].type, "xen")
+ @mock.patch.object(objects.Flavor, 'get_by_id')
+ def test_get_guest_config_with_type_kvm_on_s390(self, mock_flavor):
+ self.flags(vnc_enabled=False)
+ self.flags(virt_type='kvm',
+ use_usb_tablet=False,
+ group='libvirt')
+
+ host_arch = arch.S390X
+ self._stub_host_capabilities_cpu_arch(host_arch)
+ self._stub_guest_cpu_config_arch(host_arch)
+
+ instance_ref = self._get_flavor_mocked_test_instance(mock_flavor)
+
+ cfg = self._get_guest_config_via_fake_api(instance_ref)
+
+ self.assertIsInstance(cfg.devices[0],
+ vconfig.LibvirtConfigGuestDisk)
+ self.assertIsInstance(cfg.devices[1],
+ vconfig.LibvirtConfigGuestDisk)
+ log_file_device = cfg.devices[2]
+ self.assertIsInstance(log_file_device,
+ vconfig.LibvirtConfigGuestConsole)
+ self.assertEqual("sclplm", log_file_device.target_type)
+ self.assertEqual("file", log_file_device.type)
+ terminal_device = cfg.devices[3]
+ self.assertIsInstance(terminal_device,
+ vconfig.LibvirtConfigGuestConsole)
+ self.assertEqual("sclp", terminal_device.target_type)
+ self.assertEqual("pty", terminal_device.type)
+ self.assertEqual("s390-ccw-virtio", cfg.os_mach_type)
+ self.assertEqual("s390x", cfg.cpu.arch)
+
+ def _stub_host_capabilities_cpu_arch(self, cpu_arch):
+ def get_host_capabilities_stub(self):
+ cpu = vconfig.LibvirtConfigGuestCPU()
+ cpu.arch = cpu_arch
+
+ caps = vconfig.LibvirtConfigCaps()
+ caps.host = vconfig.LibvirtConfigCapsHost()
+ caps.host.cpu = cpu
+ return caps
+
+ self.stubs.Set(libvirt_driver.LibvirtDriver,
+ "_get_host_capabilities",
+ get_host_capabilities_stub)
+
+ def _stub_guest_cpu_config_arch(self, cpu_arch):
+ def get_guest_cpu_config(self):
+ cpu = vconfig.LibvirtConfigGuestCPU()
+ cpu.arch = cpu_arch
+ return cpu
+
+ self.stubs.Set(libvirt_driver.LibvirtDriver,
+ "_get_guest_cpu_model_config",
+ get_guest_cpu_config)
+
+ def _get_flavor_mocked_test_instance(self, mock_flavor):
+ instance = objects.Instance(**self.test_instance)
+ flavor = instance.get_flavor()
+ flavor.extra_specs = {}
+ mock_flavor.return_value = flavor
+ return instance
+
+ def _get_guest_config_via_fake_api(self, instance):
+ conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
+ disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
+ instance)
+ return conn._get_guest_config(instance, [], {}, disk_info)
+
@mock.patch.object(objects.Flavor, 'get_by_id')
def test_get_guest_config_with_type_xen_pae_hvm(self, mock_flavor):
self.flags(vnc_enabled=True)
diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py
index 5715d46fad..26280a9317 100644
--- a/nova/virt/libvirt/config.py
+++ b/nova/virt/libvirt/config.py
@@ -1432,12 +1432,18 @@ class LibvirtConfigGuestChar(LibvirtConfigGuestCharBase):
super(LibvirtConfigGuestChar, self).__init__(**kwargs)
self.target_port = None
+ self.target_type = None
def format_dom(self):
dev = super(LibvirtConfigGuestChar, self).format_dom()
- if self.target_port is not None:
- dev.append(etree.Element("target", port=str(self.target_port)))
+ if self.target_port is not None or self.target_type is not None:
+ target = etree.Element("target")
+ if self.target_port is not None:
+ target.set("port", str(self.target_port))
+ if self.target_type is not None:
+ target.set("type", self.target_type)
+ dev.append(target)
return dev
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index 625690f7b6..48e42a803c 100644
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -3582,7 +3582,11 @@ class LibvirtDriver(driver.ComputeDriver):
# client app is connected. Thus we can't get away
# with a single type=pty console. Instead we have
# to configure two separate consoles.
- consolelog = vconfig.LibvirtConfigGuestSerial()
+ if guest.cpu.arch in (arch.S390, arch.S390X):
+ consolelog = vconfig.LibvirtConfigGuestConsole()
+ consolelog.target_type = "sclplm"
+ else:
+ consolelog = vconfig.LibvirtConfigGuestSerial()
consolelog.type = "file"
consolelog.source_path = self._get_console_log_path(instance)
guest.add_device(consolelog)
@@ -3790,7 +3794,11 @@ class LibvirtDriver(driver.ComputeDriver):
# Create the serial console char devices
self._create_serial_console_devices(guest, instance, flavor,
image_meta)
- consolepty = vconfig.LibvirtConfigGuestSerial()
+ if caps.host.cpu.arch in (arch.S390, arch.S390X):
+ consolepty = vconfig.LibvirtConfigGuestConsole()
+ consolepty.target_type = "sclp"
+ else:
+ consolepty = vconfig.LibvirtConfigGuestSerial()
else:
consolepty = vconfig.LibvirtConfigGuestConsole()