Enables or disables TRIM delete notifications.
Delete notification (also known as trim or unmap) is a feature that notifies the underlying storage devices that data blocks are no longer in use so they can be freed. Implements: blueprint delete-notifications Co-Authored-By: Micu Matei-Marius <mmicu@cloudbasesolutions.com> Change-Id: I2a1670f921fce1165df48096c6fde8660b21282e
This commit is contained in:
parent
dd3cd540a3
commit
278468d2e2
@ -224,6 +224,10 @@ class GlobalOptions(conf_base.Options):
|
|||||||
help='Volume mount points on which a Windows page file needs '
|
help='Volume mount points on which a Windows page file needs '
|
||||||
'to be created. E.g.: '
|
'to be created. E.g.: '
|
||||||
'"\\\\?\\GLOBALROOT\\device\\Harddisk1\\Partition1\\"'),
|
'"\\\\?\\GLOBALROOT\\device\\Harddisk1\\Partition1\\"'),
|
||||||
|
cfg.BoolOpt(
|
||||||
|
'trim_enabled', default=False,
|
||||||
|
help='Enables or disables TRIM delete notifications for '
|
||||||
|
'the underlying storage device.'),
|
||||||
]
|
]
|
||||||
|
|
||||||
self._cli_options = [
|
self._cli_options = [
|
||||||
|
@ -139,3 +139,7 @@ class BaseOSUtils(object):
|
|||||||
|
|
||||||
def set_real_time_clock_utc(self, utc):
|
def set_real_time_clock_utc(self, utc):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def enable_trim(self, enable):
|
||||||
|
"""Enables or disables TRIM delete notifications."""
|
||||||
|
raise NotImplementedError()
|
||||||
|
@ -1416,3 +1416,13 @@ class WindowsUtils(base.BaseOSUtils):
|
|||||||
0, winreg.KEY_ALL_ACCESS) as key:
|
0, winreg.KEY_ALL_ACCESS) as key:
|
||||||
winreg.SetValueEx(key, 'PagingFiles', 0,
|
winreg.SetValueEx(key, 'PagingFiles', 0,
|
||||||
winreg.REG_MULTI_SZ, values)
|
winreg.REG_MULTI_SZ, values)
|
||||||
|
|
||||||
|
def enable_trim(self, enable):
|
||||||
|
"""Enables or disables TRIM delete notifications."""
|
||||||
|
args = ["fsutil.exe", "behavior", "set", "disabledeletenotify",
|
||||||
|
"0" if enable else "1"]
|
||||||
|
(out, err, ret_val) = self.execute_system32_process(args)
|
||||||
|
if ret_val:
|
||||||
|
raise exception.CloudbaseInitException(
|
||||||
|
'TRIM configurating failed.\nOutput: %(out)s\nError:'
|
||||||
|
' %(err)s' % {'out': out, 'err': err})
|
||||||
|
36
cloudbaseinit/plugins/common/trim.py
Normal file
36
cloudbaseinit/plugins/common/trim.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Copyright 2017 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
|
||||||
|
from oslo_log import log as oslo_logging
|
||||||
|
|
||||||
|
from cloudbaseinit import conf as cloudbaseinit_conf
|
||||||
|
from cloudbaseinit.osutils import factory as osutils_factory
|
||||||
|
from cloudbaseinit.plugins.common import base as plugin_base
|
||||||
|
|
||||||
|
CONF = cloudbaseinit_conf.CONF
|
||||||
|
LOG = oslo_logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class TrimConfigPlugin(plugin_base.BasePlugin):
|
||||||
|
|
||||||
|
def execute(self, service, shared_data):
|
||||||
|
osutils = osutils_factory.get_os_utils()
|
||||||
|
osutils.enable_trim(CONF.trim_enabled)
|
||||||
|
LOG.info("TRIM enabled status: %s", CONF.trim_enabled)
|
||||||
|
|
||||||
|
return plugin_base.PLUGIN_EXECUTION_DONE, False
|
||||||
|
|
||||||
|
def get_os_requirements(self):
|
||||||
|
return 'win32', (6, 1)
|
@ -2336,3 +2336,28 @@ class TestWindowsUtils(testutils.CloudbaseInitTestBase):
|
|||||||
self._winreg_mock.SetValueEx.assert_called_with(
|
self._winreg_mock.SetValueEx.assert_called_with(
|
||||||
key, 'PagingFiles', 0, self._winreg_mock.REG_MULTI_SZ,
|
key, 'PagingFiles', 0, self._winreg_mock.REG_MULTI_SZ,
|
||||||
expected_values)
|
expected_values)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'.execute_system32_process')
|
||||||
|
def _test_trim(self, mock_execute_process, err):
|
||||||
|
if err:
|
||||||
|
mock_execute_process.return_value = ("fake out", "", 1)
|
||||||
|
self.assertRaises(exception.CloudbaseInitException,
|
||||||
|
self._winutils.enable_trim, True)
|
||||||
|
else:
|
||||||
|
args = ["fsutil.exe", "behavior",
|
||||||
|
"set", "disabledeletenotify"]
|
||||||
|
|
||||||
|
mock_execute_process.return_value = ("fake out", "fake err", 0)
|
||||||
|
|
||||||
|
self._winutils.enable_trim(True)
|
||||||
|
mock_execute_process.assert_called_with(args + ["0"])
|
||||||
|
|
||||||
|
self._winutils.enable_trim(False)
|
||||||
|
mock_execute_process.assert_called_with(args + ["1"])
|
||||||
|
|
||||||
|
def test_trim(self):
|
||||||
|
self._test_trim(err=False)
|
||||||
|
|
||||||
|
def test_trim_exception(self):
|
||||||
|
self._test_trim(err=True)
|
||||||
|
53
cloudbaseinit/tests/plugins/common/test_trim.py
Normal file
53
cloudbaseinit/tests/plugins/common/test_trim.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Copyright 2017 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
try:
|
||||||
|
import unittest.mock as mock
|
||||||
|
except ImportError:
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from cloudbaseinit.plugins.common import base
|
||||||
|
from cloudbaseinit.plugins.common import trim
|
||||||
|
from cloudbaseinit.tests import testutils
|
||||||
|
|
||||||
|
|
||||||
|
class TrimPluginPluginTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._trim_plugin = trim.TrimConfigPlugin()
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.factory.get_os_utils')
|
||||||
|
def _test_trim(self, mock_get_os_utils, status):
|
||||||
|
shared_data = 'fake_shared_data'
|
||||||
|
mock_os_utils = mock.Mock()
|
||||||
|
mock_get_os_utils.return_value = mock_os_utils
|
||||||
|
|
||||||
|
with testutils.ConfPatcher('trim_enabled', status):
|
||||||
|
response = self._trim_plugin.execute(mock.Mock(), shared_data)
|
||||||
|
|
||||||
|
mock_os_utils.enable_trim.assert_called_once_with(status)
|
||||||
|
self.assertEqual(response, (base.PLUGIN_EXECUTION_DONE, False))
|
||||||
|
|
||||||
|
def test_trim_enable(self):
|
||||||
|
self._test_trim(status=True)
|
||||||
|
|
||||||
|
def test_trim_disable(self):
|
||||||
|
self._test_trim(status=False)
|
||||||
|
|
||||||
|
def test_get_os_requirements(self):
|
||||||
|
response = self._trim_plugin.get_os_requirements()
|
||||||
|
|
||||||
|
self.assertEqual(response, ('win32', (6, 1)))
|
Loading…
x
Reference in New Issue
Block a user