Add validation for "caas_oam" networking type
[ta/cm-plugins.git] / validators / src / NetworkingValidation.py
1 #! /usr/bin/python
2 # Copyright 2019 Nokia
3 #
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
7 #
8 #    http://www.apache.org/licenses/LICENSE-2.0
9 #
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.
15
16 import json
17 import re
18 from netaddr import IPNetwork
19
20 from cmdatahandlers.api import validation
21 from cmframework.apis import cmvalidator
22
23
24 class NetworkingValidation(cmvalidator.CMValidator):
25     SUBSCRIPTION = r'^cloud\.networking$'
26     DOMAIN = 'cloud.networking'
27
28     MAX_MTU = 9000
29     MIN_MTU = 1280
30     MIN_VLAN = 2
31     MAX_VLAN = 4094
32     MAX_PROVNET_LEN = 64
33     MAX_DNS = 2
34     PROVNET_NAME_MATCH = r'^[a-zA-Z][\da-zA-Z-_]+[\da-zA-Z]$'
35     NET_DOMAIN_MATCH = PROVNET_NAME_MATCH
36     MAX_NET_DOMAIN_LEN = MAX_PROVNET_LEN
37     DEFAULT_ROUTE_DEST = '0.0.0.0/0'
38
39     NETWORK_DOMAINS = 'network_domains'
40     INFRA_EXTERNAL = 'infra_external'
41     INFRA_INTERNAL = 'infra_internal'
42     INFRA_STORAGE_CLUSTER = 'infra_storage_cluster'
43     CAAS_OAM = 'caas_oam'
44     INFRA_NETWORKS = [INFRA_EXTERNAL,
45                       INFRA_INTERNAL,
46                       INFRA_STORAGE_CLUSTER,
47                       CAAS_OAM]
48
49     DNS = 'dns'
50     MTU = 'mtu'
51     VLAN = 'vlan'
52     GATEWAY = 'gateway'
53     CIDR = 'cidr'
54     IP_START = 'ip_range_start'
55     IP_END = 'ip_range_end'
56     ROUTES = 'routes'
57     TO = 'to'
58     VIA = 'via'
59
60     PROVIDER_NETWORKS = 'provider_networks'
61     VLAN_RANGES = 'vlan_ranges'
62     SHARED = 'shared'
63
64     INPUT_ERR_CONTEXT = 'validate_set() input'
65     ERR_INPUT_NOT_DICT = 'Invalid %s, not a dictionary' % INPUT_ERR_CONTEXT
66
67     ERR_MISSING = 'Missing {1} configuration in {0}'
68     ERR_NOT_DICT = 'Invalid {1} value in {0}: Empty or not a dictionary'
69     ERR_NOT_LIST = 'Invalid {1} value in {0}: Empty, contains duplicates or not a list'
70     ERR_NOT_STR = 'Invalid {1} value in {0}: Not a string'
71     ERR_NOT_INT = 'Invalid {1} value in {0}: Not an integer'
72     ERR_NOT_BOOL = 'Invalid {1} value in {0}: Not a boolean value'
73
74     ERR_MTU = 'Invalid {} mtu: Not in range %i - %i' % (MIN_MTU, MAX_MTU)
75     ERR_VLAN = 'Invalid {} vlan: Not in range %i - %i' % (MIN_VLAN, MAX_VLAN)
76     ERR_DUPLICATE_INFRA_VLAN = 'Same VLAN ID {} used for multiple infra networks'
77     ERR_CIDRS_OVERLAPPING = 'Network CIDR values {} and {} are overlapping'
78     ERR_GW_NOT_SUPPORTED = 'Gateway address not supported for {}'
79     ERR_INVALID_ROUTES = 'Invalid static routes format for {0} {1}'
80     ERR_DEFAULT_ROUTE = 'Default route not supported for {0} {1}'
81
82     ERR_VLAN_RANGES_FORMAT = 'Invalid {} vlan_ranges format'
83     ERR_VLAN_RANGES_OVERLAPPING = 'Provider network vlan ranges {} and {} are overlapping'
84
85     ERR_INVALID_PROVNET_NAME = 'Invalid provider network name'
86     ERR_PROVNET_LEN = 'Too long provider network name, max %s chars' % MAX_PROVNET_LEN
87     ERR_SHARED_NETWORKS = 'Only one provider network can be configured as shared'
88
89     ERR_INVALID_NET_DOMAIN_NAME = 'Invalid network domain name'
90     ERR_NET_DOMAIN_LEN = 'Too long network domain name, max %s chars' % MAX_NET_DOMAIN_LEN
91
92     ERR_TOO_MANY_DNS = 'Too many DNS server IP addresses, max %i supported' % MAX_DNS
93
94     ERR_MTU_INSIDE_NETWORK_DOMAIN = 'Missplaced MTU inside {} network domain {}'
95
96     @staticmethod
97     def err_input_not_dict():
98         raise validation.ValidationError(NetworkingValidation.ERR_INPUT_NOT_DICT)
99
100     @staticmethod
101     def err_missing(context, key):
102         raise validation.ValidationError(NetworkingValidation.ERR_MISSING.format(context, key))
103
104     @staticmethod
105     def err_not_dict(context, key):
106         raise validation.ValidationError(NetworkingValidation.ERR_NOT_DICT.format(context, key))
107
108     @staticmethod
109     def err_not_list(context, key):
110         raise validation.ValidationError(NetworkingValidation.ERR_NOT_LIST.format(context, key))
111
112     @staticmethod
113     def err_not_str(context, key):
114         raise validation.ValidationError(NetworkingValidation.ERR_NOT_STR.format(context, key))
115
116     @staticmethod
117     def err_not_int(context, key):
118         raise validation.ValidationError(NetworkingValidation.ERR_NOT_INT.format(context, key))
119
120     @staticmethod
121     def err_not_bool(context, key):
122         raise validation.ValidationError(NetworkingValidation.ERR_NOT_BOOL.format(context, key))
123
124     @staticmethod
125     def err_mtu(context):
126         raise validation.ValidationError(NetworkingValidation.ERR_MTU.format(context))
127
128     @staticmethod
129     def err_vlan(context):
130         raise validation.ValidationError(NetworkingValidation.ERR_VLAN.format(context))
131
132     @staticmethod
133     def err_duplicate_vlan(vid):
134         raise validation.ValidationError(NetworkingValidation.ERR_DUPLICATE_INFRA_VLAN.format(vid))
135
136     @staticmethod
137     def err_vlan_ranges_format(provnet):
138         err = NetworkingValidation.ERR_VLAN_RANGES_FORMAT.format(provnet)
139         raise validation.ValidationError(err)
140
141     @staticmethod
142     def err_vlan_ranges_overlapping(range1, range2):
143         ranges = sorted([range1, range2])
144         err = NetworkingValidation.ERR_VLAN_RANGES_OVERLAPPING.format(ranges[0], ranges[1])
145         raise validation.ValidationError(err)
146
147     @staticmethod
148     def err_invalid_provnet_name():
149         raise validation.ValidationError(NetworkingValidation.ERR_INVALID_PROVNET_NAME)
150
151     @staticmethod
152     def err_provnet_len():
153         raise validation.ValidationError(NetworkingValidation.ERR_PROVNET_LEN)
154
155     @staticmethod
156     def err_invalid_net_domain_name():
157         raise validation.ValidationError(NetworkingValidation.ERR_INVALID_NET_DOMAIN_NAME)
158
159     @staticmethod
160     def err_net_domain_len():
161         raise validation.ValidationError(NetworkingValidation.ERR_NET_DOMAIN_LEN)
162
163     @staticmethod
164     def err_cidrs_overlapping(cidr1, cidr2):
165         cidrs = sorted([cidr1, cidr2])
166         err = NetworkingValidation.ERR_CIDRS_OVERLAPPING.format(cidrs[0], cidrs[1])
167         raise validation.ValidationError(err)
168
169     @staticmethod
170     def err_gw_not_supported(network):
171         raise validation.ValidationError(NetworkingValidation.ERR_GW_NOT_SUPPORTED.format(network))
172
173     @staticmethod
174     def err_invalid_routes(network, domain):
175         err = NetworkingValidation.ERR_INVALID_ROUTES.format(network, domain)
176         raise validation.ValidationError(err)
177
178     @staticmethod
179     def err_default_route(network, domain):
180         err = NetworkingValidation.ERR_DEFAULT_ROUTE.format(network, domain)
181         raise validation.ValidationError(err)
182
183     @staticmethod
184     def err_too_many_dns():
185         raise validation.ValidationError(NetworkingValidation.ERR_TOO_MANY_DNS)
186
187     @staticmethod
188     def err_shared_networks():
189         raise validation.ValidationError(NetworkingValidation.ERR_SHARED_NETWORKS)
190
191     @staticmethod
192     def err_mtu_inside_network_domain(infra, domain):
193         err = NetworkingValidation.ERR_MTU_INSIDE_NETWORK_DOMAIN.format(infra, domain)
194         raise validation.ValidationError(err)
195
196     @staticmethod
197     def is_dict(conf):
198         return isinstance(conf, dict)
199
200     @staticmethod
201     def key_exists(conf_dict, key):
202         return key in conf_dict
203
204     @staticmethod
205     def val_is_str(conf_dict, key):
206         return isinstance(conf_dict[key], basestring)
207
208     @staticmethod
209     def val_is_list(conf_dict, key):
210         return isinstance(conf_dict[key], list)
211
212     @staticmethod
213     def val_is_non_empty_list(conf_dict, key):
214         return (isinstance(conf_dict[key], list) and
215                 len(conf_dict[key]) > 0 and
216                 len(conf_dict[key]) == len(set(conf_dict[key])))
217
218     @staticmethod
219     def val_is_non_empty_dict(conf_dict, key):
220         return isinstance(conf_dict[key], dict) and len(conf_dict[key]) > 0
221
222     @staticmethod
223     def val_is_int(conf_dict, key):
224         return isinstance(conf_dict[key], (int, long))
225
226     @staticmethod
227     def val_is_bool(conf_dict, key):
228         return isinstance(conf_dict[key], bool)
229
230     @staticmethod
231     def key_must_exist(conf_dict, entry, key):
232         if not NetworkingValidation.key_exists(conf_dict[entry], key):
233             NetworkingValidation.err_missing(entry, key)
234
235     @staticmethod
236     def must_be_str(conf_dict, entry, key):
237         NetworkingValidation.key_must_exist(conf_dict, entry, key)
238         if not NetworkingValidation.val_is_str(conf_dict[entry], key):
239             NetworkingValidation.err_not_str(entry, key)
240
241     @staticmethod
242     def must_be_list(conf_dict, entry, key):
243         NetworkingValidation.key_must_exist(conf_dict, entry, key)
244         if not NetworkingValidation.val_is_non_empty_list(conf_dict[entry], key):
245             NetworkingValidation.err_not_list(entry, key)
246
247     @staticmethod
248     def must_be_dict(conf_dict, entry, key):
249         NetworkingValidation.key_must_exist(conf_dict, entry, key)
250         if not NetworkingValidation.val_is_non_empty_dict(conf_dict[entry], key):
251             NetworkingValidation.err_not_dict(entry, key)
252
253     @staticmethod
254     def exists_as_dict(conf_dict, entry, key):
255         if not NetworkingValidation.key_exists(conf_dict[entry], key):
256             return False
257         if not NetworkingValidation.val_is_non_empty_dict(conf_dict[entry], key):
258             NetworkingValidation.err_not_dict(entry, key)
259         return True
260
261     @staticmethod
262     def exists_as_int(conf_dict, entry, key):
263         if not NetworkingValidation.key_exists(conf_dict[entry], key):
264             return False
265         if not NetworkingValidation.val_is_int(conf_dict[entry], key):
266             NetworkingValidation.err_not_int(entry, key)
267         return True
268
269     @staticmethod
270     def exists_as_bool(conf_dict, entry, key):
271         if not NetworkingValidation.key_exists(conf_dict[entry], key):
272             return False
273         if not NetworkingValidation.val_is_bool(conf_dict[entry], key):
274             NetworkingValidation.err_not_bool(entry, key)
275         return True
276
277     def __init__(self):
278         cmvalidator.CMValidator.__init__(self)
279         self.utils = validation.ValidationUtils()
280         self.conf = None
281         self.net_conf = None
282
283     def get_subscription_info(self):
284         return self.SUBSCRIPTION
285
286     def validate_set(self, props):
287         self.prepare_validate(props)
288         self.validate()
289
290     def prepare_validate(self, props):
291         if not self.is_dict(props):
292             self.err_input_not_dict()
293
294         if not self.key_exists(props, self.DOMAIN):
295             self.err_missing(self.INPUT_ERR_CONTEXT, self.DOMAIN)
296
297         self.net_conf = json.loads(props[self.DOMAIN])
298         self.conf = {self.DOMAIN: self.net_conf}
299
300         if not self.val_is_non_empty_dict(self.conf, self.DOMAIN):
301             self.err_not_dict(self.INPUT_ERR_CONTEXT, self.DOMAIN)
302
303     def validate(self):
304         self.validate_dns()
305         self.validate_default_mtu()
306         self.validate_infra_networks()
307         self.validate_provider_networks()
308         self.validate_no_overlapping_cidrs()
309
310     def validate_dns(self):
311         self.must_be_list(self.conf, self.DOMAIN, self.DNS)
312         for server in self.net_conf[self.DNS]:
313             self.utils.validate_ip_address(server)
314         if len(self.net_conf[self.DNS]) > self.MAX_DNS:
315             self.err_too_many_dns()
316
317     def validate_default_mtu(self):
318         self.validate_mtu(self.conf, self.DOMAIN)
319
320     def validate_infra_networks(self):
321         self.validate_infra_internal()
322         self.validate_infra_external()
323         self.validate_infra_storage_cluster()
324         self.validate_caas_oam()
325         self.validate_no_duplicate_infra_vlans()
326
327     def validate_infra_internal(self):
328         self.validate_network_exists(self.INFRA_INTERNAL)
329         self.validate_infra_network(self.INFRA_INTERNAL)
330         self.validate_no_gateway(self.INFRA_INTERNAL)
331
332     def validate_infra_external(self):
333         self.validate_network_exists(self.INFRA_EXTERNAL)
334         self.validate_infra_network(self.INFRA_EXTERNAL)
335         self.validate_gateway(self.INFRA_EXTERNAL)
336
337     def validate_infra_storage_cluster(self):
338         if self.network_exists(self.INFRA_STORAGE_CLUSTER):
339             self.validate_network_domains(self.INFRA_STORAGE_CLUSTER)
340             self.validate_infra_network(self.INFRA_STORAGE_CLUSTER)
341             self.validate_no_gateway(self.INFRA_STORAGE_CLUSTER)
342
343     def validate_caas_oam(self):
344         if self.network_exists(self.CAAS_OAM):
345             self.validate_infra_network(self.CAAS_OAM)
346             if self.gateway_exists(self.CAAS_OAM):
347                 self.validate_gateway(self.CAAS_OAM)
348
349     def gateway_exists(self, network):
350         return self.exists_as_dict(self.conf[self.DOMAIN], network, 'gateway')
351
352     def validate_infra_network(self, network, vlan_must_exist=False):
353         self.validate_mtu(self.net_conf, network)
354         self.validate_cidr(network)
355         self.validate_vlan(network, vlan_must_exist)
356         self.validate_ip_range(network)
357         self.validate_routes(network)
358         self.validate_no_mtu_inside_network_domain(network)
359
360     def validate_no_duplicate_infra_vlans(self):
361         domvids = {}
362         for network in self.INFRA_NETWORKS:
363             if self.key_exists(self.net_conf, network):
364                 for domain, domain_conf in self.net_conf[network][self.NETWORK_DOMAINS].iteritems():
365                     if self.key_exists(domain_conf, self.VLAN):
366                         if domain not in domvids:
367                             domvids[domain] = []
368                         domvids[domain].append(domain_conf[self.VLAN])
369         for vids in domvids.itervalues():
370             prev_vid = 0
371             for vid in sorted(vids):
372                 if vid == prev_vid:
373                     self.err_duplicate_vlan(vid)
374                 prev_vid = vid
375
376     def validate_no_overlapping_cidrs(self):
377         cidrs = []
378         for network in self.INFRA_NETWORKS:
379             if self.key_exists(self.net_conf, network):
380                 for domain_conf in self.net_conf[network][self.NETWORK_DOMAINS].itervalues():
381                     cidrs.append(IPNetwork(domain_conf[self.CIDR]))
382         for idx, cidr1 in enumerate(cidrs):
383             for cidr2 in cidrs[(idx+1):]:
384                 if not (cidr1[0] > cidr2[-1] or cidr1[-1] < cidr2[0]):
385                     self.err_cidrs_overlapping(str(cidr1), str(cidr2))
386
387     def validate_ip_range(self, network):
388         domains = self.net_conf[network][self.NETWORK_DOMAINS]
389         for domain in domains:
390             ip_start = self.get_ip_range_start(domains, domain)
391             ip_end = self.get_ip_range_end(domains, domain)
392             self.utils.validate_ip_range(ip_start, ip_end)
393
394     def get_ip_range_start(self, domains, domain):
395         if self.key_exists(domains[domain], self.IP_START):
396             self.validate_ip_range_limiter(domains, domain, self.IP_START)
397             return domains[domain][self.IP_START]
398         return str(IPNetwork(domains[domain][self.CIDR])[1])
399
400     def get_ip_range_end(self, domains, domain):
401         if self.key_exists(domains[domain], self.IP_END):
402             self.validate_ip_range_limiter(domains, domain, self.IP_END)
403             return domains[domain][self.IP_END]
404         return str(IPNetwork(domains[domain][self.CIDR])[-2])
405
406     def validate_ip_range_limiter(self, domains, domain, key):
407         self.must_be_str(domains, domain, key)
408         self.utils.validate_ip_address(domains[domain][key])
409         self.utils.validate_ip_in_subnet(domains[domain][key],
410                                          domains[domain][self.CIDR])
411
412     def validate_provider_networks(self):
413         if self.network_exists(self.PROVIDER_NETWORKS):
414             for netname in self.net_conf[self.PROVIDER_NETWORKS]:
415                 self.validate_providernet(netname)
416             self.validate_shared_provider_network(self.net_conf[self.PROVIDER_NETWORKS])
417
418     def validate_providernet(self, netname):
419         self.validate_providernet_name(netname)
420         self.must_be_dict(self.net_conf, self.PROVIDER_NETWORKS, netname)
421         self.validate_mtu(self.net_conf[self.PROVIDER_NETWORKS], netname)
422         self.validate_vlan_ranges(self.net_conf[self.PROVIDER_NETWORKS], netname)
423
424     def validate_shared_provider_network(self, provider_conf):
425         shared_counter = 0
426         for netname in provider_conf:
427             if self.exists_as_bool(provider_conf, netname, self.SHARED):
428                 if provider_conf[netname][self.SHARED] is True:
429                     shared_counter += 1
430         if shared_counter > 1:
431             self.err_shared_networks()
432
433     def validate_mtu(self, conf, network):
434         if self.exists_as_int(conf, network, self.MTU):
435             mtu = conf[network][self.MTU]
436             if mtu < self.MIN_MTU or mtu > self.MAX_MTU:
437                 self.err_mtu(network)
438
439     def validate_no_mtu_inside_network_domain(self, network):
440         domains = self.net_conf[network][self.NETWORK_DOMAINS]
441         for domain in domains:
442             if self.key_exists(domains[domain], self.MTU):
443                 self.err_mtu_inside_network_domain(network, domain)
444
445     def validate_vlan(self, network, must_exist=False):
446         domains = self.net_conf[network][self.NETWORK_DOMAINS]
447         for domain in domains:
448             if must_exist and not self.key_exists(domains[domain], self.VLAN):
449                 self.err_missing(network, self.VLAN)
450             if self.exists_as_int(domains, domain, self.VLAN):
451                 self.validate_vlan_id(network, domains[domain][self.VLAN])
452
453     def validate_network_exists(self, network):
454         self.must_be_dict(self.conf, self.DOMAIN, network)
455         self.validate_network_domains(network)
456
457     def validate_network_domains(self, network):
458         self.must_be_dict(self.net_conf, network, self.NETWORK_DOMAINS)
459         for domain in self.net_conf[network][self.NETWORK_DOMAINS]:
460             self.validate_net_domain_name(domain)
461
462     def validate_net_domain_name(self, domain_name):
463         if (not isinstance(domain_name, basestring) or
464                 not re.match(self.NET_DOMAIN_MATCH, domain_name)):
465             self.err_invalid_net_domain_name()
466         if len(domain_name) > self.MAX_NET_DOMAIN_LEN:
467             self.err_net_domain_len()
468
469     def network_exists(self, network):
470         return self.exists_as_dict(self.conf, self.DOMAIN, network)
471
472     def validate_cidr(self, network):
473         domains = self.net_conf[network][self.NETWORK_DOMAINS]
474         for domain in domains:
475             self.must_be_str(domains, domain, self.CIDR)
476             self.utils.validate_subnet_address(domains[domain][self.CIDR])
477
478     def validate_gateway(self, network):
479         domains = self.net_conf[network][self.NETWORK_DOMAINS]
480         for domain in domains:
481             self.must_be_str(domains, domain, self.GATEWAY)
482             self.utils.validate_ip_address(domains[domain][self.GATEWAY])
483             self.utils.validate_ip_in_subnet(domains[domain][self.GATEWAY],
484                                              domains[domain][self.CIDR])
485             self.utils.validate_ip_not_in_range(domains[domain][self.GATEWAY],
486                                                 self.get_ip_range_start(domains, domain),
487                                                 self.get_ip_range_end(domains, domain))
488
489     def validate_no_gateway(self, network):
490         for domain_conf in self.net_conf[network][self.NETWORK_DOMAINS].itervalues():
491             if self.key_exists(domain_conf, self.GATEWAY):
492                 self.err_gw_not_supported(network)
493
494     def validate_routes(self, network):
495         domains = self.net_conf[network][self.NETWORK_DOMAINS]
496         for domain in domains:
497             if self.key_exists(domains[domain], self.ROUTES):
498                 if (not self.val_is_list(domains[domain], self.ROUTES) or
499                         not domains[domain][self.ROUTES]):
500                     self.err_invalid_routes(network, domain)
501                 for route in domains[domain][self.ROUTES]:
502                     self.validate_route(network, domain, route)
503                     self.utils.validate_ip_in_subnet(route[self.VIA],
504                                                      domains[domain][self.CIDR])
505                     self.utils.validate_ip_not_in_range(route[self.VIA],
506                                                         self.get_ip_range_start(domains, domain),
507                                                         self.get_ip_range_end(domains, domain))
508
509     def validate_route(self, network, domain, route):
510         if (not self.is_dict(route) or
511                 self.TO not in route or
512                 self.VIA not in route or
513                 not self.val_is_str(route, self.TO) or
514                 not self.val_is_str(route, self.VIA)):
515             self.err_invalid_routes(network, domain)
516         self.utils.validate_subnet_address(route[self.TO])
517         self.utils.validate_ip_address(route[self.VIA])
518         if route[self.TO] == self.DEFAULT_ROUTE_DEST:
519             self.err_default_route(network, domain)
520
521     def validate_providernet_name(self, netname):
522         if not isinstance(netname, basestring) or not re.match(self.PROVNET_NAME_MATCH, netname):
523             self.err_invalid_provnet_name()
524         if len(netname) > self.MAX_PROVNET_LEN:
525             self.err_provnet_len()
526
527     def validate_vlan_ranges(self, provnet_conf, provnet):
528         self.must_be_str(provnet_conf, provnet, self.VLAN_RANGES)
529         vlan_ranges = []
530         for vlan_range in provnet_conf[provnet][self.VLAN_RANGES].split(','):
531             vids = vlan_range.split(':')
532             if len(vids) != 2:
533                 self.err_vlan_ranges_format(provnet)
534             try:
535                 start = int(vids[0])
536                 end = int(vids[1])
537             except ValueError:
538                 self.err_vlan_ranges_format(provnet)
539             self.validate_vlan_id(provnet, start)
540             self.validate_vlan_id(provnet, end)
541             if end < start:
542                 self.err_vlan_ranges_format(provnet)
543             vlan_ranges.append([start, end])
544         self.validate_vlan_ranges_not_overlapping(vlan_ranges)
545
546     def validate_vlan_ranges_not_overlapping(self, vlan_ranges):
547         for idx, range1 in enumerate(vlan_ranges):
548             for range2 in vlan_ranges[(idx+1):]:
549                 if not (range1[0] > range2[1] or range1[1] < range2[0]):
550                     self.err_vlan_ranges_overlapping(range1, range2)
551
552     def validate_vlan_id(self, network, vid):
553         if vid < self.MIN_VLAN or vid > self.MAX_VLAN:
554             self.err_vlan(network)