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 SUBSCRIPTION = r'^cloud\.performance_profiles$'
25 HUGEPAGESZ = 'hugepagesz'
26 DEFAULT_HUGEPAGESZ = 'default_hugepagesz'
27 HUGEPAGES = 'hugepages'
28 PLATFORM_CPUS = 'platform_cpus'
29 DPDK_CPUS = 'ovs_dpdk_cpus'
30 CAAS_CPU_POOLS = 'caas_cpu_pools'
31 CAAS_CPU_POOL_ATTRIBUTES = ['exclusive_pool_percentage', 'shared_pool_percentage']
32 CAAS_CPU_POOL_SHARE = 'caas_cpu_pool_share'
36 NUMA_VALUES = [NUMA0, NUMA1]
38 HUGEPAGESZ_VALUES = ['2M', '1G']
40 INFO_HUGEPAGESZ = 'Valid values: %s' % HUGEPAGESZ_VALUES
41 INFO_HUGEPAGES = 'Must be positive integer'
42 INFO_CPUS = 'Must be zero or positive integer'
43 INFO_PLATFORM_CPUS = 'Platform requires at least one core from NUMA0'
45 ERR_MISSING_DATA = 'Performance profiles validation input does not contain {} data'
46 ERR_INVALID_VALUE = 'Invalid %s value in performance profile {}: %s'
48 ERR_HUGEPAGESZ = ERR_INVALID_VALUE % (HUGEPAGESZ, INFO_HUGEPAGESZ)
49 ERR_DEFAULT_HUGEPAGESZ = ERR_INVALID_VALUE % (DEFAULT_HUGEPAGESZ, INFO_HUGEPAGESZ)
50 ERR_HUGEPAGES = ERR_INVALID_VALUE % (HUGEPAGES, INFO_HUGEPAGES)
52 ERR_NUMA = "Invalid NUMA value in performance profile {}"
53 ERR_CPUS = ERR_INVALID_VALUE % ("platform/ovs_dpdk cpu", INFO_CPUS)
54 ERR_PLATFORM_CPUS = ERR_INVALID_VALUE % ("platform_cpus", INFO_PLATFORM_CPUS)
55 ERR_CPU_POOL_RATIO = 'caas_cpu_pools total cpu percentage exceeded'
56 ERR_CAAS_CPU_POOL_TYPE = 'caas_cpu_pools percentage values should be integer'
57 ERR_CAAS_DEFAULT_POOL = 'caas_cpu_pool_share value should be integer between 0 and 100'
60 def raise_error(context, err_type):
61 raise validation.ValidationError(err_type.format(context))
63 def get_subscription_info(self):
64 return self.SUBSCRIPTION
66 def validate_set(self, props):
67 conf = self.get_conf(props)
68 if isinstance(conf, dict):
71 def get_conf(self, props):
72 domain = 'cloud.performance_profiles'
73 if not isinstance(props, dict) or domain not in props:
74 self.raise_error(domain, self.ERR_MISSING_DATA)
75 return json.loads(props[domain])
77 def validate(self, conf):
78 for profile, entries in conf.iteritems():
79 if isinstance(entries, dict):
80 self.validate_profile(profile, entries)
82 def validate_profile(self, profile, entries):
83 for key, value in entries.iteritems():
84 self.validate_value(profile, key, value)
86 def validate_value(self, profile, key, value):
87 if key == self.HUGEPAGESZ:
88 self.validate_hugepagesz(profile, value)
89 elif key == self.DEFAULT_HUGEPAGESZ:
90 self.validate_default_hugepagesz(profile, value)
91 elif key == self.HUGEPAGES:
92 self.validate_hugepages(profile, value)
93 elif key == self.PLATFORM_CPUS:
94 self.validate_platform_cpus(profile, value)
95 elif key == self.DPDK_CPUS:
96 self.validate_ovs_dpdk_cpus(profile, value)
97 elif key == self.CAAS_CPU_POOLS:
98 self.validate_caas_cpu_pools(profile, value)
99 elif key == self.CAAS_CPU_POOL_SHARE:
100 self.validate_caas_cpu_pool_share(value)
102 def validate_hugepagesz(self, profile, value):
103 if value not in self.HUGEPAGESZ_VALUES:
104 self.raise_error(profile, self.ERR_HUGEPAGESZ)
106 def validate_default_hugepagesz(self, profile, value):
107 if value not in self.HUGEPAGESZ_VALUES:
108 self.raise_error(profile, self.ERR_DEFAULT_HUGEPAGESZ)
110 def validate_hugepages(self, profile, value):
111 if not (isinstance(value, (int, long)) and value > 0):
112 self.raise_error(profile, self.ERR_HUGEPAGES)
114 def validate_numa_names(self, profile, cpus):
115 if isinstance(cpus, dict):
116 for key in cpus.keys():
117 if key not in self.NUMA_VALUES:
118 self.raise_error(profile, self.ERR_NUMA)
120 def validate_cpu_values(self, profile, cpus):
121 if isinstance(cpus, dict):
122 for value in cpus.values():
123 if not (isinstance(value, (int, long)) and value >= 0):
124 self.raise_error(profile, self.ERR_CPUS)
126 def validate_platform_cpus(self, profile, cpus):
127 self.validate_numa_names(profile, cpus)
128 if cpus.get(self.NUMA1, None) is not None and cpus.get(self.NUMA0, None) is None:
129 self.raise_error(profile, self.ERR_PLATFORM_CPUS)
130 if cpus.get(self.NUMA1, None) is not None and cpus.get(self.NUMA0, None) == 0:
131 self.raise_error(profile, self.ERR_PLATFORM_CPUS)
132 self.validate_cpu_values(profile, cpus)
134 def validate_ovs_dpdk_cpus(self, profile, cpus):
135 self.validate_numa_names(profile, cpus)
136 self.validate_cpu_values(profile, cpus)
138 def validate_caas_cpu_pools(self, profile, pools):
140 self.allowed_attributes(profile, pools, self.CAAS_CPU_POOL_ATTRIBUTES)
141 self.is_attribute_present(profile, pools, self.CAAS_CPU_POOL_ATTRIBUTES)
142 for value in pools.values():
143 if not isinstance(value, int) or (value > 100) or (value < 0):
144 self.raise_error(profile, self.ERR_CAAS_CPU_POOL_TYPE)
147 self.raise_error(profile, self.ERR_CPU_POOL_RATIO)
149 def allowed_attributes(self, profile, entries, allowed_attributes):
150 for key in entries.keys():
151 if key not in allowed_attributes:
152 self.raise_error(profile, 'Attribute %s is not allowed in profile %s, '
153 'allowed attributes: \"%s\"' %
154 (key, profile, str(",".join(allowed_attributes))))
156 def is_attribute_present(self, profile, entries, attributes):
158 for key in entries.keys():
159 if key in attributes:
162 self.raise_error(profile, 'Profile: %s should contain at least one of the following '
163 'attributes: \"%s\"' % (profile, str(",".join(attributes))))
165 def validate_caas_cpu_pool_share(self, value):
166 if not isinstance(value, (int)) or (value > 100) or (value < 0):
167 self.raise_error(value, self.ERR_CAAS_DEFAULT_POOL)