8b2f087910966012c8fa99e5c97b6ed433043f9d
[ta/config-manager.git] / cmdatahandlers / src / cmdatahandlers / performance_profiles / config.py
1 # Copyright 2019 Nokia
2
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 from cmdatahandlers.api import configerror
16 from cmdatahandlers.api import config
17 from cmdatahandlers.api import utils
18
19
20 class Config(config.Config):
21
22     DEFAULT_HUGEPAGESZ = 'default_hugepagesz'
23     HUGEPAGESZ = 'hugepagesz'
24     HUGEPAGES = 'hugepages'
25     PLATFORM_CPUS = 'platform_cpus'
26     OVS_DPDK_CPUS = 'ovs_dpdk_cpus'
27     PROFILE_OPTIONS = {DEFAULT_HUGEPAGESZ: 'get_profile_default_hugepage_size',
28                        HUGEPAGESZ: 'get_profile_hugepage_size',
29                        HUGEPAGES: 'get_profile_hugepage_count',
30                        PLATFORM_CPUS: 'get_platform_cpus',
31                        OVS_DPDK_CPUS: 'get_ovs_dpdk_cpus'}
32
33     ERR_INVALID_PROFILE = 'Invalid profile name {}'
34     ERR_MISSING_PROFILE_KEY = 'Profile {} does not have %s'
35     ERR_MISSING_DEFAULT_HUGEPAGESZ = ERR_MISSING_PROFILE_KEY % DEFAULT_HUGEPAGESZ
36     ERR_MISSING_HUGEPAGESZ = ERR_MISSING_PROFILE_KEY % HUGEPAGESZ
37     ERR_MISSING_HUGEPAGES = ERR_MISSING_PROFILE_KEY % HUGEPAGES
38     ERR_MISSING_PLATFORM_CPUS = ERR_MISSING_PROFILE_KEY % PLATFORM_CPUS
39     ERR_MISSING_OVS_DPDK_CPUS = ERR_MISSING_PROFILE_KEY % OVS_DPDK_CPUS
40
41     @staticmethod
42     def raise_error(context, err_type):
43         raise configerror.ConfigError(err_type.format(context))
44
45     def __init__(self, confman):
46         super(Config, self).__init__(confman)
47         self.ROOT = 'cloud.performance_profiles'
48         self.DOMAIN = 'performance_profiles'
49
50     def init(self):
51         pass
52
53     def validate(self):
54         self.validate_root()
55         self._validate_performance_profiles()
56
57     def _validate_performance_profiles(self):
58         profiles = self.get_performance_profiles()
59         utils.validate_list_items_unique(profiles)
60         for profile in profiles:
61             self._validate_performance_profile(profile)
62
63     def _validate_performance_profile(self, profile):
64         self.get_profile_default_hugepage_size(profile)
65         self.get_profile_hugepage_size(profile)
66         self.get_profile_hugepage_count(profile)
67         self.get_platform_cpus(profile)
68         self.get_ovs_dpdk_cpus(profile)
69
70     def is_valid_profile(self, profile):
71         profiles = self.get_performance_profiles()
72         if profile not in profiles:
73             self.raise_error(profile, self.ERR_INVALID_PROFILE)
74
75     def get_performance_profiles(self):
76         """ get the performance profiles list
77
78             Return:
79
80             A list of performance profile(s) names
81
82             Raise:
83
84             ConfigError in-case of an error
85         """
86         self.validate_root()
87         return self.config[self.ROOT].keys()
88
89     # pylint: disable=invalid-name
90     def get_profile_default_hugepage_size(self, profile):
91         """ get the default hugepage size
92
93             Argument:
94
95             profile name
96
97             Return:
98
99             The default hugepage size
100
101             Raise:
102
103             ConfigError in-case of an error
104         """
105         self.is_valid_profile(profile)
106
107         if self.DEFAULT_HUGEPAGESZ not in self.config[self.ROOT][profile]:
108             self.raise_error(profile, self.ERR_MISSING_DEFAULT_HUGEPAGESZ)
109
110         return self.config[self.ROOT][profile][self.DEFAULT_HUGEPAGESZ]
111
112     def get_profile_hugepage_size(self, profile):
113         """ get the hugepage size
114
115             Argument:
116
117             profile name
118
119             Return:
120
121             The hugepage size
122
123             Raise:
124
125             ConfigError in-case of an error
126         """
127         self.is_valid_profile(profile)
128
129         if self.HUGEPAGESZ not in self.config[self.ROOT][profile]:
130             self.raise_error(profile, self.ERR_MISSING_HUGEPAGESZ)
131
132         return self.config[self.ROOT][profile][self.HUGEPAGESZ]
133
134     def get_profile_hugepage_count(self, profile):
135         """ get the hugepage count
136
137             Argument:
138
139             profile name
140
141             Return:
142
143             The hugepage count
144
145             Raise:
146
147             ConfigError in-case of an error
148         """
149         self.is_valid_profile(profile)
150
151         if self.HUGEPAGES not in self.config[self.ROOT][profile]:
152             self.raise_error(profile, self.ERR_MISSING_HUGEPAGES)
153
154         return self.config[self.ROOT][profile][self.HUGEPAGES]
155
156     def get_platform_cpus(self, profile):
157         """ get the Platforma CPUs (isolate CPUs from the general scheduler).
158
159             Argument:
160
161             profile name
162
163             Return:
164
165             The platform CPUs dictionary
166
167             Raise:
168
169             ConfigError in-case of an error
170         """
171         self.is_valid_profile(profile)
172
173         if self.PLATFORM_CPUS not in self.config[self.ROOT][profile]:
174             self.raise_error(profile, self.ERR_MISSING_PLATFORM_CPUS)
175
176         return self.config[self.ROOT][profile][self.PLATFORM_CPUS]
177
178     def get_ovs_dpdk_cpus(self, profile):
179         """ get the ovs-dpdk cpu(s)
180
181             Argument:
182
183             profile name
184
185             Return:
186
187             The ovs-dpdk dedicated cpu(s) string
188
189             Raise:
190
191             ConfigError in-case of an error
192         """
193         self.is_valid_profile(profile)
194
195         if self.OVS_DPDK_CPUS not in self.config[self.ROOT][profile]:
196             self.raise_error(profile, self.ERR_MISSING_OVS_DPDK_CPUS)
197
198         return self.config[self.ROOT][profile][self.OVS_DPDK_CPUS]
199
200     def dump(self):
201         """ Dump all performaceprofiles data. """
202
203         self.validate_root()
204         return self.config[self.ROOT]
205
206     def _fill_option_value(self, profile_data, profile, option, value):
207         if value is None:
208             try:
209                 value = getattr(self, self.PROFILE_OPTIONS[option])(profile)
210             except configerror.ConfigError:
211                 return
212         profile_data.update({option:value})
213
214     # pylint: disable=too-many-arguments
215     def update(self, name, platform_cpus=None, ovs_dpdk_cpus=None, hugepages=None,
216                default_hugepagesz=None, hugepagesz=None):
217         """ Update performance profile, overwriting existing profile.
218
219             Parameters
220             ----------
221             name : str
222                    profile name.
223             platform_cpus : dict, optional
224                        Platform CPUs.
225                        The syntax is: {'numa0': <int>, 'numa1': <int>, ..., 'numaN': <int>}
226             ovs_dpdk_cpus : dict, optional
227                         OVS-DPDK dedicated cores.
228                         The syntax is the same as platform_cpus.
229             hugepages : int, optional
230                         The number of allocated persistent huge pages.
231             default_hugepagesz : str, optional
232                                  Default huge page size (the default value is '1G').
233                                  Valid values are '2M' and '1G'
234             hugepagesz : str, optional
235                          Huge page size (the default value is '1G').
236                          Valid values are '2M' and '1G'
237
238         """
239         data = {}
240         self._fill_option_value(data, name, 'platform_cpus', platform_cpus)
241         self._fill_option_value(data, name, 'ovs_dpdk_cpus', ovs_dpdk_cpus)
242         self._fill_option_value(data, name, 'hugepages', hugepages)
243         self._fill_option_value(data, name, 'default_hugepagesz', default_hugepagesz)
244         self._fill_option_value(data, name, 'hugepagesz', hugepagesz)
245         self.config[self.ROOT].update({name:data})
246
247     def delete(self, name):
248         """ Remove profile.
249
250             Parametes
251             ---------
252             name : str
253                    profile name.
254
255             Raises
256             ------
257             Raises ConfigError if profile does not exist.
258         """
259         try:
260             self.config[self.ROOT].pop(name)
261         except KeyError:
262             self.raise_error(name, self.ERR_INVALID_PROFILE)