CAL refactoring
[osm/SO.git] / rwcal / plugins / vala / rwcal_openstack / rift / rwcal / openstack / utils / flavor.py
1 #!/usr/bin/python
2
3 #
4 # Copyright 2017 RIFT.IO Inc
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18
19 import re
20 import gi
21
22 gi.require_version('RwcalYang', '1.0')
23 from gi.repository import RwcalYang
24
25
26 class GuestEPAUtils(object):
27 """
28 Utility class for Host EPA to Openstack flavor extra_specs conversion routines
29 """
30 def __init__(self):
31 self._mano_to_espec_cpu_pinning_policy = {
32 'DEDICATED' : 'dedicated',
33 'SHARED' : 'shared',
34 'ANY' : 'any',
35 }
36
37 self._espec_to_mano_cpu_pinning_policy = {
38 'dedicated' : 'DEDICATED',
39 'shared' : 'SHARED',
40 'any' : 'ANY',
41 }
42
43 self._mano_to_espec_mempage_size = {
44 'LARGE' : 'large',
45 'SMALL' : 'small',
46 'SIZE_2MB' : 2048,
47 'SIZE_1GB' : 1048576,
48 'PREFER_LARGE' : 'large',
49 }
50
51 self._espec_to_mano_mempage_size = {
52 'large' : 'LARGE',
53 'small' : 'SMALL',
54 2048 : 'SIZE_2MB',
55 1048576 : 'SIZE_1GB',
56 'large' : 'PREFER_LARGE',
57 }
58
59 self._mano_to_espec_cpu_thread_pinning_policy = {
60 'AVOID' : 'avoid',
61 'SEPARATE' : 'separate',
62 'ISOLATE' : 'isolate',
63 'PREFER' : 'prefer',
64 }
65
66 self._espec_to_mano_cpu_thread_pinning_policy = {
67 'avoid' : 'AVOID',
68 'separate' : 'SEPARATE',
69 'isolate' : 'ISOLATE',
70 'prefer' : 'PREFER',
71 }
72
73 self._espec_to_mano_numa_memory_policy = {
74 'strict' : 'STRICT',
75 'preferred': 'PREFERRED'
76 }
77
78 self._mano_to_espec_numa_memory_policy = {
79 'STRICT' : 'strict',
80 'PREFERRED': 'preferred'
81 }
82
83 def mano_to_extra_spec_cpu_pinning_policy(self, cpu_pinning_policy):
84 if cpu_pinning_policy in self._mano_to_espec_cpu_pinning_policy:
85 return self._mano_to_espec_cpu_pinning_policy[cpu_pinning_policy]
86 else:
87 return None
88
89 def extra_spec_to_mano_cpu_pinning_policy(self, cpu_pinning_policy):
90 if cpu_pinning_policy in self._espec_to_mano_cpu_pinning_policy:
91 return self._espec_to_mano_cpu_pinning_policy[cpu_pinning_policy]
92 else:
93 return None
94
95 def mano_to_extra_spec_mempage_size(self, mempage_size):
96 if mempage_size in self._mano_to_espec_mempage_size:
97 return self._mano_to_espec_mempage_size[mempage_size]
98 else:
99 return None
100
101 def extra_spec_to_mano_mempage_size(self, mempage_size):
102 if mempage_size in self._espec_to_mano_mempage_size:
103 return self._espec_to_mano_mempage_size[mempage_size]
104 else:
105 return None
106
107 def mano_to_extra_spec_cpu_thread_pinning_policy(self, cpu_thread_pinning_policy):
108 if cpu_thread_pinning_policy in self._mano_to_espec_cpu_thread_pinning_policy:
109 return self._mano_to_espec_cpu_thread_pinning_policy[cpu_thread_pinning_policy]
110 else:
111 return None
112
113 def extra_spec_to_mano_cpu_thread_pinning_policy(self, cpu_thread_pinning_policy):
114 if cpu_thread_pinning_policy in self._espec_to_mano_cpu_thread_pinning_policy:
115 return self._espec_to_mano_cpu_thread_pinning_policy[cpu_thread_pinning_policy]
116 else:
117 return None
118
119 def mano_to_extra_spec_trusted_execution(self, trusted_execution):
120 if trusted_execution:
121 return 'trusted'
122 else:
123 return 'untrusted'
124
125 def extra_spec_to_mano_trusted_execution(self, trusted_execution):
126 if trusted_execution == 'trusted':
127 return True
128 elif trusted_execution == 'untrusted':
129 return False
130 else:
131 return None
132
133 def mano_to_extra_spec_numa_node_count(self, numa_node_count):
134 return numa_node_count
135
136 def extra_specs_to_mano_numa_node_count(self, numa_node_count):
137 return int(numa_node_count)
138
139 def mano_to_extra_spec_numa_memory_policy(self, numa_memory_policy):
140 if numa_memory_policy in self._mano_to_espec_numa_memory_policy:
141 return self._mano_to_espec_numa_memory_policy[numa_memory_policy]
142 else:
143 return None
144
145 def extra_to_mano_spec_numa_memory_policy(self, numa_memory_policy):
146 if numa_memory_policy in self._espec_to_mano_numa_memory_policy:
147 return self._espec_to_mano_numa_memory_policy[numa_memory_policy]
148 else:
149 return None
150
151
152
153
154 class HostEPAUtils(object):
155 """
156 Utility class for Host EPA to Openstack flavor extra_specs conversion routines
157 """
158 def __init__(self):
159 self._mano_to_espec_cpumodel = {
160 "PREFER_WESTMERE" : "Westmere",
161 "REQUIRE_WESTMERE" : "Westmere",
162 "PREFER_SANDYBRIDGE" : "SandyBridge",
163 "REQUIRE_SANDYBRIDGE" : "SandyBridge",
164 "PREFER_IVYBRIDGE" : "IvyBridge",
165 "REQUIRE_IVYBRIDGE" : "IvyBridge",
166 "PREFER_HASWELL" : "Haswell",
167 "REQUIRE_HASWELL" : "Haswell",
168 "PREFER_BROADWELL" : "Broadwell",
169 "REQUIRE_BROADWELL" : "Broadwell",
170 "PREFER_NEHALEM" : "Nehalem",
171 "REQUIRE_NEHALEM" : "Nehalem",
172 "PREFER_PENRYN" : "Penryn",
173 "REQUIRE_PENRYN" : "Penryn",
174 "PREFER_CONROE" : "Conroe",
175 "REQUIRE_CONROE" : "Conroe",
176 "PREFER_CORE2DUO" : "Core2Duo",
177 "REQUIRE_CORE2DUO" : "Core2Duo",
178 }
179
180 self._espec_to_mano_cpumodel = {
181 "Westmere" : "REQUIRE_WESTMERE",
182 "SandyBridge" : "REQUIRE_SANDYBRIDGE",
183 "IvyBridge" : "REQUIRE_IVYBRIDGE",
184 "Haswell" : "REQUIRE_HASWELL",
185 "Broadwell" : "REQUIRE_BROADWELL",
186 "Nehalem" : "REQUIRE_NEHALEM",
187 "Penryn" : "REQUIRE_PENRYN",
188 "Conroe" : "REQUIRE_CONROE",
189 "Core2Duo" : "REQUIRE_CORE2DUO",
190 }
191
192 self._mano_to_espec_cpuarch = {
193 "PREFER_X86" : "x86",
194 "REQUIRE_X86" : "x86",
195 "PREFER_X86_64" : "x86_64",
196 "REQUIRE_X86_64" : "x86_64",
197 "PREFER_I686" : "i686",
198 "REQUIRE_I686" : "i686",
199 "PREFER_IA64" : "ia64",
200 "REQUIRE_IA64" : "ia64",
201 "PREFER_ARMV7" : "ARMv7",
202 "REQUIRE_ARMV7" : "ARMv7",
203 "PREFER_ARMV8" : "ARMv8-A",
204 "REQUIRE_ARMV8" : "ARMv8-A",
205 }
206
207 self._espec_to_mano_cpuarch = {
208 "x86" : "REQUIRE_X86",
209 "x86_64" : "REQUIRE_X86_64",
210 "i686" : "REQUIRE_I686",
211 "ia64" : "REQUIRE_IA64",
212 "ARMv7-A" : "REQUIRE_ARMV7",
213 "ARMv8-A" : "REQUIRE_ARMV8",
214 }
215
216 self._mano_to_espec_cpuvendor = {
217 "PREFER_INTEL" : "Intel",
218 "REQUIRE_INTEL" : "Intel",
219 "PREFER_AMD" : "AMD",
220 "REQUIRE_AMD" : "AMD",
221 }
222
223 self._espec_to_mano_cpuvendor = {
224 "Intel" : "REQUIRE_INTEL",
225 "AMD" : "REQUIRE_AMD",
226 }
227
228 self._mano_to_espec_cpufeatures = {
229 "PREFER_AES" : "aes",
230 "REQUIRE_AES" : "aes",
231 "REQUIRE_VME" : "vme",
232 "PREFER_VME" : "vme",
233 "REQUIRE_DE" : "de",
234 "PREFER_DE" : "de",
235 "REQUIRE_PSE" : "pse",
236 "PREFER_PSE" : "pse",
237 "REQUIRE_TSC" : "tsc",
238 "PREFER_TSC" : "tsc",
239 "REQUIRE_MSR" : "msr",
240 "PREFER_MSR" : "msr",
241 "REQUIRE_PAE" : "pae",
242 "PREFER_PAE" : "pae",
243 "REQUIRE_MCE" : "mce",
244 "PREFER_MCE" : "mce",
245 "REQUIRE_CX8" : "cx8",
246 "PREFER_CX8" : "cx8",
247 "REQUIRE_APIC" : "apic",
248 "PREFER_APIC" : "apic",
249 "REQUIRE_SEP" : "sep",
250 "PREFER_SEP" : "sep",
251 "REQUIRE_MTRR" : "mtrr",
252 "PREFER_MTRR" : "mtrr",
253 "REQUIRE_PGE" : "pge",
254 "PREFER_PGE" : "pge",
255 "REQUIRE_MCA" : "mca",
256 "PREFER_MCA" : "mca",
257 "REQUIRE_CMOV" : "cmov",
258 "PREFER_CMOV" : "cmov",
259 "REQUIRE_PAT" : "pat",
260 "PREFER_PAT" : "pat",
261 "REQUIRE_PSE36" : "pse36",
262 "PREFER_PSE36" : "pse36",
263 "REQUIRE_CLFLUSH" : "clflush",
264 "PREFER_CLFLUSH" : "clflush",
265 "REQUIRE_DTS" : "dts",
266 "PREFER_DTS" : "dts",
267 "REQUIRE_ACPI" : "acpi",
268 "PREFER_ACPI" : "acpi",
269 "REQUIRE_MMX" : "mmx",
270 "PREFER_MMX" : "mmx",
271 "REQUIRE_FXSR" : "fxsr",
272 "PREFER_FXSR" : "fxsr",
273 "REQUIRE_SSE" : "sse",
274 "PREFER_SSE" : "sse",
275 "REQUIRE_SSE2" : "sse2",
276 "PREFER_SSE2" : "sse2",
277 "REQUIRE_SS" : "ss",
278 "PREFER_SS" : "ss",
279 "REQUIRE_HT" : "ht",
280 "PREFER_HT" : "ht",
281 "REQUIRE_TM" : "tm",
282 "PREFER_TM" : "tm",
283 "REQUIRE_IA64" : "ia64",
284 "PREFER_IA64" : "ia64",
285 "REQUIRE_PBE" : "pbe",
286 "PREFER_PBE" : "pbe",
287 "REQUIRE_RDTSCP" : "rdtscp",
288 "PREFER_RDTSCP" : "rdtscp",
289 "REQUIRE_PNI" : "pni",
290 "PREFER_PNI" : "pni",
291 "REQUIRE_PCLMULQDQ": "pclmulqdq",
292 "PREFER_PCLMULQDQ" : "pclmulqdq",
293 "REQUIRE_DTES64" : "dtes64",
294 "PREFER_DTES64" : "dtes64",
295 "REQUIRE_MONITOR" : "monitor",
296 "PREFER_MONITOR" : "monitor",
297 "REQUIRE_DS_CPL" : "ds_cpl",
298 "PREFER_DS_CPL" : "ds_cpl",
299 "REQUIRE_VMX" : "vmx",
300 "PREFER_VMX" : "vmx",
301 "REQUIRE_SMX" : "smx",
302 "PREFER_SMX" : "smx",
303 "REQUIRE_EST" : "est",
304 "PREFER_EST" : "est",
305 "REQUIRE_TM2" : "tm2",
306 "PREFER_TM2" : "tm2",
307 "REQUIRE_SSSE3" : "ssse3",
308 "PREFER_SSSE3" : "ssse3",
309 "REQUIRE_CID" : "cid",
310 "PREFER_CID" : "cid",
311 "REQUIRE_FMA" : "fma",
312 "PREFER_FMA" : "fma",
313 "REQUIRE_CX16" : "cx16",
314 "PREFER_CX16" : "cx16",
315 "REQUIRE_XTPR" : "xtpr",
316 "PREFER_XTPR" : "xtpr",
317 "REQUIRE_PDCM" : "pdcm",
318 "PREFER_PDCM" : "pdcm",
319 "REQUIRE_PCID" : "pcid",
320 "PREFER_PCID" : "pcid",
321 "REQUIRE_DCA" : "dca",
322 "PREFER_DCA" : "dca",
323 "REQUIRE_SSE4_1" : "sse4_1",
324 "PREFER_SSE4_1" : "sse4_1",
325 "REQUIRE_SSE4_2" : "sse4_2",
326 "PREFER_SSE4_2" : "sse4_2",
327 "REQUIRE_X2APIC" : "x2apic",
328 "PREFER_X2APIC" : "x2apic",
329 "REQUIRE_MOVBE" : "movbe",
330 "PREFER_MOVBE" : "movbe",
331 "REQUIRE_POPCNT" : "popcnt",
332 "PREFER_POPCNT" : "popcnt",
333 "REQUIRE_TSC_DEADLINE_TIMER" : "tsc_deadline_timer",
334 "PREFER_TSC_DEADLINE_TIMER" : "tsc_deadline_timer",
335 "REQUIRE_XSAVE" : "xsave",
336 "PREFER_XSAVE" : "xsave",
337 "REQUIRE_AVX" : "avx",
338 "PREFER_AVX" : "avx",
339 "REQUIRE_F16C" : "f16c",
340 "PREFER_F16C" : "f16c",
341 "REQUIRE_RDRAND" : "rdrand",
342 "PREFER_RDRAND" : "rdrand",
343 "REQUIRE_FSGSBASE" : "fsgsbase",
344 "PREFER_FSGSBASE" : "fsgsbase",
345 "REQUIRE_BMI1" : "bmi1",
346 "PREFER_BMI1" : "bmi1",
347 "REQUIRE_HLE" : "hle",
348 "PREFER_HLE" : "hle",
349 "REQUIRE_AVX2" : "avx2",
350 "PREFER_AVX2" : "avx2",
351 "REQUIRE_SMEP" : "smep",
352 "PREFER_SMEP" : "smep",
353 "REQUIRE_BMI2" : "bmi2",
354 "PREFER_BMI2" : "bmi2",
355 "REQUIRE_ERMS" : "erms",
356 "PREFER_ERMS" : "erms",
357 "REQUIRE_INVPCID" : "invpcid",
358 "PREFER_INVPCID" : "invpcid",
359 "REQUIRE_RTM" : "rtm",
360 "PREFER_RTM" : "rtm",
361 "REQUIRE_MPX" : "mpx",
362 "PREFER_MPX" : "mpx",
363 "REQUIRE_RDSEED" : "rdseed",
364 "PREFER_RDSEED" : "rdseed",
365 "REQUIRE_ADX" : "adx",
366 "PREFER_ADX" : "adx",
367 "REQUIRE_SMAP" : "smap",
368 "PREFER_SMAP" : "smap",
369 }
370
371 self._espec_to_mano_cpufeatures = {
372 "aes" : "REQUIRE_AES",
373 "vme" : "REQUIRE_VME",
374 "de" : "REQUIRE_DE",
375 "pse" : "REQUIRE_PSE",
376 "tsc" : "REQUIRE_TSC",
377 "msr" : "REQUIRE_MSR",
378 "pae" : "REQUIRE_PAE",
379 "mce" : "REQUIRE_MCE",
380 "cx8" : "REQUIRE_CX8",
381 "apic" : "REQUIRE_APIC",
382 "sep" : "REQUIRE_SEP",
383 "mtrr" : "REQUIRE_MTRR",
384 "pge" : "REQUIRE_PGE",
385 "mca" : "REQUIRE_MCA",
386 "cmov" : "REQUIRE_CMOV",
387 "pat" : "REQUIRE_PAT",
388 "pse36" : "REQUIRE_PSE36",
389 "clflush" : "REQUIRE_CLFLUSH",
390 "dts" : "REQUIRE_DTS",
391 "acpi" : "REQUIRE_ACPI",
392 "mmx" : "REQUIRE_MMX",
393 "fxsr" : "REQUIRE_FXSR",
394 "sse" : "REQUIRE_SSE",
395 "sse2" : "REQUIRE_SSE2",
396 "ss" : "REQUIRE_SS",
397 "ht" : "REQUIRE_HT",
398 "tm" : "REQUIRE_TM",
399 "ia64" : "REQUIRE_IA64",
400 "pbe" : "REQUIRE_PBE",
401 "rdtscp" : "REQUIRE_RDTSCP",
402 "pni" : "REQUIRE_PNI",
403 "pclmulqdq": "REQUIRE_PCLMULQDQ",
404 "dtes64" : "REQUIRE_DTES64",
405 "monitor" : "REQUIRE_MONITOR",
406 "ds_cpl" : "REQUIRE_DS_CPL",
407 "vmx" : "REQUIRE_VMX",
408 "smx" : "REQUIRE_SMX",
409 "est" : "REQUIRE_EST",
410 "tm2" : "REQUIRE_TM2",
411 "ssse3" : "REQUIRE_SSSE3",
412 "cid" : "REQUIRE_CID",
413 "fma" : "REQUIRE_FMA",
414 "cx16" : "REQUIRE_CX16",
415 "xtpr" : "REQUIRE_XTPR",
416 "pdcm" : "REQUIRE_PDCM",
417 "pcid" : "REQUIRE_PCID",
418 "dca" : "REQUIRE_DCA",
419 "sse4_1" : "REQUIRE_SSE4_1",
420 "sse4_2" : "REQUIRE_SSE4_2",
421 "x2apic" : "REQUIRE_X2APIC",
422 "movbe" : "REQUIRE_MOVBE",
423 "popcnt" : "REQUIRE_POPCNT",
424 "tsc_deadline_timer" : "REQUIRE_TSC_DEADLINE_TIMER",
425 "xsave" : "REQUIRE_XSAVE",
426 "avx" : "REQUIRE_AVX",
427 "f16c" : "REQUIRE_F16C",
428 "rdrand" : "REQUIRE_RDRAND",
429 "fsgsbase" : "REQUIRE_FSGSBASE",
430 "bmi1" : "REQUIRE_BMI1",
431 "hle" : "REQUIRE_HLE",
432 "avx2" : "REQUIRE_AVX2",
433 "smep" : "REQUIRE_SMEP",
434 "bmi2" : "REQUIRE_BMI2",
435 "erms" : "REQUIRE_ERMS",
436 "invpcid" : "REQUIRE_INVPCID",
437 "rtm" : "REQUIRE_RTM",
438 "mpx" : "REQUIRE_MPX",
439 "rdseed" : "REQUIRE_RDSEED",
440 "adx" : "REQUIRE_ADX",
441 "smap" : "REQUIRE_SMAP",
442 }
443
444 def mano_to_extra_spec_cpu_model(self, cpu_model):
445 if cpu_model in self._mano_to_espec_cpumodel:
446 return self._mano_to_espec_cpumodel[cpu_model]
447 else:
448 return None
449
450 def extra_specs_to_mano_cpu_model(self, cpu_model):
451 if cpu_model in self._espec_to_mano_cpumodel:
452 return self._espec_to_mano_cpumodel[cpu_model]
453 else:
454 return None
455
456 def mano_to_extra_spec_cpu_arch(self, cpu_arch):
457 if cpu_arch in self._mano_to_espec_cpuarch:
458 return self._mano_to_espec_cpuarch[cpu_arch]
459 else:
460 return None
461
462 def extra_specs_to_mano_cpu_arch(self, cpu_arch):
463 if cpu_arch in self._espec_to_mano_cpuarch:
464 return self._espec_to_mano_cpuarch[cpu_arch]
465 else:
466 return None
467
468 def mano_to_extra_spec_cpu_vendor(self, cpu_vendor):
469 if cpu_vendor in self._mano_to_espec_cpuvendor:
470 return self._mano_to_espec_cpuvendor[cpu_vendor]
471 else:
472 return None
473
474 def extra_spec_to_mano_cpu_vendor(self, cpu_vendor):
475 if cpu_vendor in self._espec_to_mano_cpuvendor:
476 return self._espec_to_mano_cpuvendor[cpu_vendor]
477 else:
478 return None
479
480 def mano_to_extra_spec_cpu_socket_count(self, cpu_sockets):
481 return cpu_sockets
482
483 def extra_spec_to_mano_cpu_socket_count(self, cpu_sockets):
484 return int(cpu_sockets)
485
486 def mano_to_extra_spec_cpu_core_count(self, cpu_core_count):
487 return cpu_core_count
488
489 def extra_spec_to_mano_cpu_core_count(self, cpu_core_count):
490 return int(cpu_core_count)
491
492 def mano_to_extra_spec_cpu_core_thread_count(self, core_thread_count):
493 return core_thread_count
494
495 def extra_spec_to_mano_cpu_core_thread_count(self, core_thread_count):
496 return int(core_thread_count)
497
498 def mano_to_extra_spec_cpu_features(self, features):
499 cpu_features = []
500 epa_feature_str = None
501 for f in features:
502 if f in self._mano_to_espec_cpufeatures:
503 cpu_features.append(self._mano_to_espec_cpufeatures[f])
504
505 if len(cpu_features) > 1:
506 epa_feature_str = '<all-in> '+ " ".join(cpu_features)
507 elif len(cpu_features) == 1:
508 epa_feature_str = " ".join(cpu_features)
509
510 return epa_feature_str
511
512 def extra_spec_to_mano_cpu_features(self, features):
513 oper_symbols = ['=', '<in>', '<all-in>', '==', '!=', '>=', '<=', 's==', 's!=', 's<', 's<=', 's>', 's>=']
514 cpu_features = []
515 result = None
516 for oper in oper_symbols:
517 regex = '^'+oper+' (.*?)$'
518 result = re.search(regex, features)
519 if result is not None:
520 break
521
522 if result is not None:
523 feature_list = result.group(1)
524 else:
525 feature_list = features
526
527 for f in feature_list.split():
528 if f in self._espec_to_mano_cpufeatures:
529 cpu_features.append(self._espec_to_mano_cpufeatures[f])
530
531 return cpu_features
532
533
534 class ExtraSpecUtils(object):
535 """
536 General utility class for flavor Extra Specs processing
537 """
538 def __init__(self):
539 self.host = HostEPAUtils()
540 self.guest = GuestEPAUtils()
541 self.extra_specs_keywords = [ 'hw:cpu_policy',
542 'hw:cpu_threads_policy',
543 'hw:mem_page_size',
544 'hw:numa_nodes',
545 'hw:numa_mempolicy',
546 'hw:numa_cpus',
547 'hw:numa_mem',
548 'trust:trusted_host',
549 'pci_passthrough:alias',
550 'capabilities:cpu_info:model',
551 'capabilities:cpu_info:arch',
552 'capabilities:cpu_info:vendor',
553 'capabilities:cpu_info:topology:sockets',
554 'capabilities:cpu_info:topology:cores',
555 'capabilities:cpu_info:topology:threads',
556 'capabilities:cpu_info:features',
557 ]
558 self.extra_specs_regex = re.compile("^"+"|^".join(self.extra_specs_keywords))
559
560
561
562 class FlavorUtils(object):
563 """
564 Utility class for handling the flavor
565 """
566 def __init__(self, driver):
567 """
568 Constructor for class
569 Arguments:
570 driver: object of OpenstackDriver()
571 """
572 self._epa = ExtraSpecUtils()
573 self._driver = driver
574 self.log = driver.log
575
576 @property
577 def driver(self):
578 return self._driver
579
580 def _get_guest_epa_specs(self, guest_epa):
581 """
582 Returns EPA Specs dictionary for guest_epa attributes
583 """
584 epa_specs = dict()
585 if guest_epa.has_field('mempage_size'):
586 mempage_size = self._epa.guest.mano_to_extra_spec_mempage_size(guest_epa.mempage_size)
587 if mempage_size is not None:
588 epa_specs['hw:mem_page_size'] = mempage_size
589
590 if guest_epa.has_field('cpu_pinning_policy'):
591 cpu_pinning_policy = self._epa.guest.mano_to_extra_spec_cpu_pinning_policy(guest_epa.cpu_pinning_policy)
592 if cpu_pinning_policy is not None:
593 epa_specs['hw:cpu_policy'] = cpu_pinning_policy
594
595 if guest_epa.has_field('cpu_thread_pinning_policy'):
596 cpu_thread_pinning_policy = self._epa.guest.mano_to_extra_spec_cpu_thread_pinning_policy(guest_epa.cpu_thread_pinning_policy)
597 if cpu_thread_pinning_policy is None:
598 epa_specs['hw:cpu_threads_policy'] = cpu_thread_pinning_policy
599
600 if guest_epa.has_field('trusted_execution'):
601 trusted_execution = self._epa.guest.mano_to_extra_spec_trusted_execution(guest_epa.trusted_execution)
602 if trusted_execution is not None:
603 epa_specs['trust:trusted_host'] = trusted_execution
604
605 if guest_epa.has_field('numa_node_policy'):
606 if guest_epa.numa_node_policy.has_field('node_cnt'):
607 numa_node_count = self._epa.guest.mano_to_extra_spec_numa_node_count(guest_epa.numa_node_policy.node_cnt)
608 if numa_node_count is not None:
609 epa_specs['hw:numa_nodes'] = numa_node_count
610
611 if guest_epa.numa_node_policy.has_field('mem_policy'):
612 numa_memory_policy = self._epa.guest.mano_to_extra_spec_numa_memory_policy(guest_epa.numa_node_policy.mem_policy)
613 if numa_memory_policy is not None:
614 epa_specs['hw:numa_mempolicy'] = numa_memory_policy
615
616 if guest_epa.numa_node_policy.has_field('node'):
617 for node in guest_epa.numa_node_policy.node:
618 if node.has_field('vcpu') and node.vcpu:
619 epa_specs['hw:numa_cpus.'+str(node.id)] = ','.join([str(j.id) for j in node.vcpu])
620 if node.memory_mb:
621 epa_specs['hw:numa_mem.'+str(node.id)] = str(node.memory_mb)
622
623 if guest_epa.has_field('pcie_device'):
624 pci_devices = []
625 for device in guest_epa.pcie_device:
626 pci_devices.append(device.device_id +':'+str(device.count))
627 epa_specs['pci_passthrough:alias'] = ','.join(pci_devices)
628
629 return epa_specs
630
631 def _get_host_epa_specs(self,host_epa):
632 """
633 Returns EPA Specs dictionary for host_epa attributes
634 """
635 epa_specs = dict()
636
637 if host_epa.has_field('cpu_model'):
638 cpu_model = self._epa.host.mano_to_extra_spec_cpu_model(host_epa.cpu_model)
639 if cpu_model is not None:
640 epa_specs['capabilities:cpu_info:model'] = cpu_model
641
642 if host_epa.has_field('cpu_arch'):
643 cpu_arch = self._epa.host.mano_to_extra_spec_cpu_arch(host_epa.cpu_arch)
644 if cpu_arch is not None:
645 epa_specs['capabilities:cpu_info:arch'] = cpu_arch
646
647 if host_epa.has_field('cpu_vendor'):
648 cpu_vendor = self._epa.host.mano_to_extra_spec_cpu_vendor(host_epa.cpu_vendor)
649 if cpu_vendor is not None:
650 epa_specs['capabilities:cpu_info:vendor'] = cpu_vendor
651
652 if host_epa.has_field('cpu_socket_count'):
653 cpu_socket_count = self._epa.host.mano_to_extra_spec_cpu_socket_count(host_epa.cpu_socket_count)
654 if cpu_socket_count is not None:
655 epa_specs['capabilities:cpu_info:topology:sockets'] = cpu_socket_count
656
657 if host_epa.has_field('cpu_core_count'):
658 cpu_core_count = self._epa.host.mano_to_extra_spec_cpu_core_count(host_epa.cpu_core_count)
659 if cpu_core_count is not None:
660 epa_specs['capabilities:cpu_info:topology:cores'] = cpu_core_count
661
662 if host_epa.has_field('cpu_core_thread_count'):
663 cpu_core_thread_count = self._epa.host.mano_to_extra_spec_cpu_core_thread_count(host_epa.cpu_core_thread_count)
664 if cpu_core_thread_count is not None:
665 epa_specs['capabilities:cpu_info:topology:threads'] = cpu_core_thread_count
666
667 if host_epa.has_field('cpu_feature'):
668 cpu_features = []
669 espec_cpu_features = []
670 for feature in host_epa.cpu_feature:
671 cpu_features.append(feature.feature)
672 espec_cpu_features = self._epa.host.mano_to_extra_spec_cpu_features(cpu_features)
673 if espec_cpu_features is not None:
674 epa_specs['capabilities:cpu_info:features'] = espec_cpu_features
675 return epa_specs
676
677 def _get_hypervisor_epa_specs(self,guest_epa):
678 """
679 Returns EPA Specs dictionary for hypervisor_epa attributes
680 """
681 hypervisor_epa = dict()
682 return hypervisor_epa
683
684 def _get_vswitch_epa_specs(self, guest_epa):
685 """
686 Returns EPA Specs dictionary for vswitch_epa attributes
687 """
688 vswitch_epa = dict()
689 return vswitch_epa
690
691 def _get_host_aggregate_epa_specs(self, host_aggregate):
692 """
693 Returns EPA Specs dictionary for host aggregates
694 """
695 epa_specs = dict()
696 for aggregate in host_aggregate:
697 epa_specs['aggregate_instance_extra_specs:'+aggregate.metadata_key] = aggregate.metadata_value
698
699 return epa_specs
700
701 def get_extra_specs(self, flavor):
702 """
703 Returns epa_specs dictionary based on flavor information
704 Arguments
705 flavor -- Protobuf GI object for flavor_info (RwcalYang.FlavorInfoItem())
706 Returns:
707 A dictionary of extra_specs in format understood by novaclient library
708 """
709 epa_specs = dict()
710 if flavor.has_field('guest_epa'):
711 guest_epa = self._get_guest_epa_specs(flavor.guest_epa)
712 epa_specs.update(guest_epa)
713 if flavor.has_field('host_epa'):
714 host_epa = self._get_host_epa_specs(flavor.host_epa)
715 epa_specs.update(host_epa)
716 if flavor.has_field('hypervisor_epa'):
717 hypervisor_epa = self._get_hypervisor_epa_specs(flavor.hypervisor_epa)
718 epa_specs.update(hypervisor_epa)
719 if flavor.has_field('vswitch_epa'):
720 vswitch_epa = self._get_vswitch_epa_specs(flavor.vswitch_epa)
721 epa_specs.update(vswitch_epa)
722 if flavor.has_field('host_aggregate'):
723 host_aggregate = self._get_host_aggregate_epa_specs(flavor.host_aggregate)
724 epa_specs.update(host_aggregate)
725 return epa_specs
726
727
728 def parse_vm_flavor_epa_info(self, flavor_info):
729 """
730 Parse the flavor_info dictionary (returned by python-client) for vm_flavor
731
732 Arguments:
733 flavor_info: A dictionary object return by novaclient library listing flavor attributes
734
735 Returns:
736 vm_flavor = RwcalYang.FlavorInfoItem_VmFlavor()
737 """
738 vm_flavor = RwcalYang.FlavorInfoItem_VmFlavor()
739
740 if 'vcpus' in flavor_info and flavor_info['vcpus']:
741 vm_flavor.vcpu_count = flavor_info['vcpus']
742
743 if 'ram' in flavor_info and flavor_info['ram']:
744 vm_flavor.memory_mb = flavor_info['ram']
745
746 if 'disk' in flavor_info and flavor_info['disk']:
747 vm_flavor.storage_gb = flavor_info['disk']
748
749 return vm_flavor
750
751 def parse_guest_epa_info(self, flavor_info):
752 """
753 Parse the flavor_info dictionary (returned by python-client) for guest_epa
754
755 Arguments:
756 flavor_info: A dictionary object return by novaclient library listing flavor attributes
757
758 Returns:
759 guest_epa = RwcalYang.FlavorInfoItem_GuestEpa()
760 """
761 guest_epa = RwcalYang.FlavorInfoItem_GuestEpa()
762 for attr in flavor_info['extra_specs']:
763 if attr == 'hw:cpu_policy':
764 cpu_pinning_policy = self._epa.guest.extra_spec_to_mano_cpu_pinning_policy(flavor_info['extra_specs']['hw:cpu_policy'])
765 if cpu_pinning_policy is not None:
766 guest_epa.cpu_pinning_policy = cpu_pinning_policy
767
768 elif attr == 'hw:cpu_threads_policy':
769 cpu_thread_pinning_policy = self._epa.guest.extra_spec_to_mano_cpu_thread_pinning_policy(flavor_info['extra_specs']['hw:cpu_threads_policy'])
770 if cpu_thread_pinning_policy is not None:
771 guest_epa.cpu_thread_pinning_policy = cpu_thread_pinning_policy
772
773 elif attr == 'hw:mem_page_size':
774 mempage_size = self._epa.guest.extra_spec_to_mano_mempage_size(flavor_info['extra_specs']['hw:mem_page_size'])
775 if mempage_size is not None:
776 guest_epa.mempage_size = mempage_size
777
778 elif attr == 'hw:numa_nodes':
779 numa_node_count = self._epa.guest.extra_specs_to_mano_numa_node_count(flavor_info['extra_specs']['hw:numa_nodes'])
780 if numa_node_count is not None:
781 guest_epa.numa_node_policy.node_cnt = numa_node_count
782
783 elif attr.startswith('hw:numa_cpus.'):
784 node_id = attr.split('.')[1]
785 nodes = [ n for n in guest_epa.numa_node_policy.node if n.id == int(node_id) ]
786 if nodes:
787 numa_node = nodes[0]
788 else:
789 numa_node = guest_epa.numa_node_policy.node.add()
790 numa_node.id = int(node_id)
791
792 for x in flavor_info['extra_specs'][attr].split(','):
793 numa_node_vcpu = numa_node.vcpu.add()
794 numa_node_vcpu.id = int(x)
795
796 elif attr.startswith('hw:numa_mem.'):
797 node_id = attr.split('.')[1]
798 nodes = [ n for n in guest_epa.numa_node_policy.node if n.id == int(node_id) ]
799 if nodes:
800 numa_node = nodes[0]
801 else:
802 numa_node = guest_epa.numa_node_policy.node.add()
803 numa_node.id = int(node_id)
804
805 numa_node.memory_mb = int(flavor_info['extra_specs'][attr])
806
807 elif attr == 'hw:numa_mempolicy':
808 numa_memory_policy = self._epa.guest.extra_to_mano_spec_numa_memory_policy(flavor_info['extra_specs']['hw:numa_mempolicy'])
809 if numa_memory_policy is not None:
810 guest_epa.numa_node_policy.mem_policy = numa_memory_policy
811
812 elif attr == 'trust:trusted_host':
813 trusted_execution = self._epa.guest.extra_spec_to_mano_trusted_execution(flavor_info['extra_specs']['trust:trusted_host'])
814 if trusted_execution is not None:
815 guest_epa.trusted_execution = trusted_execution
816
817 elif attr == 'pci_passthrough:alias':
818 device_types = flavor_info['extra_specs']['pci_passthrough:alias']
819 for device in device_types.split(','):
820 dev = guest_epa.pcie_device.add()
821 dev.device_id = device.split(':')[0]
822 dev.count = int(device.split(':')[1])
823 return guest_epa
824
825 def parse_host_epa_info(self, flavor_info):
826 """
827 Parse the flavor_info dictionary (returned by python-client) for host_epa
828
829 Arguments:
830 flavor_info: A dictionary object return by novaclient library listing flavor attributes
831
832 Returns:
833 host_epa = RwcalYang.FlavorInfoItem_HostEpa()
834 """
835 host_epa = RwcalYang.FlavorInfoItem_HostEpa()
836 for attr in flavor_info['extra_specs']:
837 if attr == 'capabilities:cpu_info:model':
838 cpu_model = self._epa.host.extra_specs_to_mano_cpu_model(flavor_info['extra_specs']['capabilities:cpu_info:model'])
839 if cpu_model is not None:
840 host_epa.cpu_model = cpu_model
841
842 elif attr == 'capabilities:cpu_info:arch':
843 cpu_arch = self._epa.host.extra_specs_to_mano_cpu_arch(flavor_info['extra_specs']['capabilities:cpu_info:arch'])
844 if cpu_arch is not None:
845 host_epa.cpu_arch = cpu_arch
846
847 elif attr == 'capabilities:cpu_info:vendor':
848 cpu_vendor = self._epa.host.extra_spec_to_mano_cpu_vendor(flavor_info['extra_specs']['capabilities:cpu_info:vendor'])
849 if cpu_vendor is not None:
850 host_epa.cpu_vendor = cpu_vendor
851
852 elif attr == 'capabilities:cpu_info:topology:sockets':
853 cpu_sockets = self._epa.host.extra_spec_to_mano_cpu_socket_count(flavor_info['extra_specs']['capabilities:cpu_info:topology:sockets'])
854 if cpu_sockets is not None:
855 host_epa.cpu_socket_count = cpu_sockets
856
857 elif attr == 'capabilities:cpu_info:topology:cores':
858 cpu_cores = self._epa.host.extra_spec_to_mano_cpu_core_count(flavor_info['extra_specs']['capabilities:cpu_info:topology:cores'])
859 if cpu_cores is not None:
860 host_epa.cpu_core_count = cpu_cores
861
862 elif attr == 'capabilities:cpu_info:topology:threads':
863 cpu_threads = self._epa.host.extra_spec_to_mano_cpu_core_thread_count(flavor_info['extra_specs']['capabilities:cpu_info:topology:threads'])
864 if cpu_threads is not None:
865 host_epa.cpu_core_thread_count = cpu_threads
866
867 elif attr == 'capabilities:cpu_info:features':
868 cpu_features = self._epa.host.extra_spec_to_mano_cpu_features(flavor_info['extra_specs']['capabilities:cpu_info:features'])
869 if cpu_features is not None:
870 for feature in cpu_features:
871 host_epa.cpu_feature.append(feature)
872 return host_epa
873
874 def parse_host_aggregate_epa_info(self, flavor_info):
875 """
876 Parse the flavor_info dictionary (returned by python-client) for host_aggregate
877
878 Arguments:
879 flavor_info: A dictionary object return by novaclient library listing flavor attributes
880
881 Returns:
882 A list of objects host_aggregate of type RwcalYang.FlavorInfoItem_HostAggregate()
883 """
884 host_aggregates = list()
885 for attr in flavor_info['extra_specs']:
886 if attr.startswith('aggregate_instance_extra_specs:'):
887 aggregate = RwcalYang.FlavorInfoItem_HostAggregate()
888 aggregate.metadata_key = ":".join(attr.split(':')[1::])
889 aggregate.metadata_value = flavor_info['extra_specs'][attr]
890 host_aggregates.append(aggregate)
891 return host_aggregates
892
893
894 def parse_flavor_info(self, flavor_info):
895 """
896 Parse the flavor_info dictionary and put value in RIFT GI object for flavor
897 Arguments:
898 flavor_info: A dictionary object returned by novaclient library listing flavor attributes
899
900 Returns:
901 Protobuf GI Object of type RwcalYang.FlavorInfoItem()
902
903 """
904 flavor = RwcalYang.FlavorInfoItem()
905 if 'name' in flavor_info and flavor_info['name']:
906 flavor.name = flavor_info['name']
907 if 'id' in flavor_info and flavor_info['id']:
908 flavor.id = flavor_info['id']
909
910 ### If extra_specs in flavor_info
911 if 'extra_specs' in flavor_info:
912 flavor.vm_flavor = self.parse_vm_flavor_epa_info(flavor_info)
913 flavor.guest_epa = self.parse_guest_epa_info(flavor_info)
914 flavor.host_epa = self.parse_host_epa_info(flavor_info)
915 for aggr in self.parse_host_aggregate_epa_info(flavor_info):
916 ha = flavor.host_aggregate.add()
917 ha.from_dict(aggr.as_dict())
918 return flavor
919
920 def _match_vm_flavor(self, required, available):
921 self.log.info("Matching VM Flavor attributes")
922 if available.vcpu_count != required.vcpu_count:
923 self.log.debug("VCPU requirement mismatch. Required: %d, Available: %d",
924 required.vcpu_count,
925 available.vcpu_count)
926 return False
927 if available.memory_mb != required.memory_mb:
928 self.log.debug("Memory requirement mismatch. Required: %d MB, Available: %d MB",
929 required.memory_mb,
930 available.memory_mb)
931 return False
932 if available.storage_gb != required.storage_gb:
933 self.log.debug("Storage requirement mismatch. Required: %d GB, Available: %d GB",
934 required.storage_gb,
935 available.storage_gb)
936 return False
937 self.log.debug("VM Flavor match found")
938 return True
939
940 def _match_guest_epa(self, required, available):
941 self.log.info("Matching Guest EPA attributes")
942 if required.has_field('pcie_device'):
943 self.log.debug("Matching pcie_device")
944 if available.has_field('pcie_device') == False:
945 self.log.debug("Matching pcie_device failed. Not available in flavor")
946 return False
947 else:
948 for dev in required.pcie_device:
949 if not [ d for d in available.pcie_device
950 if ((d.device_id == dev.device_id) and (d.count == dev.count)) ]:
951 self.log.debug("Matching pcie_device failed. Required: %s, Available: %s",
952 required.pcie_device, available.pcie_device)
953 return False
954 elif available.has_field('pcie_device'):
955 self.log.debug("Rejecting available flavor because pcie_device not required but available")
956 return False
957
958
959 if required.has_field('mempage_size'):
960 self.log.debug("Matching mempage_size")
961 if available.has_field('mempage_size') == False:
962 self.log.debug("Matching mempage_size failed. Not available in flavor")
963 return False
964 else:
965 if required.mempage_size != available.mempage_size:
966 self.log.debug("Matching mempage_size failed. Required: %s, Available: %s",
967 required.mempage_size, available.mempage_size)
968 return False
969 elif available.has_field('mempage_size'):
970 self.log.debug("Rejecting available flavor because mempage_size not required but available")
971 return False
972
973 if required.has_field('cpu_pinning_policy'):
974 self.log.debug("Matching cpu_pinning_policy")
975 if required.cpu_pinning_policy != 'ANY':
976 if available.has_field('cpu_pinning_policy') == False:
977 self.log.debug("Matching cpu_pinning_policy failed. Not available in flavor")
978 return False
979 else:
980 if required.cpu_pinning_policy != available.cpu_pinning_policy:
981 self.log.debug("Matching cpu_pinning_policy failed. Required: %s, Available: %s",
982 required.cpu_pinning_policy, available.cpu_pinning_policy)
983 return False
984 elif available.has_field('cpu_pinning_policy'):
985 self.log.debug("Rejecting available flavor because cpu_pinning_policy not required but available")
986 return False
987
988 if required.has_field('cpu_thread_pinning_policy'):
989 self.log.debug("Matching cpu_thread_pinning_policy")
990 if available.has_field('cpu_thread_pinning_policy') == False:
991 self.log.debug("Matching cpu_thread_pinning_policy failed. Not available in flavor")
992 return False
993 else:
994 if required.cpu_thread_pinning_policy != available.cpu_thread_pinning_policy:
995 self.log.debug("Matching cpu_thread_pinning_policy failed. Required: %s, Available: %s",
996 required.cpu_thread_pinning_policy, available.cpu_thread_pinning_policy)
997 return False
998 elif available.has_field('cpu_thread_pinning_policy'):
999 self.log.debug("Rejecting available flavor because cpu_thread_pinning_policy not required but available")
1000 return False
1001
1002 if required.has_field('trusted_execution'):
1003 self.log.debug("Matching trusted_execution")
1004 if required.trusted_execution == True:
1005 if available.has_field('trusted_execution') == False:
1006 self.log.debug("Matching trusted_execution failed. Not available in flavor")
1007 return False
1008 else:
1009 if required.trusted_execution != available.trusted_execution:
1010 self.log.debug("Matching trusted_execution failed. Required: %s, Available: %s",
1011 required.trusted_execution, available.trusted_execution)
1012 return False
1013 elif available.has_field('trusted_execution'):
1014 self.log.debug("Rejecting available flavor because trusted_execution not required but available")
1015 return False
1016
1017 if required.has_field('numa_node_policy'):
1018 self.log.debug("Matching numa_node_policy")
1019 if available.has_field('numa_node_policy') == False:
1020 self.log.debug("Matching numa_node_policy failed. Not available in flavor")
1021 return False
1022 else:
1023 if required.numa_node_policy.has_field('node_cnt'):
1024 self.log.debug("Matching numa_node_policy node_cnt")
1025 if available.numa_node_policy.has_field('node_cnt') == False:
1026 self.log.debug("Matching numa_node_policy node_cnt failed. Not available in flavor")
1027 return False
1028 else:
1029 if required.numa_node_policy.node_cnt != available.numa_node_policy.node_cnt:
1030 self.log.debug("Matching numa_node_policy node_cnt failed. Required: %s, Available: %s",
1031 required.numa_node_policy.node_cnt, available.numa_node_policy.node_cnt)
1032 return False
1033 elif available.numa_node_policy.has_field('node_cnt'):
1034 self.log.debug("Rejecting available flavor because numa node count not required but available")
1035 return False
1036
1037 if required.numa_node_policy.has_field('mem_policy'):
1038 self.log.debug("Matching numa_node_policy mem_policy")
1039 if available.numa_node_policy.has_field('mem_policy') == False:
1040 self.log.debug("Matching numa_node_policy mem_policy failed. Not available in flavor")
1041 return False
1042 else:
1043 if required.numa_node_policy.mem_policy != available.numa_node_policy.mem_policy:
1044 self.log.debug("Matching numa_node_policy mem_policy failed. Required: %s, Available: %s",
1045 required.numa_node_policy.mem_policy, available.numa_node_policy.mem_policy)
1046 return False
1047 elif available.numa_node_policy.has_field('mem_policy'):
1048 self.log.debug("Rejecting available flavor because num node mem_policy not required but available")
1049 return False
1050
1051 if required.numa_node_policy.has_field('node'):
1052 self.log.debug("Matching numa_node_policy nodes configuration")
1053 if available.numa_node_policy.has_field('node') == False:
1054 self.log.debug("Matching numa_node_policy nodes configuration failed. Not available in flavor")
1055 return False
1056 for required_node in required.numa_node_policy.node:
1057 self.log.debug("Matching numa_node_policy nodes configuration for node %s",
1058 required_node)
1059 numa_match = False
1060 for available_node in available.numa_node_policy.node:
1061 if required_node.id != available_node.id:
1062 self.log.debug("Matching numa_node_policy nodes configuration failed. Required: %s, Available: %s",
1063 required_node, available_node)
1064 continue
1065 if required_node.vcpu != available_node.vcpu:
1066 self.log.debug("Matching numa_node_policy nodes configuration failed. Required: %s, Available: %s",
1067 required_node, available_node)
1068 continue
1069 if required_node.memory_mb != available_node.memory_mb:
1070 self.log.debug("Matching numa_node_policy nodes configuration failed. Required: %s, Available: %s",
1071 required_node, available_node)
1072 continue
1073 numa_match = True
1074 if numa_match == False:
1075 return False
1076 elif available.numa_node_policy.has_field('node'):
1077 self.log.debug("Rejecting available flavor because numa nodes not required but available")
1078 return False
1079 elif available.has_field('numa_node_policy'):
1080 self.log.debug("Rejecting available flavor because numa_node_policy not required but available")
1081 return False
1082 self.log.info("Successful match for Guest EPA attributes")
1083 return True
1084
1085 def _match_vswitch_epa(self, required, available):
1086 self.log.debug("VSwitch EPA match found")
1087 return True
1088
1089 def _match_hypervisor_epa(self, required, available):
1090 self.log.debug("Hypervisor EPA match found")
1091 return True
1092
1093 def _match_host_epa(self, required, available):
1094 self.log.info("Matching Host EPA attributes")
1095 if required.has_field('cpu_model'):
1096 self.log.debug("Matching CPU model")
1097 if available.has_field('cpu_model') == False:
1098 self.log.debug("Matching CPU model failed. Not available in flavor")
1099 return False
1100 else:
1101 #### Convert all PREFER to REQUIRE since flavor will only have REQUIRE attributes
1102 if required.cpu_model.replace('PREFER', 'REQUIRE') != available.cpu_model:
1103 self.log.debug("Matching CPU model failed. Required: %s, Available: %s",
1104 required.cpu_model, available.cpu_model)
1105 return False
1106 elif available.has_field('cpu_model'):
1107 self.log.debug("Rejecting available flavor because cpu_model not required but available")
1108 return False
1109
1110 if required.has_field('cpu_arch'):
1111 self.log.debug("Matching CPU architecture")
1112 if available.has_field('cpu_arch') == False:
1113 self.log.debug("Matching CPU architecture failed. Not available in flavor")
1114 return False
1115 else:
1116 #### Convert all PREFER to REQUIRE since flavor will only have REQUIRE attributes
1117 if required.cpu_arch.replace('PREFER', 'REQUIRE') != available.cpu_arch:
1118 self.log.debug("Matching CPU architecture failed. Required: %s, Available: %s",
1119 required.cpu_arch, available.cpu_arch)
1120 return False
1121 elif available.has_field('cpu_arch'):
1122 self.log.debug("Rejecting available flavor because cpu_arch not required but available")
1123 return False
1124
1125 if required.has_field('cpu_vendor'):
1126 self.log.debug("Matching CPU vendor")
1127 if available.has_field('cpu_vendor') == False:
1128 self.log.debug("Matching CPU vendor failed. Not available in flavor")
1129 return False
1130 else:
1131 #### Convert all PREFER to REQUIRE since flavor will only have REQUIRE attributes
1132 if required.cpu_vendor.replace('PREFER', 'REQUIRE') != available.cpu_vendor:
1133 self.log.debug("Matching CPU vendor failed. Required: %s, Available: %s",
1134 required.cpu_vendor, available.cpu_vendor)
1135 return False
1136 elif available.has_field('cpu_vendor'):
1137 self.log.debug("Rejecting available flavor because cpu_vendor not required but available")
1138 return False
1139
1140 if required.has_field('cpu_socket_count'):
1141 self.log.debug("Matching CPU socket count")
1142 if available.has_field('cpu_socket_count') == False:
1143 self.log.debug("Matching CPU socket count failed. Not available in flavor")
1144 return False
1145 else:
1146 if required.cpu_socket_count != available.cpu_socket_count:
1147 self.log.debug("Matching CPU socket count failed. Required: %s, Available: %s",
1148 required.cpu_socket_count, available.cpu_socket_count)
1149 return False
1150 elif available.has_field('cpu_socket_count'):
1151 self.log.debug("Rejecting available flavor because cpu_socket_count not required but available")
1152 return False
1153
1154 if required.has_field('cpu_core_count'):
1155 self.log.debug("Matching CPU core count")
1156 if available.has_field('cpu_core_count') == False:
1157 self.log.debug("Matching CPU core count failed. Not available in flavor")
1158 return False
1159 else:
1160 if required.cpu_core_count != available.cpu_core_count:
1161 self.log.debug("Matching CPU core count failed. Required: %s, Available: %s",
1162 required.cpu_core_count, available.cpu_core_count)
1163 return False
1164 elif available.has_field('cpu_core_count'):
1165 self.log.debug("Rejecting available flavor because cpu_core_count not required but available")
1166 return False
1167
1168 if required.has_field('cpu_core_thread_count'):
1169 self.log.debug("Matching CPU core thread count")
1170 if available.has_field('cpu_core_thread_count') == False:
1171 self.log.debug("Matching CPU core thread count failed. Not available in flavor")
1172 return False
1173 else:
1174 if required.cpu_core_thread_count != available.cpu_core_thread_count:
1175 self.log.debug("Matching CPU core thread count failed. Required: %s, Available: %s",
1176 required.cpu_core_thread_count, available.cpu_core_thread_count)
1177 return False
1178 elif available.has_field('cpu_core_thread_count'):
1179 self.log.debug("Rejecting available flavor because cpu_core_thread_count not required but available")
1180 return False
1181
1182 if required.has_field('cpu_feature'):
1183 self.log.debug("Matching CPU feature list")
1184 if available.has_field('cpu_feature') == False:
1185 self.log.debug("Matching CPU feature list failed. Not available in flavor")
1186 return False
1187 else:
1188 for feature in required.cpu_feature:
1189 if feature not in available.cpu_feature:
1190 self.log.debug("Matching CPU feature list failed. Required feature: %s is not present. Available features: %s",
1191 feature, available.cpu_feature)
1192 return False
1193 elif available.has_field('cpu_feature'):
1194 self.log.debug("Rejecting available flavor because cpu_feature not required but available")
1195 return False
1196 self.log.info("Successful match for Host EPA attributes")
1197 return True
1198
1199
1200 def _match_placement_group_inputs(self, required, available):
1201 self.log.info("Matching Host aggregate attributes")
1202
1203 if not required and not available:
1204 # Host aggregate not required and not available => success
1205 self.log.info("Successful match for Host Aggregate attributes")
1206 return True
1207 if required and available:
1208 # Host aggregate requested and available => Do a match and decide
1209 xx = [ x.as_dict() for x in required ]
1210 yy = [ y.as_dict() for y in available ]
1211 for i in xx:
1212 if i not in yy:
1213 self.log.debug("Rejecting available flavor because host Aggregate mismatch. Required: %s, Available: %s",
1214 required, available)
1215 return False
1216 self.log.info("Successful match for Host Aggregate attributes")
1217 return True
1218 else:
1219 # Either of following conditions => Failure
1220 # - Host aggregate required but not available
1221 # - Host aggregate not required but available
1222 self.log.debug("Rejecting available flavor because host Aggregate mismatch. Required: %s, Available: %s",
1223 required, available)
1224 return False
1225
1226
1227 def _match_epa_params(self, resource_info, request_params):
1228 """
1229 Match EPA attributes
1230 Arguments:
1231 resource_info: Protobuf GI object RwcalYang.FlavorInfoItem()
1232 Following attributes would be accessed
1233 - vm_flavor
1234 - guest_epa
1235 - host_epa
1236 - host_aggregate
1237
1238 request_params: Protobuf GI object RwcalYang.VDUInitParams().
1239 Following attributes would be accessed
1240 - vm_flavor
1241 - guest_epa
1242 - host_epa
1243 - host_aggregate
1244 Returns:
1245 True -- Match between resource_info and request_params
1246 False -- No match between resource_info and request_params
1247 """
1248 result = False
1249 result = self._match_vm_flavor(getattr(request_params, 'vm_flavor'),
1250 getattr(resource_info, 'vm_flavor'))
1251 if result == False:
1252 self.log.debug("VM Flavor mismatched")
1253 return False
1254
1255 result = self._match_guest_epa(getattr(request_params, 'guest_epa'),
1256 getattr(resource_info, 'guest_epa'))
1257 if result == False:
1258 self.log.debug("Guest EPA mismatched")
1259 return False
1260
1261 result = self._match_vswitch_epa(getattr(request_params, 'vswitch_epa'),
1262 getattr(resource_info, 'vswitch_epa'))
1263 if result == False:
1264 self.log.debug("Vswitch EPA mismatched")
1265 return False
1266
1267 result = self._match_hypervisor_epa(getattr(request_params, 'hypervisor_epa'),
1268 getattr(resource_info, 'hypervisor_epa'))
1269 if result == False:
1270 self.log.debug("Hypervisor EPA mismatched")
1271 return False
1272
1273 result = self._match_host_epa(getattr(request_params, 'host_epa'),
1274 getattr(resource_info, 'host_epa'))
1275 if result == False:
1276 self.log.debug("Host EPA mismatched")
1277 return False
1278
1279 result = self._match_placement_group_inputs(getattr(request_params, 'host_aggregate'),
1280 getattr(resource_info, 'host_aggregate'))
1281
1282 if result == False:
1283 self.log.debug("Host Aggregate mismatched")
1284 return False
1285
1286 return True
1287
1288 def match_resource_flavor(self, vdu_init, flavor_list):
1289 """
1290 Arguments:
1291 vdu_init: Protobuf GI object RwcalYang.VDUInitParams().
1292 flavor_list: List of Protobuf GI object RwcalYang.FlavorInfoItem()
1293
1294 Returns:
1295 Flavor_ID -- If match is found between vdu_init and one of flavor_info from flavor_list
1296 None -- No match between vdu_init and one of flavor_info from flavor_list
1297
1298 Select a existing flavor if it matches the request or create new flavor
1299 """
1300 for flv in flavor_list:
1301 self.log.info("Attempting to match compute requirement for VDU: %s with flavor %s",
1302 vdu_init.name, flv)
1303 if self._match_epa_params(flv, vdu_init):
1304 self.log.info("Flavor match found for compute requirements for VDU: %s with flavor name: %s, flavor-id: %s",
1305 vdu_init.name, flv.name, flv.id)
1306 return flv.id
1307 return None
1308