From 11a2ed09655090483a27f06adcc4af8f424df7a6 Mon Sep 17 00:00:00 2001 From: Markus Zoeller Date: Fri, 28 Nov 2014 15:14:19 +0100 Subject: [PATCH] libvirt: Enable console and log for system z guests If the host architecture is system z (s390, s390x), the interactive console and the log of instances will be defined as "console" devices (instead of "serial" devices) in libvirts domain XML. These console devices need to have a "target type". For the interactive console this is "sclp" and for the log "sclplm". Partial-Implements blueprint libvirt-kvm-systemz Change-Id: I20d5e32fee660e77c52b6fc5fdf1128a996bb994 --- nova/tests/unit/virt/libvirt/test_config.py | 37 +++++++++++ nova/tests/unit/virt/libvirt/test_driver.py | 69 +++++++++++++++++++++ nova/virt/libvirt/config.py | 10 ++- nova/virt/libvirt/driver.py | 12 +++- 4 files changed, 124 insertions(+), 4 deletions(-) diff --git a/nova/tests/unit/virt/libvirt/test_config.py b/nova/tests/unit/virt/libvirt/test_config.py index c3c6d088bf..9e49fe060f 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 1c94ea7a4b..818bd98d2a 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -2207,6 +2207,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 35b83021cc..0071a99c9d 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 1af343c7cf..b5ab14c45b 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -3903,7 +3903,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) @@ -4111,7 +4115,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()