# Copyright 2019 Nokia # 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 cmdatahandlers.api import configerror from cmdatahandlers.api import config from cmdatahandlers.api import utils class Config(config.Config): DEFAULT_HUGEPAGESZ = 'default_hugepagesz' HUGEPAGESZ = 'hugepagesz' HUGEPAGES = 'hugepages' PLATFORM_CPUS = 'platform_cpus' OVS_DPDK_CPUS = 'ovs_dpdk_cpus' 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'} ERR_INVALID_PROFILE = 'Invalid profile name {}' ERR_MISSING_PROFILE_KEY = 'Profile {} does not have %s' ERR_MISSING_DEFAULT_HUGEPAGESZ = ERR_MISSING_PROFILE_KEY % DEFAULT_HUGEPAGESZ ERR_MISSING_HUGEPAGESZ = ERR_MISSING_PROFILE_KEY % HUGEPAGESZ 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 @staticmethod def raise_error(context, err_type): raise configerror.ConfigError(err_type.format(context)) def __init__(self, confman): super(Config, self).__init__(confman) self.ROOT = 'cloud.performance_profiles' self.DOMAIN = 'performance_profiles' def init(self): pass def validate(self): self.validate_root() self._validate_performance_profiles() def _validate_performance_profiles(self): profiles = self.get_performance_profiles() utils.validate_list_items_unique(profiles) for profile in profiles: self._validate_performance_profile(profile) def _validate_performance_profile(self, profile): self.get_profile_default_hugepage_size(profile) self.get_profile_hugepage_size(profile) self.get_profile_hugepage_count(profile) self.get_platform_cpus(profile) self.get_ovs_dpdk_cpus(profile) def is_valid_profile(self, profile): profiles = self.get_performance_profiles() if profile not in profiles: self.raise_error(profile, self.ERR_INVALID_PROFILE) def get_performance_profiles(self): """ get the performance profiles list Return: A list of performance profile(s) names Raise: ConfigError in-case of an error """ self.validate_root() return self.config[self.ROOT].keys() # pylint: disable=invalid-name def get_profile_default_hugepage_size(self, profile): """ get the default hugepage size Argument: profile name Return: The default hugepage size Raise: ConfigError in-case of an error """ self.is_valid_profile(profile) if self.DEFAULT_HUGEPAGESZ not in self.config[self.ROOT][profile]: self.raise_error(profile, self.ERR_MISSING_DEFAULT_HUGEPAGESZ) return self.config[self.ROOT][profile][self.DEFAULT_HUGEPAGESZ] def get_profile_hugepage_size(self, profile): """ get the hugepage size Argument: profile name Return: The hugepage size Raise: ConfigError in-case of an error """ self.is_valid_profile(profile) if self.HUGEPAGESZ not in self.config[self.ROOT][profile]: self.raise_error(profile, self.ERR_MISSING_HUGEPAGESZ) return self.config[self.ROOT][profile][self.HUGEPAGESZ] def get_profile_hugepage_count(self, profile): """ get the hugepage count Argument: profile name Return: The hugepage count Raise: ConfigError in-case of an error """ self.is_valid_profile(profile) if self.HUGEPAGES not in self.config[self.ROOT][profile]: self.raise_error(profile, self.ERR_MISSING_HUGEPAGES) return self.config[self.ROOT][profile][self.HUGEPAGES] def get_platform_cpus(self, profile): """ get the Platforma CPUs (isolate CPUs from the general scheduler). Argument: profile name Return: The platform CPUs dictionary Raise: ConfigError in-case of an error """ self.is_valid_profile(profile) if self.PLATFORM_CPUS not in self.config[self.ROOT][profile]: self.raise_error(profile, self.ERR_MISSING_PLATFORM_CPUS) return self.config[self.ROOT][profile][self.PLATFORM_CPUS] def get_ovs_dpdk_cpus(self, profile): """ get the ovs-dpdk cpu(s) Argument: profile name Return: The ovs-dpdk dedicated cpu(s) string Raise: ConfigError in-case of an error """ self.is_valid_profile(profile) if self.OVS_DPDK_CPUS not in self.config[self.ROOT][profile]: self.raise_error(profile, self.ERR_MISSING_OVS_DPDK_CPUS) return self.config[self.ROOT][profile][self.OVS_DPDK_CPUS] def dump(self): """ Dump all performaceprofiles data. """ self.validate_root() return self.config[self.ROOT] def _fill_option_value(self, profile_data, profile, option, value): if value is None: try: value = getattr(self, self.PROFILE_OPTIONS[option])(profile) except configerror.ConfigError: return profile_data.update({option:value}) # pylint: disable=too-many-arguments def update(self, name, platform_cpus=None, ovs_dpdk_cpus=None, hugepages=None, default_hugepagesz=None, hugepagesz=None): """ Update performance profile, overwriting existing profile. Parameters ---------- name : str profile name. platform_cpus : dict, optional Platform CPUs. The syntax is: {'numa0': , 'numa1': , ..., 'numaN': } ovs_dpdk_cpus : dict, optional OVS-DPDK dedicated cores. The syntax is the same as platform_cpus. hugepages : int, optional The number of allocated persistent huge pages. default_hugepagesz : str, optional Default huge page size (the default value is '1G'). Valid values are '2M' and '1G' hugepagesz : str, optional Huge page size (the default value is '1G'). Valid values are '2M' and '1G' """ data = {} self._fill_option_value(data, name, 'platform_cpus', platform_cpus) self._fill_option_value(data, name, 'ovs_dpdk_cpus', ovs_dpdk_cpus) 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.config[self.ROOT].update({name:data}) def delete(self, name): """ Remove profile. Parametes --------- name : str profile name. Raises ------ Raises ConfigError if profile does not exist. """ try: self.config[self.ROOT].pop(name) except KeyError: self.raise_error(name, self.ERR_INVALID_PROFILE)