Skip to content

Commit

Permalink
Merge pull request #2438 from smitterl/add_kernel_module_helper_state…
Browse files Browse the repository at this point in the history
…less

Add stateless kernel module handler for kvm hugepage support
  • Loading branch information
chunfuwen authored Apr 30, 2020
2 parents 3e224f6 + ef73b5a commit 1b6c5c9
Show file tree
Hide file tree
Showing 3 changed files with 413 additions and 0 deletions.
11 changes: 11 additions & 0 deletions virttest/env_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from virttest import utils_package
from virttest import utils_qemu
from virttest import migration
from virttest import utils_kernel_module
from virttest.utils_version import VersionInterval
from virttest.compat_52lts import decode_to_text
from virttest.staging import service
Expand Down Expand Up @@ -80,6 +81,8 @@
postprocess_vm_on_hook = None
postprocess_vm_off_hook = None

#: Object to handle kvm module reloads with certain parameters
KVM_MODULE_HANDLER = None

#: QEMU version regex. Attempts to extract the simple and extended version
#: information from the output produced by `qemu -version`
Expand Down Expand Up @@ -1049,6 +1052,11 @@ def preprocess(test, params, env):
env["cpu_driver"] = cpu_driver[0]
params["cpu_driver"] = env.get("cpu_driver")

kvm_module_params = params.get("kvm_module_parameters", "")
force_load = params.get("kvm_module_force_load", "no") == "yes"
global KVM_MODULE_HANDLER
KVM_MODULE_HANDLER = utils_kernel_module.reload("kvm", force_load, kvm_module_params)

version_info = {}
# Get the KVM kernel module version
if os.path.exists("/dev/kvm"):
Expand Down Expand Up @@ -1589,6 +1597,9 @@ def postprocess(test, params, env):
err += "\nTHP cleanup: %s" % str(details).replace('\\n', '\n ')
logging.error(details)

if KVM_MODULE_HANDLER:
KVM_MODULE_HANDLER.restore()

if params.get("setup_ksm") == "yes":
try:
ksm = test_setup.KSMConfig(params, env)
Expand Down
206 changes: 206 additions & 0 deletions virttest/unittests/test_utils_kernel_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import unittest

try:
from unittest import mock
except ImportError:
import mock

from virttest import utils_kernel_module

# Test values
some_module_name = 'skvm'
some_module_param = 'force_emulation_prefix'
some_module_val = 'N'
some_module_config = {some_module_param: some_module_val,
'halt_poll_ns_shrink': '0'}
some_module_params = "%s=%s" % (some_module_param, some_module_val)

# Mocks
getstatusoutput_ok = mock.Mock(return_value=(0, ""))


@mock.patch.object(utils_kernel_module.os, 'listdir', return_value=[some_module_param])
@mock.patch.object(utils_kernel_module, 'open', mock.mock_open(read_data=some_module_val + '\n'))
@mock.patch.object(utils_kernel_module.process, 'getstatusoutput', getstatusoutput_ok)
class TestReloadModule(unittest.TestCase):
"""
Tests the reload_module method
"""

def tearDown(self):
getstatusoutput_ok.reset_mock()

def assertLoadedWith(self, params):
self.assertTrue(getstatusoutput_ok.called)
cmd = getstatusoutput_ok.call_args[0][0]
if params != "":
self.assertTrue(params in cmd)
else:
self.assertTrue(cmd.endswith(some_module_name))

