Source code for networkapi.util

# -*- coding: utf-8 -*-
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import
from __future__ import unicode_literals

import copy
import functools
import logging
import re
import socket
import sys
import time
import warnings
from hashlib import sha1

from django.core import validators
from django.core.cache import cache
from django.forms.models import model_to_dict

from networkapi.infrastructure.ipaddr import AddressValueError
from networkapi.infrastructure.ipaddr import IPAddress
from networkapi.plugins import exceptions as plugins_exceptions
# from .decorators import deprecated

LOCK = 'LOCK'
PATTERN_XML_PASSWORD = [
    '<password>(.*?)</password>', '<enable_pass>(.*?)</enable_pass>', '<pass>(.*?)</pass>']


[docs]def valid_expression(operator, value1, value2): if operator == 'eq': return value1 == value2 elif operator == 'ne': return value1 != value2 else: return False
[docs]def search_hide_password(msg): """ Search and hide password """ for text in PATTERN_XML_PASSWORD: r = re.compile(text) m = r.search(msg) if m: password = m.group(1) msg = msg.replace(password, '****') return msg
[docs]def valid_regex(string, regex): pattern = re.compile(regex) return re.search(pattern, string) is not None
[docs]def is_valid_regex(string, regex): """Checks if the parameter is a valid value by regex. :param param: Value to be validated. :return: True if the parameter has a valid vakue, or False otherwise. """ pattern = re.compile(regex) return pattern.match(string) is not None
[docs]def is_valid_ip(address): """Verifica se address é um endereço ip válido.""" pattern = r'\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b' return re.match(pattern, address)
[docs]def to_ip(address): """Resolve o endereço IP caso address seja um hostname. :param address: Hostname ou endereço IP. :return: Endereço IP correspondente ao endereço informado. """ if is_valid_ip(address): # Se for um ip válido retorna return address # Se não for um ip válido tenta resolver o ip considerando que address é # um hostname return socket.gethostbyname(address)
[docs]def is_valid_int_param(param, required=True): """Checks if the parameter is a valid integer value. @param param: Value to be validated. @return True if the parameter has a valid integer value, or False otherwise. """ if param is None and not required: return True elif param is None: return False try: int(param) except (TypeError, ValueError): return False return True
[docs]def is_valid_int_greater_zero_param(param, required=True): """Checks if the parameter is a valid integer value and greater than zero. @param param: Value to be validated. @return True if the parameter has a valid integer value, or False otherwise. """ if param is None and not required: return True elif param is None: return False try: param = int(param) if param <= 0: return False except (TypeError, ValueError): return False return True
[docs]def is_valid_int_greater_equal_zero_param(param): """Checks if the parameter is a valid integer value and greater and equal than zero. @param param: Value to be validated. @return True if the parameter has a valid integer value, or False otherwise. """ if param is None: return False try: param = int(param) if param < 0: return False except (TypeError, ValueError): return False return True
[docs]def is_valid_string_maxsize(param, maxsize=None, required=True): """Checks if the parameter is a valid string and his size is less than maxsize. If the parameter maxsize is None than the size is ignored If the parameter required is True than the string can not be None @param param: Value to be validated. @param maxsize: Max size of the value to be validated. @param required: Check if the value can be None @return True if the parameter is valid or False otherwise. """ if required is True and param is None: return False elif required is False and (param is None or param == ''): return True if '' == param.strip(): return False if param is not None and not isinstance(param, basestring): return False if param is not None and maxsize is not None: if is_valid_int_greater_zero_param(maxsize): if len(param.strip()) > maxsize: return False return True
[docs]def is_valid_string_minsize(param, minsize=None, required=True): """Checks if the parameter is a valid string and his size is more than minsize. If the parameter minsize is None than the size is ignored If the parameter required is True than the string can not be None @param param: Value to be validated. @param minsize: Min size of the value to be validated. @param required: Check if the value can be None @return True if the parameter is valid or False otherwise. """ if required is True and param is None: return False elif required is False and (param is None or param == ''): return True if '' == param.strip(): return False if param is not None and not isinstance(param, basestring): return False if param is not None and minsize is not None: if is_valid_int_greater_zero_param(minsize): if len(param.strip()) < minsize: return False return True
[docs]def is_valid_boolean_param(param, required=True): """Checks if the parameter is a valid boolean. @param param: Value to be validated. @return True if the parameter has a valid boolean value, or False otherwise. """ if param is None and not required: return True elif param is None: return False if param in ['0', '1', 'False', 'True', False, True]: return True else: return False
[docs]def is_valid_zero_one_param(param, required=True): """Checks if the parameter is a valid zero or one string. @param param: Value to be validated. @return True if the parameter has a valid zero or one value, or False otherwise. """ if param is None and not required: return True elif param is None: return False if param == '0': return True elif param == '1': return True else: return False
[docs]def is_valid_yes_no_choice(param): """Checks if the parameter is valid 'S' or 'N' char. @param param: valid to be validated. @return True if the parameter is a valid choice, or False otherwise. """ if param in ('S', 'N'): return True else: return False
[docs]def is_valid_uri(param): """Checks if the parameter is a valid uri. @param param: Value to be validated. @return True if the parameter has a valid uri value, or False otherwise. """ pattern = r"^[a-zA-Z0-9\\-_\\\-\\.!\\~\\*'\\(\\);/\\?:\\@\\&=\\{\\}\\#\\\[\\\]\\,]*$" return re.match(pattern, param)
[docs]def is_valid_text(param, required=True): """Checks if the parameter is a valid field text and should follow the format of [A-Za-z] and special characters hyphen and underline. @param param: Value to be validated. @param required: Check if the value can be None @return True if the parameter has a valid text value, or False otherwise. """ if required is True and param is None: return False elif required is False and (param is None or param == ''): return True pattern = r'^[a-zA-Z0-9\\-_\\\-\\ ]*$' return re.match(pattern, param)
[docs]def is_valid_pool_identifier_text(param, required=True): """Checks if the parameter is a valid field text and should follow the format of [A-Za-z] and special characters hyphen and underline. @param param: Value to be validated. @param required: Check if the value can be None @return True if the parameter has a valid text value, or False otherwise. """ if required is True and param is None: return False elif required is False and (param is None or param == ''): return True pattern = r'^[a-zA-Z]+[a-zA-Z0-9\._-]*$' return re.match(pattern, param)
[docs]def is_valid_option(param): """Checks if the parameter is a valid field text and 0-9 and should follow the format of [A-Za-z] and special characters hyphen, underline and point. @param param: Value to be validated. @return True if the parameter has a valid text value, or False otherwise. """ pattern = r'^[0-9a-zA-Z\\-_.\\\-\\ ]*$' return re.match(pattern, param)
[docs]def is_valid_email(param): """Checks if the parameter is a valid e-mail. @param param: Value to be validated. @return True if the parameter has a valid e-mail value, or False otherwise. """ pattern = re.compile(r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"' r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', re.IGNORECASE) return re.match(pattern, param)
[docs]def is_valid_healthcheck_destination(param): """Checks if the parameter is a valid healthcheck_destination. @param param: Value to be validated. @return True if the parameter has a valid healthcheck_destination value, or False otherwise. """ pattern = re.compile(r'^([0-9]+|\*):([0-9]+|\*)$') return re.match(pattern, param)
[docs]def is_valid_ipv4(param): """Checks if the parameter is a valid ipv4. @param param: Value to be validated. @return True if the parameter has a valid ipv4 value, or False otherwise. """ try: IPAddress(param, 4) return True except AddressValueError: return False
[docs]def is_valid_ipv6(param): """Checks if the parameter is a valid ipv6. @param param: Value to be validated. @return True if the parameter has a valid ipv6 value, or False otherwise. """ try: IPAddress(param, 6) return True except AddressValueError: return False
[docs]def is_valid_ip_ipaddr(param): """Checks if the parameter is a valid ip is ipv4 or ipv6. @param param: Value to be validated. @return True if the parameter has a valid ipv6 or ipv4 value, or False otherwise. """ try: IPAddress(param) return True except ValueError: return False
[docs]def convert_boolean_to_int(param): """Convert the parameter of boolean to int. @param param: parameter to be converted. @return Parameter converted. """ if param is True: return int(1) elif param is False: return int(0)
[docs]def convert_string_or_int_to_boolean(param, force=None): """Convert the parameter of string or int to boolean. @param param: parameter to be converted. @return Parameter converted. """ if param == '1' or param == int(1) or param == 'True' or param == 'true': return True elif param == '0' or param == int(0) or param == 'False' or param == 'false': return False elif force: return False
[docs]def clone(obj): """Clone the object @param obj: object to be cloned @return object cloned. """ return copy.copy(obj)
[docs]def is_valid_version_ip(param, IP_VERSION): """Checks if the parameter is a valid ip version value. @param param: Value to be validated. @return True if the parameter has a valid ip version value, or False otherwise. """ if param is None: return False if param == IP_VERSION.IPv4[0] or param == IP_VERSION.IPv6[0]: return True return False
[docs]def mount_ipv4_string(ip): return str(str(ip.oct1) + '.' + str(ip.oct2) + '.' + str(ip.oct3) + '.' + str(ip.oct4))
[docs]def mount_ipv6_string(ip): return str(str(ip.block1) + ':' + str(ip.block2) + ':' + str(ip.block3) + ':' + str(ip.block4) + ':' + str(ip.block5) + ':' + str(ip.block6) + ':' + str(ip.block7) + ':' + str(ip.block8))
[docs]def cache_function(length, equipment=False): """ Cache the result of function @param length: time in seconds to stay in cache """ def _decorated(func): def _cache(*args, **kwargs): if equipment is True: key = sha1(str(args[0].id) + 'equipment').hexdigest() print str(args[0].id) + 'equipment' else: key = sha1(str(args[0].id)).hexdigest() print str(args[0].id) # Search in cache if it exists if key in cache: # Get value in cache value = cache.get(key) # If was locked if value == LOCK: # Try until unlock while value == LOCK: time.sleep(1) value = cache.get(key) # Return value of cache return value # If not exists in cache else: # Function can be called several times before it finishes and is put into the cache, # then lock it to others wait it finishes. cache.set(key, LOCK, length) # Execute method result = func(*args, **kwargs) # Set in cache the result of method cache.set(key, result, length) # If not exists in cache # key_list = cache.get(sha1('key_networkapi_vlans').hexdigest()) # if(key_list is None): # key_list = [] # Set in cache the keys # key_list.append(key) # cache.set(sha1('key_networkapi_vlans').hexdigest(), key_list) return result return _cache return _decorated
[docs]def destroy_cache_function(key_list, equipment=False): for key in key_list: key = str(key) if equipment is True: key = str(key) + 'equipment' if sha1(key).hexdigest() in cache: cache.delete(sha1(key).hexdigest())
[docs]class IP_VERSION: IPv6 = ('v6', 'IPv6') IPv4 = ('v4', 'IPv4') List = (IPv4, IPv6)
[docs]def get_environment_map(environment): environment_map = dict() environment_map['id'] = environment.id environment_map['link'] = environment.link environment_map['id_divisao'] = environment.divisao_dc.id environment_map['nome_divisao'] = environment.divisao_dc.nome environment_map['id_ambiente_logico'] = environment.ambiente_logico.id environment_map['nome_ambiente_logico'] = environment.ambiente_logico.nome environment_map['id_grupo_l3'] = environment.grupo_l3.id environment_map['nome_grupo_l3'] = environment.grupo_l3.nome environment_map['ambiente_rede'] = environment.divisao_dc.nome + ' - ' + \ environment.ambiente_logico.nome + ' - ' + \ environment.grupo_l3.nome if environment.filter is not None: environment_map['id_filter'] = environment.filter.id environment_map['filter_name'] = environment.filter.name environment_map['acl_path'] = environment.acl_path environment_map['vrf'] = environment.vrf environment_map['ipv4_template'] = environment.ipv4_template environment_map['ipv6_template'] = environment.ipv6_template environment_map['min_num_vlan_1'] = environment.min_num_vlan_1 environment_map['max_num_vlan_1'] = environment.max_num_vlan_1 environment_map['min_num_vlan_2'] = environment.min_num_vlan_2 environment_map['max_num_vlan_2'] = environment.max_num_vlan_2 return environment_map
[docs]def get_vlan_map(vlan, network_ipv4, network_ipv6): vlan_map = model_to_dict(vlan) if network_ipv4 is not None and len(network_ipv4) > 0: net_map = [] for net in network_ipv4: net_dict = model_to_dict(net) net_map.append(net_dict) vlan_map['redeipv4'] = net_map else: vlan_map['redeipv4'] = None if network_ipv6 is not None and len(network_ipv6) > 0: net_map = [] for net in network_ipv6: net_dict = model_to_dict(net) net_map.append(net_dict) vlan_map['redeipv6'] = net_map else: vlan_map['redeipv6'] = None return vlan_map
[docs]def clear_newline_chr(string): str_return = string.replace(chr(10), '').replace(chr(13), '') return str_return
[docs]def is_valid_list_int_greater_zero_param(list_param, required=True): """Checks if the parameter list is a valid integer value and greater than zero. @param param: Value to be validated. @raise ValidationError: If there is validation error in the field """ if required and list_param in validators.EMPTY_VALUES: raise ValueError('Field is required.') try: for param in list_param: if param is None and required: raise ValueError('Field is required.') try: param = int(param) if param < 1: raise ValueError('Field must be an positive integer.') except Exception: raise ValueError('Field must be an integer.') except Exception: raise ValueError('Invalid List Parameter.') return True
[docs]def is_healthcheck_valid(healthcheck): if healthcheck['healthcheck_type'] != 'HTTP' and healthcheck['healthcheck_type'] != 'HTTPS': if healthcheck['healthcheck_expect'] != '': raise plugins_exceptions.ValueInvalid( 'healthcheck expect must be empty') if healthcheck['healthcheck_request'] != '': raise plugins_exceptions.ValueInvalid( 'healthcheck request must be empty') return True