From f9a3ceca1e875ff9ad6ae423663f433f67aa1fe6 Mon Sep 17 00:00:00 2001 From: Jorge Niedbalski Date: Thu, 9 Mar 2017 14:20:53 -0300 Subject: [PATCH] Exposes new ksm config directive. This change exposes the ksm config directive used for enable/disable the KSM feature on the /e/d/qemu-kvm file. - Updated templates/qemu-kvm - Added tests for the new config option Closes-Bug: #1670281 Change-Id: I24b44dc3e66d73c39fac0be0949be52710b571fd Signed-off-by: Jorge Niedbalski --- config.yaml | 19 ++++++++---- hooks/nova_compute_context.py | 11 +++++++ templates/qemu-kvm | 10 ++++++ unit_tests/test_nova_compute_contexts.py | 39 ++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/config.yaml b/config.yaml index cece3b25..1bca26ed 100644 --- a/config.yaml +++ b/config.yaml @@ -226,18 +226,18 @@ options: type: string default: description: | - Set to 'host-model' to clone the host CPU feature flags; to - 'host-passthrough' to use the host CPU model exactly; to 'custom' to - use a named CPU model; to 'none' to not set any CPU model. If - virt_type='kvm|qemu', it will default to 'host-model', otherwise it will + Set to 'host-model' to clone the host CPU feature flags; to + 'host-passthrough' to use the host CPU model exactly; to 'custom' to + use a named CPU model; to 'none' to not set any CPU model. If + virt_type='kvm|qemu', it will default to 'host-model', otherwise it will default to 'none'. Defaults to 'host-passthrough' for ppc64el, ppc64le if no value is set. cpu-model: type: string default: description: | - Set to a named libvirt CPU model (see names listed in - /usr/share/libvirt/cpu_map.xml). Only has effect if cpu_mode='custom' and + Set to a named libvirt CPU model (see names listed in + /usr/share/libvirt/cpu_map.xml). Only has effect if cpu_mode='custom' and virt_type='kvm|qemu'. # Storage configuration options libvirt-image-backend: @@ -308,6 +308,13 @@ options: For a systemd system (wily and later) the prefered approach is to enable hugepages via kernel parameters set in MAAS and systemd will mount them automatically. + ksm: + type: string + default: "AUTO" + description: | + Set to 1 to enable KSM, 0 to disable KSM, and AUTO to use default settings. + Please note that the AUTO value works for qemu 2.2+ (> Kilo), older + releases will be set to 1 as default. action-managed-upgrade: type: boolean default: False diff --git a/hooks/nova_compute_context.py b/hooks/nova_compute_context.py index 9ab16947..b23061f5 100644 --- a/hooks/nova_compute_context.py +++ b/hooks/nova_compute_context.py @@ -33,6 +33,7 @@ from charmhelpers.core.hookenv import ( related_units, service_name, ERROR, + INFO, ) from charmhelpers.contrib.openstack.utils import ( get_os_version_package, @@ -191,6 +192,16 @@ class NovaComputeLibvirtContext(context.OSContextGenerator): else: ctxt['kvm_hugepages'] = 0 + if config('ksm') in ("1", "0",): + ctxt['ksm'] = config('ksm') + else: + if release < 'kilo': + log("KSM set to 1 by default on openstack releases < kilo", + level=INFO) + ctxt['ksm'] = "1" + else: + ctxt['ksm'] = "AUTO" + if config('pci-passthrough-whitelist'): ctxt['pci_passthrough_whitelist'] = \ config('pci-passthrough-whitelist') diff --git a/templates/qemu-kvm b/templates/qemu-kvm index dcaceaa7..e2fcbbb7 100644 --- a/templates/qemu-kvm +++ b/templates/qemu-kvm @@ -2,5 +2,15 @@ # [ WARNING ] # Configuration file maintained by Juju. Local changes may be overwritten. ############################################################################### +# Set to 1 to enable KSM, 0 to disable KSM, and AUTO to use default settings. +# After changing this setting restart the qemu-kvm service. +KSM_ENABLED={{ ksm }} +SLEEP_MILLISECS=200 +# To load the vhost_net module, which in some cases can speed up +# network performance, set VHOST_NET_ENABLED to 1. +VHOST_NET_ENABLED=0 + +# Set this to 1 if you want hugepages to be available to kvm under +# /run/hugepages/kvm KVM_HUGEPAGES={{ kvm_hugepages }} diff --git a/unit_tests/test_nova_compute_contexts.py b/unit_tests/test_nova_compute_contexts.py index 452f0064..589e7ab0 100644 --- a/unit_tests/test_nova_compute_contexts.py +++ b/unit_tests/test_nova_compute_contexts.py @@ -76,6 +76,7 @@ class NovaComputeContextTests(CharmTestCase): def setUp(self): super(NovaComputeContextTests, self).setUp(context, TO_PATCH) + self.os_release.return_value = 'kilo' self.relation_get.side_effect = self.test_relation.get self.config.side_effect = self.test_config.get self.log.side_effect = fake_log @@ -202,6 +203,7 @@ class NovaComputeContextTests(CharmTestCase): {'libvirtd_opts': '', 'libvirt_user': 'libvirt', 'arch': platform.machine(), + 'ksm': 'AUTO', 'kvm_hugepages': 0, 'listen_tls': 0, 'host_uuid': self.host_uuid, @@ -216,6 +218,7 @@ class NovaComputeContextTests(CharmTestCase): {'libvirtd_opts': '-d', 'libvirt_user': 'libvirtd', 'arch': platform.machine(), + 'ksm': 'AUTO', 'kvm_hugepages': 0, 'listen_tls': 0, 'host_uuid': self.host_uuid, @@ -230,6 +233,7 @@ class NovaComputeContextTests(CharmTestCase): {'libvirtd_opts': '-d -l', 'libvirt_user': 'libvirtd', 'arch': platform.machine(), + 'ksm': 'AUTO', 'kvm_hugepages': 0, 'listen_tls': 0, 'host_uuid': self.host_uuid, @@ -245,6 +249,7 @@ class NovaComputeContextTests(CharmTestCase): 'libvirt_user': 'libvirtd', 'disk_cachemodes': 'file=unsafe,block=none', 'arch': platform.machine(), + 'ksm': 'AUTO', 'kvm_hugepages': 0, 'listen_tls': 0, 'host_uuid': self.host_uuid, @@ -260,6 +265,7 @@ class NovaComputeContextTests(CharmTestCase): 'libvirt_user': 'libvirtd', 'arch': platform.machine(), 'hugepages': True, + 'ksm': 'AUTO', 'kvm_hugepages': 1, 'listen_tls': 0, 'host_uuid': self.host_uuid, @@ -342,6 +348,7 @@ class NovaComputeContextTests(CharmTestCase): {'libvirtd_opts': '-d', 'libvirt_user': 'libvirtd', 'arch': platform.machine(), + 'ksm': 'AUTO', 'hugepages': True, 'kvm_hugepages': 1, 'listen_tls': 0, @@ -350,6 +357,38 @@ class NovaComputeContextTests(CharmTestCase): 'vcpu_pin_set': '^0^2', 'pci_passthrough_whitelist': 'mypcidevices'}, libvirt()) + def test_ksm_configs(self): + self.test_config.set('ksm', '1') + libvirt = context.NovaComputeLibvirtContext() + self.assertTrue(libvirt()['ksm'] == '1') + + self.test_config.set('ksm', '0') + libvirt = context.NovaComputeLibvirtContext() + self.assertTrue(libvirt()['ksm'] == '0') + + self.test_config.set('ksm', 'AUTO') + libvirt = context.NovaComputeLibvirtContext() + self.assertTrue(libvirt()['ksm'] == 'AUTO') + + self.test_config.set('ksm', '') + libvirt = context.NovaComputeLibvirtContext() + self.assertTrue(libvirt()['ksm'] == 'AUTO') + + self.os_release.return_value = 'ocata' + self.test_config.set('ksm', 'AUTO') + libvirt = context.NovaComputeLibvirtContext() + self.assertTrue(libvirt()['ksm'] == 'AUTO') + + self.os_release.return_value = 'kilo' + self.test_config.set('ksm', 'AUTO') + libvirt = context.NovaComputeLibvirtContext() + self.assertTrue(libvirt()['ksm'] == 'AUTO') + + self.os_release.return_value = 'cactus' + self.test_config.set('ksm', 'AUTO') + libvirt = context.NovaComputeLibvirtContext() + self.assertTrue(libvirt()['ksm'] == '1') + @patch.object(context.uuid, 'uuid4') def test_libvirt_cpu_mode_default(self, mock_uuid): libvirt = context.NovaComputeLibvirtContext()