def assertNotLoaded(self):
getstatusoutput_ok.assert_not_called()

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=False)
def test_tc1(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.handler.reload_module(force=True, params=some_module_params)
self.assertLoadedWith(some_module_params)

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=False)
def test_tc2(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.handler.reload_module(force=False, params=some_module_params)
self.assertNotLoaded()

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=True)
def test_tc3(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.handler.reload_module(force=True, params=some_module_params)
self.assertLoadedWith(some_module_params)

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=True)
def test_tc3_empty(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.handler.reload_module(force=True, params="")
self.assertLoadedWith("")

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=True)
def test_tc4(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.handler.reload_module(force=True, params="key=value")
self.assertLoadedWith("key=value")

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=True)
def test_tc5(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.handler.reload_module(force=False, params=some_module_params)
self.assertNotLoaded()

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=True)
def test_tc5_empty(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.handler.reload_module(force=False, params="")
self.assertNotLoaded()

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=True)
def test_tc6(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.handler.reload_module(force=False, params="key=value")
self.assertLoadedWith("key=value")

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=True)
def test_tc6_partial(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.assertEqual(some_module_params, self.handler.config_backup)
self.handler.reload_module(force=False, params=some_module_params + " key=value")
self.assertLoadedWith("key=value")


@mock.patch.object(utils_kernel_module.process, 'getstatusoutput', getstatusoutput_ok)
@mock.patch.object(utils_kernel_module.os, 'listdir', return_value=[some_module_param])
@mock.patch.object(utils_kernel_module, 'open', mock.mock_open(read_data=some_module_val + '\n'))
class TestInit(unittest.TestCase):
"""
Tests if module status is backed up correctly
"""

def tearDown(self):
getstatusoutput_ok.reset_mock()

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=True)
def test_reloaded(self, *mocks):
handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.assertTrue(handler.was_loaded)
self.assertEqual(some_module_params, handler.config_backup)

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=False)
def test_not_reloaded(self, *mocks):
handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.assertFalse(handler.was_loaded)
self.assertIsNone(handler.config_backup)


@mock.patch.object(utils_kernel_module.os, 'listdir', return_value=[some_module_param])
@mock.patch.object(utils_kernel_module, 'open', mock.mock_open(read_data=some_module_val + '\n'))
@mock.patch.object(utils_kernel_module.process, 'getstatusoutput', getstatusoutput_ok)
class TestRestore(unittest.TestCase):
"""
Tests the restore method
"""

def tearDown(self):
getstatusoutput_ok.reset_mock()

def assertRestored(self, params):
self.assertTrue(getstatusoutput_ok.called)
cmd = getstatusoutput_ok.call_args[0][0]
self.assertTrue(params in cmd)

def assertNoRestore(self):
self.assertFalse(getstatusoutput_ok.called)

def assertUnloaded(self):
self.assertTrue(getstatusoutput_ok.called)
cmd = getstatusoutput_ok.call_args[0][0]
self.assertTrue("modprobe -r" in cmd)

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=True)
def test_tc1(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
orig_config = self.handler.config_backup
self.handler.reload_module(True, "key=value")
self.handler.restore()
self.assertRestored(orig_config)

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=True)
def test_tc1_reload_twice(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
orig_config = self.handler.config_backup
self.handler.reload_module(True, "key=value")
self.handler.reload_module(True, "key1=value1")
self.handler.restore()
self.assertRestored(orig_config)

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=True)
def test_tc2(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.handler.restore()
self.assertNoRestore()

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=False)
def test_tc3(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.handler.reload_module(True, "key=value")
self.handler.restore()
self.assertUnloaded()

@mock.patch.object(utils_kernel_module.os.path, 'exists', return_value=False)
def test_tc4(self, *mocks):
self.handler = utils_kernel_module.KernelModuleHandler(some_module_name)
self.handler.restore()
self.assertNoRestore()


@mock.patch.object(utils_kernel_module.KernelModuleHandler, '__init__', return_value=None)
@mock.patch.object(utils_kernel_module.KernelModuleHandler, 'reload_module', return_value=None)
class TestReload(unittest.TestCase):
"""
Tests the module global reload method
"""

def test_empty_params_1(self, *mocks):
self.assertIsNone(utils_kernel_module.reload(some_module_name, force=False, params=""))

def test_empty_params_2(self, *mocks):
self.assertIsNotNone(utils_kernel_module.reload(some_module_name, force=True, params=""))

def test_non_empty_params_1(self, *mocks):
self.assertIsNotNone(utils_kernel_module.reload(some_module_name, force=False, params=some_module_params))

def test_non_empty_params_2(self, *mocks):
self.assertIsNotNone(utils_kernel_module.reload(some_module_name, force=True, params=some_module_params))


if __name__ == '__main__':
unittest.main()
Loading

0 comments on commit 1b6c5c9

Please sign in to comment.