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.
19 from cmdatahandlers.api import validation
20 from cmframework.apis import cmvalidator
21 from cmdatahandlers.api import utils
24 class NetworkProfilesValidation(cmvalidator.CMValidator):
25 SUBSCRIPTION = r'^cloud\.network_profiles|cloud\.networking$'
26 DOMAIN = 'cloud.network_profiles'
27 NETWORKING = 'cloud.networking'
29 MAX_IFACE_NAME_LEN = 15
30 IFACE_NAME_MATCH = r'^[a-z][\da-z]+$'
31 BOND_NAME_MATCH = r'^bond[\d]+$'
33 INTERFACE_NET_MAPPING = 'interface_net_mapping'
34 PROVIDER_NETWORK_INTERFACES = 'provider_network_interfaces'
35 PROVIDER_NETWORKS = 'provider_networks'
36 SRIOV_PROVIDER_NETWORKS = 'sriov_provider_networks'
37 INTERFACES = 'interfaces'
41 DPDK_MAX_RX_QUEUES = 'dpdk_max_rx_queues'
42 BONDING_INTERFACES = 'bonding_interfaces'
43 LINUX_BONDING_OPTIONS = 'linux_bonding_options'
44 OVS_BONDING_OPTIONS = 'ovs_bonding_options'
47 TYPE_OVS_DPDK = 'ovs-dpdk'
48 TYPE_OVS_OFFLOAD_SRIOV = "ovs-offload-sriov"
49 TYPE_OVS_OFFLOAD_VIRTIO = "ovs-offload-virtio"
50 VALID_TYPES = [TYPE_OVS, TYPE_OVS_DPDK, TYPE_OVS_OFFLOAD_SRIOV, TYPE_OVS_OFFLOAD_VIRTIO]
52 MODE_LACP = 'mode=lacp'
53 MODE_LACP_LAYER34 = 'mode=lacp-layer34'
54 MODE_AB = 'mode=active-backup'
55 VALID_BONDING_OPTIONS = [MODE_LACP, MODE_LACP_LAYER34, MODE_AB]
57 VLAN_RANGES = 'vlan_ranges'
61 NETWORK_DOMAINS = 'network_domains'
65 INPUT_ERR_CONTEXT = 'validate_set() input'
66 ERR_INPUT_NOT_DICT = 'Invalid %s, not a dictionary' % INPUT_ERR_CONTEXT
68 ERR_MISSING = 'Missing {1} configuration in {0}'
69 ERR_NOT_DICT = 'Invalid {1} value in {0}: Empty or not a dictionary'
70 ERR_NOT_LIST = 'Invalid {1} value in {0}: Empty, contains duplicates or not a list'
71 ERR_NOT_STR = 'Invalid {1} value in {0}: Not a string'
72 ERR_NOT_INT = 'Invalid {1} value in {0}: Not an integer'
73 ERR_NOT_BOOL = 'Invalid {1} value in {0}: Not a boolean value'
75 ERR_INVALID_IFACE_NAME = 'Invalid interface name in {}'
76 ERR_IFACE_NAME_LEN = 'Too long interface name in {}, max %s chars' % MAX_IFACE_NAME_LEN
77 ERR_IFACE_VLAN = 'Interface in {0} cannot be vlan interface: {1}'
78 ERR_IFACE_BOND = 'Interface in {0} cannot be bond interface: {1}'
79 ERR_IFACE_NOT_BOND = 'Invalid bonding interface name {1} in {0}'
80 ERR_NET_MAPPING_CONFLICT = 'Network {1} mapped to multiple interfaces in {0}'
81 ERR_UNTAGGED_INFRA_CONFLICT = 'Multiple untagged networks on interface {1} in {0}'
82 ERR_UNTAGGED_MTU_SIZE = 'Untagged network {1} in {0} has too small MTU, ' + \
83 'VLAN tagged networks with bigger MTU exists on the same interface'
85 ERR_INVALID_TYPE = 'Invalid provider network type for interface {}, valid types: %s' % \
87 ERR_DPDK_MAX_RX_QUEUES = 'Invalid %s value {}, must be positive integer' % DPDK_MAX_RX_QUEUES
88 ERR_MISSPLACED_MTU = 'Missplaced MTU inside %s interface {}' % PROVIDER_NETWORK_INTERFACES
89 ERR_OVS_TYPE_CONFLICT = 'Cannot have both %s and %s types of provider networks in {}' % \
90 (TYPE_OVS, TYPE_OVS_DPDK)
91 ERR_DPDK_SRIOV_CONFLICT = 'Cannot have both %s and sr-iov on same interface in {}' % \
93 ERR_OFFLOAD_SRIOV_CONFLICT = 'Cannot have both %s and sr-iov on same profile in {}' % \
94 TYPE_OVS_OFFLOAD_SRIOV
95 ERR_OFFLOAD_DPDK_CONFLICT = 'Cannot have both %s and %s types of provider networks in {}' % \
96 (TYPE_OVS_OFFLOAD_SRIOV, TYPE_OVS_DPDK)
98 ERR_INVALID_BONDING_OPTIONS = 'Invalid {1} in {0}, valid options: %s' % VALID_BONDING_OPTIONS
99 ERR_MISSING_BOND = 'Missing bonding interface definition for {1} in {0}'
100 ERR_LACP_SLAVE_COUNT = 'Invalid bonding slave interface count for {1} in {0} ' + \
101 'at least two interfaces required with %s' % MODE_LACP
102 ERR_AB_SLAVE_COUNT = 'Invalid bonding slave interface count for {1} in {0}, ' + \
103 'exactly two interfaces required with %s' % MODE_AB
104 ERR_SLAVE_CONFLICT = 'Same interface mapped to multiple bond interfaces in {}'
105 ERR_SLAVE_IN_NET = 'Network physical interface {1} mapped also as part of bond in {0}'
107 ERR_SRIOV_MTU_SIZE = 'SR-IOV network {0} MTU {1} cannot be greater than interface {2} MTU {3}'
108 ERR_SRIOV_INFRA_VLAN_CONFLICT = \
109 'SR-IOV network {} vlan range is conflicting with infra network vlan'
110 ERR_SRIOV_PROVIDER_VLAN_CONFLICT = \
111 'SR-IOV network {} vlan range is conflicting with other provider network vlan'
112 ERR_SINGLE_NIC_VIOLATION = \
113 'Provider and infa networks on the same interface in {}: ' + \
114 'Supported only if all networks on the same interface'
115 ERR_SINGLE_NIC_DPDK = \
116 'Provider and infa networks on the same interface in {}: ' + \
117 'Not supported for %s type of provider networks' % TYPE_OVS_DPDK
118 ERR_INFRA_PROVIDER_VLAN_CONFLICT = \
119 'Provider network {} vlan range is conflicting with infra network vlan'
120 ERR_INFRA_PROVIDER_UNTAGGED_CONFLICT = \
121 'Sharing untagged infra and provider network {} not supported'
122 ERR_SRIOV_LACP_CONFLICT = 'Bonding mode %s not supported with SR-IOV networks' % MODE_LACP
123 ERR_SRIOV_IFACE_CONFLICT = 'Same interface mapped to multiple SR-IOV networks in {}'
124 ERR_VF_COUNT = 'SR-IOV network {} %s must be positive integer' % VF_COUNT
126 ERR_PROVIDER_VLAN_CONFLICT = 'Provider network vlan ranges conflicting on interface {}'
129 def err_input_not_dict():
130 err = NetworkProfilesValidation.ERR_INPUT_NOT_DICT
131 raise validation.ValidationError(err)
134 def err_missing(context, key):
135 err = NetworkProfilesValidation.ERR_MISSING.format(context, key)
136 raise validation.ValidationError(err)
139 def err_not_dict(context, key):
140 err = NetworkProfilesValidation.ERR_NOT_DICT.format(context, key)
141 raise validation.ValidationError(err)
144 def err_not_list(context, key):
145 err = NetworkProfilesValidation.ERR_NOT_LIST.format(context, key)
146 raise validation.ValidationError(err)
149 def err_not_str(context, key):
150 raise validation.ValidationError(NetworkProfilesValidation.ERR_NOT_STR.format(context, key))
153 def err_not_int(context, key):
154 raise validation.ValidationError(NetworkProfilesValidation.ERR_NOT_INT.format(context, key))
157 def err_not_bool(context, key):
158 err = NetworkProfilesValidation.ERR_NOT_BOOL.format(context, key)
159 raise validation.ValidationError(err)
162 def err_invalid_iface_name(context):
163 err = NetworkProfilesValidation.ERR_INVALID_IFACE_NAME.format(context)
164 raise validation.ValidationError(err)
167 def err_iface_name_len(context):
168 err = NetworkProfilesValidation.ERR_IFACE_NAME_LEN.format(context)
169 raise validation.ValidationError(err)
172 def err_iface_vlan(context, iface):
173 err = NetworkProfilesValidation.ERR_IFACE_VLAN.format(context, iface)
174 raise validation.ValidationError(err)
177 def err_iface_bond(context, iface):
178 err = NetworkProfilesValidation.ERR_IFACE_BOND.format(context, iface)
179 raise validation.ValidationError(err)
182 def err_provnet_type(iface):
183 err = NetworkProfilesValidation.ERR_INVALID_TYPE.format(iface)
184 raise validation.ValidationError(err)
187 def err_dpdk_max_rx_queues(value):
188 err = NetworkProfilesValidation.ERR_DPDK_MAX_RX_QUEUES.format(value)
189 raise validation.ValidationError(err)
192 def err_missplaced_mtu(iface):
193 err = NetworkProfilesValidation.ERR_MISSPLACED_MTU.format(iface)
194 raise validation.ValidationError(err)
197 def err_iface_not_bond(context, iface):
198 err = NetworkProfilesValidation.ERR_IFACE_NOT_BOND.format(context, iface)
199 raise validation.ValidationError(err)
202 def err_bonding_options(profile, options_type):
203 err = NetworkProfilesValidation.ERR_INVALID_BONDING_OPTIONS.format(profile, options_type)
204 raise validation.ValidationError(err)
207 def err_missing_bond_def(profile, iface):
208 err = NetworkProfilesValidation.ERR_MISSING_BOND.format(profile, iface)
209 raise validation.ValidationError(err)
212 def err_lacp_slave_count(profile, iface):
213 err = NetworkProfilesValidation.ERR_LACP_SLAVE_COUNT.format(profile, iface)
214 raise validation.ValidationError(err)
217 def err_ab_slave_count(profile, iface):
218 err = NetworkProfilesValidation.ERR_AB_SLAVE_COUNT.format(profile, iface)
219 raise validation.ValidationError(err)
222 def err_slave_conflict(profile):
223 err = NetworkProfilesValidation.ERR_SLAVE_CONFLICT.format(profile)
224 raise validation.ValidationError(err)
227 def err_slave_in_net(profile, iface):
228 err = NetworkProfilesValidation.ERR_SLAVE_IN_NET.format(profile, iface)
229 raise validation.ValidationError(err)
232 def err_ovs_type_conflict(profile):
233 err = NetworkProfilesValidation.ERR_OVS_TYPE_CONFLICT.format(profile)
234 raise validation.ValidationError(err)
237 def err_offload_dpdk_conflict(profile):
238 err = NetworkProfilesValidation.ERR_OFFLOAD_DPDK_CONFLICT.format(profile)
239 raise validation.ValidationError(err)
242 def err_dpdk_sriov_conflict(profile):
243 err = NetworkProfilesValidation.ERR_DPDK_SRIOV_CONFLICT.format(profile)
244 raise validation.ValidationError(err)
247 def err_offload_sriov_conflict(profile):
248 err = NetworkProfilesValidation.ERR_OFFLOAD_SRIOV_CONFLICT.format(profile)
249 raise validation.ValidationError(err)
252 def err_net_mapping_conflict(profile, network):
253 err = NetworkProfilesValidation.ERR_NET_MAPPING_CONFLICT.format(profile, network)
254 raise validation.ValidationError(err)
257 def err_untagged_infra_conflict(profile, iface):
258 err = NetworkProfilesValidation.ERR_UNTAGGED_INFRA_CONFLICT.format(profile, iface)
259 raise validation.ValidationError(err)
262 def err_untagged_mtu_size(context, network):
263 err = NetworkProfilesValidation.ERR_UNTAGGED_MTU_SIZE.format(context, network)
264 raise validation.ValidationError(err)
267 def err_sriov_mtu_size(sriov_net, sriov_mtu, phys_iface, iface_mtu):
268 err = NetworkProfilesValidation.ERR_SRIOV_MTU_SIZE.format(sriov_net, sriov_mtu,
269 phys_iface, iface_mtu)
270 raise validation.ValidationError(err)
273 def err_sriov_infra_vlan_conflict(network):
274 err = NetworkProfilesValidation.ERR_SRIOV_INFRA_VLAN_CONFLICT.format(network)
275 raise validation.ValidationError(err)
278 def err_sriov_provider_vlan_conflict(network):
279 err = NetworkProfilesValidation.ERR_SRIOV_PROVIDER_VLAN_CONFLICT.format(network)
280 raise validation.ValidationError(err)
283 def err_single_nic_violation(profile):
284 err = NetworkProfilesValidation.ERR_SINGLE_NIC_VIOLATION.format(profile)
285 raise validation.ValidationError(err)
288 def err_single_nic_dpdk(profile):
289 err = NetworkProfilesValidation.ERR_SINGLE_NIC_DPDK.format(profile)
290 raise validation.ValidationError(err)
293 def err_infra_provider_vlan_conflict(network):
294 err = NetworkProfilesValidation.ERR_INFRA_PROVIDER_VLAN_CONFLICT.format(network)
295 raise validation.ValidationError(err)
298 def err_infra_provider_untagged_conflict(network):
299 err = NetworkProfilesValidation.ERR_INFRA_PROVIDER_UNTAGGED_CONFLICT.format(network)
300 raise validation.ValidationError(err)
303 def err_sriov_lacp_conflict():
304 err = NetworkProfilesValidation.ERR_SRIOV_LACP_CONFLICT
305 raise validation.ValidationError(err)
308 def err_sriov_iface_conflict():
309 err = NetworkProfilesValidation.ERR_SRIOV_IFACE_CONFLICT
310 raise validation.ValidationError(err)
313 def err_vf_count(network):
314 err = NetworkProfilesValidation.ERR_VF_COUNT.format(network)
315 raise validation.ValidationError(err)
318 def err_provider_vlan_conflict(iface):
319 err = NetworkProfilesValidation.ERR_PROVIDER_VLAN_CONFLICT.format(iface)
320 raise validation.ValidationError(err)
324 return isinstance(conf, dict)
327 def is_bond_iface(iface):
328 return re.match(NetworkProfilesValidation.BOND_NAME_MATCH, iface)
331 def is_non_empty_dict(conf):
332 return isinstance(conf, dict) and len(conf) > 0
335 def key_exists(conf_dict, key):
336 return key in conf_dict
339 def val_is_int(conf_dict, key):
340 return isinstance(conf_dict[key], (int, long))
343 def val_is_bool(conf_dict, key):
344 return isinstance(conf_dict[key], bool)
347 def val_is_str(conf_dict, key):
348 return isinstance(conf_dict[key], basestring)
351 def val_is_non_empty_list(conf_dict, key):
352 return (isinstance(conf_dict[key], list) and
353 len(conf_dict[key]) > 0 and
354 len(conf_dict[key]) == len(set(conf_dict[key])))
357 def val_is_non_empty_dict(conf_dict, key):
358 return NetworkProfilesValidation.is_non_empty_dict(conf_dict[key])
361 def key_must_exist(conf_dict, entry, key):
362 if not NetworkProfilesValidation.key_exists(conf_dict[entry], key):
363 NetworkProfilesValidation.err_missing(entry, key)
366 def must_be_str(conf_dict, entry, key):
367 NetworkProfilesValidation.key_must_exist(conf_dict, entry, key)
368 if not NetworkProfilesValidation.val_is_str(conf_dict[entry], key):
369 NetworkProfilesValidation.err_not_str(entry, key)
372 def must_be_list(conf_dict, entry, key):
373 NetworkProfilesValidation.key_must_exist(conf_dict, entry, key)
374 if not NetworkProfilesValidation.val_is_non_empty_list(conf_dict[entry], key):
375 NetworkProfilesValidation.err_not_list(entry, key)
378 def must_be_dict(conf_dict, entry, key):
379 NetworkProfilesValidation.key_must_exist(conf_dict, entry, key)
380 if not NetworkProfilesValidation.val_is_non_empty_dict(conf_dict[entry], key):
381 NetworkProfilesValidation.err_not_dict(entry, key)
384 def exists_as_dict(conf_dict, entry, key):
385 if not NetworkProfilesValidation.key_exists(conf_dict[entry], key):
387 if not NetworkProfilesValidation.val_is_non_empty_dict(conf_dict[entry], key):
388 NetworkProfilesValidation.err_not_dict(entry, key)
392 def exists_as_int(conf_dict, entry, key):
393 if not NetworkProfilesValidation.key_exists(conf_dict[entry], key):
395 if not NetworkProfilesValidation.val_is_int(conf_dict[entry], key):
396 NetworkProfilesValidation.err_not_int(entry, key)
400 def are_overlapping(ranges1, ranges2):
401 for range1 in ranges1:
402 for range2 in ranges2:
403 if not (range1[0] > range2[1] or range1[1] < range2[0]):
408 cmvalidator.CMValidator.__init__(self)
410 self.networking = None
412 def get_subscription_info(self):
413 return self.SUBSCRIPTION
415 def validate_set(self, props):
416 if not self.is_dict(props):
417 self.err_input_not_dict()
419 if not (self.key_exists(props, self.DOMAIN) or
420 self.key_exists(props, self.NETWORKING)):
421 self.err_missing(self.INPUT_ERR_CONTEXT,
422 '{} or {}'.format(self.DOMAIN, self.NETWORKING))
424 if self.key_exists(props, self.DOMAIN):
425 if not props[self.DOMAIN]:
426 self.err_not_dict(self.INPUT_ERR_CONTEXT, self.DOMAIN)
427 self.conf = json.loads(props[self.DOMAIN])
429 self.conf = json.loads(self.get_plugin_client().get_property(self.DOMAIN))
431 if not self.is_non_empty_dict(self.conf):
432 self.err_not_dict(self.INPUT_ERR_CONTEXT, self.DOMAIN)
434 if self.key_exists(props, self.NETWORKING):
435 if not props[self.NETWORKING]:
436 self.err_not_dict(self.INPUT_ERR_CONTEXT, self.NETWORKING)
437 self.networking = json.loads(props[self.NETWORKING])
439 self.networking = json.loads(self.get_plugin_client().get_property(self.NETWORKING))
441 if not self.is_non_empty_dict(self.networking):
442 self.err_not_dict(self.INPUT_ERR_CONTEXT, self.NETWORKING)
447 for profile_name in self.conf:
448 if not self.val_is_non_empty_dict(self.conf, profile_name):
449 self.err_not_dict(self.DOMAIN, profile_name)
450 self.validate_network_profile(profile_name)
452 def validate_network_profile(self, profile_name):
453 self.validate_interface_net_mapping(profile_name)
454 self.validate_bonding_interfaces(profile_name)
455 self.validate_bonding_options(profile_name)
456 self.validate_provider_net_ifaces(profile_name)
457 self.validate_network_integrity(profile_name)
458 self.validate_sriov_provider_networks(profile_name)
459 self.validate_provider_networks(profile_name)
461 def validate_interface_net_mapping(self, profile_name):
462 self.must_be_dict(self.conf, profile_name, self.INTERFACE_NET_MAPPING)
464 for iface in self.conf[profile_name][self.INTERFACE_NET_MAPPING]:
465 self.validate_iface_name(self.INTERFACE_NET_MAPPING, iface)
466 self.validate_not_vlan(self.INTERFACE_NET_MAPPING, iface)
467 self.must_be_list(self.conf[profile_name], self.INTERFACE_NET_MAPPING, iface)
468 iface_nets = self.conf[profile_name][self.INTERFACE_NET_MAPPING][iface]
469 self.validate_used_infra_networks_defined(iface_nets)
470 for domain in self.get_network_domains(iface_nets):
471 self.validate_untagged_infra_integrity(iface_nets, iface, profile_name, domain)
472 networks.extend(iface_nets)
473 self.validate_networks_mapped_only_once(profile_name, networks)
475 def validate_used_infra_networks_defined(self, networks):
477 if not self.key_exists(self.networking, net):
478 self.err_missing(self.NETWORKING, net)
479 self.must_be_dict(self.networking, net, self.NETWORK_DOMAINS)
480 for domain in self.networking[net][self.NETWORK_DOMAINS]:
481 self.must_be_dict(self.networking[net], self.NETWORK_DOMAINS, domain)
483 def get_network_domains(self, networks):
486 domains.update(self.networking[net][self.NETWORK_DOMAINS].keys())
489 def validate_untagged_infra_integrity(self, iface_nets, iface, profile_name, network_domain):
493 default_mtu = self.get_default_mtu()
495 for net in iface_nets:
496 if self.key_exists(self.networking[net][self.NETWORK_DOMAINS], network_domain):
497 if not self.key_exists(self.networking[net][self.NETWORK_DOMAINS][network_domain],
499 untagged_infras.append(net)
500 if self.exists_as_int(self.networking, net, self.MTU):
501 untagged_mtu = self.networking[net][self.MTU]
503 untagged_mtu = default_mtu
505 if self.exists_as_int(self.networking, net, self.MTU):
506 mtu = self.networking[net][self.MTU]
509 if mtu > max_vlan_mtu:
512 if not utils.is_virtualized():
513 if len(untagged_infras) > 1:
514 self.err_untagged_infra_conflict(profile_name, iface)
516 if untagged_mtu and untagged_mtu < max_vlan_mtu:
517 self.err_untagged_mtu_size(self.NETWORKING, untagged_infras[0])
519 def validate_bonding_interfaces(self, profile_name):
521 if self.exists_as_dict(self.conf, profile_name, self.BONDING_INTERFACES):
522 for iface in self.conf[profile_name][self.BONDING_INTERFACES]:
523 self.validate_iface_name(self.BONDING_INTERFACES, iface)
524 if not self.is_bond_iface(iface):
525 self.err_iface_not_bond(self.BONDING_INTERFACES, iface)
526 self.must_be_list(self.conf[profile_name], self.BONDING_INTERFACES, iface)
527 for slave in self.conf[profile_name][self.BONDING_INTERFACES][iface]:
528 self.validate_bond_slave(iface, slave)
530 if len(slaves) != len(set(slaves)):
531 self.err_slave_conflict(profile_name)
533 def validate_bond_slave(self, iface, slave):
534 self.validate_iface_name(iface, slave)
535 self.validate_not_vlan(iface, slave)
536 self.validate_not_bond(iface, slave)
538 def validate_not_bond(self, context, iface):
540 self.err_iface_bond(context, iface)
542 def validate_bonding_options(self, profile_name):
543 self.validate_bonding_option(profile_name, self.LINUX_BONDING_OPTIONS)
544 self.validate_bonding_option(profile_name, self.OVS_BONDING_OPTIONS)
546 def validate_bonding_option(self, profile_name, options_type):
547 if self.key_exists(self.conf[profile_name], options_type):
548 if self.conf[profile_name][options_type] not in self.VALID_BONDING_OPTIONS:
549 self.err_bonding_options(profile_name, options_type)
551 def validate_provider_net_ifaces(self, profile_name):
552 if self.exists_as_dict(self.conf, profile_name, self.PROVIDER_NETWORK_INTERFACES):
555 for iface in self.conf[profile_name][self.PROVIDER_NETWORK_INTERFACES]:
556 self.validate_iface_name(self.PROVIDER_NETWORK_INTERFACES, iface)
557 self.validate_not_vlan(self.PROVIDER_NETWORK_INTERFACES, iface)
558 provnet_ifaces_conf = self.conf[profile_name][self.PROVIDER_NETWORK_INTERFACES]
559 self.validate_provider_net_type(provnet_ifaces_conf, iface)
560 self.validate_provider_net_vf_count(provnet_ifaces_conf, iface)
561 self.validate_dpdk_max_rx_queues(provnet_ifaces_conf, iface)
562 self.validate_no_mtu(provnet_ifaces_conf, iface)
563 self.must_be_list(provnet_ifaces_conf, iface, self.PROVIDER_NETWORKS)
564 types.add(provnet_ifaces_conf[iface][self.TYPE])
565 networks.extend(provnet_ifaces_conf[iface][self.PROVIDER_NETWORKS])
566 if self.TYPE_OVS_DPDK in types and self.TYPE_OVS in types:
567 self.err_ovs_type_conflict(profile_name)
568 if self.TYPE_OVS_DPDK in types and self.TYPE_OVS_OFFLOAD_SRIOV in types:
569 self.err_offload_dpdk_conflict(profile_name)
570 self.validate_networks_mapped_only_once(profile_name, networks)
571 self.validate_used_provider_networks_defined(networks)
573 def validate_sriov_provider_networks(self, profile_name):
574 if self.exists_as_dict(self.conf, profile_name, self.SRIOV_PROVIDER_NETWORKS):
575 networks = self.conf[profile_name][self.SRIOV_PROVIDER_NETWORKS]
576 self.validate_used_provider_networks_defined(networks)
578 for network in networks:
579 if (self.exists_as_int(networks, network, self.VF_COUNT) and
580 networks[network][self.VF_COUNT] < 1):
581 self.err_vf_count(network)
582 if (self.key_exists(networks[network], self.TRUSTED) and
583 not self.val_is_bool(networks[network], self.TRUSTED)):
584 self.err_not_bool(network, self.TRUSTED)
585 self.must_be_list(networks, network, self.INTERFACES)
586 for iface in networks[network][self.INTERFACES]:
587 sriov_ifaces.append(iface)
588 self.validate_iface_name(network, iface)
589 self.validate_not_vlan(network, iface)
590 self.validate_not_bond(network, iface)
591 self.validate_not_part_of_lacp(self.conf[profile_name], iface)
592 infra_info = self.get_iface_infra_info(self.conf[profile_name], iface)
593 if infra_info is not None:
594 self.validate_shared_sriov_infra(network, iface, infra_info)
595 provider_info = self.get_iface_provider_info(self.conf[profile_name], iface)
596 if provider_info[self.TYPE] == self.TYPE_OVS_DPDK:
597 self.err_dpdk_sriov_conflict(profile_name)
598 if provider_info[self.TYPE] == self.TYPE_OVS_OFFLOAD_SRIOV:
599 self.err_offload_sriov_conflict(profile_name)
600 if provider_info[self.VLAN_RANGES]:
601 self.validate_shared_sriov_provider(network,
602 provider_info[self.VLAN_RANGES])
603 if len(sriov_ifaces) != len(set(sriov_ifaces)):
604 self.err_sriov_iface_conflict()
606 def validate_provider_networks(self, profile_name):
607 if self.key_exists(self.conf[profile_name], self.PROVIDER_NETWORK_INTERFACES):
608 for iface in self.conf[profile_name][self.PROVIDER_NETWORK_INTERFACES]:
609 iface_info = self.conf[profile_name][self.PROVIDER_NETWORK_INTERFACES][iface]
610 vlan_ranges_list = []
611 for network in iface_info[self.PROVIDER_NETWORKS]:
612 vlan_ranges = self.get_vlan_ranges(network)
613 vlan_ranges_list.append(vlan_ranges)
614 infra_info = self.get_iface_infra_info(self.conf[profile_name], iface)
615 if infra_info is not None:
616 if (len(self.conf[profile_name][self.PROVIDER_NETWORK_INTERFACES]) > 1 or
617 len(self.conf[profile_name][self.INTERFACE_NET_MAPPING]) > 1):
618 self.err_single_nic_violation(profile_name)
619 if iface_info[self.TYPE] == self.TYPE_OVS_DPDK:
620 self.err_single_nic_dpdk(profile_name)
621 self.validate_shared_infra_provider(network, infra_info, vlan_ranges)
622 for idx, ranges1 in enumerate(vlan_ranges_list):
623 for ranges2 in vlan_ranges_list[(idx+1):]:
624 if self.are_overlapping(ranges1, ranges2):
625 self.err_provider_vlan_conflict(iface)
627 def validate_not_part_of_lacp(self, profile_conf, iface):
628 if self.key_exists(profile_conf, self.PROVIDER_NETWORK_INTERFACES):
629 for provider_iface in profile_conf[self.PROVIDER_NETWORK_INTERFACES]:
630 if self.is_bond_iface(provider_iface):
631 if iface in profile_conf[self.BONDING_INTERFACES][provider_iface]:
632 if profile_conf[self.OVS_BONDING_OPTIONS] == self.MODE_LACP:
633 self.err_sriov_lacp_conflict()
634 # part of ovs bonding
635 # do not check linux bonding options even if shared with infra networks
637 for infra_iface in profile_conf[self.INTERFACE_NET_MAPPING]:
638 if self.is_bond_iface(infra_iface):
639 if iface in profile_conf[self.BONDING_INTERFACES][infra_iface]:
640 if profile_conf[self.LINUX_BONDING_OPTIONS] == self.MODE_LACP:
641 self.err_sriov_lacp_conflict()
644 def validate_shared_sriov_infra(self, sriov_net, iface, infra_info):
645 sriov_info = self.get_sriov_info(sriov_net)
646 if sriov_info[self.MTU] > infra_info[self.MTU]:
647 self.err_sriov_mtu_size(sriov_net, sriov_info[self.MTU], iface, infra_info[self.MTU])
648 for vlan_range in sriov_info[self.VLAN_RANGES]:
649 for infra_vlan in infra_info[self.VLAN]:
650 if not (infra_vlan < vlan_range[0] or infra_vlan > vlan_range[1]):
651 self.err_sriov_infra_vlan_conflict(sriov_net)
653 def validate_shared_sriov_provider(self, sriov_net, ovs_vlan_ranges):
654 sriov_vlan_ranges = self.get_vlan_ranges(sriov_net)
655 if self.are_overlapping(sriov_vlan_ranges, ovs_vlan_ranges):
656 self.err_sriov_provider_vlan_conflict(sriov_net)
658 def validate_shared_infra_provider(self, provider_net, infra_info, vlan_ranges):
659 if infra_info[self.UNTAGGED]:
660 self.err_infra_provider_untagged_conflict(provider_net)
661 for vlan in infra_info[self.VLAN]:
662 for vlan_range in vlan_ranges:
663 if not (vlan_range[0] > vlan or vlan_range[1] < vlan):
664 self.err_infra_provider_vlan_conflict(provider_net)
666 def get_iface_infra_info(self, profile_conf, iface):
667 infra_info = {self.VLAN: [], self.MTU: 0, self.UNTAGGED: False}
668 default_mtu = self.get_default_mtu()
669 infra_iface = self.get_master_iface(profile_conf, iface)
671 if self.key_exists(profile_conf[self.INTERFACE_NET_MAPPING], infra_iface):
672 for infra in profile_conf[self.INTERFACE_NET_MAPPING][infra_iface]:
673 for domain in self.networking[infra][self.NETWORK_DOMAINS].itervalues():
674 if self.key_exists(domain, self.VLAN):
675 infra_info[self.VLAN].append(domain[self.VLAN])
677 infra_info[self.UNTAGGED] = True
678 if self.exists_as_int(self.networking, infra, self.MTU):
679 mtu = self.networking[infra][self.MTU]
682 if mtu > infra_info[self.MTU]:
683 infra_info[self.MTU] = mtu
685 if infra_info[self.MTU] == 0:
690 def get_iface_provider_info(self, profile_conf, iface):
691 provider_info = {self.TYPE: None, self.VLAN_RANGES: []}
692 provider_iface = self.get_master_iface(profile_conf, iface)
694 if self.key_exists(profile_conf, self.PROVIDER_NETWORK_INTERFACES):
695 if self.key_exists(profile_conf[self.PROVIDER_NETWORK_INTERFACES], provider_iface):
696 iface_info = profile_conf[self.PROVIDER_NETWORK_INTERFACES][provider_iface]
697 provider_info[self.TYPE] = iface_info[self.TYPE]
698 for network in iface_info[self.PROVIDER_NETWORKS]:
699 provider_info[self.VLAN_RANGES].extend(self.get_vlan_ranges(network))
703 def get_master_iface(self, profile_conf, slave_iface):
704 if self.key_exists(profile_conf, self.BONDING_INTERFACES):
705 for bond in profile_conf[self.BONDING_INTERFACES]:
706 if slave_iface in profile_conf[self.BONDING_INTERFACES][bond]:
710 def get_sriov_info(self, network):
711 sriov_info = {self.VLAN_RANGES: []}
712 if self.exists_as_int(self.networking[self.PROVIDER_NETWORKS], network, self.MTU):
713 sriov_info[self.MTU] = self.networking[self.PROVIDER_NETWORKS][network][self.MTU]
715 sriov_info[self.MTU] = self.get_default_mtu()
716 sriov_info[self.VLAN_RANGES] = self.get_vlan_ranges(network)
719 def get_vlan_ranges(self, network):
721 networks = self.networking[self.PROVIDER_NETWORKS]
722 self.must_be_str(networks, network, self.VLAN_RANGES)
723 for vlan_range in networks[network][self.VLAN_RANGES].split(','):
724 vids = vlan_range.split(':')
733 vlan_ranges.append([start, end])
736 def get_default_mtu(self):
737 if (self.key_exists(self.networking, self.MTU) and
738 self.val_is_int(self.networking, self.MTU)):
739 return self.networking[self.MTU]
740 return self.DEFAULT_MTU
742 def validate_iface_name(self, context, iface):
743 if not isinstance(iface, basestring) or not re.match(self.IFACE_NAME_MATCH, iface):
744 self.err_invalid_iface_name(context)
745 if len(iface) > self.MAX_IFACE_NAME_LEN:
746 self.err_iface_name_len(context)
748 def validate_not_vlan(self, context, iface):
750 self.err_iface_vlan(context, iface)
752 def validate_provider_net_type(self, provnet_ifaces_conf, iface):
753 self.must_be_str(provnet_ifaces_conf, iface, self.TYPE)
754 if provnet_ifaces_conf[iface][self.TYPE] not in self.VALID_TYPES:
755 self.err_provnet_type(iface)
757 def validate_provider_net_vf_count(self, provnet_ifaces_conf, iface):
758 if self.exists_as_int(provnet_ifaces_conf, iface, self.VF_COUNT):
759 value = provnet_ifaces_conf[iface][self.VF_COUNT]
761 self.err_vf_count(iface)
763 def validate_dpdk_max_rx_queues(self, provnet_ifaces_conf, iface):
764 if self.exists_as_int(provnet_ifaces_conf, iface, self.DPDK_MAX_RX_QUEUES):
765 value = provnet_ifaces_conf[iface][self.DPDK_MAX_RX_QUEUES]
767 self.err_dpdk_max_rx_queues(value)
769 def validate_no_mtu(self, provnet_ifaces_conf, iface):
770 if self.key_exists(provnet_ifaces_conf[iface], self.MTU):
771 self.err_missplaced_mtu(iface)
773 def validate_networks_mapped_only_once(self, profile_name, networks):
775 for net in sorted(networks):
777 self.err_net_mapping_conflict(profile_name, net)
780 def validate_used_provider_networks_defined(self, networks):
782 self.key_must_exist(self.networking, self.PROVIDER_NETWORKS, net)
784 def validate_network_integrity(self, profile_name):
786 if self.key_exists(self.conf[profile_name], self.PROVIDER_NETWORK_INTERFACES):
787 for iface in self.conf[profile_name][self.PROVIDER_NETWORK_INTERFACES]:
788 self.validate_net_iface_integrity(profile_name, iface, self.OVS_BONDING_OPTIONS)
789 provider_ifaces.append(iface)
790 for iface in self.conf[profile_name][self.INTERFACE_NET_MAPPING]:
791 if iface not in provider_ifaces:
792 self.validate_net_iface_integrity(profile_name, iface, self.LINUX_BONDING_OPTIONS)
794 def validate_net_iface_integrity(self, profile_name, iface, bonding_type):
795 if self.is_bond_iface(iface):
796 if (not self.key_exists(self.conf[profile_name], self.BONDING_INTERFACES) or
797 iface not in self.conf[profile_name][self.BONDING_INTERFACES]):
798 self.err_missing_bond_def(profile_name, iface)
799 self.key_must_exist(self.conf, profile_name, bonding_type)
800 self.validate_bond_slave_count(profile_name, iface,
801 self.conf[profile_name][bonding_type])
802 elif self.key_exists(self.conf[profile_name], self.BONDING_INTERFACES):
803 for bond in self.conf[profile_name][self.BONDING_INTERFACES]:
804 for slave in self.conf[profile_name][self.BONDING_INTERFACES][bond]:
806 self.err_slave_in_net(profile_name, iface)
808 def validate_bond_slave_count(self, profile_name, iface, bonding_mode):
809 slave_count = len(self.conf[profile_name][self.BONDING_INTERFACES][iface])
810 if bonding_mode == self.MODE_AB and slave_count != 2:
811 self.err_ab_slave_count(profile_name, iface)
812 elif bonding_mode == self.MODE_LACP and slave_count < 2:
813 self.err_lacp_slave_count(profile_name, iface)