From 82b7d75b8609bec0f3086d93b2162375ba71e961 Mon Sep 17 00:00:00 2001 From: Krisztian Lengyel Date: Wed, 4 Sep 2019 16:42:31 -0400 Subject: [PATCH] Add tuning option to performance profiles Add an optional `tuning` parameter to performance profiles. Currently it supports only "low_latency" & "standard" modes. Change-Id: I6646b04220733091eb946c547d136dee0ae48706 Signed-off-by: Krisztian Lengyel --- .../cmdatahandlers/performance_profiles/config.py | 87 +++++++++++++++++++++- .../tests/performance_profiles_config_test.py | 45 +++++++++-- userconfigtemplate/user_config.yaml | 7 +- 3 files changed, 127 insertions(+), 12 deletions(-) diff --git a/cmdatahandlers/src/cmdatahandlers/performance_profiles/config.py b/cmdatahandlers/src/cmdatahandlers/performance_profiles/config.py index 8b2f087..4ba0648 100644 --- a/cmdatahandlers/src/cmdatahandlers/performance_profiles/config.py +++ b/cmdatahandlers/src/cmdatahandlers/performance_profiles/config.py @@ -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): diff --git a/cmdatahandlers/tests/performance_profiles_config_test.py b/cmdatahandlers/tests/performance_profiles_config_test.py index 4a603d9..89d551d 100644 --- a/cmdatahandlers/tests/performance_profiles_config_test.py +++ b/cmdatahandlers/tests/performance_profiles_config_test.py @@ -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}) diff --git a/userconfigtemplate/user_config.yaml b/userconfigtemplate/user_config.yaml index de9e18d..2664b1f 100644 --- a/userconfigtemplate/user_config.yaml +++ b/userconfigtemplate/user_config.yaml @@ -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: #numa1: + ### Optional. Performance tuning. + ### Valid values are low_latency and standard (default). + ### Note that low_latency mode will turn off power saving, etc + #tuning: + ### Optional. Create CPU pools in CaaS CPU manager. ### Type of this parameter is dictionary, consisting of the following attributes: ### - exclusive_pool_percentage -- 2.16.6