Add tuning option to performance profiles 66/1566/5
authorKrisztian Lengyel <krisztian.lengyel@nokia.com>
Wed, 4 Sep 2019 20:42:31 +0000 (16:42 -0400)
committerKrisztian Lengyel <krisztian.lengyel@nokia.com>
Wed, 18 Sep 2019 17:08:11 +0000 (13:08 -0400)
Add an optional `tuning` parameter to performance profiles. Currently it
supports only "low_latency" & "standard" modes.

Change-Id: I6646b04220733091eb946c547d136dee0ae48706
Signed-off-by: Krisztian Lengyel <krisztian.lengyel@nokia.com>
cmdatahandlers/src/cmdatahandlers/performance_profiles/config.py
cmdatahandlers/tests/performance_profiles_config_test.py
userconfigtemplate/user_config.yaml

index 8b2f087..4ba0648 100644 (file)
@@ -24,11 +24,15 @@ class Config(config.Config):
     HUGEPAGES = 'hugepages'
     PLATFORM_CPUS = 'platform_cpus'
     OVS_DPDK_CPUS = 'ovs_dpdk_cpus'
+    TUNING = 'tuning'
+    LOW_LATENCY_OPTIONS = 'low_latency_options'
     PROFILE_OPTIONS = {DEFAULT_HUGEPAGESZ: 'get_profile_default_hugepage_size',
                        HUGEPAGESZ: 'get_profile_hugepage_size',
                        HUGEPAGES: 'get_profile_hugepage_count',
                        PLATFORM_CPUS: 'get_platform_cpus',
-                       OVS_DPDK_CPUS: 'get_ovs_dpdk_cpus'}
+                       OVS_DPDK_CPUS: 'get_ovs_dpdk_cpus',
+                       TUNING: 'get_tuning',
+                       LOW_LATENCY_OPTIONS: 'get_low_latency_kcmd_options'}
 
     ERR_INVALID_PROFILE = 'Invalid profile name {}'
     ERR_MISSING_PROFILE_KEY = 'Profile {} does not have %s'
@@ -37,6 +41,9 @@ class Config(config.Config):
     ERR_MISSING_HUGEPAGES = ERR_MISSING_PROFILE_KEY % HUGEPAGES
     ERR_MISSING_PLATFORM_CPUS = ERR_MISSING_PROFILE_KEY % PLATFORM_CPUS
     ERR_MISSING_OVS_DPDK_CPUS = ERR_MISSING_PROFILE_KEY % OVS_DPDK_CPUS
+    ERR_MISSING_TUNING = ERR_MISSING_PROFILE_KEY % TUNING
+    ERR_INVALID_PROFILE_KEY = 'Profile {} got invalid option %s'
+    ERR_INVALID_LOW_LATENCY_OPTIONS = ERR_INVALID_PROFILE_KEY % LOW_LATENCY_OPTIONS
 
     @staticmethod
     def raise_error(context, err_type):
@@ -66,6 +73,11 @@ class Config(config.Config):
         self.get_profile_hugepage_count(profile)
         self.get_platform_cpus(profile)
         self.get_ovs_dpdk_cpus(profile)
+        self._validate_mandatory_option(profile, self.TUNING)
+
+    def _validate_mandatory_option(self, profile, option):
+        if getattr(self, self.PROFILE_OPTIONS[option])(profile) is None:
+            self.raise_error(profile, self.ERR_MISSING_PROFILE_KEY % option)
 
     def is_valid_profile(self, profile):
         profiles = self.get_performance_profiles()
@@ -197,6 +209,72 @@ class Config(config.Config):
 
         return self.config[self.ROOT][profile][self.OVS_DPDK_CPUS]
 
