4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
18 from cmdatahandlers.api import validation
19 from cmframework.apis import cmvalidator
22 class PerformanceProfilesValidation(cmvalidator.CMValidator):
23 DOMAIN = 'cloud.performance_profiles'
24 SUBSCRIPTION = r'^cloud\.performance_profiles$'
26 HUGEPAGESZ = 'hugepagesz'
27 DEFAULT_HUGEPAGESZ = 'default_hugepagesz'
28 HUGEPAGES = 'hugepages'
29 PLATFORM_CPUS = 'platform_cpus'
30 DPDK_CPUS = 'ovs_dpdk_cpus'
31 CAAS_CPU_POOLS = 'caas_cpu_pools'
32 CAAS_CPU_POOL_ATTRIBUTES = ['exclusive_pool_percentage', 'shared_pool_percentage']
33 CAAS_CPU_POOL_SHARE = 'caas_cpu_pool_share'
38 NUMA_VALUES = [NUMA0, NUMA1]
40 HUGEPAGESZ_VALUES = ['2M', '1G']
41 TUNING_OPTIONS = ['low_latency', 'standard']
43 INFO_HUGEPAGESZ = 'Valid values: %s' % HUGEPAGESZ_VALUES
44 INFO_HUGEPAGES = 'Must be positive integer'
45 INFO_CPUS = 'Must be zero or positive integer'
46 INFO_PLATFORM_CPUS = 'Platform requires at least one core from NUMA0'
47 INFO_TUNING = 'Valid tuning options are %s' % TUNING_OPTIONS
49 ERR_MISSING_DATA = 'Performance profiles validation input does not contain {} data'
50 ERR_INVALID_VALUE = 'Invalid %s value in performance profile {}: %s'
51 ERR_INVALID_CONFIG = 'Invalid {} config (not a dict)'
53 ERR_HUGEPAGESZ = ERR_INVALID_VALUE % (HUGEPAGESZ, INFO_HUGEPAGESZ)
54 ERR_DEFAULT_HUGEPAGESZ = ERR_INVALID_VALUE % (DEFAULT_HUGEPAGESZ, INFO_HUGEPAGESZ)
55 ERR_HUGEPAGES = ERR_INVALID_VALUE % (HUGEPAGES, INFO_HUGEPAGES)
57 ERR_NUMA = "Invalid NUMA value in performance profile {}"
58 ERR_CPUS = ERR_INVALID_VALUE % ("platform/ovs_dpdk cpu", INFO_CPUS)
59 ERR_PLATFORM_CPUS = ERR_INVALID_VALUE % ("platform_cpus", INFO_PLATFORM_CPUS)
60 ERR_CPU_POOL_RATIO = 'caas_cpu_pools total cpu percentage exceeded'
61 ERR_CAAS_CPU_POOL_TYPE = 'caas_cpu_pools percentage values should be integer'
62 ERR_CAAS_DEFAULT_POOL = 'caas_cpu_pool_share value should be integer between 0 and 100'
63 ERR_TUNING = "Invalid %s value in {}. %s" % (TUNING, INFO_TUNING)
66 def raise_error(context, err_type):
67 raise validation.ValidationError(err_type.format(context))
69 def get_subscription_info(self):
70 return self.SUBSCRIPTION
72 def validate_set(self, props):
73 conf = self.get_conf(props)
74 if isinstance(conf, dict):
77 self.raise_error(self.DOMAIN, self.ERR_INVALID_CONFIG)
79 def get_conf(self, props):
80 if not isinstance(props, dict) or self.DOMAIN not in props:
81 self.raise_error(self.DOMAIN, self.ERR_MISSING_DATA)
82 return json.loads(props[self.DOMAIN])
84 def validate(self, conf):
85 for profile, entries in conf.iteritems():
86 if isinstance(entries, dict):
87 self.validate_profile(profile, entries)
89 def validate_profile(self, profile, entries):
90 for key, value in entries.iteritems():
91 self.validate_value(profile, key, value)
93 def validate_value(self, profile, key, value):
94 if key == self.HUGEPAGESZ:
95 self.validate_hugepagesz(profile, value)
96 elif key == self.DEFAULT_HUGEPAGESZ:
97 self.validate_default_hugepagesz(profile, value)
98 elif key == self.HUGEPAGES:
99 self.validate_hugepages(profile, value)
100 elif key == self.PLATFORM_CPUS:
101 self.validate_platform_cpus(profile, value)
102 elif key == self.DPDK_CPUS:
103 self.validate_ovs_dpdk_cpus(profile, value)
104 elif key == self.CAAS_CPU_POOLS:
105 self.validate_caas_cpu_pools(profile, value)
106 elif key == self.CAAS_CPU_POOL_SHARE:
107 self.validate_caas_cpu_pool_share(value)
108 elif key == self.TUNING:
109 self.validate_tuning(profile, value)
111 def validate_hugepagesz(self, profile, value):
112 if value not in self.HUGEPAGESZ_VALUES:
113 self.raise_error(profile, self.ERR_HUGEPAGESZ)
115 def validate_default_hugepagesz(self, profile, value):
116 if value not in self.HUGEPAGESZ_VALUES:
117 self.raise_error(profile, self.ERR_DEFAULT_HUGEPAGESZ)
119 def validate_hugepages(self, profile, value):
120 if not (isinstance(value, (int, long)) and value > 0):
121 self.raise_error(profile, self.ERR_HUGEPAGES)
123 def validate_numa_names(self, profile, cpus):
124 if isinstance(cpus, dict):
125 for key in cpus.keys():
126 if key not in self.NUMA_VALUES:
127 self.raise_error(profile, self.ERR_NUMA)
129 def validate_cpu_values(self, profile, cpus):
130 if isinstance(cpus, dict):
131 for value in cpus.values():
132 if not (isinstance(value, (int, long)) and value >= 0):
133 self.raise_error(profile, self.ERR_CPUS)
135 def validate_platform_cpus(self, profile, cpus):
136 self.validate_numa_names(profile, cpus)
137 if cpus.get(self.NUMA1, None) is not None and cpus.get(self.NUMA0, None) is None:
138 self.raise_error(profile, self.ERR_PLATFORM_CPUS)
139 if cpus.get(self.NUMA1, None) is not None and cpus.get(self.NUMA0, None) == 0:
140 self.raise_error(profile, self.ERR_PLATFORM_CPUS)
141 self.validate_cpu_values(profile, cpus)
143 def validate_ovs_dpdk_cpus(self, profile, cpus):
144 self.validate_numa_names(profile, cpus)
145 self.validate_cpu_values(profile, cpus)
147 def validate_caas_cpu_pools(self, profile, pools):
149 self.allowed_attributes(profile, pools, self.CAAS_CPU_POOL_ATTRIBUTES)
150 self.is_attribute_present(profile, pools, self.CAAS_CPU_POOL_ATTRIBUTES)
151 for value in pools.values():
152 if not isinstance(value, int) or (value > 100) or (value < 0):
153 self.raise_error(profile, self.ERR_CAAS_CPU_POOL_TYPE)
156 self.raise_error(profile, self.ERR_CPU_POOL_RATIO)
158 def validate_tuning(self, profile, option):
159 if option not in self.TUNING_OPTIONS:
160 self.raise_error(profile, self.ERR_TUNING)
162 def allowed_attributes(self, profile, entries, allowed_attributes):
163 for key in entries.keys():
164 if key not in allowed_attributes:
165 self.raise_error(profile, 'Attribute %s is not allowed in profile %s, '
166 'allowed attributes: \"%s\"' %
167 (key, profile, str(",".join(allowed_attributes))))
169 def is_attribute_present(self, profile, entries, attributes):
171 for key in entries.keys():
172 if key in attributes:
175 self.raise_error(profile, 'Profile: %s should contain at least one of the following '
176 'attributes: \"%s\"' % (profile, str(",".join(attributes))))
178 def validate_caas_cpu_pool_share(self, value):
179 if not isinstance(value, (int)) or (value > 100) or (value < 0):
180 self.raise_error(value, self.ERR_CAAS_DEFAULT_POOL)