+    def get_tuning(self, profile):
+        """ get performance tuning option
+
+            Parameters
+            ----------
+            profile_name : str
+                           Performance profile name.
+            Returns
+            -------
+            str
+                Performance tuning option.
+
+            Raises
+            ------
+            ConfigError
+        """
+        self.is_valid_profile(profile)
+        if self.TUNING not in self.config[self.ROOT][profile]:
+            return None
+
+        return self.config[self.ROOT][profile][self.TUNING]
+
+    def get_low_latency_kcmd_options(self, profile):
+        """ get low latency kernel cmd option
+
+            Parameters
+            ----------
+            profile_name : str
+                           Performance profile name.
+            Returns
+            -------
+            str
+                Low latency kernel cmd options.
+
+            Raises
+            ------
+            ConfigError
+        """
+        self.is_valid_profile(profile)
+        if self.LOW_LATENCY_OPTIONS not in self.config[self.ROOT][profile]:
+            return None
+
+        return self.config[self.ROOT][profile][self.LOW_LATENCY_OPTIONS]
+
+    def set_low_latency_kcmd_options(self, profile, options):
+        """ set low latency kernel cmd option
+
+            Parameters
+            ----------
+            profile_name : str
+                           Performance profile name.
+            Returns
+            -------
+            str
+                Low latency kernel cmd options.
+
+            Raises
+            ------
+            ConfigError
+        """
+        self.is_valid_profile(profile)
+        if not isinstance(options, list):
+            self.raise_error(profile, self.ERR_INVALID_LOW_LATENCY_OPTIONS)
+
+        self._fill_option_value(self.config[self.ROOT][profile], profile, self.LOW_LATENCY_OPTIONS, options)
+
     def dump(self):
         """ Dump all performaceprofiles data. """
 
@@ -213,7 +291,7 @@ class Config(config.Config):
 
     # pylint: disable=too-many-arguments
     def update(self, name, platform_cpus=None, ovs_dpdk_cpus=None, hugepages=None,
-               default_hugepagesz=None, hugepagesz=None):
+               default_hugepagesz=None, hugepagesz=None, tuning=None):
         """ Update performance profile, overwriting existing profile.
 
             Parameters
@@ -234,7 +312,9 @@ class Config(config.Config):
             hugepagesz : str, optional
                          Huge page size (the default value is '1G').
                          Valid values are '2M' and '1G'
-
+            tuning : str, optional
+                     Performance tuning option.
+                     Valid values are 'low_latency and 'standard' (default).
         """
         data = {}
         self._fill_option_value(data, name, 'platform_cpus', platform_cpus)
@@ -242,6 +322,7 @@ class Config(config.Config):
         self._fill_option_value(data, name, 'hugepages', hugepages)
         self._fill_option_value(data, name, 'default_hugepagesz', default_hugepagesz)
         self._fill_option_value(data, name, 'hugepagesz', hugepagesz)
+        self._fill_option_value(data, name, 'tuning', tuning)
         self.config[self.ROOT].update({name:data})
 
     def delete(self, name):
index 4a603d9..89d551d 100644 (file)
@@ -16,30 +16,31 @@ from unittest import TestCase
 from cmdatahandlers.api import configmanager
 import cmdatahandlers.performance_profiles.config
 from cmdatahandlers.api.configerror import ConfigError
+import copy
 
 
 class PerformanceProfilesConfigTest(TestCase):
 
-
     profile = 'dpdk_profile'
-    profile_data = {profile: {'platform_cpus': {'numa0': 1, 'numa1': 1},
+    profile_data = { profile: {'platform_cpus': {'numa0': 1, 'numa1': 1},
                               'ovs_dpdk_cpus': {'numa0': 2, 'numa1': 2},
                               'default_hugepagesz': '1M',
                               'hugepagesz': '1G',
-                              'hugepages': 192
-                             }
-                   }
-    hosts_data = {'controller-1':{'service_profiles': ['controller']}}
+                              'hugepages': 192,
+                              'tuning': 'low_latency'
+                              }
+                    }
+    hosts_data = {'controller-1': {'service_profiles': ['controller']}}
 
     config = {'cloud.performance_profiles': profile_data,
               'cloud.hosts': hosts_data }
 
-    fail_profile ='dpdk_fail_profile'
+    fail_profile = 'dpdk_fail_profile'
     config_fail = {'cloud.performance_profiles': {fail_profile: {} },
                    'cloud.hosts': hosts_data }
 
     def setUp(self):
-        confman = configmanager.ConfigManager(self.config)
+        confman = configmanager.ConfigManager(copy.deepcopy(self.config))
         self.pp_handler = confman.get_performance_profiles_config_handler()
 
         confman_fail = configmanager.ConfigManager(self.config_fail)
@@ -107,6 +108,33 @@ class PerformanceProfilesConfigTest(TestCase):
         with self.assertRaisesRegexp(ConfigError, error_text):
             self.pp_handler_fail.get_ovs_dpdk_cpus(self.fail_profile)
 
+    def test_tuning(self):
+        tuning_data = self.pp_handler.get_tuning(self.profile)
+        expected_data = 'low_latency'
+        self.assertEqual(tuning_data, expected_data)
+
+    def test_tuning_does_not_raises_error(self):
+        self.assertEqual(self.pp_handler_fail.get_tuning(self.fail_profile), None)
+
+    def test_low_latency_kcmd_options(self):
+        expected_data = ["fancytuning", "thiswillmakeitfast"]
+        self.pp_handler.set_low_latency_kcmd_options(self.profile, expected_data)
+        low_latency_kcmd_data = self.pp_handler.get_low_latency_kcmd_options(self.profile)
+        print self
+        self.assertEqual(low_latency_kcmd_data, expected_data)
+
+    def test_missing_low_latency_kcmd_options(self):
+        expected_data = None
+        low_latency_kcmd_data = self.pp_handler.get_low_latency_kcmd_options(self.profile)
+        self.assertEqual(low_latency_kcmd_data, expected_data)
+
+    def test_invalid_low_latency_kcmd_options(self):
+        error_text = "Profile {} got invalid option low_latency_options".format(
+            self.profile)
+        with self.assertRaisesRegexp(ConfigError, error_text):
+            low_latency_kcmd_data = "this fancytuning is sadly invalid"
+            self.pp_handler.set_low_latency_kcmd_options(self.profile, low_latency_kcmd_data)
+
     def test__fill_option_value(self):
         data = {}
         self.pp_handler._fill_option_value(data, self.profile, 'platform_cpus', None)
@@ -130,6 +158,7 @@ class PerformanceProfilesConfigTest(TestCase):
             h.get_profile_hugepage_size(profile)
         with self.assertRaisesRegexp(ConfigError, 'Profile niksnaks does not have default_hugepagesz'):
             h.get_profile_default_hugepage_size(profile)
+        self.assertEqual(h.get_tuning(profile), None)
 
     def test_delete(self):
         cman = configmanager.ConfigManager({'cloud.performance_profiles': {}, 'cloud.hosts': self.hosts_data})
index de9e18d..2664b1f 100644 (file)
@@ -29,7 +29,7 @@
 ###        - Minor changes in template (e.g. new optional attributes or
 ###          changes in possible values, value ranges or default values)
 ###        - Backwards compatible
-version: 2.0.4
+version: 2.0.5
 
 ### Cloud name can consist of lower case letters, digits and dash (-).
 ### Name must start and end with a letter or a digit.
@@ -428,6 +428,11 @@ performance_profiles:
             #numa0: <COUNT>
             #numa1: <COUNT>
 
+        ### Optional. Performance tuning.
+        ### Valid values are low_latency and standard (default).
+        ### Note that low_latency mode will turn off power saving, etc
+        #tuning: <low_latency|standard>
+
         ### Optional. Create CPU pools in CaaS CPU manager.
         ### Type of this parameter is dictionary, consisting of the following attributes:
         ### - exclusive_pool_percentage