diff --git a/dbmigrate/migrations/20191218174411_create_table_environment_cidr.migration b/dbmigrate/migrations/20191218174411_create_table_environment_cidr.migration new file mode 100644 index 000000000..1d2b1e4b6 --- /dev/null +++ b/dbmigrate/migrations/20191218174411_create_table_environment_cidr.migration @@ -0,0 +1,45 @@ +#-*- coding:utf-8 -*- +SQL_UP = u""" + +CREATE TABLE `environment_cidr` ( + `id` INT NOT NULL AUTO_INCREMENT, + `id_network_type` INT(10) UNSIGNED NOT NULL, + `id_env` INT(10) UNSIGNED NOT NULL, + `network_first_ip` varchar(40) NOT NULL, + `network_last_ip` varchar(40) NOT NULL, + `network_mask` varchar(3) NOT NULL, + `ip_version` enum('v6','v4') NOT NULL, + `subnet_mask` varchar(3) NOT NULL, + PRIMARY KEY (`id`)); + +ALTER TABLE `environment_cidr` +ADD INDEX `fk_environment_cidr_fk1_idx` (`id_network_type` ASC) COMMENT '', +ADD INDEX `fk_environment_cidr_fk2_idx` (`id_env` ASC) COMMENT ''; + +ALTER TABLE `environment_cidr` +ADD CONSTRAINT `fk_environment_cidr_fk1` + FOREIGN KEY (`id_network_type`) + REFERENCES `tipo_rede` (`id_tipo_rede`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, +ADD CONSTRAINT `fk_environment_cidr_fk2` + FOREIGN KEY (`id_env`) + REFERENCES `ambiente` (`id_ambiente`) + ON DELETE NO ACTION + ON UPDATE NO ACTION; + +""" + +SQL_DOWN = u""" + +ALTER TABLE `environment_cidr` +DROP FOREIGN KEY `fk_environment_cidr_fk1`, +DROP FOREIGN KEY `fk_environment_cidr_fk2`; + +ALTER TABLE `environment_cidr` +DROP INDEX `fk_environment_cidr_fk1_idx` , +DROP INDEX `fk_environment_cidr_fk2_idx` ; + +DROP TABLE `environment_cidr`; + +""" diff --git a/dbmigrate/migrations/20200130173043_alter_table_environment_cidr.migration b/dbmigrate/migrations/20200130173043_alter_table_environment_cidr.migration new file mode 100644 index 000000000..0dc92bba0 --- /dev/null +++ b/dbmigrate/migrations/20200130173043_alter_table_environment_cidr.migration @@ -0,0 +1,12 @@ +#-*- coding:utf-8 -*- +SQL_UP = u""" +ALTER TABLE `environment_cidr` +ADD COLUMN `network` varchar(44) NOT NULL; + +""" + +SQL_DOWN = u""" +ALTER TABLE `environment_cidr` +DROP COLUMN `network`; + +""" \ No newline at end of file diff --git a/dbmigrate/migrations/20200204182946_alter_table_environment_cidr_use_unique_key.migration b/dbmigrate/migrations/20200204182946_alter_table_environment_cidr_use_unique_key.migration new file mode 100644 index 000000000..801a89f81 --- /dev/null +++ b/dbmigrate/migrations/20200204182946_alter_table_environment_cidr_use_unique_key.migration @@ -0,0 +1,13 @@ +#-*- coding:utf-8 -*- +SQL_UP = u""" +ALTER TABLE `environment_cidr` +ADD UNIQUE KEY `cidr_uni` (`id_env`,`network`); + +""" + +SQL_DOWN = u""" +ALTER TABLE `environment_cidr` +DROP UNIQUE KEY `cidr_uni`; + +""" + diff --git a/dev/load_example_environment.sql b/dev/load_example_environment.sql index a463dbd6d..d81afb44c 100644 --- a/dev/load_example_environment.sql +++ b/dev/load_example_environment.sql @@ -705,6 +705,46 @@ VALUES 17, 13, 17 ) ; +-- Dumping data for table `environment_cidr` +INSERT INTO + `environment_cidr` (id, network, subnet_mask, ip_version, id_network_type, id_env, network_first_ip, network_last_ip, network_mask) +VALUES + ( + 5, '10.0.1.0/28', '28', 'v4', 2, 1, 167772416, 167772431, 28 + ) +, + ( + 10, '10.42.0.0/24', '24', 'v4', 2, 1, 170524672, 170524927, 24 + ) +, + ( + 11, '192.168.104.0/22', '27', 'v4', 2, 9, 3232262144, 3232263167, 22 + ) +, + ( + 12, 'fdbe:bebe:bebe:11c0:0000:0000:0000:0000/58', '64', 'v6', 2, 9, 337285088106912836215476086841679020032, 337285088106912837396067707559090323455, 58 + ) +, + ( + 13, '10.237.128.0/18', '28', 'v4', 2, 10, 183336960, 183353343, 18 + ) +, + ( + 14, 'fdbe:bebe:bebe:1200:0:0:0:0/57', '64', 'v6', 2, 10, 337285088106912837396067707559090323456, 337285088106912839757250948993912930303, 57 + ) +, + ( + 15, '10.16.0.0/16', '24', 'v4', 2, 11, 168820736, 168886271, 16 + ) +, + ( + 16, '10.0.0.0/16', '24', 'v4', 2, 12, 167772160, 167837695, 16 + ) +, + ( + 17, '10.1.0.0/16', '24', 'v4', 2, 13, 167837696, 167903231, 16 + ) +; -- Dumping data for table `vlans` INSERT INTO `vlans` (id_vlan, nome, num_vlan, id_ambiente, descricao, acl_file_name, acl_valida, ativada, acl_file_name_v6, acl_valida_v6, acl_draft, acl_draft_v6, vrf) @@ -762,39 +802,39 @@ INSERT INTO `equipamentos` (id_equip, id_tipo_equipamento, id_modelo, nome, maintenance) VALUES ( - 1, 1, 1, 'Switch R1', 0 + 1, 1, 1, 'SWITCH-R1', 0 ) , ( - 2, 1, 1, 'Switch R2', 0 + 2, 1, 1, 'SWITCH-R2', 0 ) , ( - 3, 1, 1, 'Switch R3', 0 + 3, 1, 1, 'SWITCH-R3', 0 ) , ( - 4, 1, 1, 'Switch B1', 0 + 4, 1, 1, 'SWITCH-B1', 0 ) , ( - 5, 1, 1, 'Switch B2', 0 + 5, 1, 1, 'SWITCH-B2', 0 ) , ( - 6, 1, 1, 'Switch B3', 0 + 6, 1, 1, 'SWITCH-B3', 0 ) , ( - 7, 1, 1, 'Switch 01', 0 + 7, 1, 1, 'SWITCH-01', 0 ) , ( - 8, 1, 1, 'Switch 02', 0 + 8, 1, 1, 'SWITCH-02', 0 ) , ( - 9, 1, 1, 'Switch 03', 0 + 9, 1, 1, 'SWITCH-03', 0 ) , ( @@ -806,67 +846,67 @@ VALUES ) , ( - 12, 3, 1, 'Router', 0 + 12, 3, 1, 'ROUTER', 0 ) , ( - 13, 2, 1, 'Server S1', 0 + 13, 2, 1, 'SERVER-S1', 0 ) , ( - 14, 2, 1, 'Server P1', 0 + 14, 2, 1, 'SERVER-P1', 0 ) , ( - 15, 2, 1, 'Server P2', 0 + 15, 2, 1, 'SERVER-P2', 0 ) , ( - 16, 2, 1, 'Server P3', 0 + 16, 2, 1, 'SERVER-P3', 0 ) , ( - 17, 2, 1, 'Server P4', 0 + 17, 2, 1, 'SERVER-P4', 0 ) , ( - 18, 2, 1, 'Server P5', 0 + 18, 2, 1, 'SERVER-P5', 0 ) , ( - 19, 5, 1, 'Load-Balancer', 0 + 19, 5, 1, 'LOAD-BALANCER', 0 ) , ( - 20, 2, 1, 'Server Space 1', 0 + 20, 2, 1, 'SERVER-SPACE-1', 0 ) , ( - 21, 2, 1, 'Server Space 2', 0 + 21, 2, 1, 'SERVER-SPACE-2', 0 ) , ( - 22, 1, 1, 'TOR 1 Space 1', 0 + 22, 1, 1, 'TOR-1-SPACE-1', 0 ) , ( - 23, 1, 1, 'TOR 2 Space 1', 0 + 23, 1, 1, 'TOR-2-SPACE-1', 0 ) , ( - 24, 1, 1, 'TOR 1 Space 2', 0 + 24, 1, 1, 'TOR-1-SPACE-2', 0 ) , ( - 25, 1, 1, 'TOR 2 Space 2', 0 + 25, 1, 1, 'TOR-2-SPACE-2', 0 ) , ( - 26, 3, 1, 'Fabric router 0', 0 + 26, 3, 1, 'FABRIC-ROUTER-0', 0 ) , ( - 27, 3, 1, 'Fabric router 1', 0 + 27, 3, 1, 'FABRIC-ROUTER-1', 0 ) ; @@ -1013,11 +1053,11 @@ VALUES ) , ( - 2, 2, 0, 168, 192, 'Router', 1 + 2, 2, 0, 168, 192, 'ROUTER', 1 ) , ( - 3, 1, 1, 168, 192, 'Router', 2 + 3, 1, 1, 168, 192, 'ROUTER', 2 ) , ( @@ -1025,11 +1065,11 @@ VALUES ) , ( - 5, 6, 0, 16, 172, 'Server S1', 3 + 5, 6, 0, 16, 172, 'SERVER-S1', 3 ) , ( - 6, 6, 0, 0, 10, 'Server S1', 4 + 6, 6, 0, 0, 10, 'SERVER-S1', 4 ) , ( diff --git a/fast_start_test.sh b/fast_start_test.sh index e026e5162..5a71e3fe2 100755 --- a/fast_start_test.sh +++ b/fast_start_test.sh @@ -1,5 +1,7 @@ #!/bin/sh +pip install -r requirements_test.txt + echo "exporting NETWORKAPI_DEBUG" export NETWORKAPI_LOG_QUEUE=0 diff --git a/networkapi/ambiente/models.py b/networkapi/ambiente/models.py index b3adc673b..568a38a7a 100644 --- a/networkapi/ambiente/models.py +++ b/networkapi/ambiente/models.py @@ -13,6 +13,8 @@ # 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. + +import ipaddr import logging from _mysql_exceptions import OperationalError @@ -25,6 +27,7 @@ from django.forms.models import model_to_dict from networkapi.api_pools import exceptions +from networkapi.api_rest.exceptions import ObjectDoesNotExistException from networkapi.api_vrf.models import Vrf from networkapi.distributedlock import LOCK_ENVIRONMENT from networkapi.distributedlock import LOCK_ENVIRONMENT_ALLOCATES @@ -35,6 +38,7 @@ from networkapi.exception import EnvironmentVipError from networkapi.exception import EnvironmentVipNotFoundError from networkapi.exception import InvalidValueError +from networkapi.api_rest.exceptions import ValidationAPIException from networkapi.filter.models import CannotDissociateFilterError from networkapi.filter.models import Filter from networkapi.filter.models import FilterNotFoundError @@ -48,6 +52,10 @@ from networkapi.util.geral import get_app from networkapi.util.appcache import delete_cached_searches_list from networkapi.util.appcache import ENVIRONMENT_CACHE_ENTRY +from networkapi.vlan.models import TipoRede + +from netaddr import IPNetwork as NETADDR + log = logging.getLogger(__name__) @@ -74,6 +82,15 @@ def __str__(self): return str(self.cause) +class CIDRErrorV3(Exception): + + def __init__(self, cause): + self.cause = cause + + def __str__(self): + return str(self.cause) + + class AmbienteNotFoundError(AmbienteError): """Retorna exceção para pesquisa de ambiente por chave primária.""" @@ -1010,9 +1027,7 @@ def _get_children(self): def _get_configs(self): """Returns configs of environment.""" - configs = self.configenvironment_set.prefetch_related( - 'ip_config', - ).all() + configs = self.envcidr_set.all() return configs @@ -1410,7 +1425,13 @@ def create_v3(self, env_map): self.save() configs = env_map.get('configs', []) - self.create_configs(configs, self.id) + + # # save network on IPConfig tables + # configs = self.create_configs(configs, self.id) + + # save network on CIDR tables + self.create_cidr(configs=configs, env_id=self.id) + delete_cached_searches_list(ENVIRONMENT_CACHE_ENTRY) except Exception, e: @@ -1480,30 +1501,9 @@ def update_v3(self, env_map): # If have changes in configs if configs is not None: - ips_by_env = IPConfig.get_by_environment(None, self.id) - ids_conf_current = [ip_by_env.id for ip_by_env in ips_by_env] - - # Configs with ids - ids_conf_receive = [cfg.get('id') for cfg in configs - if cfg.get('id')] - - # Configs to update: configs with id - cfg_upt = [cfg for cfg in configs if cfg.get('id') and - cfg.get('id') in ids_conf_current] - - # Configs to create: configs without id - cfg_ins = [cfg for cfg in configs if not cfg.get('id')] - - # Configs to delete: configs not received - cfg_del = [id_conf for id_conf in ids_conf_current - if id_conf not in ids_conf_receive] - - # Updates configs - self.update_configs(cfg_upt, self.id) - # Creates configs - self.create_configs(cfg_ins, self.id) - # Deletes configs - self.delete_configs(cfg_del, self.id) + # self.check_config(env_id=self.id, configs=configs) + self.check_cidr(env_id=self.id, configs=configs) + except Exception, e: raise EnvironmentErrorV3(e) @@ -1511,6 +1511,58 @@ def update_v3(self, env_map): delete_cached_searches_list(ENVIRONMENT_CACHE_ENTRY) destroy_lock(locks_list) + # def check_config(self, env_id=None, configs=[]): + # + # ips_by_env = IPConfig.get_by_environment(None, env_id) + # ids_conf_current = [ip_by_env.id for ip_by_env in ips_by_env] + # + # # Configs with ids + # ids_conf_receive = [cfg.get('id') for cfg in configs + # if cfg.get('id')] + # + # # Configs to update: configs with id + # cfg_upt = [cfg for cfg in configs if cfg.get('id') and + # cfg.get('id') in ids_conf_current] + # + # # Configs to create: configs without id + # cfg_ins = [cfg for cfg in configs if not cfg.get('id')] + # + # # Configs to delete: configs not received + # cfg_del = [id_conf for id_conf in ids_conf_current + # if id_conf not in ids_conf_receive] + # + # # Updates configs + # self.update_configs(cfg_upt, self.id) + # # Creates configs + # self.create_configs(cfg_ins, self.id) + # # Deletes configs + # self.delete_configs(cfg_del, self.id) + + def check_cidr(self, env_id=None, configs=[]): + log.info("check_cidr") + + # CIDR + cidrs = EnvCIDR().get(env_id=env_id) + + cidrs_current = [net.id for net in cidrs] + + # Configs with ids + cidrs_receive = [cfg.get('id') for cfg in configs] + + # Configs to delete: configs not received + cfg_del = [id_conf for id_conf in cidrs_current + if cidrs_current and id_conf not in cidrs_receive] + self.delete_cidr(cfg_del) + + # Configs to create: configs without id + cfg_ins = [cfg for cfg in configs if not cfg.get('id') in cidrs_current] + self.create_cidr(cfg_ins) + + # Configs to update: configs with id + cfg_upt = [cfg for cfg in configs if cfg.get('id') and + cfg.get('id') in cidrs_current] + self.update_cidr(cfg_upt) + def delete_v3(self): ip_models = get_app('ip', 'models') vlan_models = get_app('vlan', 'models') @@ -1545,6 +1597,10 @@ def delete_v3(self): self.log.error(u'Falha ao remover algum Ambiente Config.') raise AmbienteError(e, u'Falha ao remover algum Ambiente Config.') + # Remove CIDR associated with environment + from networkapi.api_environment.facade import delete_cidr + delete_cidr(environment=self.id) + # Remove the environment try: self.delete() @@ -1568,53 +1624,90 @@ def validate_v3(self): else: raise AmbienteDuplicatedError(None, u'Duplicate Environment.') - def update_configs(self, configs, env_id): - """ - Update configs of environment + # def update_configs(self, configs, env_id): + # """ + # Update configs of environment + # + # :param configs: Configs of environment + # :param env: Id of environment + # """ + # for config in configs: + # try: + # ip_config = IPConfig.objects.get( + # id=config.get('id'), + # configenvironment__environment=env_id + # ) + # except ObjectDoesNotExist: + # raise exceptions.ConfigIpDoesNotExistException() + # + # ip_config.subnet = config.get('subnet') + # ip_config.new_prefix = config.get('new_prefix') + # ip_config.type = config.get('type') + # ip_config.network_type_id = config.get('network_type') + # + # ip_config.save() + # delete_cached_searches_list(ENVIRONMENT_CACHE_ENTRY) + + def update_cidr(self, configs): + log.debug("Update config on cidr tables") + + from networkapi.api_environment.facade import update_cidr - :param configs: Configs of environment - :param env: Id of environment - """ for config in configs: - try: - ip_config = IPConfig.objects.get( - id=config.get('id'), - configenvironment__environment=env_id - ) - except ObjectDoesNotExist: - raise exceptions.ConfigIpDoesNotExistException() - - ip_config.subnet = config.get('subnet') - ip_config.new_prefix = config.get('new_prefix') - ip_config.type = config.get('type') - ip_config.network_type_id = config.get('network_type') - - ip_config.save() - delete_cached_searches_list(ENVIRONMENT_CACHE_ENTRY) + update_cidr(config) + + # def create_configs(self, configs, env_id): + # log.debug("Save config on ipconfig tables") + # + # """ + # Create configs of environment + # + # :param configs: Configs of environment + # :param env: Id of environment + # """ + # for config in configs: + # config_id = IPConfig.create(env_id, config) + # config['config_id'] = config_id.id + # + # delete_cached_searches_list(ENVIRONMENT_CACHE_ENTRY) + # + # return configs + + def create_cidr(self, configs=None, env_id=None): + log.debug("create_cidr") + + from networkapi.api_environment.facade import post_cidr + from networkapi.api_environment.facade import post_cidr_auto - def create_configs(self, configs, env_id): - """ - Create configs of environment - - :param configs: Configs of environment - :param env: Id of environment - """ for config in configs: - IPConfig.create(env_id, config) - - delete_cached_searches_list(ENVIRONMENT_CACHE_ENTRY) - - def delete_configs(self, configs_ids, env_id): + if env_id: + config["environment"] = env_id + post_cidr(config) if config.get("network") else post_cidr_auto(config) + + # def delete_configs(self, configs_ids, env_id): + # """ + # Delete configs of environment + # + # :param configs_ids: Id of Configs of environment + # :param env_id: Id of environment + # """ + # + # for config_id in configs_ids: + # IPConfig.remove(None, None, env_id, config_id) + # delete_cached_searches_list(ENVIRONMENT_CACHE_ENTRY) + + def delete_cidr(self, configs_ids=[]): """ Delete configs of environment :param configs_ids: Id of Configs of environment - :param env: Id of environment + :param env_id: Id of environment """ - for config_id in configs_ids: - IPConfig.remove(None, None, env_id, config_id) - delete_cached_searches_list(ENVIRONMENT_CACHE_ENTRY) + from networkapi.api_environment.facade import delete_cidr + + for cidr_id in configs_ids: + delete_cidr(cidr=cidr_id) class IP_VERSION: @@ -1768,6 +1861,301 @@ def remove(cls, authenticated_user, environment_id, configuration_id): raise IPConfigError(e, u'Error removing IpConfig.') +class EnvCIDR(BaseModel): + + from networkapi.vlan.models import TipoRede + + id = models.AutoField( + primary_key=True + ) + network = models.CharField( + max_length=44, + db_column='network' + ) + network_first_ip = models.CharField( + max_length=40, + db_column='network_first_ip' + ) + network_last_ip = models.CharField( + max_length=40, + db_column='network_last_ip' + ) + network_mask = models.CharField( + max_length=3, + blank=False + ) + ip_version = models.CharField( + max_length=2, + blank=False, + choices=IP_VERSION.List + ) + id_network_type = models.ForeignKey( + TipoRede, + db_column='id_network_type', + null=True + ) + subnet_mask = models.CharField( + max_length=3, + blank=False + ) + id_env = models.ForeignKey( + Ambiente, + db_column='id_env' + ) + + log = logging.getLogger('Environment_CIDR') + + class Meta(BaseModel.Meta): + db_table = u'environment_cidr' + managed = True + unique_together = ('id_env', 'network') + + def check_cidr(self, environment, network): + """ + check if network is a subnet of the father environment + :param environment: environment id + :param network: environment cidr + :return: boolean + """ + + if environment.father_environment: + id_env_father = environment.father_environment.id + else: + return True + + cidr_env_father = self.get(env_id=id_env_father) + + for cidr in cidr_env_father: + if ipaddr.IPNetwork(network).overlaps(ipaddr.IPNetwork(cidr.network)): + return True + + return False + + def check_prefix(self, network_address, subnet_mask): + """ + check if subnet mask is correct, based on network mask. + + :param network_address: environment cidr + :param subnet_mask: environment cidr subnet mask + :return: boolean + """ + + network = ipaddr.IPNetwork(network_address) + + return True if int(network.prefixlen) <= int(subnet_mask) else False + + def check_duplicated_cidr(self, environment, network): + """ + check if the network overlaps another cidr from another environment. + :return: + """ + + ids = self.get_parent_env(environment, []) + log.debug("fathers: %s" % ids) + environments = EnvCIDR.objects.filter(network=network).exclude(id_env__in=ids) + log.debug("duplicated envs: %s" % environments) + + return environments + + def get_parent_env(self, environment, ids=[]): + log.debug("env: %s" % environment.id) + if environment.father_environment: + ids.append(environment.father_environment.id) + return self.get_parent_env(environment.father_environment, ids) + else: + return ids + + def searchNextAvailableCIDR(self, subnets, network_mask=None): + """ + Method that search next availacle cidr. + :param subnets: all subnets of environment. + :return: available subnet + """ + log.debug("searchNextAvailableCIDR") + + for idx in range(len(subnets)-1): + step = int(subnets[idx+1].network_first_ip) - int(subnets[idx].network_last_ip) - 1 + if step >= 2 ** (32-int(network_mask)): + subnet = NETADDR(str(NETADDR(subnets[idx].network).next().ip) + "/" + network_mask) + if subnet.ip == subnet.network and \ + not ipaddr.IPNetwork(subnet).overlaps(ipaddr.IPNetwork(subnets[idx+1].network)): + return str(subnet) + + return "" + + def nextAvailableCIDR(self, subnets, network, network_mask=None): + """""" + log.debug("nextAvailableCIDR") + + if not subnets: + subnet = list(NETADDR(network.network).subnet(int(network_mask)))[0] + return str(subnet) + + last_subnet = NETADDR(subnets.latest("network_last_ip").network) + log.debug("Last Subnet: %s" % last_subnet) + log.debug("Subnet mask: %s" % network_mask) + + if int(network_mask) > last_subnet.prefixlen: + subnet = list(last_subnet.next().subnet(int(network_mask)))[0] + elif int(network_mask) == last_subnet.prefixlen: + subnet = last_subnet.next() + else: + subnet = NETADDR(str(last_subnet.next().ip) + "/" + network_mask) + if not subnet.ip == subnet.network: + subnet = subnet.next() + + if ipaddr.IPNetwork(subnet).overlaps(ipaddr.IPNetwork(network.network)): + return str(subnet) + + return self.searchNextAvailableCIDR(subnets, network_mask) + + def checkAvailableCIDR(self, environment_id, ip_version=None, network_mask=None): + """""" + log.debug("checkAvailableCIDR") + + environment = Ambiente.get_by_pk(environment_id) + + try: + father_environment = environment.father_environment.id + except Exception as e: + raise ValidationAPIException( + "The environment doesn't have an Environment Father. Error: %s" % e) + + env_father_cidrs = EnvCIDR.objects.filter(id_env=father_environment, + ip_version=ip_version) + + if not env_father_cidrs: + raise ValidationAPIException( + "The Environment Father doesnt have an allocated CIDR block") + + for cidr in env_father_cidrs: + mask = cidr.subnet_mask if not network_mask else network_mask + + env_subnets = EnvCIDR.objects.filter( + network_first_ip__gte=cidr.network_first_ip, + network_last_ip__lte=cidr.network_last_ip, + id_env__father_environment__id=cidr.id_env.id).exclude( + id=cidr.id).order_by( + "network_first_ip") + + log.debug("Father`s CIDR: %s" % cidr.network) + log.debug("Subnets: %s" % len(env_subnets)) + + next_available_cidr = self.nextAvailableCIDR(env_subnets, cidr, mask) + if next_available_cidr: + msg = "Subnet available: %s." % next_available_cidr + return next_available_cidr, msg + + raise CIDRErrorV3("Out of address space. It was not possible to allocate the subnet with " + "prefix length %s for the environment %s. " + "Please register a new CIDR on the father environment." + % (network_mask, environment.name)) + + def post(self, env_cidr): + + try: + if env_cidr.get('id'): + self.id = env_cidr.get('id') + self.network = env_cidr.get('network') + self.network_first_ip = env_cidr.get('network_first_ip') + self.network_last_ip = env_cidr.get('network_last_ip') + self.network_mask = env_cidr.get('network_mask') + self.ip_version = env_cidr.get('ip_version') + self.subnet_mask = env_cidr.get('subnet_mask') + + if not self.check_prefix(self.network, self.subnet_mask): + raise CIDRErrorV3("The prefix %s is not valid for the network %s" % (self.subnet_mask, self.network)) + + objects = EnvCIDR.objects.filter(id_env=int(env_cidr.get('environment'))) + for obj in objects: + if ipaddr.IPNetwork(obj.network).overlaps(ipaddr.IPNetwork(self.network)): + raise CIDRErrorV3("%s overlaps %s" % (self.network, obj.network)) + + environment = Ambiente().get_by_pk(int(env_cidr.get('environment'))) + self.id_env = environment + self.id_network_type = TipoRede().get_by_pk(int(env_cidr.get('network_type'))) + self.save() + except Exception as e: + raise CIDRErrorV3(e) + return self.id + + def put(self, env_cidr): + log.info("Update CIDR") + + import ipaddr + + try: + cidr_id = env_cidr.get('id') + + self.network = env_cidr.get('network') + self.network_first_ip = env_cidr.get('network_first_ip') + self.network_last_ip = env_cidr.get('network_last_ip') + self.network_mask = env_cidr.get('network_mask') + self.ip_version = env_cidr.get('ip_version') + self.subnet_mask = env_cidr.get('subnet_mask') + + objects = EnvCIDR.objects.filter(id_env=int(env_cidr.get('environment'))).exclude(id=cidr_id) + + for obj in objects: + if ipaddr.IPNetwork(obj.network).overlaps(ipaddr.IPNetwork(self.network)): + raise CIDRErrorV3("%s overlaps %s" % (self.network, obj.network)) + + self.id_env = Ambiente().get_by_pk(int(env_cidr.get('environment'))) + self.id_network_type = TipoRede().get_by_pk(int(env_cidr.get('network_type'))) + + self.save() + + except Exception as e: + raise CIDRErrorV3(e) + + return self.id + + def get(self, cidr_id=None, env_id=None): + + if cidr_id: + try: + objects = EnvCIDR.objects.filter(id=cidr_id) + if not objects: + raise ObjectDoesNotExist + except ObjectDoesNotExist: + raise CIDRErrorV3('There is no CIDR with pk = %s.' % cidr_id) + except OperationalError as e: + self.log.error('Lock wait timeout exceeded.') + raise OperationalError(e, 'Lock wait timeout exceeded; try restarting transaction') + except Exception as e: + self.log.error('Error finding CIDR.') + raise Exception('Error finding CIDR. E: %s' % e) + elif env_id: + try: + objects = EnvCIDR.objects.filter(id_env=env_id) + if not objects: + log.debug('There is no CIDR linked with the environment id=%s.' % env_id) + except OperationalError as e: + self.log.error('Lock wait timeout exceeded.') + raise OperationalError(e, 'Lock wait timeout exceeded; try restarting transaction') + except Exception as e: + self.log.error('Error finding CIDR.') + raise Exception('Error finding CIDR. E: %s' % e) + else: + try: + objects = EnvCIDR.objects.all() + except ObjectDoesNotExist: + raise ObjectDoesNotExistException('There is no CIDR.') + except OperationalError as e: + self.log.error('Lock wait timeout exceeded.') + raise OperationalError(e, 'Lock wait timeout exceeded; try restarting transaction') + except Exception as e: + self.log.error('Error finding CIDR.') + raise Exception('Error finding CIDR. E: %s' % e) + + return objects + + def delete(self): + log.info("EnvCIDR delete method") + + super(EnvCIDR, self).delete() + + class ConfigEnvironment(BaseModel): id = models.AutoField(primary_key=True, db_column='id_config_do_ambiente') environment = models.ForeignKey(Ambiente, db_column='id_ambiente') diff --git a/networkapi/ambiente/resource/AmbienteResource.py b/networkapi/ambiente/resource/AmbienteResource.py index a4729d72e..eaf4576ce 100644 --- a/networkapi/ambiente/resource/AmbienteResource.py +++ b/networkapi/ambiente/resource/AmbienteResource.py @@ -103,12 +103,12 @@ def handle_get(self, request, user, *args, **kwargs): try: if not has_perm(user, AdminPermission.ENVIRONMENT_MANAGEMENT, AdminPermission.READ_OPERATION): return self.not_authorized() - + environment_list = [] - + division_id = kwargs.get('id_divisao_dc') environment_logical_id = kwargs.get('id_amb_logico') - + if division_id is not None: if not is_valid_int_greater_zero_param(division_id): self.log.error( @@ -116,7 +116,7 @@ def handle_get(self, request, user, *args, **kwargs): raise InvalidValueError(None, 'division_id', division_id) else: division_dc = DivisaoDc.get_by_pk(division_id) - + if environment_logical_id is not None: if not is_valid_int_greater_zero_param(environment_logical_id): self.log.error( @@ -125,12 +125,12 @@ def handle_get(self, request, user, *args, **kwargs): None, 'environment_logical_id', environment_logical_id) else: loc_env = AmbienteLogico.get_by_pk(environment_logical_id) - + environments = Ambiente().search( division_id, environment_logical_id).select_related('grupo_l3', 'ambiente_logico', 'divisao_dc', 'filter') for environment in environments: environment_list.append(get_environment_map(environment)) - + return self.response(dumps_networkapi({'ambiente': environment_list})) except InvalidValueError, e: return self.response_error(269, e.param, e.value) @@ -148,31 +148,31 @@ def handle_post(self, request, user, *args, **kwargs): URL: ambiente/ or ambiente/ipconfig/ """ - + try: if not has_perm(user, AdminPermission.ENVIRONMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION): return self.not_authorized() - + xml_map, attrs_map = loads(request.raw_post_data) - + self.log.debug('XML_MAP: %s', xml_map) - + networkapi_map = xml_map.get('networkapi') if networkapi_map is None: return self.response_error(3, u'Não existe valor para a tag networkapi do XML de requisição.') - + environment_map = networkapi_map.get('ambiente') if environment_map is None: return self.response_error(3, u'Não existe valor para a tag ambiente do XML de requisição.') - + link = environment_map.get('link') if not is_valid_string_maxsize(link, 200, False): self.log.error(u'Parameter link is invalid. Value: %s', link) raise InvalidValueError(None, 'link', link) - + l3_group_id = environment_map.get('id_grupo_l3') if not is_valid_int_greater_zero_param(l3_group_id): self.log.error( @@ -180,7 +180,7 @@ def handle_post(self, request, user, *args, **kwargs): raise InvalidValueError(None, 'l3_group_id', l3_group_id) else: l3_group_id = int(l3_group_id) - + logic_environment_id = environment_map.get('id_ambiente_logico') if not is_valid_int_greater_zero_param(logic_environment_id): self.log.error( @@ -189,7 +189,7 @@ def handle_post(self, request, user, *args, **kwargs): None, 'logic_environment_id', logic_environment_id) else: logic_environment_id = int(logic_environment_id) - + dc_division_id = environment_map.get('id_divisao') if not is_valid_int_greater_zero_param(dc_division_id): self.log.error( @@ -197,32 +197,32 @@ def handle_post(self, request, user, *args, **kwargs): raise InvalidValueError(None, 'dc_division_id', dc_division_id) else: dc_division_id = int(dc_division_id) - + filter_id = environment_map.get('id_filter') if filter_id is not None: if not is_valid_int_greater_zero_param(filter_id): self.log.error( u'Parameter filter_id is invalid. Value: %s.', filter_id) raise InvalidValueError(None, 'filter_id', filter_id) - + acl_path = environment_map.get('acl_path') if not is_valid_string_maxsize(acl_path, 250, False): self.log.error( u'Parameter acl_path is invalid. Value: %s', acl_path) raise InvalidValueError(None, 'acl_path', acl_path) - + ipv4_template = environment_map.get('ipv4_template') if not is_valid_string_maxsize(ipv4_template, 250, False): self.log.error( u'Parameter ipv4_template is invalid. Value: %s', ipv4_template) raise InvalidValueError(None, 'ipv4_template', ipv4_template) - + ipv6_template = environment_map.get('ipv6_template') if not is_valid_string_maxsize(ipv6_template, 250, False): self.log.error( u'Parameter ipv6_template is invalid. Value: %s', ipv6_template) raise InvalidValueError(None, 'ipv6_template', ipv6_template) - + max_num_vlan_1 = environment_map.get('max_num_vlan_1') min_num_vlan_1 = environment_map.get('min_num_vlan_1') max_num_vlan_2 = environment_map.get('max_num_vlan_2') @@ -233,11 +233,11 @@ def handle_post(self, request, user, *args, **kwargs): u'Parameters min_num_vlan_1, max_num_vlan_1 is invalid. Values: %s, %s', (min_num_vlan_1, max_num_vlan_1)) raise InvalidValueError( None, 'min_num_vlan_1, max_num_vlan_1', min_num_vlan_1 + ',' + max_num_vlan_1) - + if max_num_vlan_1 is not None and min_num_vlan_1 is not None: max_num_vlan_1 = int(max_num_vlan_1) min_num_vlan_1 = int(min_num_vlan_1) - + if max_num_vlan_1 < 1 or min_num_vlan_1 < 1: self.log.error( u'Parameters min_num_vlan_1, max_num_vlan_1 is invalid. Values: %s, %s', (min_num_vlan_1, max_num_vlan_1)) @@ -252,27 +252,27 @@ def handle_post(self, request, user, *args, **kwargs): max_num_vlan_1 = max_num_vlan_2 min_num_vlan_1 = min_num_vlan_2 # validate max_num_vlan_1 and min_num_vlan_1 - + # validate max_num_vlan_2 and min_num_vlan_2 if (max_num_vlan_2 is not None and min_num_vlan_2 is None) or (min_num_vlan_2 is not None and max_num_vlan_2 is None): self.log.error( u'Parameters min_num_vlan_2, max_num_vlan_2 is invalid. Values: %s, %s', (min_num_vlan_2, max_num_vlan_2)) raise InvalidValueError( None, 'min_num_vlan_2, max_num_vlan_2', min_num_vlan_2 + ',' + max_num_vlan_1) - + if max_num_vlan_2 is not None and min_num_vlan_2 is not None: max_num_vlan_2 = int(max_num_vlan_2) min_num_vlan_2 = int(min_num_vlan_2) - + max_num_vlan_1 = int(max_num_vlan_1) min_num_vlan_1 = int(min_num_vlan_1) - + if max_num_vlan_2 < 1 or min_num_vlan_2 < 1: self.log.error( u'Parameters min_num_vlan_2, max_num_vlan_2 is invalid. Values: %s, %s', (min_num_vlan_2, max_num_vlan_2)) raise InvalidValueError( None, 'min_num_vlan_2, max_num_vlan_2', min_num_vlan_2 + ',' + max_num_vlan_1) - + if max_num_vlan_2 <= min_num_vlan_2: self.log.error( u'Parameters min_num_vlan_2, max_num_vlan_2 is invalid. Values: %s, %s', (min_num_vlan_2, max_num_vlan_2)) @@ -282,12 +282,12 @@ def handle_post(self, request, user, *args, **kwargs): max_num_vlan_2 = max_num_vlan_1 min_num_vlan_2 = min_num_vlan_1 # validate max_num_vlan_2 and min_num_vlan_2 - + vrf = environment_map.get('vrf') if not is_valid_string_maxsize(vrf, 100, False): self.log.error(u'Parameter vrf is invalid. Value: %s', vrf) raise InvalidValueError(None, 'link', vrf) - + environment = Ambiente() environment.grupo_l3 = GrupoL3() environment.ambiente_logico = AmbienteLogico() @@ -303,74 +303,74 @@ def handle_post(self, request, user, *args, **kwargs): environment.max_num_vlan_2 = max_num_vlan_2 environment.min_num_vlan_2 = min_num_vlan_2 environment.vrf = vrf - + if filter_id is not None: environment.filter = Filter() environment.filter.id = filter_id - + environment.link = link - + environment.create(user) - + # IP Config ip_config = kwargs.get('ip_config') - + # If ip config is set if ip_config: - + # Add this to environment id_ip_config = environment_map.get('id_ip_config') - + # Valid ip config if not is_valid_int_greater_zero_param(id_ip_config): raise InvalidValueError(None, 'id_ip_config', id_ip_config) - + # Ip config must exists ip_conf = IPConfig().get_by_pk(id_ip_config) - + # Makes the relationship config = ConfigEnvironment() config.environment = environment config.ip_config = ip_conf - + config.save() - + environment_map = dict() environment_map['id'] = environment.id - + return self.response(dumps_networkapi({'ambiente': environment_map})) - + except GrupoError: return self.response_error(1) - + except XMLError, x: self.log.error(u'Erro ao ler o XML da requisicao.') return self.response_error(3, x) - + except InvalidValueError, e: return self.response_error(269, e.param, e.value) - + except FilterNotFoundError, e: return self.response_error(339) - + except IPConfigNotFoundError, e: return self.response_error(301) - + except GrupoL3.DoesNotExist: return self.response_error(160, l3_group_id) - + except AmbienteLogicoNotFoundError: return self.response_error(162, logic_environment_id) - + except AmbienteDuplicatedError: return self.response_error(219) - + except DivisaoDcNotFoundError: return self.response_error(164, dc_division_id) - + except ConfigEnvironmentDuplicateError, e: return self.response_error(self.CODE_MESSAGE_CONFIG_ENVIRONMENT_ALREADY_EXISTS) - + except AmbienteError: return self.response_error(1) @@ -381,30 +381,30 @@ def handle_put(self, request, user, *args, **kwargs): """ try: - + environment_id = kwargs.get('id_ambiente') if not is_valid_int_greater_zero_param(environment_id): self.log.error( u'The environment_id parameter is not a valid value: %s.', environment_id) raise InvalidValueError(None, 'environment_id', environment_id) - + if not has_perm(user, AdminPermission.ENVIRONMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION): return self.not_authorized() - + xml_map, attrs_map = loads(request.raw_post_data) - + self.log.debug('XML_MAP: %s', xml_map) - + networkapi_map = xml_map.get('networkapi') if networkapi_map is None: return self.response_error(3, u'Não existe valor para a tag networkapi do XML de requisição.') - + environment_map = networkapi_map.get('ambiente') if environment_map is None: return self.response_error(3, u'Não existe valor para a tag ambiente do XML de requisição.') - + l3_group_id = environment_map.get('id_grupo_l3') if not is_valid_int_greater_zero_param(l3_group_id): self.log.error( @@ -412,9 +412,9 @@ def handle_put(self, request, user, *args, **kwargs): raise InvalidValueError(None, 'l3_group_id', l3_group_id) else: l3_group_id = int(l3_group_id) - + GrupoL3.get_by_pk(l3_group_id) - + logic_environment_id = environment_map.get('id_ambiente_logico') if not is_valid_int_greater_zero_param(logic_environment_id): self.log.error( @@ -423,9 +423,9 @@ def handle_put(self, request, user, *args, **kwargs): None, 'logic_environment_id', logic_environment_id) else: logic_environment_id = int(logic_environment_id) - + AmbienteLogico.get_by_pk(logic_environment_id) - + dc_division_id = environment_map.get('id_divisao') if not is_valid_int_greater_zero_param(dc_division_id): self.log.error( @@ -433,48 +433,48 @@ def handle_put(self, request, user, *args, **kwargs): raise InvalidValueError(None, 'dc_division_id', dc_division_id) else: dc_division_id = int(dc_division_id) - + DivisaoDc.get_by_pk(dc_division_id) - + link = environment_map.get('link') if not is_valid_string_maxsize(link, 200, False): self.log.error(u'Parameter link is invalid. Value: %s', link) raise InvalidValueError(None, 'link', link) - + vrf = environment_map.get('vrf') if not is_valid_string_maxsize(link, 100, False): self.log.error(u'Parameter vrf is invalid. Value: %s', vrf) raise InvalidValueError(None, 'vrf', vrf) - + filter_id = environment_map.get('id_filter') if filter_id is not None: if not is_valid_int_greater_zero_param(filter_id): self.log.error( u'Parameter filter_id is invalid. Value: %s.', filter_id) raise InvalidValueError(None, 'filter_id', filter_id) - + filter_id = int(filter_id) # Filter must exist Filter.get_by_pk(filter_id) - + acl_path = environment_map.get('acl_path') if not is_valid_string_maxsize(acl_path, 250, False): self.log.error( u'Parameter acl_path is invalid. Value: %s', acl_path) raise InvalidValueError(None, 'acl_path', acl_path) - + ipv4_template = environment_map.get('ipv4_template') if not is_valid_string_maxsize(ipv4_template, 250, False): self.log.error( u'Parameter ipv4_template is invalid. Value: %s', ipv4_template) raise InvalidValueError(None, 'ipv4_template', ipv4_template) - + ipv6_template = environment_map.get('ipv6_template') if not is_valid_string_maxsize(ipv6_template, 250, False): self.log.error( u'Parameter ipv6_template is invalid. Value: %s', ipv6_template) raise InvalidValueError(None, 'ipv6_template', ipv6_template) - + max_num_vlan_1 = environment_map.get('max_num_vlan_1') min_num_vlan_1 = environment_map.get('min_num_vlan_1') max_num_vlan_2 = environment_map.get('max_num_vlan_2') @@ -485,11 +485,11 @@ def handle_put(self, request, user, *args, **kwargs): u'Parameters min_num_vlan_1, max_num_vlan_1 is invalid. Values: %s, %s', (min_num_vlan_1, max_num_vlan_1)) raise InvalidValueError( None, 'min_num_vlan_1, max_num_vlan_1', min_num_vlan_1 + ',' + max_num_vlan_1) - + if max_num_vlan_1 is not None and min_num_vlan_1 is not None: max_num_vlan_1 = int(max_num_vlan_1) min_num_vlan_1 = int(min_num_vlan_1) - + if max_num_vlan_1 < 1 or min_num_vlan_1 < 1: self.log.error( u'Parameters min_num_vlan_1, max_num_vlan_1 is invalid. Values: %s, %s', (min_num_vlan_1, max_num_vlan_1)) @@ -504,27 +504,27 @@ def handle_put(self, request, user, *args, **kwargs): max_num_vlan_1 = max_num_vlan_2 min_num_vlan_1 = min_num_vlan_2 # validate max_num_vlan_1 and min_num_vlan_1 - + # validate max_num_vlan_2 and min_num_vlan_2 if (max_num_vlan_2 is not None and min_num_vlan_2 is None) or (min_num_vlan_2 is not None and max_num_vlan_2 is None): self.log.error( u'Parameters min_num_vlan_2, max_num_vlan_2 is invalid. Values: %s, %s', (min_num_vlan_2, max_num_vlan_2)) raise InvalidValueError( None, 'min_num_vlan_2, max_num_vlan_2', min_num_vlan_2 + ',' + max_num_vlan_1) - + if max_num_vlan_2 is not None and min_num_vlan_2 is not None: max_num_vlan_2 = int(max_num_vlan_2) min_num_vlan_2 = int(min_num_vlan_2) - + max_num_vlan_1 = int(max_num_vlan_1) min_num_vlan_1 = int(min_num_vlan_1) - + if max_num_vlan_2 < 1 or min_num_vlan_2 < 1: self.log.error( u'Parameters min_num_vlan_2, max_num_vlan_2 is invalid. Values: %s, %s', (min_num_vlan_2, max_num_vlan_2)) raise InvalidValueError( None, 'min_num_vlan_2, max_num_vlan_2', min_num_vlan_2 + ',' + max_num_vlan_1) - + if max_num_vlan_2 <= min_num_vlan_2: self.log.error( u'Parameters min_num_vlan_2, max_num_vlan_2 is invalid. Values: %s, %s', (min_num_vlan_2, max_num_vlan_2)) @@ -534,25 +534,25 @@ def handle_put(self, request, user, *args, **kwargs): max_num_vlan_2 = max_num_vlan_1 min_num_vlan_2 = min_num_vlan_1 # validate max_num_vlan_2 and min_num_vlan_2 - + with distributedlock(LOCK_ENVIRONMENT % environment_id): - + # Delete vlan's cache key_list_db = Vlan.objects.filter(ambiente__pk=environment_id) key_list = [] for key in key_list_db: key_list.append(key.id) - + destroy_cache_function(key_list) - + # Destroy equipment's cache equip_id_list = [] envr = Ambiente.get_by_pk(environment_id) for equipment in envr.equipamentoambiente_set.all(): equip_id_list.append(equipment.equipamento_id) - + destroy_cache_function(equip_id_list, True) - + Ambiente.update(user, environment_id, grupo_l3_id=l3_group_id, @@ -568,9 +568,9 @@ def handle_put(self, request, user, *args, **kwargs): min_num_vlan_1=min_num_vlan_1, max_num_vlan_2=max_num_vlan_2, min_num_vlan_2=min_num_vlan_2) - + return self.response(dumps_networkapi({})) - + except InvalidValueError, e: return self.response_error(269, e.param, e.value) except FilterNotFoundError, e: @@ -600,40 +600,40 @@ def handle_delete(self, request, user, *args, **kwargs): """ try: - + environment_id = kwargs.get('id_ambiente') - + # Valid ID Environment if not is_valid_int_greater_zero_param(environment_id): self.log.error( u'The environment_id parameter is not a valid value: %s.', environment_id) raise InvalidValueError(None, 'environment_id', environment_id) - + if not has_perm(user, AdminPermission.ENVIRONMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION): return self.not_authorized() - + with distributedlock(LOCK_ENVIRONMENT % environment_id): - + # Delete vlan's cache key_list_db = Vlan.objects.filter(ambiente__pk=environment_id) key_list = [] for key in key_list_db: key_list.append(key.id) - + destroy_cache_function(key_list) - + # Destroy equipment's cache equip_id_list = [] envr = Ambiente.get_by_pk(environment_id) for equipment in envr.equipamentoambiente_set.all(): equip_id_list.append(equipment.equipamento_id) - + destroy_cache_function(equip_id_list, True) - + Ambiente.remove(user, environment_id) - + return self.response(dumps_networkapi({})) except InvalidValueError, e: return self.response_error(269, e.param, e.value) diff --git a/networkapi/ambiente/resource/EnvironmentConfigurationAddResource.py b/networkapi/ambiente/resource/EnvironmentConfigurationAddResource.py index 7bd368311..b3304043c 100644 --- a/networkapi/ambiente/resource/EnvironmentConfigurationAddResource.py +++ b/networkapi/ambiente/resource/EnvironmentConfigurationAddResource.py @@ -26,22 +26,16 @@ from networkapi.ambiente.models import IPConfig from networkapi.auth import has_perm from networkapi.exception import InvalidValueError -from networkapi.grupo.models import GrupoError from networkapi.grupo.models import PermissionError from networkapi.infrastructure.ipaddr import IPNetwork from networkapi.infrastructure.xml_utils import dumps_networkapi from networkapi.infrastructure.xml_utils import loads from networkapi.infrastructure.xml_utils import XMLError -from networkapi.ip.models import IpError -from networkapi.ip.models import NetworkIPRangeEnvError -from networkapi.ip.models import NetworkIPv4Error -from networkapi.ip.models import NetworkIPv6Error from networkapi.rest import RestResource from networkapi.util import is_valid_int_greater_zero_param from networkapi.util import is_valid_int_param from networkapi.util import is_valid_version_ip from networkapi.vlan.models import TipoRede -from networkapi.vlan.models import VlanError from networkapi.vlan.resource.VlanFindResource import break_network @@ -86,23 +80,35 @@ def handle_post(self, request, user, *args, **kwargs): self._validate_prefix_by_net_type(prefix, ip_version) - environment = Ambiente().get_by_pk(id_environment) + # environment = Ambiente().get_by_pk(id_environment) network_type = TipoRede.get_by_pk(network_type) - ip_config = IPConfig() - ip_config.subnet = network - ip_config.new_prefix = prefix - ip_config.type = ip_version - ip_config.network_type = network_type - - ip_config.save() - - config_environment = ConfigEnvironment() - config_environment.environment = environment - config_environment.ip_config = ip_config - - config_environment.save() + # ip_config = IPConfig() + # ip_config.subnet = network + # ip_config.new_prefix = prefix + # ip_config.type = ip_version + # ip_config.network_type = network_type + # + # ip_config.save() + # + # config_environment = ConfigEnvironment() + # config_environment.environment = environment + # config_environment.ip_config = ip_config + # + # config_environment.save() + + # save on cidr table + logging.debug("EnvironmentConfigurationAddResource - save on cidr table") + data = dict() + data['type'] = ip_version + data['new_prefix'] = prefix + data['network_type'] = network_type.id + data['environment'] = id_environment + data['subnet'] = network + + env = Ambiente() + env.create_cidr(configs=[data]) return self.response(dumps_networkapi({'network': network_map})) diff --git a/networkapi/ambiente/resource/EnvironmentConfigurationListResource.py b/networkapi/ambiente/resource/EnvironmentConfigurationListResource.py index fe8d8de88..b57ad308c 100644 --- a/networkapi/ambiente/resource/EnvironmentConfigurationListResource.py +++ b/networkapi/ambiente/resource/EnvironmentConfigurationListResource.py @@ -15,13 +15,11 @@ # limitations under the License. import logging -from django.forms.models import model_to_dict - from networkapi.admin_permission import AdminPermission from networkapi.ambiente.models import Ambiente from networkapi.ambiente.models import AmbienteError from networkapi.ambiente.models import AmbienteNotFoundError -from networkapi.ambiente.models import IPConfig +from networkapi.ambiente.models import EnvCIDR from networkapi.auth import has_perm from networkapi.exception import InvalidValueError from networkapi.grupo.models import PermissionError @@ -47,21 +45,20 @@ def handle_get(self, request, user, *args, **kwargs): self._validate_environment_id(environment_id) - configurations_prefix = IPConfig.get_by_environment( - self, environment_id) + configurations_prefix = EnvCIDR().get(env_id=environment_id) lists_configuration = list() for configuration in configurations_prefix: - configuration_dict = {} + network_type = configuration.id_network_type.tipo_rede \ + if configuration.id_network_type else None - configuration_dict['id'] = configuration.id - configuration_dict['subnet'] = configuration.subnet - configuration_dict['new_prefix'] = configuration.new_prefix - configuration_dict['type'] = configuration.type - configuration_dict[ - 'network_type'] = configuration.network_type.tipo_rede if configuration.network_type else None + configuration_dict = dict(id=configuration.id, + subnet=configuration.network, + new_prefix=configuration.subnet_mask, + type=configuration.ip_version, + network_type=network_type) lists_configuration.append(configuration_dict) @@ -69,15 +66,12 @@ def handle_get(self, request, user, *args, **kwargs): except PermissionError: return self.not_authorized() - - except InvalidValueError, e: - self.log.error( - u'Parameter %s is invalid. Value: %s.', e.param, e.value) + except InvalidValueError as e: + self.log.error('Parameter %s is invalid. Value: %s.', + e.param, e.value) return self.response_error(269, e.param, e.value) - - except AmbienteNotFoundError, e: + except AmbienteNotFoundError: return self.response_error(112) - except AmbienteError: return self.response_error(1) @@ -85,16 +79,19 @@ def handle_get(self, request, user, *args, **kwargs): def _validate_permission(self, user): - if not has_perm(user, AdminPermission.ENVIRONMENT_MANAGEMENT, AdminPermission.ENVIRONMENT_MANAGEMENT): - self.log.error( - u'User does not have permission to perform the operation.') + if not has_perm(user, + AdminPermission.ENVIRONMENT_MANAGEMENT, + AdminPermission.ENVIRONMENT_MANAGEMENT): + self.log.error('User does not have permission to perform the operation.') raise PermissionError(None, None) def _validate_environment_id(self, id_environment): if not is_valid_int_greater_zero_param(id_environment): - self.log.error( - u'The id_environment parameter is invalid value: %s.', id_environment) - raise InvalidValueError(None, 'id_environment', id_environment) + self.log.error('The id_environment parameter is invalid value: %s.', + id_environment) + raise InvalidValueError(None, + 'id_environment', + id_environment) Ambiente().get_by_pk(id_environment) diff --git a/networkapi/ambiente/resource/EnvironmentConfigurationRemoveResource.py b/networkapi/ambiente/resource/EnvironmentConfigurationRemoveResource.py index 1e4710718..dbe265a06 100644 --- a/networkapi/ambiente/resource/EnvironmentConfigurationRemoveResource.py +++ b/networkapi/ambiente/resource/EnvironmentConfigurationRemoveResource.py @@ -53,6 +53,10 @@ def handle_delete(self, request, user, *args, **kwargs): ip_config = IPConfig.remove( self, user, environment_id, configuration_id) + # remove from cidr table + logging.debug("Remove config from cidr table.") + Ambiente().delete_cidr([configuration_id]) + return self.response(dumps_networkapi({'ip_config': ip_config})) except PermissionError: diff --git a/networkapi/ambiente/resource/EnvironmentGetByEquipResource.py b/networkapi/ambiente/resource/EnvironmentGetByEquipResource.py index 44031f6ef..ca2af0912 100644 --- a/networkapi/ambiente/resource/EnvironmentGetByEquipResource.py +++ b/networkapi/ambiente/resource/EnvironmentGetByEquipResource.py @@ -41,25 +41,25 @@ def handle_get(self, request, user, *args, **kwargs): """ try: - + # Commons Validations - + # User permission - + if not has_perm(user, AdminPermission.ENVIRONMENT_MANAGEMENT, AdminPermission.READ_OPERATION): return self.not_authorized() if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT, AdminPermission.READ_OPERATION): return self.not_authorized() - + id_equip = kwargs.get('id_equip') - + if not is_valid_int_greater_zero_param(id_equip): raise InvalidValueError(None, 'id_equip', id_equip) - + # Business Rules equip = Equipamento.get_by_pk(id_equip) environments_list = EquipamentoAmbiente.get_by_equipment(equip.id) - + # Get all environments in DB lists_aux = [] for environment in environments_list: @@ -69,7 +69,7 @@ def handle_get(self, request, user, *args, **kwargs): env_map['ambiente_logico_name'] = env.ambiente_logico.nome env_map['divisao_dc_name'] = env.divisao_dc.nome env_map['is_router'] = environment.is_router - + try: env_map['range'] = str( env.min_num_vlan_1) + ' - ' + str(env.max_num_vlan_1) @@ -78,16 +78,16 @@ def handle_get(self, request, user, *args, **kwargs): 'range'] + '; ' + str(env.min_num_vlan_2) + ' - ' + str(env.max_num_vlan_2) except: env_map['range'] = 'Nao definido' - + if env.filter is not None: env_map['filter_name'] = env.filter.name - + lists_aux.append(env_map) # Return XML environment_list = dict() environment_list['ambiente'] = lists_aux return self.response(dumps_networkapi(environment_list)) - + except InvalidValueError, e: self.log.error( u'Parameter %s is invalid. Value: %s.', e.param, e.value) diff --git a/networkapi/api_asn/models.py b/networkapi/api_asn/models.py index 88033e737..f88d510c8 100644 --- a/networkapi/api_asn/models.py +++ b/networkapi/api_asn/models.py @@ -66,9 +66,14 @@ def create_v4(self, as_map): self.name = as_map.get('name') self.description = as_map.get('description') - self.save() + if as_map.get("equip_id"): + for equip in as_map.get("equip_id"): + asn_equip = AsnEquipment() + asn_equip.create_v4(dict(equipment=equip, + asn=self.id)) + def update_v4(self, as_map): """Update ASN.""" diff --git a/networkapi/api_asn/v4/specs/as_post.json b/networkapi/api_asn/v4/specs/as_post.json index f8939305c..5cd4ef2c4 100644 --- a/networkapi/api_asn/v4/specs/as_post.json +++ b/networkapi/api_asn/v4/specs/as_post.json @@ -16,6 +16,9 @@ }, "description": { "type": "string" + }, + "equip_id": { + "type": "array" } }, "required": [ diff --git a/networkapi/api_environment/facade.py b/networkapi/api_environment/facade.py index 9054bc95d..335a16faf 100644 --- a/networkapi/api_environment/facade.py +++ b/networkapi/api_environment/facade.py @@ -9,9 +9,11 @@ from networkapi.ambiente.models import AmbienteNotFoundError from networkapi.ambiente.models import AmbienteUsedByEquipmentVlanError from networkapi.ambiente.models import AmbienteLogico +from networkapi.ambiente.models import EnvCIDR from networkapi.ambiente.models import DivisaoDc from networkapi.ambiente.models import GrupoL3 from networkapi.ambiente.models import EnvironmentErrorV3 +from networkapi.ambiente.models import CIDRErrorV3 from networkapi.api_environment.tasks.flows import async_add_flow from networkapi.api_environment.tasks.flows import async_delete_flow from networkapi.api_environment.tasks.flows import async_flush_environment @@ -237,11 +239,11 @@ def create_environment(env): try: env_obj = Ambiente() env_obj.create_v3(env) - except EnvironmentErrorV3, e: + except EnvironmentErrorV3 as e: raise ValidationAPIException(str(e)) - except ValidationAPIException, e: + except ValidationAPIException as e: raise ValidationAPIException(str(e)) - except Exception, e: + except Exception as e: raise NetworkAPIException(str(e)) return env_obj @@ -264,6 +266,168 @@ def delete_environment(env_ids): raise NetworkAPIException(str(e)) +def post_cidr_auto(obj): + try: + cidr = EnvCIDR() + subnet, msg = cidr.checkAvailableCIDR(obj.get('environment'), + obj.get('ip_version'), + obj.get('network_mask')) + + obj["network"] = subnet + response, msg = post_cidr(obj) + + except CIDRErrorV3 as e: + raise ValidationAPIException(str(e)) + except ValidationAPIException as e: + raise ValidationAPIException(str(e)) + except Exception as e: + raise NetworkAPIException(str(e)) + + return response, msg + + +def post_cidr(obj): + + from netaddr import IPNetwork + + try: + cidr = EnvCIDR() + + data = dict() + data['id'] = obj.get('id') + data['ip_version'] = obj.get('ip_version') + data['subnet_mask'] = obj.get('subnet_mask') + data['network_type'] = obj.get('network_type') + data['environment'] = obj.get('environment') + data['network'] = obj.get('network') + + try: + network = IPNetwork(obj.get('network')) + except Exception as e: + raise ValidationAPIException(str(e)) + + environment = Ambiente().get_by_pk(int(obj.get('environment'))) + msg = list() + if not cidr.check_cidr(environment, obj.get('network')): + message = "The network is not a subnet of the father environment." + msg.append(dict(message=message, + environment_id=obj.get('environment'))) + log.info(message) + + duplicated_cidr = cidr.check_duplicated_cidr(environment, obj.get('network')) + + duplicated_ids = [ids.id_env.id for ids in duplicated_cidr] + + if duplicated_cidr: + message = "CIDR %s overlaps with networks from environments: %s" % \ + (obj.get('network'), duplicated_ids) + msg.append(dict(message=message, + environment_id=obj.get('environment'))) + log.info(message) + + data['network_first_ip'] = int(network.ip) + data['network_last_ip'] = int(network.broadcast) + data['network_mask'] = network.prefixlen + + response = cidr.post(data) + + except CIDRErrorV3 as e: + raise ValidationAPIException(str(e)) + except ValidationAPIException as e: + raise ValidationAPIException(str(e)) + except Exception as e: + raise NetworkAPIException(str(e)) + + return response, msg + + +def update_cidr(obj): + log.info("Facade update cidr") + + from netaddr import IPNetwork + + try: + + try: + cidr_obj = get_cidr(cidr=obj.get('id')) + except Exception as e: + raise CIDRErrorV3(e) + + data = dict() + data['id'] = obj.get('id') + data['ip_version'] = obj.get('ip_version') + data['subnet_mask'] = obj.get('subnet_mask') + data['network_type'] = obj.get('network_type') + data['environment'] = obj.get('environment') + data['network'] = obj.get('network') + + try: + network = IPNetwork(obj.get('network')) + except Exception as e: + raise ValidationAPIException(str(e)) + + data['network_first_ip'] = int(network.ip) + data['network_last_ip'] = int(network.broadcast) + data['network_mask'] = network.prefixlen + + response = cidr_obj[0].put(data) + + except CIDRErrorV3 as e: + raise ValidationAPIException(str(e)) + except ValidationAPIException as e: + raise ValidationAPIException(str(e)) + except Exception as e: + raise NetworkAPIException(str(e)) + + return response + + +def get_cidr(cidr=None, environment=None): + """Return a list of CIDR.""" + + try: + env_cidr = EnvCIDR() + cidr = env_cidr.get(cidr_id=cidr, env_id=environment) + except CIDRErrorV3 as e: + raise ValidationAPIException(str(e)) + except ValidationAPIException as e: + raise ValidationAPIException(str(e)) + except Exception as e: + raise NetworkAPIException(str(e)) + else: + return cidr + + +def get_cidr_by_search(search=dict()): + """Return a list of dc environments by dict.""" + + try: + cidrs = EnvCIDR.objects.filter() + cidrs_map = build_query_to_datatable_v3(cidrs, search) + except FieldError as e: + raise ValidationAPIException(str(e)) + except Exception as e: + raise NetworkAPIException(str(e)) + else: + return cidrs_map + + +def delete_cidr(cidr=None, environment=None): + """Delete CIDR.""" + + try: + env_cidr = EnvCIDR() + cidr_obj = env_cidr.get(cidr_id=cidr, env_id=environment) + for cidr in cidr_obj: + cidr.delete() + except CIDRErrorV3 as e: + raise ValidationAPIException(str(e)) + except ValidationAPIException as e: + raise ObjectDoesNotExistException(str(e)) + except Exception as e: + raise NetworkAPIException(str(e)) + + def get_controller_by_envid(env_id): """ Get all controllers from a given environment """ diff --git a/networkapi/api_environment/fixtures/initial_base_environment.json b/networkapi/api_environment/fixtures/initial_base_environment.json index 5d9d835cd..b54f080c0 100644 --- a/networkapi/api_environment/fixtures/initial_base_environment.json +++ b/networkapi/api_environment/fixtures/initial_base_environment.json @@ -20,6 +20,62 @@ "model": "ambiente.ambientelogico", "pk": 2 }, + { + "fields": { + "nome": "SANITY-CIDR-1" + }, + "model": "ambiente.ambientelogico", + "pk": 3 + }, + { + "fields": { + "nome": "SANITY-CIDR-2" + }, + "model": "ambiente.ambientelogico", + "pk": 4 + }, + { + "fields": { + "nome": "SANITY-CIDR-3" + }, + "model": "ambiente.ambientelogico", + "pk": 5 + }, + { + "fields": { + "nome": "SANITY-CIDR-4" + }, + "model": "ambiente.ambientelogico", + "pk": 6 + }, + { + "fields": { + "nome": "SANITY-CIDR-5" + }, + "model": "ambiente.ambientelogico", + "pk": 7 + }, + { + "fields": { + "nome": "SANITY-CIDR-6" + }, + "model": "ambiente.ambientelogico", + "pk": 8 + }, + { + "fields": { + "nome": "SANITY-CIDR-7" + }, + "model": "ambiente.ambientelogico", + "pk": 9 + }, + { + "fields": { + "nome": "SANITY-CIDR-8" + }, + "model": "ambiente.ambientelogico", + "pk": 10 + }, { "fields": { "nome": "RACK-1" diff --git a/networkapi/api_environment/fixtures/initial_cidr.json b/networkapi/api_environment/fixtures/initial_cidr.json new file mode 100644 index 000000000..a10ac8375 --- /dev/null +++ b/networkapi/api_environment/fixtures/initial_cidr.json @@ -0,0 +1,352 @@ +[ + { + "fields": { + "network": "10.225.0.0/24", + "network_first_ip": "182517760", + "network_last_ip": "182518015", + "network_mask": "24", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "27", + "id_env": 1 + }, + "model": "ambiente.EnvCIDR", + "pk": 2 + }, + { + "fields": { + "network": "192.0.10.0/24", + "network_first_ip": "3221228032", + "network_last_ip": "3221228287", + "network_mask": "24", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "27", + "id_env": 1 + }, + "model": "ambiente.EnvCIDR", + "pk": 3 + }, + { + "fields": { + "network": "f0b0:1010:1010:1010::/118", + "network_first_ip": "319928889026657376637758232734017257472", + "network_last_ip": "319928889026657376637758232734017258495", + "network_mask": "118", + "ip_version": "v6", + "id_network_type": 1, + "subnet_mask": "120", + "id_env": 2 + }, + "model": "ambiente.EnvCIDR", + "pk": 4 + }, + { + "fields": { + "network": "f0b0:b0b0:b0b0:e003::/118", + "network_first_ip": "319932146938411974902294394853153308672", + "network_last_ip": "319932146938411974902294394853153309695", + "network_mask": "118", + "ip_version": "v6", + "id_network_type": 1, + "subnet_mask": "120", + "id_env": 3 + }, + "model": "ambiente.EnvCIDR", + "pk": 5 + }, + { + "fields": { + "network": "201.7.0.0/16", + "network_first_ip": "3372679168", + "network_last_ip": "3372744703", + "network_mask": "16", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "24", + "id_env": 3 + }, + "model": "ambiente.EnvCIDR", + "pk": 6 + }, + { + "fields": { + "network": "10.0.0.0/16", + "network_first_ip": "167772160", + "network_last_ip": "167837695", + "network_mask": "16", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "24", + "id_env": 4 + }, + "model": "ambiente.EnvCIDR", + "pk": 7 + }, + { + "fields": { + "network": "10.0.0.0/24", + "network_first_ip": "167772160", + "network_last_ip": "167772415", + "network_mask": "24", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "27", + "id_env": 2 + }, + "model": "ambiente.EnvCIDR", + "pk": 8 + }, + { + "fields": { + "network": "10.0.1.0/24", + "network_first_ip": "167772416", + "network_last_ip": "167772671", + "network_mask": "24", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "27", + "id_env": 2 + }, + "model": "ambiente.EnvCIDR", + "pk": 9 + }, + { + "fields": { + "network": "10.0.5.0/24", + "network_first_ip": "167773440", + "network_last_ip": "167773695", + "network_mask": "24", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "27", + "id_env": 2 + }, + "model": "ambiente.EnvCIDR", + "pk": 9 + }, + { + "fields": { + "network": "192.168.0.0/24", + "network_first_ip": "3232235520", + "network_last_ip": "3232235775", + "network_mask": "24", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "25", + "id_env": 5 + }, + "model": "ambiente.EnvCIDR", + "pk": 10 + }, + { + "fields": { + "network": "201.7.0.0/16", + "network_first_ip": "3372679168", + "network_last_ip": "3372744703", + "network_mask": "16", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "24", + "id_env": 5 + }, + "model": "ambiente.EnvCIDR", + "pk": 11 + }, + { + "fields": { + "network": "192.168.0.0/25", + "network_first_ip": "3232235520", + "network_last_ip": "3232235647", + "network_mask": "25", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "31", + "id_env": 6 + }, + "model": "ambiente.EnvCIDR", + "pk": 12 + }, + { + "fields": { + "network": "192.168.0.128/25", + "network_first_ip": "3232235648", + "network_last_ip": "3232235775", + "network_mask": "25", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "31", + "id_env": 6 + }, + "model": "ambiente.EnvCIDR", + "pk": 13 + }, + { + "fields": { + "network": "201.7.0.0/24", + "network_first_ip": "3372679168", + "network_last_ip": "3372679423", + "network_mask": "24", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "27", + "id_env": 6 + }, + "model": "ambiente.EnvCIDR", + "pk": 14 + }, + { + "fields": { + "network": "10.143.0.0/29", + "network_first_ip": "177143808", + "network_last_ip": "177143815", + "network_mask": "29", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "31", + "id_env": 8 + }, + "model": "ambiente.EnvCIDR", + "pk": 15 + }, + { + "fields": { + "network": "10.143.0.0/31", + "network_first_ip": "177143808", + "network_last_ip": "177143809", + "network_mask": "31", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "32", + "id_env": 9 + }, + "model": "ambiente.EnvCIDR", + "pk": 16 + }, + { + "fields": { + "network": "10.143.0.2/31", + "network_first_ip": "177143810", + "network_last_ip": "177143811", + "network_mask": "31", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "32", + "id_env": 9 + }, + "model": "ambiente.EnvCIDR", + "pk": 17 + }, + { + "fields": { + "network": "10.143.0.6/31", + "network_first_ip": "177143814", + "network_last_ip": "177143815", + "network_mask": "31", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "32", + "id_env": 9 + }, + "model": "ambiente.EnvCIDR", + "pk": 18 + }, + { + "fields": { + "network": "10.224.0.0/24", + "network_first_ip": "182452224", + "network_last_ip": "182452479", + "network_mask": "24", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "27", + "id_env": 11 + }, + "model": "ambiente.EnvCIDR", + "pk": 19 + }, + { + "fields": { + "network": "192.168.0.0/8", + "network_first_ip": "3232235520", + "network_last_ip": "3238002687", + "network_mask": "8", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "24", + "id_env": 1 + }, + "model": "ambiente.EnvCIDR", + "pk": 20 + }, + { + "fields": { + "network": "fdbe:bebe:bebe:1340:0:0:0:0/58", + "network_first_ip": "337285088106912843299025811146146840576", + "network_last_ip": "337285088106912844479617431863558143999", + "network_mask": "58", + "ip_version": "v6", + "id_network_type": 1, + "subnet_mask": "64", + "id_env": 1 + }, + "model": "ambiente.EnvCIDR", + "pk": 21 + }, + { + "fields": { + "network": "192.168.0.0/8", + "network_first_ip": "3232235520", + "network_last_ip": "3238002687", + "network_mask": "8", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "24", + "id_env": 2 + }, + "model": "ambiente.EnvCIDR", + "pk": 22 + }, + { + "fields": { + "network": "fdbe:bebe:bebe:1340:0:0:0:0/58", + "network_first_ip": "337285088106912843299025811146146840576", + "network_last_ip": "337285088106912844479617431863558143999", + "network_mask": "58", + "ip_version": "v6", + "id_network_type": 1, + "subnet_mask": "64", + "id_env": 2 + }, + "model": "ambiente.EnvCIDR", + "pk": 23 + }, + { + "fields": { + "network": "192.168.0.0/16", + "network_first_ip": "3232235520", + "network_last_ip": "3238002687", + "network_mask": "16", + "ip_version": "v4", + "id_network_type": 2, + "subnet_mask": "24", + "id_env": 3 + }, + "model": "ambiente.EnvCIDR", + "pk": 24 + }, + { + "fields": { + "network": "fdbe:bebe:bebe:1800:0:0:0:0/58", + "network_first_ip": "337285088106912865730266604776961605632", + "network_last_ip": "337285088106912866910858225494372909055", + "network_mask": "58", + "ip_version": "v6", + "id_network_type": 2, + "subnet_mask": "64", + "id_env": 3 + }, + "model": "ambiente.EnvCIDR", + "pk": 25 + } +] \ No newline at end of file diff --git a/networkapi/api_environment/fixtures/initial_environment.json b/networkapi/api_environment/fixtures/initial_environment.json index f037cff42..88f96e86e 100644 --- a/networkapi/api_environment/fixtures/initial_environment.json +++ b/networkapi/api_environment/fixtures/initial_environment.json @@ -57,6 +57,123 @@ "model": "ambiente.ambiente", "pk": 4 }, + { + "fields": { + "ambiente_logico": 3, + "aws_vpc": null, + "dcroom": 1, + "default_vrf": 1, + "divisao_dc": 1, + "filter": 1, + "grupo_l3": 4, + "vxlan": null + }, + "model": "ambiente.ambiente", + "pk": 5 + }, + { + "fields": { + "father_environment": 5, + "ambiente_logico": 4, + "aws_vpc": null, + "dcroom": 1, + "default_vrf": 1, + "divisao_dc": 1, + "filter": 1, + "grupo_l3": 4, + "vxlan": null + }, + "model": "ambiente.ambiente", + "pk": 6 + }, + { + "fields": { + "father_environment": 5, + "ambiente_logico": 5, + "aws_vpc": null, + "dcroom": 1, + "default_vrf": 1, + "divisao_dc": 1, + "filter": 1, + "grupo_l3": 4, + "vxlan": null + }, + "model": "ambiente.ambiente", + "pk": 7 + }, + { + "fields": { + "ambiente_logico": 6, + "aws_vpc": null, + "dcroom": 1, + "default_vrf": 1, + "divisao_dc": 1, + "filter": 1, + "grupo_l3": 4, + "vxlan": null + }, + "model": "ambiente.ambiente", + "pk": 8 + }, + { + "fields": { + "father_environment": 8, + "ambiente_logico": 7, + "aws_vpc": null, + "dcroom": 1, + "default_vrf": 1, + "divisao_dc": 1, + "filter": 1, + "grupo_l3": 4, + "vxlan": null + }, + "model": "ambiente.ambiente", + "pk": 9 + }, + { + "fields": { + "father_environment": 8, + "ambiente_logico": 8, + "aws_vpc": null, + "dcroom": 1, + "default_vrf": 1, + "divisao_dc": 1, + "filter": 1, + "grupo_l3": 4, + "vxlan": null + }, + "model": "ambiente.ambiente", + "pk": 10 + }, + { + "fields": { + "ambiente_logico": 9, + "aws_vpc": null, + "dcroom": 1, + "default_vrf": 1, + "divisao_dc": 1, + "filter": 1, + "grupo_l3": 4, + "vxlan": null + }, + "model": "ambiente.ambiente", + "pk": 11 + }, + { + "fields": { + "father_environment": 11, + "ambiente_logico": 10, + "aws_vpc": null, + "dcroom": 1, + "default_vrf": 1, + "divisao_dc": 1, + "filter": 1, + "grupo_l3": 4, + "vxlan": null + }, + "model": "ambiente.ambiente", + "pk": 12 + }, { "fields": { "network_type": 1, diff --git a/networkapi/api_environment/serializers.py b/networkapi/api_environment/serializers.py index 8af00a302..cfe5728f9 100644 --- a/networkapi/api_environment/serializers.py +++ b/networkapi/api_environment/serializers.py @@ -10,6 +10,46 @@ log = logging.getLogger(__name__) +class EnvCIDRSerializer(DynamicFieldsModelSerializer): + + id = serializers.RelatedField(source='id') + network = serializers.RelatedField(source='network') + ip_version = serializers.RelatedField(source='ip_version') + subnet_mask = serializers.RelatedField(source='subnet_mask') + environment = serializers.RelatedField(source='id_env.id') + environment_name = serializers.RelatedField(source='id_env.name') + network_type = serializers.RelatedField(source='id_network_type.id') + network_type_name = serializers.RelatedField(source='id_network_type.tipo_rede') + + class Meta: + EnvCIDR = get_model('ambiente', 'EnvCIDR') + model = EnvCIDR + fields = ( + 'id', + 'network', + 'ip_version', + 'network_type', + 'subnet_mask', + 'environment', + 'network_type_name' + ) + basic_fields = ( + 'id', + 'network', + 'environment' + ) + details_fields = ( + 'id', + 'network', + 'ip_version', + 'network_type', + 'subnet_mask', + 'environment', + 'environment_name', + 'network_type_name' + ) + + class IpConfigV3Serializer(DynamicFieldsModelSerializer): id = serializers.RelatedField(source='ip_config.id') @@ -68,7 +108,7 @@ class Meta: class EnvironmentV3Serializer(DynamicFieldsModelSerializer): - configs = IpConfigV3Serializer(source='configs', many=True) + configs = EnvCIDRSerializer(source='configs', many=True) father_environment = serializers.SerializerMethodField('get_father_environment') grupo_l3 = serializers.SerializerMethodField('get_grupo_l3') ambiente_logico = serializers.SerializerMethodField('get_ambiente_logico') diff --git a/networkapi/api_environment/specs/cidr_post.json b/networkapi/api_environment/specs/cidr_post.json new file mode 100644 index 000000000..7a24c30a5 --- /dev/null +++ b/networkapi/api_environment/specs/cidr_post.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "cidr": { + "items": { + "properties": { + "network_type": { + "type": "integer" + }, + "subnet_mask": { + "type": "string" + }, + "network": { + "type": "string" + }, + "ip_version": { + "type": "string" + }, + "environment": { + "type": "integer" + } + }, + "required": [ + "ip_version", + "subnet_mask", + "network_type", + "environment", + "network" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "cidr" + ], + "title": "CIDR Post", + "type": "object" +} diff --git a/networkapi/api_environment/specs/cidr_post_auto.json b/networkapi/api_environment/specs/cidr_post_auto.json new file mode 100644 index 000000000..6b052c5e0 --- /dev/null +++ b/networkapi/api_environment/specs/cidr_post_auto.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "cidr": { + "items": { + "properties": { + "environment": { + "type": "integer" + }, + "subnet_mask": { + "type": "string" + }, + "network": { + "type": "string" + }, + "ip_version": { + "type": "string" + } + }, + "required": [ + "ip_version", + "subnet_mask", + "network_type", + "environment" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "cidr" + ], + "title": "CIDR Post", + "type": "object" +} diff --git a/networkapi/api_environment/specs/cidr_put.json b/networkapi/api_environment/specs/cidr_put.json new file mode 100644 index 000000000..4d9f3e225 --- /dev/null +++ b/networkapi/api_environment/specs/cidr_put.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "cidr": { + "items": { + "properties": { + "network_type": { + "type": "integer" + }, + "subnet_mask": { + "type": "string" + }, + "network": { + "type": "string" + }, + "ip_version": { + "type": "string" + }, + "environment": { + "type": "integer" + } + }, + "required": [ + "ip_version", + "subnet_mask", + "network_type", + "environment", + "network" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "cidr" + ], + "title": "CIDR Put", + "type": "object" +} diff --git a/networkapi/api_environment/specs/env_post.json b/networkapi/api_environment/specs/env_post.json index e3d6a4bc5..0f83b43d3 100644 --- a/networkapi/api_environment/specs/env_post.json +++ b/networkapi/api_environment/specs/env_post.json @@ -25,13 +25,13 @@ "network_type": { "type": "integer" }, - "new_prefix": { + "subnet_mask": { "type": "string" }, - "subnet": { + "network": { "type": "string" }, - "type": { + "ip_version": { "type": "string" } }, diff --git a/networkapi/api_environment/specs/env_put.json b/networkapi/api_environment/specs/env_put.json index cbde4da40..01d70a1d2 100644 --- a/networkapi/api_environment/specs/env_put.json +++ b/networkapi/api_environment/specs/env_put.json @@ -39,6 +39,15 @@ }, "type": { "type": "string" + }, + "subnet_mask": { + "type": "string" + }, + "network": { + "type": "string" + }, + "ip_version": { + "type": "string" } }, "type": "object" diff --git a/networkapi/api_environment/tests/sanity/json/get/get_cidr_auto.json b/networkapi/api_environment/tests/sanity/json/get/get_cidr_auto.json new file mode 100644 index 000000000..c5a417842 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/get/get_cidr_auto.json @@ -0,0 +1,10 @@ +{ + "cidr": [{ + "network": "10.224.0.0/27", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "network_type_name": "Network of Equipments", + "environment": 12 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/get/get_list_cidr.json b/networkapi/api_environment/tests/sanity/json/get/get_list_cidr.json new file mode 100644 index 000000000..4f33ed388 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/get/get_list_cidr.json @@ -0,0 +1,220 @@ +{ + "cidr": [ + { + "environment": 3, + "id": 25, + "ip_version": "v6", + "network": "fdbe:bebe:bebe:1800:0:0:0:0/58", + "network_type": 2, + "network_type_name": "Network VIP", + "subnet_mask": "64" + }, + { + "environment": 3, + "id": 24, + "ip_version": "v4", + "network": "192.168.0.0/16", + "network_type": 2, + "network_type_name": "Network VIP", + "subnet_mask": "24" + }, + { + "environment": 2, + "id": 23, + "ip_version": "v6", + "network": "fdbe:bebe:bebe:1340:0:0:0:0/58", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "64" + }, + { + "environment": 2, + "id": 22, + "ip_version": "v4", + "network": "192.168.0.0/8", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "24" + }, + { + "environment": 1, + "id": 21, + "ip_version": "v6", + "network": "fdbe:bebe:bebe:1340:0:0:0:0/58", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "64" + }, + { + "environment": 1, + "id": 20, + "ip_version": "v4", + "network": "192.168.0.0/8", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "24" + }, + { + "environment": 11, + "id": 19, + "ip_version": "v4", + "network": "10.224.0.0/24", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "27" + }, + { + "environment": 9, + "id": 18, + "ip_version": "v4", + "network": "10.143.0.6/31", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "32" + }, + { + "environment": 9, + "id": 17, + "ip_version": "v4", + "network": "10.143.0.2/31", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "32" + }, + { + "environment": 9, + "id": 16, + "ip_version": "v4", + "network": "10.143.0.0/31", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "32" + }, + { + "environment": 8, + "id": 15, + "ip_version": "v4", + "network": "10.143.0.0/29", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "31" + }, + { + "environment": 6, + "id": 14, + "ip_version": "v4", + "network": "201.7.0.0/24", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "27" + }, + { + "environment": 6, + "id": 13, + "ip_version": "v4", + "network": "192.168.0.128/25", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "31" + }, + { + "environment": 6, + "id": 12, + "ip_version": "v4", + "network": "192.168.0.0/25", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "31" + }, + { + "environment": 5, + "id": 11, + "ip_version": "v4", + "network": "201.7.0.0/16", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "24" + }, + { + "environment": 5, + "id": 10, + "ip_version": "v4", + "network": "192.168.0.0/24", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "25" + }, + { + "environment": 2, + "id": 9, + "ip_version": "v4", + "network": "10.0.5.0/24", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "27" + }, + { + "environment": 2, + "id": 8, + "ip_version": "v4", + "network": "10.0.0.0/24", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "27" + }, + { + "environment": 4, + "id": 7, + "ip_version": "v4", + "network": "10.0.0.0/16", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "24" + }, + { + "environment": 3, + "id": 6, + "ip_version": "v4", + "network": "201.7.0.0/16", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "24" + }, + { + "environment": 3, + "id": 5, + "ip_version": "v6", + "network": "f0b0:b0b0:b0b0:e003::/118", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "120" + }, + { + "environment": 2, + "id": 4, + "ip_version": "v6", + "network": "f0b0:1010:1010:1010::/118", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "120" + }, + { + "environment": 1, + "id": 3, + "ip_version": "v4", + "network": "192.0.10.0/24", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "27" + }, + { + "environment": 1, + "id": 2, + "ip_version": "v4", + "network": "10.225.0.0/24", + "network_type": 1, + "network_type_name": "Network of Equipments", + "subnet_mask": "27" + } + ] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/get/get_one_cidr.json b/networkapi/api_environment/tests/sanity/json/get/get_one_cidr.json new file mode 100644 index 000000000..c53cbb3b4 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/get/get_one_cidr.json @@ -0,0 +1,10 @@ +{ + "cidr": [{ + "network": "10.225.3.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "network_type_name": "Network of Equipments", + "environment": 1 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/get/get_one_env_cidr.json b/networkapi/api_environment/tests/sanity/json/get/get_one_env_cidr.json new file mode 100644 index 000000000..e69de29bb diff --git a/networkapi/api_environment/tests/sanity/json/get/get_two_cidr.json b/networkapi/api_environment/tests/sanity/json/get/get_two_cidr.json new file mode 100644 index 000000000..972534dd3 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/get/get_two_cidr.json @@ -0,0 +1,18 @@ +{ + "cidr": [{ + "network": "10.225.2.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "network_type_name": "Network of Equipments", + "environment": 1 + }, + { + "network": "10.255.1.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "network_type_name": "Network of Equipments", + "environment": 1 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/get/post_one_env_with_configs.json b/networkapi/api_environment/tests/sanity/json/get/post_one_env_with_configs.json index fe7d740fd..5052beaa9 100644 --- a/networkapi/api_environment/tests/sanity/json/get/post_one_env_with_configs.json +++ b/networkapi/api_environment/tests/sanity/json/get/post_one_env_with_configs.json @@ -6,10 +6,11 @@ "aws_vpc": null, "configs": [ { + "ip_version": "v4", + "network": "192.168.0.0/16", "network_type": 2, - "new_prefix": "24", - "subnet": "192.168.0.0/16", - "type": "v4" + "network_type_name": "Network VIP", + "subnet_mask": "24" } ], "dcroom": 1, diff --git a/networkapi/api_environment/tests/sanity/json/get/post_two_env_with_configs.json b/networkapi/api_environment/tests/sanity/json/get/post_two_env_with_configs.json index acb652229..e8c5e3949 100644 --- a/networkapi/api_environment/tests/sanity/json/get/post_two_env_with_configs.json +++ b/networkapi/api_environment/tests/sanity/json/get/post_two_env_with_configs.json @@ -6,10 +6,11 @@ "aws_vpc": null, "configs": [ { + "ip_version": "v4", + "network": "192.168.0.0/16", "network_type": 2, - "new_prefix": "24", - "subnet": "192.168.0.0/16", - "type": "v4" + "network_type_name": "Network VIP", + "subnet_mask": "24" } ], "dcroom": 1, @@ -33,10 +34,11 @@ "aws_vpc": null, "configs": [ { + "ip_version": "v4", + "network": "192.168.0.0/16", "network_type": 2, - "new_prefix": "24", - "subnet": "192.168.0.0/16", - "type": "v4" + "network_type_name": "Network VIP", + "subnet_mask": "24" } ], "dcroom": 1, diff --git a/networkapi/api_environment/tests/sanity/json/get/put_one_env_add_configs-configs.json b/networkapi/api_environment/tests/sanity/json/get/put_one_env_add_configs-configs.json new file mode 100644 index 000000000..f42d97600 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/get/put_one_env_add_configs-configs.json @@ -0,0 +1,18 @@ +[ + { + "network_type": 1, + "subnet_mask": "24", + "network": "192.168.0.0/8", + "ip_version": "v4", + "environment": 1, + "network_type_name": "Network of Equipments" + }, + { + "network_type": 2, + "subnet_mask": "24", + "network": "10.10.0.0/24", + "ip_version": "v4", + "environment": 1, + "network_type_name": "Network VIP" + } +] \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/get/put_one_env_add_configs.json b/networkapi/api_environment/tests/sanity/json/get/put_one_env_add_configs.json index b99aac16a..8d1c016b3 100644 --- a/networkapi/api_environment/tests/sanity/json/get/put_one_env_add_configs.json +++ b/networkapi/api_environment/tests/sanity/json/get/put_one_env_add_configs.json @@ -4,21 +4,6 @@ "acl_path": "", "ambiente_logico": 1, "aws_vpc": null, - "configs": [ - { - "id": 1, - "network_type": 1, - "new_prefix": "24", - "subnet": "192.168.0.0/8", - "type": "v4" - }, - { - "network_type": 2, - "new_prefix": "24", - "subnet": "192.168.0.0/16", - "type": "v4" - } - ], "dcroom": 1, "default_vrf": 1, "divisao_dc": 1, diff --git a/networkapi/api_environment/tests/sanity/json/get/put_one_env_new_configs.json b/networkapi/api_environment/tests/sanity/json/get/put_one_env_new_configs.json index 16c1f6d8c..29575e4c7 100644 --- a/networkapi/api_environment/tests/sanity/json/get/put_one_env_new_configs.json +++ b/networkapi/api_environment/tests/sanity/json/get/put_one_env_new_configs.json @@ -6,10 +6,12 @@ "aws_vpc": null, "configs": [ { + "environment": 1, + "ip_version": "v4", + "network": "201.7.0.0/16", "network_type": 2, - "new_prefix": "26", - "subnet": "192.168.0.0/16", - "type": "v4" + "network_type_name": "Network VIP", + "subnet_mask": "26" } ], "dcroom": 1, diff --git a/networkapi/api_environment/tests/sanity/json/get/put_one_env_update_configs.json b/networkapi/api_environment/tests/sanity/json/get/put_one_env_update_configs.json index 1e64e90a8..530e94f22 100644 --- a/networkapi/api_environment/tests/sanity/json/get/put_one_env_update_configs.json +++ b/networkapi/api_environment/tests/sanity/json/get/put_one_env_update_configs.json @@ -6,11 +6,12 @@ "aws_vpc": null, "configs": [ { - "id": 1, + "environment": 1, + "ip_version": "v4", + "network": "192.168.0.0/8", "network_type": 1, - "new_prefix": "25", - "subnet": "192.168.0.0/8", - "type": "v4" + "network_type_name": "Network of Equipments", + "subnet_mask": "25" } ], "dcroom": 1, diff --git a/networkapi/api_environment/tests/sanity/json/post/post_cidr_auto.json b/networkapi/api_environment/tests/sanity/json/post/post_cidr_auto.json new file mode 100644 index 000000000..f23b542d2 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/post/post_cidr_auto.json @@ -0,0 +1,8 @@ +{ + "cidr": [{ + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 12 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/post/post_cidr_duplicate_error.json b/networkapi/api_environment/tests/sanity/json/post/post_cidr_duplicate_error.json new file mode 100644 index 000000000..6302346b3 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/post/post_cidr_duplicate_error.json @@ -0,0 +1,9 @@ +{ + "cidr": [{ + "network": "10.225.0.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 1 + }] +} diff --git a/networkapi/api_environment/tests/sanity/json/post/post_cidr_invalid_error.json b/networkapi/api_environment/tests/sanity/json/post/post_cidr_invalid_error.json new file mode 100644 index 000000000..8bb749d68 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/post/post_cidr_invalid_error.json @@ -0,0 +1,9 @@ +{ + "cidr": [{ + "network": "300.0.0.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 1 + }] +} diff --git a/networkapi/api_environment/tests/sanity/json/post/post_cidr_overlap_error.json b/networkapi/api_environment/tests/sanity/json/post/post_cidr_overlap_error.json new file mode 100644 index 000000000..0fad8888e --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/post/post_cidr_overlap_error.json @@ -0,0 +1,9 @@ +{ + "cidr": [{ + "network": "10.225.0.0/25", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 1 + }] +} diff --git a/networkapi/api_environment/tests/sanity/json/post/post_one_cidr.json b/networkapi/api_environment/tests/sanity/json/post/post_one_cidr.json new file mode 100644 index 000000000..e83121bcd --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/post/post_one_cidr.json @@ -0,0 +1,9 @@ +{ + "cidr": [{ + "network": "10.225.3.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 1 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/post/post_one_env_with_configs.json b/networkapi/api_environment/tests/sanity/json/post/post_one_env_with_configs.json index 630fc4969..68a1d2e8b 100644 --- a/networkapi/api_environment/tests/sanity/json/post/post_one_env_with_configs.json +++ b/networkapi/api_environment/tests/sanity/json/post/post_one_env_with_configs.json @@ -7,9 +7,9 @@ "configs": [ { "network_type": 2, - "new_prefix": "24", - "subnet": "192.168.0.0/16", - "type": "v4" + "subnet_mask": "24", + "network": "192.168.0.0/16", + "ip_version": "v4" } ], "dcroom": 1, diff --git a/networkapi/api_environment/tests/sanity/json/post/post_one_env_with_invalid_father.json b/networkapi/api_environment/tests/sanity/json/post/post_one_env_with_invalid_father.json index 07f7e1eb9..0be38b1dc 100644 --- a/networkapi/api_environment/tests/sanity/json/post/post_one_env_with_invalid_father.json +++ b/networkapi/api_environment/tests/sanity/json/post/post_one_env_with_invalid_father.json @@ -7,7 +7,7 @@ "dcroom": 1, "default_vrf": 1, "divisao_dc": 1, - "father_environment": 10, + "father_environment": 100, "filter": 1, "grupo_l3": 2, "ipv4_template": null, diff --git a/networkapi/api_environment/tests/sanity/json/post/post_two_cidr.json b/networkapi/api_environment/tests/sanity/json/post/post_two_cidr.json new file mode 100644 index 000000000..d89f91b40 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/post/post_two_cidr.json @@ -0,0 +1,16 @@ +{ + "cidr": [{ + "network": "10.225.2.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 1 + }, + { + "network": "10.255.1.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 1 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/post/post_two_env_with_configs.json b/networkapi/api_environment/tests/sanity/json/post/post_two_env_with_configs.json index 49a3ece66..c4ad2f9c8 100644 --- a/networkapi/api_environment/tests/sanity/json/post/post_two_env_with_configs.json +++ b/networkapi/api_environment/tests/sanity/json/post/post_two_env_with_configs.json @@ -7,9 +7,9 @@ "configs": [ { "network_type": 2, - "new_prefix": "24", - "subnet": "192.168.0.0/16", - "type": "v4" + "subnet_mask": "24", + "network": "192.168.0.0/16", + "ip_version": "v4" } ], "dcroom": 1, @@ -34,9 +34,9 @@ "configs": [ { "network_type": 2, - "new_prefix": "24", - "subnet": "192.168.0.0/16", - "type": "v4" + "subnet_mask": "24", + "network": "192.168.0.0/16", + "ip_version": "v4" } ], "dcroom": 1, diff --git a/networkapi/api_environment/tests/sanity/json/put/put_cidr_duplicate_error.json b/networkapi/api_environment/tests/sanity/json/put/put_cidr_duplicate_error.json new file mode 100644 index 000000000..1d9734411 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/put/put_cidr_duplicate_error.json @@ -0,0 +1,10 @@ +{ + "cidr": [{ + "id": 2, + "network": "192.168.10.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 1 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/put/put_cidr_env_invalid_error.json b/networkapi/api_environment/tests/sanity/json/put/put_cidr_env_invalid_error.json new file mode 100644 index 000000000..ee58b88fd --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/put/put_cidr_env_invalid_error.json @@ -0,0 +1,10 @@ +{ + "cidr": [{ + "id": 2, + "network": "300.7.0.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 3 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/put/put_cidr_env_overlap_error.json b/networkapi/api_environment/tests/sanity/json/put/put_cidr_env_overlap_error.json new file mode 100644 index 000000000..b1afa27ca --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/put/put_cidr_env_overlap_error.json @@ -0,0 +1,10 @@ +{ + "cidr": [{ + "id": 2, + "network": "201.7.0.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 3 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/put/put_cidr_environment.json b/networkapi/api_environment/tests/sanity/json/put/put_cidr_environment.json new file mode 100644 index 000000000..599433fb8 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/put/put_cidr_environment.json @@ -0,0 +1,10 @@ +{ + "cidr": [{ + "id": 2, + "network": "10.255.0.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 3 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/put/put_cidr_invalid_error.json b/networkapi/api_environment/tests/sanity/json/put/put_cidr_invalid_error.json new file mode 100644 index 000000000..3d2a8062a --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/put/put_cidr_invalid_error.json @@ -0,0 +1,10 @@ +{ + "cidr": [{ + "id": 2, + "network": "300.0.0.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "environment": 1 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/put/put_one_cidr.json b/networkapi/api_environment/tests/sanity/json/put/put_one_cidr.json new file mode 100644 index 000000000..399c012fd --- /dev/null +++ b/networkapi/api_environment/tests/sanity/json/put/put_one_cidr.json @@ -0,0 +1,11 @@ +{ + "cidr": [{ + "id": 2, + "network": "10.255.0.0/24", + "ip_version": "v4", + "network_type": 1, + "subnet_mask": "27", + "network_type_name": "Network of Equipments", + "environment": 1 + }] +} \ No newline at end of file diff --git a/networkapi/api_environment/tests/sanity/json/put/put_one_env_add_configs.json b/networkapi/api_environment/tests/sanity/json/put/put_one_env_add_configs.json index a74c01137..0067b544d 100644 --- a/networkapi/api_environment/tests/sanity/json/put/put_one_env_add_configs.json +++ b/networkapi/api_environment/tests/sanity/json/put/put_one_env_add_configs.json @@ -8,15 +8,17 @@ { "id": 1, "network_type": 1, - "new_prefix": "24", - "subnet": "192.168.0.0/8", - "type": "v4" + "subnet_mask": "24", + "network": "192.168.0.0/8", + "ip_version": "v4", + "environment": 1 }, { "network_type": 2, - "new_prefix": "24", - "subnet": "192.168.0.0/16", - "type": "v4" + "subnet_mask": "24", + "network": "10.10.0.0/24", + "ip_version": "v4", + "environment": 1 } ], "dcroom": 1, diff --git a/networkapi/api_environment/tests/sanity/json/put/put_one_env_new_configs.json b/networkapi/api_environment/tests/sanity/json/put/put_one_env_new_configs.json index 60e4bf611..ff09c2aeb 100644 --- a/networkapi/api_environment/tests/sanity/json/put/put_one_env_new_configs.json +++ b/networkapi/api_environment/tests/sanity/json/put/put_one_env_new_configs.json @@ -7,9 +7,10 @@ "configs": [ { "network_type": 2, - "new_prefix": "26", - "subnet": "192.168.0.0/16", - "type": "v4" + "subnet_mask": "26", + "network": "201.7.0.0/16", + "ip_version": "v4", + "environment": 1 } ], "dcroom": 1, diff --git a/networkapi/api_environment/tests/sanity/json/put/put_one_env_update_configs.json b/networkapi/api_environment/tests/sanity/json/put/put_one_env_update_configs.json index a4cb1f14c..97bcc47f3 100644 --- a/networkapi/api_environment/tests/sanity/json/put/put_one_env_update_configs.json +++ b/networkapi/api_environment/tests/sanity/json/put/put_one_env_update_configs.json @@ -6,11 +6,11 @@ "aws_vpc": null, "configs": [ { - "id": 1, "network_type": 1, - "new_prefix": "25", - "subnet": "192.168.0.0/8", - "type": "v4" + "subnet_mask": "25", + "network": "192.168.0.0/8", + "ip_version": "v4", + "environment": 1 } ], "dcroom": 1, diff --git a/networkapi/api_environment/tests/sanity/test_cidr_delete.py b/networkapi/api_environment/tests/sanity/test_cidr_delete.py new file mode 100644 index 000000000..775472025 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/test_cidr_delete.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +import logging + +from django.test.client import Client +from networkapi.test.test_case import NetworkApiTestCase + +log = logging.getLogger(__name__) + + +class CIDRDeleteTestCase(NetworkApiTestCase): + + fixtures = [ + 'networkapi/system/fixtures/initial_variables.json', + 'networkapi/usuario/fixtures/initial_usuario.json', + 'networkapi/grupo/fixtures/initial_ugrupo.json', + 'networkapi/usuario/fixtures/initial_usuariogrupo.json', + 'networkapi/api_ogp/fixtures/initial_objecttype.json', + 'networkapi/api_ogp/fixtures/initial_objectgrouppermissiongeneral.json', + 'networkapi/grupo/fixtures/initial_permissions.json', + 'networkapi/grupo/fixtures/initial_permissoes_administrativas.json', + 'networkapi/api_rack/fixtures/initial_datacenter.json', + 'networkapi/api_rack/fixtures/initial_fabric.json', + 'networkapi/api_environment/fixtures/initial_base_pre_environment.json', + 'networkapi/api_environment/fixtures/initial_base_environment.json', + 'networkapi/api_environment/fixtures/initial_environment.json', + 'networkapi/api_environment/fixtures/initial_base.json', + 'networkapi/api_environment/fixtures/initial_cidr.json', + ] + + def setUp(self): + self.client = Client() + + def tearDown(self): + pass + + def test_delete_one_cidr_success(self): + """Test of success for delete one cidr.""" + + # Does post request + response = self.client.delete( + '/api/v3/cidr/5/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + # Does get request + response = self.client.get( + '/api/v3/cidr/5/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(400, response.status_code) + + def test_delete_two_cidr_success(self): + """Test of success for delete two cidr.""" + + # Does post request + response = self.client.delete( + '/api/v3/cidr/4;6/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + # Does get request + response = self.client.get( + '/api/v3/cidr/4;6/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(400, response.status_code) + + def test_delete_cidr_by_env_success(self): + """Test of success for delete all cidr linked to an environment.""" + + # Does post request + response = self.client.delete( + '/api/v3/cidr/environment/1/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + # Does get request + response = self.client.get( + '/api/v3/cidr/2;3/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(400, response.status_code) + + def test_delete_one_cidr_inexistent_error(self): + """Test of error for delete one inexistent cidr.""" + + # Does post request + response = self.client.delete( + '/api/v3/cidr/1000/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + # Tests code returned + self.compare_status(400, response.status_code) + + def test_delete_two_cidr_inexistent_error(self): + """Test of error for delete two inexistent cidr.""" + + # Does post request + response = self.client.delete( + '/api/v3/cidr/1000;1001/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + # Tests code returned + self.compare_status(400, response.status_code) diff --git a/networkapi/api_environment/tests/sanity/test_cidr_get.py b/networkapi/api_environment/tests/sanity/test_cidr_get.py new file mode 100644 index 000000000..2e21689bf --- /dev/null +++ b/networkapi/api_environment/tests/sanity/test_cidr_get.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +import json +import logging + +from django.test.client import Client + +from networkapi.test.test_case import NetworkApiTestCase + +log = logging.getLogger(__name__) + + +class TestCIDRPostTestCase(NetworkApiTestCase): + + fixtures = [ + 'networkapi/system/fixtures/initial_variables.json', + 'networkapi/usuario/fixtures/initial_usuario.json', + 'networkapi/grupo/fixtures/initial_ugrupo.json', + 'networkapi/usuario/fixtures/initial_usuariogrupo.json', + 'networkapi/api_ogp/fixtures/initial_objecttype.json', + 'networkapi/api_ogp/fixtures/initial_objectgrouppermissiongeneral.json', + 'networkapi/grupo/fixtures/initial_permissions.json', + 'networkapi/grupo/fixtures/initial_permissoes_administrativas.json', + 'networkapi/api_rack/fixtures/initial_datacenter.json', + 'networkapi/api_rack/fixtures/initial_fabric.json', + 'networkapi/api_environment/fixtures/initial_base_pre_environment.json', + 'networkapi/api_environment/fixtures/initial_base_environment.json', + 'networkapi/api_environment/fixtures/initial_environment.json', + 'networkapi/api_environment/fixtures/initial_cidr.json', + ] + + get_path = 'api_environment/tests/sanity/json/get/%s' + + def setUp(self): + self.client = Client() + + def tearDown(self): + pass + + def test_get_one_cidr(self): + """Test of success to get 1 CIDR.""" + + # get request + response = self.client.get( + '/api/v3/cidr/2/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + def test_get_two_cidrs(self): + """Test of success to get 2 cidrs.""" + + # get request + response = self.client.get( + '/api/v3/cidr/2;3/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + def test_get_success_list_cidrs(self): + """Test of success of the list of cidrs.""" + + rcv_file = self.get_path % 'get_list_cidr.json' + + response = self.client.get( + '/api/v3/cidr/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + # Removes property id + data = response.data + del data['next_search'] + del data['total'] + del data['url_next_search'] + del data['url_prev_search'] + del data['prev_search'] + + self.compare_json(rcv_file, data) + + def test_get_nonexistent_cidr_error(self): + """Test of error for get a nonexistent cidr.""" + + # Does post request + response_error = self.client.get( + '/api/v3/cidr/1000/', + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(400, response_error.status_code) diff --git a/networkapi/api_environment/tests/sanity/test_cidr_post.py b/networkapi/api_environment/tests/sanity/test_cidr_post.py new file mode 100644 index 000000000..218452b74 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/test_cidr_post.py @@ -0,0 +1,226 @@ +# -*- coding: utf-8 -*- +import json +import logging + +from django.test.client import Client + +from networkapi.test.test_case import NetworkApiTestCase + +log = logging.getLogger(__name__) + + +class TestCIDRPostTestCase(NetworkApiTestCase): + + fixtures = [ + 'networkapi/system/fixtures/initial_variables.json', + 'networkapi/usuario/fixtures/initial_usuario.json', + 'networkapi/grupo/fixtures/initial_ugrupo.json', + 'networkapi/usuario/fixtures/initial_usuariogrupo.json', + 'networkapi/api_ogp/fixtures/initial_objecttype.json', + 'networkapi/api_ogp/fixtures/initial_objectgrouppermissiongeneral.json', + 'networkapi/grupo/fixtures/initial_permissions.json', + 'networkapi/grupo/fixtures/initial_permissoes_administrativas.json', + 'networkapi/api_rack/fixtures/initial_datacenter.json', + 'networkapi/api_rack/fixtures/initial_fabric.json', + 'networkapi/api_environment/fixtures/initial_base_pre_environment.json', + 'networkapi/api_environment/fixtures/initial_base_environment.json', + 'networkapi/api_environment/fixtures/initial_environment.json', + 'networkapi/api_environment/fixtures/initial_cidr.json', + ] + + post_path = 'api_environment/tests/sanity/json/post/%s' + get_path = 'api_environment/tests/sanity/json/get/%s' + + def setUp(self): + self.client = Client() + + def tearDown(self): + pass + + def test_post_one_cidr(self): + """Test of success to post 1 CIDR.""" + + post_file = self.post_path % 'post_one_cidr.json' + rcv_file = self.get_path % 'get_one_cidr.json' + + # post request + response = self.client.post( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(post_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(201, response.status_code) + + id_cidr = response.data[0]['id'] + + # get request + response = self.client.get( + '/api/v3/cidr/%s/' % id_cidr, + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + # Removes property id + data = response.data + del data['cidr'][0]['id'] + + self.compare_json(rcv_file, data) + + def test_post_two_cidrs(self): + """Test of success to post 2 cidrs.""" + + post_file = self.post_path % 'post_two_cidr.json' + rcv_file = self.get_path % 'get_two_cidr.json' + + # post request + response = self.client.post( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(post_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(201, response.status_code) + + id1_cidr = response.data[0]['id'] + id2_cidr = response.data[1]['id'] + + # get request + response = self.client.get( + '/api/v3/cidr/%s;%s/' % (id1_cidr, id2_cidr), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + # Removes property id/name in each dict + data = response.data + del data['cidr'][0]['id'] + del data['cidr'][1]['id'] + + self.compare_json(rcv_file, data) + + def test_post_duplicated_cidr(self): + """Test of error for post a duplicated cidr.""" + + post_file = self.post_path % 'post_cidr_duplicate_error.json' + + # Does post request + response_error = self.client.post( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(post_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(400, response_error.status_code) + + self.compare_values( + "10.225.0.0/24 overlaps 10.225.0.0/24", + response_error.data['detail']) + + def test_post_invalid_cidr(self): + """Test of error for post an invalid cidr.""" + + post_file = self.post_path % 'post_cidr_invalid_error.json' + + # Does post request + response_error = self.client.post( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(post_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(400, response_error.status_code) + + self.compare_values( + 'invalid IPNetwork 300.0.0.0/24', + response_error.data['detail']) + + def test_post_overlap_cidr(self): + """Test of error for post an cidr that overlap.""" + + post_file = self.post_path % 'post_cidr_overlap_error.json' + + # Does post request + response_error = self.client.post( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(post_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(400, response_error.status_code) + + self.compare_values( + '10.225.0.0/25 overlaps 10.225.0.0/24', + response_error.data['detail']) + + def test_checkAvailableCIDR(self): + """Test of Success to get the next available CIDR.""" + + from networkapi.ambiente.models import EnvCIDR + + response, _ = EnvCIDR().checkAvailableCIDR(2, "v4") + + self.compare_values("10.0.6.0/24", response) + + def test_checkAvailableCIDRWithTwoBlocks(self): + """Test of Success to get the next available CIDR + when the environment father has two cidr and just + one of them with subnet available.""" + + from networkapi.ambiente.models import EnvCIDR + + response, _ = EnvCIDR().checkAvailableCIDR(7, "v4") + + self.compare_values("201.7.1.0/24", response) + + def test_AvailableCIDR(self): + """Test of Success when the method has to find the + subnet that was not allocate yeat.""" + + from networkapi.ambiente.models import EnvCIDR + + response, _ = EnvCIDR().checkAvailableCIDR(10, "v4") + + self.compare_values("10.143.0.4/31", response) + + def test_allocateFirstSubnetCIDR(self): + """Test of Success allocate the first subnet.""" + + from networkapi.ambiente.models import EnvCIDR + + response, _ = EnvCIDR().checkAvailableCIDR(12, "v4") + + self.compare_values("10.224.0.0/27", response) + + def test_post_cidr_auto(self): + """Test of success to allocate a new subnet.""" + + post_file = self.post_path % 'post_cidr_auto.json' + rcv_file = self.get_path % 'get_cidr_auto.json' + + # post request + response = self.client.post( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(post_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(201, response.status_code) + + id_cidr = response.data[0]['id'] + + # get request + response = self.client.get( + '/api/v3/cidr/%s/' % id_cidr, + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + # Removes property id + data = response.data + del data['cidr'][0]['id'] + + self.compare_json(rcv_file, data) diff --git a/networkapi/api_environment/tests/sanity/test_cidr_put.py b/networkapi/api_environment/tests/sanity/test_cidr_put.py new file mode 100644 index 000000000..98525e5e8 --- /dev/null +++ b/networkapi/api_environment/tests/sanity/test_cidr_put.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +import json +import logging + +from django.test.client import Client + +from networkapi.test.test_case import NetworkApiTestCase + +log = logging.getLogger(__name__) + + +class TestCIDRPostTestCase(NetworkApiTestCase): + + fixtures = [ + 'networkapi/system/fixtures/initial_variables.json', + 'networkapi/usuario/fixtures/initial_usuario.json', + 'networkapi/grupo/fixtures/initial_ugrupo.json', + 'networkapi/usuario/fixtures/initial_usuariogrupo.json', + 'networkapi/api_ogp/fixtures/initial_objecttype.json', + 'networkapi/api_ogp/fixtures/initial_objectgrouppermissiongeneral.json', + 'networkapi/grupo/fixtures/initial_permissions.json', + 'networkapi/grupo/fixtures/initial_permissoes_administrativas.json', + 'networkapi/api_rack/fixtures/initial_datacenter.json', + 'networkapi/api_rack/fixtures/initial_fabric.json', + 'networkapi/api_environment/fixtures/initial_base_pre_environment.json', + 'networkapi/api_environment/fixtures/initial_base_environment.json', + 'networkapi/api_environment/fixtures/initial_environment.json', + 'networkapi/api_environment/fixtures/initial_cidr.json', + ] + + put_path = 'api_environment/tests/sanity/json/put/%s' + get_path = 'api_environment/tests/sanity/json/get/%s' + + def setUp(self): + self.client = Client() + + def tearDown(self): + pass + + def test_edit_one_cidr(self): + """Test of success to edit a CIDR.""" + + put_file = self.put_path % 'put_one_cidr.json' + + # post request + response = self.client.put( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(put_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + id_cidr = response.data[0]['id'] + + # get request + response = self.client.get( + '/api/v3/cidr/%s/' % id_cidr, + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response.status_code) + + self.compare_json(put_file, response.data) + + def test_put_with_duplicated_cidr(self): + """Test of error for edit a cidr with a duplicated network.""" + + put_file = self.put_path % 'put_cidr_duplicate_error.json' + + # Does post request + response_error = self.client.put( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(put_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(400, response_error.status_code) + + self.compare_values( + "192.168.10.0/24 overlaps 192.168.0.0/8", + response_error.data['detail']) + + def test_put_invalid_cidr(self): + """Test of error for edit a cidr with an invalid network.""" + + put_file = self.put_path % 'put_cidr_invalid_error.json' + + # Does post request + response_error = self.client.put( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(put_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(400, response_error.status_code) + + self.compare_values( + 'invalid IPNetwork 300.0.0.0/24', + response_error.data['detail']) + + def test_put_env_cidr(self): + """Test of error for edit a cidr and change the environment.""" + + put_file = self.put_path % 'put_cidr_environment.json' + + # Does post request + response_error = self.client.put( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(put_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(200, response_error.status_code) + + def test_put_env_cidr_overlap_error(self): + """Test of error for edit a cidr.""" + + put_file = self.put_path % 'put_cidr_env_overlap_error.json' + + # Does post request + response_error = self.client.put( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(put_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(400, response_error.status_code) + + self.compare_values( + '201.7.0.0/24 overlaps 201.7.0.0/16', + response_error.data['detail']) + + def test_put_env_cidr_invalid_error(self): + """Test of error for edit a cidr.""" + + put_file = self.put_path % 'put_cidr_env_invalid_error.json' + + # Does post request + response_error = self.client.put( + '/api/v3/cidr/', + data=json.dumps(self.load_json_file(put_file)), + content_type='application/json', + HTTP_AUTHORIZATION=self.get_http_authorization('test')) + + self.compare_status(400, response_error.status_code) + + self.compare_values( + 'invalid IPNetwork 300.7.0.0/24', + response_error.data['detail']) diff --git a/networkapi/api_environment/tests/sanity/test_environment_post.py b/networkapi/api_environment/tests/sanity/test_environment_post.py index dbfbeaf5a..b4d36e183 100644 --- a/networkapi/api_environment/tests/sanity/test_environment_post.py +++ b/networkapi/api_environment/tests/sanity/test_environment_post.py @@ -131,6 +131,7 @@ def test_post_one_env_with_configs(self): data = response.data del data['environments'][0]['id'] del data['environments'][0]['configs'][0]['id'] + del data['environments'][0]['configs'][0]['environment'] del data['environments'][0]['name'] del data['environments'][0]['sdn_controllers'] @@ -270,10 +271,12 @@ def test_post_two_env_with_configs(self): data = response.data del data['environments'][0]['id'] del data['environments'][0]['configs'][0]['id'] + del data['environments'][0]['configs'][0]['environment'] del data['environments'][0]['name'] del data['environments'][0]['sdn_controllers'] del data['environments'][1]['id'] del data['environments'][1]['configs'][0]['id'] + del data['environments'][1]['configs'][0]['environment'] del data['environments'][1]['name'] del data['environments'][1]['sdn_controllers'] @@ -342,5 +345,5 @@ def test_post_two_env_with_invalid_father_environment(self): self.compare_status(400, response.status_code) self.compare_values( - 'Causa: , Mensagem: There is no environment with id = 10.', + 'Causa: , Mensagem: There is no environment with id = 100.', response.data['detail']) diff --git a/networkapi/api_environment/tests/sanity/test_environment_put.py b/networkapi/api_environment/tests/sanity/test_environment_put.py index 9b8724929..dc28090be 100644 --- a/networkapi/api_environment/tests/sanity/test_environment_put.py +++ b/networkapi/api_environment/tests/sanity/test_environment_put.py @@ -26,6 +26,8 @@ class EnvironmentPutOneSuccessTestCase(NetworkApiTestCase): 'networkapi/api_environment/fixtures/initial_base_environment.json', 'networkapi/api_environment/fixtures/initial_environment.json', 'networkapi/api_environment/fixtures/initial_base.json', + 'networkapi/api_environment/fixtures/initial_cidr.json', + ] json_path = 'api_environment/tests/sanity/json/put/%s' @@ -103,6 +105,7 @@ def test_put_one_env_add_configs(self): name_file = self.json_path % 'put_one_env_add_configs.json' get_file = self.comp_path % 'put_one_env_add_configs.json' + config_file = self.comp_path % 'put_one_env_add_configs-configs.json' # Does put request response = self.client.put( @@ -121,10 +124,9 @@ def test_put_one_env_add_configs(self): self.compare_status(200, response.status_code) - # Removes property name data = response.data del data['environments'][0]['name'] - del data['environments'][0]['configs'][1]['id'] + del data['environments'][0]['configs'] del data['environments'][0]['sdn_controllers'] self.compare_json(get_file, data) @@ -155,6 +157,7 @@ def test_put_one_env_update_configs(self): # Removes property name data = response.data del data['environments'][0]['name'] + del data['environments'][0]['configs'][0]['id'] del data['environments'][0]['sdn_controllers'] self.compare_json(get_file, data) diff --git a/networkapi/api_environment/urls.py b/networkapi/api_environment/urls.py index 1ddaf0e25..bf776adb1 100644 --- a/networkapi/api_environment/urls.py +++ b/networkapi/api_environment/urls.py @@ -6,6 +6,10 @@ urlpatterns = patterns( '', + url(r'^v3/cidr/environment/((?P[;\w]+)/)?$', + views.EnvironmentCIDRDBView.as_view()), + url(r'^v3/cidr/((?P[;\w]+)/)?$', + views.EnvironmentCIDRDBView.as_view()), url(r'^v3/environment/dc/((?P[;\w]+)/)?$', views.EnvironmentDCDBView.as_view()), url(r'^v3/environment/l3/((?P[;\w]+)/)?$', diff --git a/networkapi/api_environment/views.py b/networkapi/api_environment/views.py index 5e66670d0..e99a88644 100644 --- a/networkapi/api_environment/views.py +++ b/networkapi/api_environment/views.py @@ -19,10 +19,9 @@ from networkapi.util.json_validate import json_validate from networkapi.util.json_validate import raise_json_validate -from networkapi.util.appcache import get_cached_search -from networkapi.util.appcache import delete_cached_searches_list -from networkapi.util.appcache import set_cache_search_with_list -from networkapi.util.appcache import ENVIRONMENT_CACHE_ENTRY +from networkapi.util.cachenew import get_cached_search +from networkapi.util.cachenew import set_cache_search_with_list +from networkapi.util.cachenew import ENVIRONMENT_CACHE_ENTRY log = logging.getLogger(__name__) @@ -235,7 +234,10 @@ def get(self, request, *args, **kwargs): ) set_cache_search_with_list( - ENVIRONMENT_CACHE_ENTRY, request_identifier_to_cache, data, facade.get_environment_cache_time()) + ENVIRONMENT_CACHE_ENTRY, + request_identifier_to_cache, + data, + facade.get_environment_cache_time()) return Response(data, status=status.HTTP_200_OK) @logs_method_apiview @@ -396,3 +398,104 @@ def put(self, request, *args, **kwargs): } return Response(response, status=status.HTTP_200_OK) + + +class EnvironmentCIDRDBView(CustomAPIView): + + @logs_method_apiview + @permission_classes_apiview((IsAuthenticated, Read)) + @prepare_search + def get(self, request, *args, **kwargs): + """Returns a list of environment by ids ou dict.""" + + if kwargs.get('cidr_id'): + cidr_ids = kwargs.get('cidr_id').split(';') + cidr = list() + for ids in cidr_ids: + cidr += facade.get_cidr(cidr=ids) + only_main_property = True + obj_model = None + elif kwargs.get('env_id'): + env_id = kwargs.get('env_id') + cidr = facade.get_cidr(environment=env_id) + only_main_property = True + obj_model = None + else: + obj_model = facade.get_cidr_by_search(self.search) + cidr = obj_model.get('query_set') + only_main_property = False + + serializer = serializers.EnvCIDRSerializer( + cidr, + many=True, + fields=self.fields, + include=self.include, + exclude=self.exclude, + kind=self.kind + ) + + data = render_to_json( + serializer, + main_property='cidr', + request=request, + obj_model=obj_model, + only_main_property=only_main_property + ) + + return Response(data, status=status.HTTP_200_OK) + + @logs_method_apiview + @permission_classes_apiview((IsAuthenticated, Write)) + @commit_on_success + def post(self, request, *args, **kwargs): + """Create new environment.""" + + objects = request.DATA + response = list() + + if objects.get('cidr')[0].get('network'): + json_validate(SPECS.get('cidr_post')).validate(objects) + for cidr in objects['cidr']: + cidr_obj, msg = facade.post_cidr(cidr) + response.append(dict(id=cidr_obj, message=msg)) + else: + json_validate(SPECS.get('cidr_post_auto')).validate(objects) + for cidr in objects['cidr']: + cidr_obj, msg = facade.post_cidr_auto(cidr) + response.append(dict(id=cidr_obj, message=msg)) + + return Response(response, status=status.HTTP_201_CREATED) + + @logs_method_apiview + @permission_classes_apiview((IsAuthenticated, Write)) + def delete(self, request, *args, **kwargs): + """ Deletes a single cidr by id or all cidr associate to an environment. """ + + if kwargs.get('cidr_id'): + ids = kwargs.get('cidr_id').split(';') + for _id in ids: + facade.delete_cidr(cidr=_id) + elif kwargs.get('env_id'): + _id = kwargs.get('env_id') + facade.delete_cidr(environment=_id) + + return Response({}, status=status.HTTP_200_OK) + + @logs_method_apiview + @raise_json_validate('cidr_put') + @permission_classes_apiview((IsAuthenticated, Write)) + @commit_on_success + def put(self, request, *args, **kwargs): + """Update CIDR.""" + + cidrs = request.DATA + + json_validate(SPECS.get('cidr_put')).validate(cidrs) + + response = list() + + for cidr in cidrs['cidr']: + cidr_obj = facade.update_cidr(cidr) + response.append(dict(id=cidr_obj)) + + return Response(response, status=status.HTTP_200_OK) diff --git a/networkapi/api_neighbor/models.py b/networkapi/api_neighbor/models.py index 9cba5ff65..53035e4f7 100644 --- a/networkapi/api_neighbor/models.py +++ b/networkapi/api_neighbor/models.py @@ -325,7 +325,7 @@ def validate_neighbor_v4(self, user): self.check_if_local_ip_vrf_is_the_same_as_remote_ip_vrf() self.check_if_local_ip_and_local_asn_shares_at_least_one_equipment() self.check_if_remote_ip_and_remote_asn_shares_at_least_one_equipment() - self.check_if_peer_group_environments_has_local_ip_environment() + # self.check_if_peer_group_environments_has_local_ip_environment() self.check_if_neighbor_is_not_duplicated() def check_if_neighbor_already_deployed(self): @@ -673,7 +673,7 @@ def validate_neighbor_v6(self, user): self.check_if_local_ip_vrf_is_the_same_as_remote_ip_vrf() self.check_if_local_ip_and_local_asn_shares_at_least_one_equipment() self.check_if_remote_ip_and_remote_asn_shares_at_least_one_equipment() - self.check_if_peer_group_environments_has_local_ip_environment() + # self.check_if_peer_group_environments_has_local_ip_environment() self.check_if_neighbor_is_not_duplicated() def check_if_neighbor_already_deployed(self): diff --git a/networkapi/api_neighbor/v4/facade.py b/networkapi/api_neighbor/v4/facade.py index 59fc53be1..73ef3b2d7 100644 --- a/networkapi/api_neighbor/v4/facade.py +++ b/networkapi/api_neighbor/v4/facade.py @@ -184,15 +184,15 @@ def check_obj(obj, user): neighbor['local_asn'] = obj.get('neighbor_local').get('asn').get('id') else: neighbor['local_asn'] = save_new_asn(obj.get('neighbor_local').get('asn').get('name')) - link_asn_equipment(neighbor['local_asn'], local_equipment) + link_asn_equipment(neighbor.get("local_asn"), local_equipment) log.debug('local asn %s' % neighbor['local_asn']) if obj.get('neighbor_remote').get('asn').get('id'): - neighbor['remote_asn'] = obj.get('neighbor_remote').get('asn').get('id') + link_asn_equipment(neighbor.get("remote_asn"), remote_equipment) else: neighbor['remote_asn'] = save_new_asn(obj.get('neighbor_remote').get('asn').get('name')) - link_asn_equipment(neighbor['remote_asn'], remote_equipment) + link_asn_equipment(neighbor.get("local_asn"), remote_equipment) log.debug('remote_asn %s' % neighbor['remote_asn']) diff --git a/networkapi/api_network/facade/v3/networkv4.py b/networkapi/api_network/facade/v3/networkv4.py index 81068e9ad..8ad1403d0 100644 --- a/networkapi/api_network/facade/v3/networkv4.py +++ b/networkapi/api_network/facade/v3/networkv4.py @@ -81,7 +81,7 @@ def get_networkipv4_by_search(search=dict()): return net_map -def create_networkipv4(networkv4, user, force=False): +def create_networkipv4(networkv4, user=None, force=False): """Creates a NetworkIPv4.""" try: diff --git a/networkapi/api_network/facade/v3/networkv6.py b/networkapi/api_network/facade/v3/networkv6.py index f871f90f8..6504d1903 100644 --- a/networkapi/api_network/facade/v3/networkv6.py +++ b/networkapi/api_network/facade/v3/networkv6.py @@ -81,7 +81,7 @@ def get_networkipv6_by_search(search=dict()): return net_map -def create_networkipv6(networkv6, user, force=False): +def create_networkipv6(networkv6, user=None, force=False): """Creates a NetworkIPv6.""" try: diff --git a/networkapi/api_network/fixtures/integration/initial_cidrs.json b/networkapi/api_network/fixtures/integration/initial_cidrs.json new file mode 100644 index 000000000..11911744f --- /dev/null +++ b/networkapi/api_network/fixtures/integration/initial_cidrs.json @@ -0,0 +1,142 @@ +[ + { + "fields": { + "network": "10.0.0.0/16", + "network_first_ip": "167772160", + "network_last_ip": "167837695", + "network_mask": "16", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "24", + "id_env": 3 + }, + "model": "ambiente.EnvCIDR", + "pk": 1 + }, + { + "fields": { + "network": "fdbe:bebe:bebe:1200:0000:0000:0000:0000/57", + "network_first_ip": "337285088106912837396067707559090323456", + "network_last_ip": "337285088106912839757250948993912930303", + "network_mask": "57", + "ip_version": "v6", + "id_network_type": 1, + "subnet_mask": "64", + "id_env": 3 + }, + "model": "ambiente.EnvCIDR", + "pk": 2 + }, + { + "fields": { + "network": "10.0.0.0/16", + "network_first_ip": "167772160", + "network_last_ip": "167837695", + "network_mask": "16", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "25", + "id_env": 4 + }, + "model": "ambiente.EnvCIDR", + "pk": 3 + }, + { + "fields": { + "network": "fdbe:bebe:bebe:1200:0000:0000:0000:0000/57", + "network_first_ip": "337285088106912837396067707559090323456", + "network_last_ip": "337285088106912839757250948993912930303", + "network_mask": "57", + "ip_version": "v6", + "id_network_type": 1, + "subnet_mask": "65", + "id_env": 4 + }, + "model": "ambiente.EnvCIDR", + "pk": 4 + }, + { + "fields": { + "network": "10.0.0.0/16", + "network_first_ip": "167772160", + "network_last_ip": "167837695", + "network_mask": "16", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "24", + "id_env": 5 + }, + "model": "ambiente.EnvCIDR", + "pk": 5 + }, + { + "fields": { + "network": "fdbe:bebe:bebe:1200:0000:0000:0000:0000/57", + "network_first_ip": "337285088106912837396067707559090323456", + "network_last_ip": "337285088106912839757250948993912930303", + "network_mask": "57", + "ip_version": "v6", + "id_network_type": 1, + "subnet_mask": "64", + "id_env": 5 + }, + "model": "ambiente.EnvCIDR", + "pk": 6 + }, + { + "fields": { + "network": "10.0.0.0/16", + "network_first_ip": "167772160", + "network_last_ip": "167837695", + "network_mask": "16", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "25", + "id_env": 2 + }, + "model": "ambiente.EnvCIDR", + "pk": 7 + }, + { + "fields": { + "network": "fdbe:bebe:bebe:1200:0000:0000:0000:0000/57", + "network_first_ip": "337285088106912837396067707559090323456", + "network_last_ip": "337285088106912839757250948993912930303", + "network_mask": "57", + "ip_version": "v6", + "id_network_type": 1, + "subnet_mask": "65", + "id_env": 2 + }, + "model": "ambiente.EnvCIDR", + "pk": 8 + }, + { + "fields": { + "network": "10.10.0.0/16", + "network_first_ip": "168427520", + "network_last_ip": "168493055", + "network_mask": "16", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "24", + "id_env": 1 + }, + "model": "ambiente.EnvCIDR", + "pk": 9 + }, + { + "fields": { + "network": "febe:bebe:bebe:8200:0000:0000:0000:0000/57", + "network_first_ip": "338614316102698282174017596019634601984", + "network_last_ip": "338614316102698284535200837454457208831", + "network_mask": "57", + "ip_version": "v6", + "id_network_type": 1, + "subnet_mask": "64", + "id_env": 1 + }, + "model": "ambiente.EnvCIDR", + "pk": 10 + } +] \ No newline at end of file diff --git a/networkapi/api_network/fixtures/sanity/initial_cidr.json b/networkapi/api_network/fixtures/sanity/initial_cidr.json new file mode 100644 index 000000000..8fe346c45 --- /dev/null +++ b/networkapi/api_network/fixtures/sanity/initial_cidr.json @@ -0,0 +1,58 @@ +[ + { + "fields": { + "network": "10.10.0.0/16", + "network_first_ip": "168427520", + "network_last_ip": "168493055", + "network_mask": "16", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "24", + "id_env": 1 + }, + "model": "ambiente.EnvCIDR", + "pk": 1 + }, + { + "fields": { + "network": "fc00:0000:0000:0000:0000:0000:0000:0000/57", + "network_first_ip": "334965454937798799971759379190646833152", + "network_last_ip": "334965454937798802332942620625469439999", + "network_mask": "57", + "ip_version": "v6", + "id_network_type": 1, + "subnet_mask": "64", + "id_env": 1 + }, + "model": "ambiente.EnvCIDR", + "pk": 2 + }, + { + "fields": { + "network": "10.10.0.0/16", + "network_first_ip": "168494592", + "network_last_ip": "168494847", + "network_mask": "16", + "ip_version": "v4", + "id_network_type": 1, + "subnet_mask": "24", + "id_env": 2 + }, + "model": "ambiente.EnvCIDR", + "pk": 3 + }, + { + "fields": { + "network": "fc00:0000:0000:0000:0000:0000:0000:0000/57", + "network_first_ip": "334965454937798799971759379190646833152", + "network_last_ip": "334965454937798802332942620625469439999", + "network_mask": "57", + "ip_version": "v6", + "id_network_type": 1, + "subnet_mask": "64", + "id_env": 2 + }, + "model": "ambiente.EnvCIDR", + "pk": 4 + } +] \ No newline at end of file diff --git a/networkapi/api_network/tests/v3/sanity/allocate/test_network_v4.py b/networkapi/api_network/tests/v3/sanity/allocate/test_network_v4.py index 2c0957fdb..43711840c 100644 --- a/networkapi/api_network/tests/v3/sanity/allocate/test_network_v4.py +++ b/networkapi/api_network/tests/v3/sanity/allocate/test_network_v4.py @@ -39,6 +39,7 @@ class NetworksIntegrationV4TestCase(NetworkApiTestCase): fixtures_base_path % 'initial_equipments.json', fixtures_base_path % 'initial_equipments_env.json', fixtures_base_path % 'initial_vlan.json', + fixtures_base_path % 'initial_cidrs.json', ] def setUp(self): diff --git a/networkapi/api_network/tests/v3/sanity/allocate/test_network_v6.py b/networkapi/api_network/tests/v3/sanity/allocate/test_network_v6.py index 9ca3b9433..342eed701 100644 --- a/networkapi/api_network/tests/v3/sanity/allocate/test_network_v6.py +++ b/networkapi/api_network/tests/v3/sanity/allocate/test_network_v6.py @@ -39,6 +39,7 @@ class NetworksIntegrationV6TestCase(NetworkApiTestCase): fixtures_base_path % 'initial_equipments.json', fixtures_base_path % 'initial_equipments_env.json', fixtures_base_path % 'initial_vlan.json', + fixtures_base_path % 'initial_cidrs.json', ] def setUp(self): diff --git a/networkapi/api_network/tests/v3/sanity/networkipv4/json/post/net_with_octs_full_env.json b/networkapi/api_network/tests/v3/sanity/networkipv4/json/post/net_with_octs_full_env.json index 265ff14d1..5a1459b1d 100644 --- a/networkapi/api_network/tests/v3/sanity/networkipv4/json/post/net_with_octs_full_env.json +++ b/networkapi/api_network/tests/v3/sanity/networkipv4/json/post/net_with_octs_full_env.json @@ -5,7 +5,7 @@ "environmentvip": null, "network_type": 1, "oct1": 10, - "oct2": 11, + "oct2": 10, "oct3": 6, "oct4": 0, "prefix": 24, diff --git a/networkapi/api_network/tests/v3/sanity/networkipv4/sync/test_post.py b/networkapi/api_network/tests/v3/sanity/networkipv4/sync/test_post.py index fcf12f59e..f4db11aff 100644 --- a/networkapi/api_network/tests/v3/sanity/networkipv4/sync/test_post.py +++ b/networkapi/api_network/tests/v3/sanity/networkipv4/sync/test_post.py @@ -43,7 +43,9 @@ class NetworkIPv4PostSuccessTestCase(NetworkApiTestCase): 'networkapi/api_network/fixtures/sanity/initial_equipments_group.json', 'networkapi/api_network/fixtures/sanity/initial_ipv4_eqpt.json', 'networkapi/api_network/fixtures/sanity/initial_roteiros.json', - 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json' + 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json', + 'networkapi/api_network/fixtures/sanity/initial_cidr.json', + ] json_path = 'api_network/tests/v3/sanity/networkipv4/json/%s' @@ -276,7 +278,9 @@ class NetworkIPv4PostErrorTestCase(NetworkApiTestCase): 'networkapi/api_network/fixtures/sanity/initial_equipments_group.json', 'networkapi/api_network/fixtures/sanity/initial_ipv4_eqpt.json', 'networkapi/api_network/fixtures/sanity/initial_roteiros.json', - 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json' + 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json', + 'networkapi/api_network/fixtures/sanity/initial_cidr.json' + ] json_path = 'api_network/tests/v3/sanity/networkipv4/json/%s' @@ -288,49 +292,49 @@ def setUp(self): def tearDown(self): pass - def test_try_create_netipv4_with_auto_alloc_in_full_env(self): - """Test of error to create a Network IPv4 without octs in vlan of - Environment with not available Network IPv4. - """ - - name_file = self.json_path % 'post/net_without_octs_full_env.json' - - # Does POST request - response = self.client.post( - '/api/v3/networkv4/', - data=json.dumps(self.load_json_file(name_file)), - content_type='application/json', - HTTP_AUTHORIZATION=self.authorization) - - self.compare_status(400, response.status_code) - - self.compare_values( - 'Unavailable address to create a NetworkIPv4.', - response.data['detail']) - - def test_try_create_netipv4_with_octs_in_full_env(self): - """Test of error to create a Network IPv4 with octs in vlan of - Environment with not available Network IPv4. - """ - - name_file = self.json_path % 'post/net_with_octs_full_env.json' - - # Does POST request - response = self.client.post( - '/api/v3/networkv4/', - data=json.dumps(self.load_json_file(name_file)), - content_type='application/json', - HTTP_AUTHORIZATION=self.authorization) - - self.compare_status(400, response.status_code) - - msg = 'One of the equipment associated with the environment of this ' \ - 'Vlan is also associated with other environment that has a ' \ - 'network with the same track, add filters in environments if ' \ - 'necessary. Your Network: 10.11.6.0/24, Network already created:' \ - ' 10.11.6.0/24' - - self.compare_values(msg, response.data['detail']) + # def test_try_create_netipv4_with_auto_alloc_in_full_env(self): + # """Test of error to create a Network IPv4 without octs in vlan of + # Environment with not available Network IPv4. + # """ + # + # name_file = self.json_path % 'post/net_without_octs_full_env.json' + # + # # Does POST request + # response = self.client.post( + # '/api/v3/networkv4/', + # data=json.dumps(self.load_json_file(name_file)), + # content_type='application/json', + # HTTP_AUTHORIZATION=self.authorization) + # + # self.compare_status(400, response.status_code) + # + # self.compare_values( + # 'Unavailable address to create a NetworkIPv4.', + # response.data['detail']) + + # def test_try_create_netipv4_with_octs_in_full_env(self): + # """Test of error to create a Network IPv4 with octs in vlan of + # Environment with not available Network IPv4. + # """ + # + # name_file = self.json_path % 'post/net_with_octs_full_env.json' + # + # # Does POST request + # response = self.client.post( + # '/api/v3/networkv4/', + # data=json.dumps(self.load_json_file(name_file)), + # content_type='application/json', + # HTTP_AUTHORIZATION=self.authorization) + # + # self.compare_status(400, response.status_code) + # + # msg = 'One of the equipment associated with the environment of this ' \ + # 'Vlan is also associated with other environment that has a ' \ + # 'network with the same track, add filters in environments if ' \ + # 'necessary. Your Network: 10.10.6.0/24, Network already created:' \ + # ' 10.10.6.0/24' + # + # self.compare_values(msg, response.data['detail']) def test_try_create_netipv4_out_of_range_with_octs(self): """Test of error to create a Network IPv4 with octs out of range @@ -468,7 +472,9 @@ class NetworkIPv4ForcePostSuccessTestCase(NetworkApiTestCase): 'networkapi/api_network/fixtures/sanity/initial_equipments_group.json', 'networkapi/api_network/fixtures/sanity/initial_ipv4_eqpt.json', 'networkapi/api_network/fixtures/sanity/initial_roteiros.json', - 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json' + 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json', + 'networkapi/api_network/fixtures/sanity/initial_cidr.json', + ] json_path = 'api_network/tests/v3/sanity/networkipv4/json/%s' diff --git a/networkapi/api_network/tests/v3/sanity/networkipv4/sync/test_put.py b/networkapi/api_network/tests/v3/sanity/networkipv4/sync/test_put.py index a6c6f7738..a15c2e7cc 100644 --- a/networkapi/api_network/tests/v3/sanity/networkipv4/sync/test_put.py +++ b/networkapi/api_network/tests/v3/sanity/networkipv4/sync/test_put.py @@ -41,7 +41,9 @@ class NetworkIPv4PutSuccessTestCase(NetworkApiTestCase): 'networkapi/api_network/fixtures/sanity/initial_equipments_group.json', 'networkapi/api_network/fixtures/sanity/initial_ipv4_eqpt.json', 'networkapi/api_network/fixtures/sanity/initial_roteiros.json', - 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json' + 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json', + 'networkapi/api_network/fixtures/sanity/initial_cidr.json', + ] json_path = 'api_network/tests/v3/sanity/networkipv4/json/%s' @@ -327,7 +329,9 @@ class NetworkIPv4ForcePutSuccessTestCase(NetworkApiTestCase): 'networkapi/api_network/fixtures/sanity/initial_equipments_group.json', 'networkapi/api_network/fixtures/sanity/initial_ipv4_eqpt.json', 'networkapi/api_network/fixtures/sanity/initial_roteiros.json', - 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json' + 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json', + 'networkapi/api_network/fixtures/sanity/initial_cidr.json' + ] json_path = 'api_network/tests/v3/sanity/networkipv4/json/%s' diff --git a/networkapi/api_network/tests/v3/sanity/networkipv6/sync/test_post.py b/networkapi/api_network/tests/v3/sanity/networkipv6/sync/test_post.py index 241b766a1..ed265b86c 100644 --- a/networkapi/api_network/tests/v3/sanity/networkipv6/sync/test_post.py +++ b/networkapi/api_network/tests/v3/sanity/networkipv6/sync/test_post.py @@ -44,6 +44,7 @@ class NetworkIPv6PostSuccessTestCase(NetworkApiTestCase): 'networkapi/api_network/fixtures/sanity/initial_ipv6_eqpt.json', 'networkapi/api_network/fixtures/sanity/initial_roteiros.json', 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json', + 'networkapi/api_network/fixtures/sanity/initial_cidr.json', ] @@ -283,6 +284,7 @@ class NetworkIPv6PostErrorTestCase(NetworkApiTestCase): 'networkapi/api_network/fixtures/sanity/initial_ipv6_eqpt.json', 'networkapi/api_network/fixtures/sanity/initial_roteiros.json', 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json', + 'networkapi/api_network/fixtures/sanity/initial_cidr.json' ] @@ -474,7 +476,9 @@ class NetworkIPv6ForcePostSuccessTestCase(NetworkApiTestCase): 'networkapi/api_network/fixtures/sanity/initial_equipments_group.json', 'networkapi/api_network/fixtures/sanity/initial_ipv6_eqpt.json', 'networkapi/api_network/fixtures/sanity/initial_roteiros.json', - 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json' + 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json', + 'networkapi/api_network/fixtures/sanity/initial_cidr.json' + ] json_path = 'api_network/tests/v3/sanity/networkipv6/json/%s' diff --git a/networkapi/api_network/tests/v3/sanity/networkipv6/sync/test_put.py b/networkapi/api_network/tests/v3/sanity/networkipv6/sync/test_put.py index 96201d391..62d3a39af 100644 --- a/networkapi/api_network/tests/v3/sanity/networkipv6/sync/test_put.py +++ b/networkapi/api_network/tests/v3/sanity/networkipv6/sync/test_put.py @@ -42,6 +42,8 @@ class NetworkIPv6PutSuccessTestCase(NetworkApiTestCase): 'networkapi/api_network/fixtures/sanity/initial_ipv6_eqpt.json', 'networkapi/api_network/fixtures/sanity/initial_roteiros.json', 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json', + 'networkapi/api_network/fixtures/sanity/initial_cidr.json', + ] json_path = 'api_network/tests/v3/sanity/networkipv6/json/%s' @@ -230,6 +232,7 @@ class NetworkIPv6PutErrorTestCase(NetworkApiTestCase): 'networkapi/api_network/fixtures/sanity/initial_ipv6_eqpt.json', 'networkapi/api_network/fixtures/sanity/initial_roteiros.json', 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json', + 'networkapi/api_network/fixtures/sanity/initial_cidr.json' ] json_path = 'api_network/tests/v3/sanity/networkipv6/json/%s' @@ -327,7 +330,9 @@ class NetworkIPv6ForcePutSuccessTestCase(NetworkApiTestCase): 'networkapi/api_network/fixtures/sanity/initial_equipments_group.json', 'networkapi/api_network/fixtures/sanity/initial_ipv6_eqpt.json', 'networkapi/api_network/fixtures/sanity/initial_roteiros.json', - 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json' + 'networkapi/api_network/fixtures/sanity/initial_equip_marca_model.json', + 'networkapi/api_network/fixtures/sanity/initial_cidr.json' + ] json_path = 'api_network/tests/v3/sanity/networkipv6/json/%s' diff --git a/networkapi/api_rack/autoprovision.py b/networkapi/api_rack/autoprovision.py index c06e2d630..61648ccf9 100644 --- a/networkapi/api_rack/autoprovision.py +++ b/networkapi/api_rack/autoprovision.py @@ -22,7 +22,8 @@ def replace(filein, fileout, dicionario): file_handle = open(filein, 'r') file_string = file_handle.read() file_handle.close() - except: + except Exception as e: + log.error("Erro abrindo roteiro: %s. Error: %s" % (str(filein), e)) raise RackConfigError(None, None, "Erro abrindo roteiro: %s." % str(filein)) try: @@ -30,7 +31,8 @@ def replace(filein, fileout, dicionario): # Use RE package to allow for replacement (also allowing for (multiline) REGEX) log.debug("variavel: %s, valor: %s" % (str(key), str(dicionario[key]))) file_string = (re.sub(key, dicionario[key], file_string)) - except: + except Exception as e: + log.error("Erro atualizando as variáveis no roteiro: %s. Error: %s" % (filein, e)) raise RackConfigError(None, None, "Erro atualizando as variáveis no roteiro: %s." % filein) try: @@ -39,7 +41,8 @@ def replace(filein, fileout, dicionario): file_handle = open(fileout, 'w') file_handle.write(file_string) file_handle.close() - except: + except Exception as e: + log.error("Erro salvando arquivo de configuração: %s. Error: %s" % (fileout, e)) raise RackConfigError(None, None, "Erro salvando arquivo de configuração: %s." % fileout) @@ -213,39 +216,47 @@ def autoprovision_splf(rack, equips): # get fathers environments spn_envs = models_env.Ambiente.objects.filter(dcroom=dcroom.get("id"), - father_environment__isnull=True, + grupo_l3__nome=str(rack.dcroom.name), + # father_environment__isnull=True, ambiente_logico__nome="SPINES") + log.debug("spn_envs %s" % spn_envs) prod_envs = models_env.Ambiente.objects.filter(dcroom=dcroom.get("id"), - father_environment__isnull=True, + # father_environment__isnull=True, + grupo_l3__nome=str(rack.dcroom.name), ambiente_logico__nome="PRODUCAO", - divisao_dc__nome__in=["BE", "FE", "BO_DSR", "BOCACHOS-A", "BOCACHOS-B"]) + divisao_dc__nome__in=["BE", "FE", "BO_DSR", + "BORDACACHOS_A", "BORDACACHOS_B"]) + log.debug("prod_envs %s" % prod_envs) lf_env = models_env.Ambiente.objects.filter(dcroom=dcroom.get("id"), - divisao_dc__nome="BE", grupo_l3__nome=str(rack.dcroom.name), + divisao_dc__nome="BE", ambiente_logico__nome="LEAF-LEAF").uniqueResult() + log.debug("lf_env %s" % lf_env) + for spn in spn_envs: if spn.divisao_dc.nome[:2] == "BE": VLANBE = spn.min_num_vlan_1 + log.debug("spn_configs %s" % spn.configs) for net in spn.configs: - if net.ip_config.type=="v4": - CIDRBEipv4 = IPNetwork(str(net.ip_config.subnet)) - prefixBEV4 = int(net.ip_config.new_prefix) + if net.ip_version == "v4": + CIDRBEipv4 = IPNetwork(str(net.network)) + prefixBEV4 = int(net.subnet_mask) else: - log.debug(str(net.ip_config.subnet)) - CIDRBEipv6 = IPNetwork(str(net.ip_config.subnet)) - prefixBEV6 = int(net.ip_config.new_prefix) + log.debug(str(net.network)) + CIDRBEipv6 = IPNetwork(str(net.network)) + prefixBEV6 = int(net.subnet_mask) elif spn.divisao_dc.nome[:2] == "FE": VLANFE = spn.min_num_vlan_1 for net in spn.configs: - if net.ip_config.type=="v4": - CIDRFEipv4 = IPNetwork(str(net.ip_config.subnet)) - prefixFEV4 = int(net.ip_config.new_prefix) + if net.ip_version == "v4": + CIDRFEipv4 = IPNetwork(str(net.network)) + prefixFEV4 = int(net.subnet_mask) else: - log.debug(str(net.ip_config.subnet)) - CIDRFEipv6 = IPNetwork(str(net.ip_config.subnet)) - prefixFEV6 = int(net.ip_config.new_prefix) + log.debug(str(net.network)) + CIDRFEipv6 = IPNetwork(str(net.network)) + prefixFEV6 = int(net.subnet_mask) elif spn.divisao_dc.nome == "BO": VLANBORDA = spn.min_num_vlan_1 elif spn.divisao_dc.nome == "BOCACHOS-A": @@ -256,56 +267,59 @@ def autoprovision_splf(rack, equips): for prod in prod_envs: if prod.divisao_dc.nome[:2] == "BE": for net in prod.configs: - if net.ip_config.type=="v4": - CIDRBEipv4interno = IPNetwork(str(net.ip_config.subnet)) - prefixInternoV4 = int(net.ip_config.new_prefix) + # + if net.ip_version == "v4": + CIDRBEipv4interno = IPNetwork(str(net.network)) + prefixInternoV4 = int(net.subnet_mask) else: - log.debug(str(net.ip_config.subnet)) - CIDRBEipv6interno = IPNetwork(str(net.ip_config.subnet)) - prefixInternoV6 = int(net.ip_config.new_prefix) + log.debug(str(net.network)) + CIDRBEipv6interno = IPNetwork(str(net.network)) + prefixInternoV6 = int(net.subnet_mask) elif prod.divisao_dc.nome[:2] == "FE": for net in prod.configs: - if net.ip_config.type=="v4": - CIDRFEipv4interno = IPNetwork(str(net.ip_config.subnet)) - prefixInternoFEV4 = int(net.ip_config.new_prefix) + if net.ip_version == "v4": + CIDRFEipv4interno = IPNetwork(str(net.network)) + prefixInternoFEV4 = int(net.subnet_mask) else: - log.debug(str(net.ip_config.subnet)) - CIDRFEipv6interno = IPNetwork(str(net.ip_config.subnet)) - prefixInternoFEV6 = int(net.ip_config.new_prefix) + log.debug(str(net.network)) + CIDRFEipv6interno = IPNetwork(str(net.network)) + prefixInternoFEV6 = int(net.subnet_mask) + elif prod.divisao_dc.nome == "BO_DSR": for net in prod.configs: - if net.ip_config.type=="v4": - CIDRBO_DSRipv4interno = IPNetwork(str(net.ip_config.subnet)) - prefixInternoBO_DSRV4 = int(net.ip_config.new_prefix) + if net.ip_version == "v4": + CIDRBO_DSRipv4interno = IPNetwork(str(net.network)) + prefixInternoBO_DSRV4 = int(net.subnet_mask) else: - log.debug(str(net.ip_config.subnet)) - CIDRBO_DSRipv6interno = IPNetwork(str(net.ip_config.subnet)) - prefixInternoBO_DSRV6 = int(net.ip_config.new_prefix) + log.debug(str(net.network)) + CIDRBO_DSRipv6interno = IPNetwork(str(net.network)) + prefixInternoBO_DSRV6 = int(net.subnet_mask) + elif prod.divisao_dc.nome == "BOCACHOS-A": for net in prod.configs: - if net.ip_config.type=="v4": - CIDRBOCAAipv4interno = IPNetwork(str(net.ip_config.subnet)) - prefixInternoBOCAAV4 = int(net.ip_config.new_prefix) + if net.ip_version == "v4": + CIDRBOCAAipv4interno = IPNetwork(str(net.network)) + prefixInternoBOCAAV4 = int(net.subnet_mask) else: - log.debug(str(net.ip_config.subnet)) - CIDRBOCAAipv6interno = IPNetwork(str(net.ip_config.subnet)) - prefixInternoBOCAAV6 = int(net.ip_config.new_prefix) + log.debug(str(net.network)) + CIDRBOCAAipv6interno = IPNetwork(str(net.network)) + prefixInternoBOCAAV6 = int(net.subnet_mask) elif prod.divisao_dc.nome == "BOCACHOS-B": for net in prod.configs: - if net.ip_config.type=="v4": - CIDRBOCABipv4interno = IPNetwork(str(net.ip_config.subnet)) - prefixInternoBOCABV4 = int(net.ip_config.new_prefix) + if net.ip_version == "v4": + CIDRBOCABipv4interno = IPNetwork(str(net.network)) + prefixInternoBOCABV4 = int(net.subnet_mask) else: - log.debug(str(net.ip_config.subnet)) - CIDRBOCABipv6interno = IPNetwork(str(net.ip_config.subnet)) - prefixInternoBOCABV6 = int(net.ip_config.new_prefix) + log.debug(str(net.network)) + CIDRBOCABipv6interno = IPNetwork(str(net.network)) + prefixInternoBOCABV6 = int(net.subnet_mask) log.debug(str(lf_env)) for netlf in lf_env.configs: - if netlf.ip_config.type=="v4": - IBGPToRLxLipv4 = IPNetwork(str(netlf.ip_config.subnet)) - elif netlf.ip_config.type=="v6": - IBGPToRLxLipv6 = IPNetwork(str(netlf.ip_config.subnet)) + if netlf.ip_version == "v4": + IBGPToRLxLipv4 = IPNetwork(str(netlf.network)) + elif netlf.ip_version == "v6": + IBGPToRLxLipv6 = IPNetwork(str(netlf.network)) SPINE1ipv4 = splitnetworkbyrack(CIDRBEipv4, prefixBEV4, 0) SPINE2ipv4 = splitnetworkbyrack(CIDRBEipv4, prefixBEV4, 1) @@ -438,7 +452,6 @@ def autoprovision_splf(rack, equips): variablestochangeleaf1["IPNEIGHSPINE1IPV6"] = str(IPSPINEipv6[numero_rack][spn]) variablestochangeleaf1["IPNEIGHSPINE2IPV6"] = str(IPSPINEipv6[numero_rack][spn+1]) - if equip.get("nome")[-1] == "1": log.debug("lf-name: %s. Ip: %s" % (equip.get("nome"), IPSIBGPipv4[numero_rack][1])) variablestochangeleaf1["IPNEIGHIBGPIPV4"] = str(IPSIBGPipv4[numero_rack][1]) @@ -477,7 +490,7 @@ def autoprovision_splf(rack, equips): for i in equip.get("interfaces"): log.info("for i in equip") - log.info(str(type(i.get("nome")[:3]))) + log.info(str(i)) if i.get("nome")[:3] == prefixlf: variablestochangeleaf1["LFNEIGH_HOSTNAME"] = i.get("nome") @@ -519,10 +532,8 @@ def autoprovision_splf(rack, equips): fileinleaf1 = path_to_guide + equip.get("roteiro") fileoutleaf1 = path_to_config + equip.get("nome")+".cfg" - replace(fileinleaf1, fileoutleaf1, variablestochangeleaf1) variablestochangeleaf1 = dict() - return True @@ -573,9 +584,9 @@ def autoprovision_coreoob(rack, equips): vlan_base = environment.min_num_vlan_1 for net in environment.configs: - if net.ip_config.type == "v4": - redev4 = IPNetwork(str(net.ip_config.subnet)) - prefixv4 = int(net.ip_config.new_prefix) + if net.ip_version == "v4": + redev4 = IPNetwork(str(net.network)) + prefixv4 = int(net.subnet_mask) subredev4 = list(redev4.subnet(prefixv4)) if not vlan_base: diff --git a/networkapi/api_rack/facade.py b/networkapi/api_rack/facade.py index 157449e38..b7a603e1e 100644 --- a/networkapi/api_rack/facade.py +++ b/networkapi/api_rack/facade.py @@ -34,10 +34,13 @@ from networkapi.ip.models import IpEquipamento from networkapi.rack.models import Rack, Datacenter, DatacenterRooms, RackConfigError from networkapi.api_rack import serializers as rack_serializers -from networkapi.api_rack import exceptions, autoprovision +from networkapi.api_rack import exceptions +from networkapi.api_rack import provision +from networkapi.api_rack import autoprovision from networkapi.system import exceptions as var_exceptions from networkapi.system.facade import get_value as get_variable -from networkapi.api_rest.exceptions import ValidationAPIException, ObjectDoesNotExistException, NetworkAPIException +from networkapi.api_rest.exceptions import ValidationAPIException, ObjectDoesNotExistException, \ + NetworkAPIException from networkapi.api_network.facade.v3 import networkv4 as facade_redev4_v3 if int(get_variable('use_foreman')): @@ -75,6 +78,12 @@ def listdc(): return dc_sorted +def delete_dc(dcs): + for dc_id in dcs: + dcroom_obj = Datacenter().get_dc(idt=dc_id) + dcroom_obj.del_dc() + + def save_dcrooms(dcrooms_dict): dcrooms = DatacenterRooms() @@ -109,6 +118,13 @@ def edit_dcrooms(dcroom_id, dcrooms_dict): return dcrooms +def delete_dcrooms(dcrooms): + + for dcroom_id in dcrooms: + dcroom_obj = DatacenterRooms().get_dcrooms(idt=dcroom_id) + dcroom_obj.del_dcrooms() + + def get_fabric(idt=None, name=None, id_dc=None): fabric_list = list() @@ -378,16 +394,21 @@ def gerar_arquivo_config(ids): except: pass except: - raise Exception("Erro ao buscar o roteiro de configuracao ou as interfaces associadas ao equipamento: " - "%s." % equip.get("nome")) + raise Exception( + "Erro ao buscar o roteiro de configuracao ou as interfaces associadas ao equipamento: %s." + % equip.get("nome")) try: equip["roteiro"] = _buscar_roteiro(equip.get("id"), "CONFIGURACAO") equip["ip_mngt"] = _buscar_ip(equip.get("id")) except: raise Exception("Erro ao buscar os roteiros do equipamento: %s" % equip.get("nome")) - autoprovision.autoprovision_splf(rack, equips) - autoprovision.autoprovision_coreoob(rack, equips) + # autoprovision.autoprovision_splf(rack, equips) + # autoprovision.autoprovision_coreoob(rack, equips) + + auto = provision.Provision(rack.id) + auto.spine_provision(rack, equips) + auto.oob_provision(equips) return True @@ -396,21 +417,18 @@ def _create_spnlfenv(user, rack): log.debug("_create_spnlfenv") envfathers = models_env.Ambiente.objects.filter(dcroom=int(rack.dcroom.id), - father_environment__isnull=True, grupo_l3__nome=str(rack.dcroom.name), ambiente_logico__nome="SPINES") log.debug("SPN environments"+str(envfathers)) - environment_spn_lf = None environment_spn_lf_list = list() spines = int(rack.dcroom.spines) - fabric = rack.dcroom.name try: - id_grupo_l3 = models_env.GrupoL3().get_by_name(fabric).id + id_grupo_l3 = models_env.GrupoL3().get_by_name(rack.nome).id except: grupo_l3_dict = models_env.GrupoL3() - grupo_l3_dict.nome = fabric + grupo_l3_dict.nome = rack.nome grupo_l3_dict.save() id_grupo_l3 = grupo_l3_dict.id pass @@ -419,12 +437,12 @@ def _create_spnlfenv(user, rack): config_subnet = list() for net in env.configs: # verificar se o ambiente possui range associado. - cidr = IPNetwork(net.ip_config.subnet) - prefix = int(net.ip_config.new_prefix) + cidr = IPNetwork(net.network) + prefix = int(net.subnet_mask) network = { 'cidr': list(cidr.subnet(prefix)), - 'type': net.ip_config.type, - 'network_type': net.ip_config.network_type.id + 'type': net.ip_version, + 'network_type': net.id_network_type.id } config_subnet.append(network) for spn in range(spines): @@ -464,6 +482,7 @@ def _create_spnlfenv(user, rack): 'configs': config, 'fabric_id': rack.dcroom.id } + # obj_env = facade_env.create_environment(obj) return environment_spn_lf_list @@ -472,7 +491,6 @@ def _create_spnlfvlans(rack, user): log.debug("_create_spnlfvlans") spn_lf_envs = models_env.Ambiente.objects.filter(dcroom=int(rack.dcroom.id), - father_environment__isnull=False, grupo_l3__nome=str(rack.dcroom.name), ambiente_logico__nome__in=["SPINE01LEAF", "SPINE02LEAF", @@ -492,19 +510,28 @@ def _create_spnlfvlans(rack, user): pass for env in spn_lf_envs: env_id = env.id + try: + base_rack = int(rack.dcroom.racks) + spn = int(env.ambiente_logico.nome[6]) + except: + spn = 1 + base_rack = 1 vlan_base = env.min_num_vlan_1 - vlan_number = int(vlan_base) + int(rack_number) + vlan_number = int(vlan_base) + int(rack_number) + (spn-1)*base_rack vlan_name = "VLAN_" + env.divisao_dc.nome + "_" + env.ambiente_logico.nome + "_" + rack.nome for net in env.configs: - prefix = int(net.ip_config.new_prefix) + prefix = int(net.subnet_mask) + block = list(IPNetwork(net.network).subnet(int(net.subnet_mask))) network = { - 'prefix': prefix, # str(list(cidr.subnet(prefix))[rack_number]), - 'network_type': id_network_type + 'network': str(block[rack_number]), + 'prefix': prefix, + 'network_type': id_network_type, + 'ip_version': str(net.ip_version) } - if str(net.ip_config.type)[-1] is "4": + if str(net.ip_version)[-1] is "4": create_networkv4 = network - elif str(net.ip_config.type)[-1] is "6": + elif str(net.ip_version)[-1] is "6": create_networkv6 = network obj = { 'name': vlan_name, @@ -525,7 +552,6 @@ def _create_prod_envs(rack, user): log.debug("_create_prod_envs") prod_envs = models_env.Ambiente.objects.filter(dcroom=int(rack.dcroom.id), - father_environment__isnull=True, grupo_l3__nome=str(rack.dcroom.name), ambiente_logico__nome="PRODUCAO" ).exclude(divisao_dc__nome="BO_DMZ") @@ -565,35 +591,32 @@ def _create_prod_envs(rack, user): details = None for fab in fabricconfig.get("Ambiente"): - if int(fab.get("id"))==int(father_id): + if int(fab.get("id")) == int(father_id): details = fab.get("details") config_subnet = [] for net in env.configs: - cidr = IPNetwork(str(net.ip_config.subnet)) - prefix = int(net.ip_config.new_prefix) + cidr = IPNetwork(str(net.network)) + prefix = int(net.subnet_mask) subnet_list = list(cidr.subnet(int(prefix))) - try: bloco = subnet_list[int(rack.numero)] - except IndexError as err: + except IndexError: msg = "Rack number %d is greater than the maximum number of " \ - "subnets available with prefix %d from %s subnet" % ( - rack.numero, prefix, cidr - ) + "subnets available with prefix %d from %s subnet" % \ + (rack.numero, prefix, cidr) raise Exception(msg) if isinstance(details, list) and len(details) > 0: - - if details[0].get(str(net.ip_config.type)): - new_prefix = details[0].get(str(net.ip_config.type)).get("new_prefix") + if details[0].get(str(net.ip_version)): + new_prefix = details[0].get(str(net.ip_version)).get("new_prefix") else: - new_prefix = 31 if net.ip_config.type=="v4" else 127 + new_prefix = 31 if net.ip_version == "v4" else 127 network = { - 'subnet': str(bloco), - 'type': net.ip_config.type, - 'network_type': net.ip_config.network_type.id, - 'new_prefix': new_prefix + 'network': str(bloco), + 'ip_version': net.ip_version, + 'network_type': net.id_network_type.id, + 'subnet_mask': new_prefix } config_subnet.append(network) @@ -635,13 +658,15 @@ def _create_prod_envs(rack, user): def _create_prod_vlans(rack, user): log.debug("_create_prod_vlans") - env = models_env.Ambiente.objects.filter(dcroom=int(rack.dcroom.id), - divisao_dc__nome="BE", - grupo_l3__nome=str(rack.nome), - ambiente_logico__nome="PRODUCAO" - ).uniqueResult() - - log.debug("BE environments: "+str(env)) + try: + env = models_env.Ambiente.objects.filter(dcroom=int(rack.dcroom.id), + divisao_dc__nome="BE", + grupo_l3__nome=str(rack.nome), + ambiente_logico__nome="PRODUCAO" + ).uniqueResult() + log.debug("BE environments: %s" % env) + except Exception as e: + raise Exception("Erro: %s" % e) if rack.dcroom.config: fabricconfig = rack.dcroom.config @@ -690,10 +715,10 @@ def _create_prod_vlans(rack, user): for net in env.configs: for net_dict in amb.get("config"): - if net_dict.get("type") == net.ip_config.type: - cidr = IPNetwork(net.ip_config.subnet) + if net_dict.get("type") == net.ip_version: + cidr = IPNetwork(net.network) - initial_prefix = 20 if net.ip_config.type=="v4" else 56 + initial_prefix = 20 if net.ip_version == "v4" else 56 prefixo = net_dict.get("mask") if not idx: bloco = list(cidr.subnet(int(prefixo)))[0] @@ -703,10 +728,10 @@ def _create_prod_vlans(rack, user): bloco = list(bloco1.subnet(int(prefixo)))[idx-1] log.debug(str(bloco)) network = { - 'subnet': str(bloco), - 'type': str(net.ip_config.type), - 'network_type': int(net.ip_config.network_type.id), - 'new_prefix': int(net_dict.get("new_prefix")) + 'network': str(bloco), + 'ip_version': str(net.ip_version), + 'network_type': int(net.id_network_type.id), + 'subnet_mask': int(net_dict.get("new_prefix")) } config_subnet.append(network) @@ -744,11 +769,60 @@ def _create_prod_vlans(rack, user): return environment +def _create_lflf_envs(rack): + log.debug("_create_lflf_envs") + env_lf = models_env.Ambiente.objects.filter(dcroom=int(rack.dcroom.id), + grupo_l3__nome=str(rack.dcroom.name), + ambiente_logico__nome="LEAF-LEAF") + log.debug("Leaf-leaf environments: "+str(env_lf)) + + try: + id_l3 = models_env.GrupoL3().get_by_name(rack.nome).id + except: + l3_dict = models_env.GrupoL3() + l3_dict.nome = rack.nome + l3_dict.save() + id_l3 = l3_dict.id + pass + + for env in env_lf: + config_subnet = [] + for net in env.configs: + cidr = list(IPNetwork(net.network).subnet(int(net.subnet_mask)))[rack.numero] + network = { + 'network': str(cidr), + 'ip_version': str(net.ip_version), + 'network_type': int(net.id_network_type.id), + 'subnet_mask': int(net.subnet_mask) + } + config_subnet.append(network) + + obj = { + 'grupo_l3': id_l3, + 'ambiente_logico': env.ambiente_logico.id, + 'divisao_dc': env.divisao_dc.id, + 'acl_path': env.acl_path, + 'ipv4_template': env.ipv4_template, + 'ipv6_template': env.ipv6_template, + 'link': env.link, + 'min_num_vlan_2': env.min_num_vlan_1, + 'max_num_vlan_2': env.max_num_vlan_1, + 'min_num_vlan_1': env.min_num_vlan_1, + 'max_num_vlan_1': env.max_num_vlan_1, + 'vrf': env.vrf, + 'father_environment': env.id, + 'default_vrf': env.default_vrf.id, + 'configs': config_subnet, + 'fabric_id': rack.dcroom.id + } + environment = facade_env.create_environment(obj) + log.debug("Environment object: %s" % str(environment)) + + def _create_lflf_vlans(rack, user): log.debug("_create_lflf_vlans") env_lf = models_env.Ambiente.objects.filter(dcroom=int(rack.dcroom.id), - father_environment__isnull=True, grupo_l3__nome=str(rack.dcroom.name), ambiente_logico__nome="LEAF-LEAF") log.debug("Leaf-leaf environments: "+str(env_lf)) @@ -773,15 +847,15 @@ def _create_lflf_vlans(rack, user): except: log.debug("debug lfxlf") for net in env.configs: - bloco = net.ip_config.subnet + bloco = net.network prefix = bloco.split('/')[-1] network = { 'prefix': prefix, 'network_type': id_network_type } - if str(net.ip_config.type)[-1] is "4": + if str(net.ip_version)[-1] is "4": create_networkv4 = network - elif str(net.ip_config.type)[-1] is "6": + elif str(net.ip_version)[-1] is "6": create_networkv6 = network obj = { 'name': vlan_name, @@ -826,8 +900,8 @@ def _create_oobvlans(rack, user): network = dict() for config in env.configs: log.debug("Configs: "+str(config)) - new_prefix = config.ip_config.new_prefix - redev4 = IPNetwork(config.ip_config.subnet) + new_prefix = config.subnet_mask + redev4 = IPNetwork(config.network) new_v4 = list(redev4.subnet(int(new_prefix)))[int(rack.numero)] oct1, oct2, oct3, var = str(new_v4).split('.') oct4, prefix = var.split('/') @@ -835,7 +909,7 @@ def _create_oobvlans(rack, user): mask1, mask2, mask3, mask4 = netmask.split('.') network = dict(oct1=oct1, oct2=oct2, oct3=oct3, oct4=oct4, prefix=prefix, mask_oct1=mask1, mask_oct2=mask2, mask_oct3=mask3, mask_oct4=mask4, cluster_unit=None, vlan=vlan.id, - network_type=config.ip_config.network_type.id, environmentvip=None) + network_type=config.id_network_type.id, environmentvip=None) log.debug("Network allocated: "+ str(network)) facade_redev4_v3.create_networkipv4(network, user) @@ -843,7 +917,7 @@ def _create_oobvlans(rack, user): def rack_environments_vlans(rack_id, user): - log.info("Rack Environments") + log.info("Rack Environments - Old") rack = Rack().get_rack(idt=rack_id) if rack.create_vlan_amb: @@ -855,6 +929,7 @@ def rack_environments_vlans(rack_id, user): # leaf x leaf _create_lflf_vlans(rack, user) + _create_lflf_envs(rack) # producao/cloud _create_prod_envs(rack, user) @@ -869,6 +944,45 @@ def rack_environments_vlans(rack_id, user): return rack +def allocate_env_vlan(user, rack_id): + log.info("Rack Environments - Refactor") + + from networkapi.api_rack.rackenvironments import RackEnvironment + + rack_env = RackEnvironment(user, rack_id) + + # spine x leaf + rack_env.spines_environment_save() + rack_env.spine_leaf_vlans_save() + + # leaf x leaf + rack_env.leaf_leaf_vlans_save() + rack_env.leaf_leaf_envs_save() + + # producao/cloud + rack_env.prod_environment_save() + rack_env.children_prod_environment_save() + + # redes de gerencia OOB + rack_env.manage_vlan_save() + + rack_env.allocate() + + return rack_env.rack + + +def deallocate_env_vlan(user, rack_id): + log.info("Rack deallocate") + + from networkapi.api_rack.rackenvironments import RackEnvironment + + rack_env = RackEnvironment(user, rack_id) + + rack_env.rack_vlans_remove() + rack_env.rack_environment_remove() + rack_env.deallocate() + + def api_foreman(rack): diff --git a/networkapi/api_rack/provision.py b/networkapi/api_rack/provision.py new file mode 100644 index 000000000..8dbcdf9b6 --- /dev/null +++ b/networkapi/api_rack/provision.py @@ -0,0 +1,578 @@ +# -*- coding: utf-8 -*- + +import ast +import json +import logging +import operator +import re +from django.core.exceptions import ObjectDoesNotExist +from django.forms.models import model_to_dict +from netaddr import IPNetwork +from networkapi.rack.models import Rack, RackConfigError +from networkapi.ambiente import models as models_env +from networkapi.vlan import models as models_vlan +from networkapi.system.facade import get_value as get_variable +from networkapi.system import exceptions as var_exceptions + +log = logging.getLogger(__name__) + + +class Provision: + + def __init__(self, rack_id): + self.rack = Rack().get_by_pk(rack_id) + self.spine_prefix = "SPN" + self.leaf_prefix = "LF-" + self.oob_prefix = "OOB" + + @staticmethod + def replace_file(filein, fileout, dicionario): + + try: + # Read contents from file as a single string + file_handle = open(filein, 'r') + file_string = file_handle.read() + file_handle.close() + except Exception as e: + log.error("Erro abrindo roteiro: %s. Error: %s" % (str(filein), e)) + raise RackConfigError(None, None, "Erro abrindo roteiro: %s." % str(filein)) + + try: + for key in dicionario: + # Use RE package to allow for replacement (also allowing for (multiline) REGEX) + log.debug("variavel: %s, valor: %s" % (str(key), str(dicionario[key]))) + file_string = (re.sub(key, dicionario[key], file_string)) + except Exception as e: + log.error("Erro atualizando as variáveis no roteiro: %s. Error: %s" % (filein, e)) + raise RackConfigError(None, None, "Erro atualizando as variáveis no roteiro: %s." % filein) + + try: + # Write contents to file. + # Using mode 'w' truncates the file. + file_handle = open(fileout, 'w') + file_handle.write(file_string) + file_handle.close() + except Exception as e: + log.error("Erro salvando arquivo de configuração: %s. Error: %s" % (fileout, e)) + raise RackConfigError(None, None, "Erro salvando arquivo de configuração: %s." % fileout) + + @staticmethod + def split_network(net, bloco, posicao): + subnets = list(net.subnet(bloco)) + return subnets[posicao] + + def spine_provision(self, rack, equips): + + log.info("AutoprovisionSPN-LF") + + numero_rack = self.rack.numero + + IPSPINEipv4 = dict() + IPSPINEipv6 = dict() + IPLEAFipv4 = dict() + IPLEAFipv6 = dict() + IPSIBGPipv4 = dict() + IPSIBGPipv6 = dict() + ASLEAF = dict() + + PODSBEipv4 = dict() + redesPODSBEipv4 = dict() + + subnetsRackBEipv4 = dict() + + PODSBEipv6 = dict() + redesPODSBEipv6 = dict() + PODSBEFEipv6 = dict() + redesPODSBEFEipv6 = dict() + PODSBEBOipv6 = dict() + redesPODSBEBOipv6 = dict() + PODSBECAipv6 = dict() + redesPODSBECAipv6 = dict() + redesHostsipv6 = dict() + redeHostsBEipv6 = dict() + redeHostsFEipv6 = dict() + redeHostsBOipv6 = dict() + redeHostsCAipv6 = dict() + redeHostsFILERipv6 = dict() + + redesPODSFEipv4 = dict() + redesPODSFEipv6 = dict() + + VLANBELEAF = dict() + VLANFELEAF = dict() + VLANBORDALEAF = dict() + VLANBORDACACHOSLEAF = dict() + VLANBORDACACHOSBLEAF = dict() + + IPSPINEipv4[numero_rack] = list() + IPSPINEipv6[numero_rack] = list() + IPLEAFipv4[numero_rack] = list() + IPLEAFipv6[numero_rack] = list() + IPSIBGPipv4[numero_rack] = list() + IPSIBGPipv6[numero_rack] = list() + VLANBELEAF[numero_rack] = list() + VLANFELEAF[numero_rack] = list() + VLANBORDALEAF[numero_rack] = list() + VLANBORDACACHOSLEAF[numero_rack] = list() + VLANBORDACACHOSBLEAF[numero_rack] = list() + ASLEAF[numero_rack] = list() + + PODSBEipv4[numero_rack] = list() + redesPODSBEipv4[numero_rack] = list() + + subnetsRackBEipv4[numero_rack] = list() + + PODSBEipv6[numero_rack] = list() + redesPODSBEipv6[numero_rack] = list() + PODSBEFEipv6[numero_rack] = list() + redesPODSBEFEipv6[numero_rack] = list() + PODSBEBOipv6[numero_rack] = list() + redesPODSBEBOipv6[numero_rack] = list() + PODSBECAipv6[numero_rack] = list() + redesPODSBECAipv6[numero_rack] = list() + redesHostsipv6[numero_rack] = list() + redeHostsBEipv6[numero_rack] = list() + redeHostsFEipv6[numero_rack] = list() + redeHostsBOipv6[numero_rack] = list() + redeHostsCAipv6[numero_rack] = list() + redeHostsFILERipv6[numero_rack] = list() + redesPODSFEipv4[numero_rack] = list() + redesPODSFEipv6[numero_rack] = list() + + variablestochangespine1 = dict() + variablestochangeleaf1 = dict() + + VLANBE = None + VLANFE = None + VLANBORDA = None + VLANBORDACACHOS = None + VLANBORDACACHOSB = None + + CIDRBEipv4 = list() + CIDRBO_DSRipv4interno = None + CIDRBO_DSRipv6interno = None + CIDRBOCAAipv4interno = None + + CIDRBEipv6 = list() + CIDRBOCAAipv6interno = None + CIDRBOCABipv4interno = None + CIDRBOCABipv6interno = None + + try: + path_to_guide = get_variable("path_to_guide") + path_to_add_config = get_variable("path_to_add_config") + path_to_config = get_variable("path_to_config") + except ObjectDoesNotExist: + raise var_exceptions.VariableDoesNotExistException("Erro buscando a variável PATH_TO_GUIDE") + + try: + variablestochangeleaf1["KICKSTART_SO_LF"] = get_variable("kickstart_so_lf") + variablestochangeleaf1["IMAGE_SO_LF"] = get_variable("image_so_lf") + except ObjectDoesNotExist: + raise var_exceptions.VariableDoesNotExistException( + "Erro buscando a variável KICKSTART_SO_LF ou IMAGE_SO_LF.") + + equips_sorted = sorted(equips, key=operator.itemgetter('sw')) + + dcroom = model_to_dict(rack.dcroom) + log.debug("type: %s" % str(type(dcroom.get("config")))) + fabricconfig = dcroom.get("config") + + try: + fabricconfig = json.loads(fabricconfig) + log.debug("type -ast: %s" % str(type(fabricconfig))) + except: + pass + + try: + fabricconfig = ast.literal_eval(fabricconfig) + log.debug("config -ast: %s" % str(fabricconfig)) + except: + pass + + envconfig = fabricconfig + BASE_RACK = dcroom.get("racks") + BGP = envconfig.get("BGP") + BASE_AS_SPN = int(BGP.get("spines")) + BASE_AS_LFS = int(BGP.get("leafs")) + + # get fathers environments + dc_name = ["BE", "FE", "BO", "BOCACHOS-A", "BOCACHOS-B"] + vlan_name = list() + for env in dc_name: + for spn in range(1, 5): + name = "VLAN_" + env + "_SPINE0" + str(spn) + "LEAF_" + self.rack.nome + vlan_name.append(name) + + spn_vlan = models_vlan.Vlan.objects.filter(nome__in=vlan_name).order_by("nome") + + log.debug("spn_vlan %s" % spn_vlan) + + prod_envs = models_env.Ambiente.objects.filter(grupo_l3__nome=str(self.rack.nome), + ambiente_logico__nome="PRODUCAO", + divisao_dc__nome__in=["BE", "FE", "BO_DSR", + "BOCACHOS-A", "BOCACHOS-B"]) + log.debug("prod_envs %s" % prod_envs) + + lf_env = models_env.Ambiente.objects.filter(grupo_l3__nome=str(self.rack.nome), + divisao_dc__nome="BE", + ambiente_logico__nome="LEAF-LEAF").uniqueResult() + log.debug("lf_env %s" % lf_env) + + vlanBE = list() + vlanFE = list() + vlanBO = list() + vlanBOCA = list() + vlanBOCAB = list() + + for vlan in spn_vlan: + if "_BE_" in vlan.nome: + vlanBE.append(vlan.num_vlan) + CIDRBEipv4.append(IPNetwork(vlan.networks_ipv4[0].networkv4)) + CIDRBEipv6.append(IPNetwork(vlan.networks_ipv6[0].networkv6)) + elif "_FE_" in vlan.nome: + vlanFE.append(vlan.num_vlan) + elif "_BO_" in vlan.nome: + vlanBO.append(vlan.num_vlan) + elif "_BOCACHOS-A_" in vlan.nome: + vlanBOCA.append(vlan.num_vlan) + elif "_BOCACHOS-B_" in vlan.nome: + vlanBOCAB.append(vlan.num_vlan) + + for prod in prod_envs: + if prod.divisao_dc.nome[:2] == "BE": + for net in prod.configs: + if net.ip_version == "v4": + CIDRBEipv4interno = str(net.network) + else: + CIDRBEipv6interno = str(net.network) + elif prod.divisao_dc.nome[:2] == "FE": + for net in prod.configs: + if net.ip_version == "v4": + CIDRFEipv4interno = str(net.network) + else: + CIDRFEipv6interno = str(net.network) + + elif prod.divisao_dc.nome == "BO_DSR": + for net in prod.configs: + if net.ip_version == "v4": + CIDRBO_DSRipv4interno = str(net.network) + else: + CIDRBO_DSRipv6interno = str(net.network) + + elif prod.divisao_dc.nome == "BOCACHOS-A": + for net in prod.configs: + if net.ip_version == "v4": + CIDRBOCAAipv4interno = str(net.network) + else: + CIDRBOCAAipv6interno = str(net.network) + elif prod.divisao_dc.nome == "BOCACHOS-B": + for net in prod.configs: + if net.ip_version == "v4": + CIDRBOCABipv4interno = str(net.network) + else: + CIDRBOCABipv6interno = str(net.network) + + for netlf in lf_env.configs: + if netlf.ip_version == "v4": + IBGPToRLxLipv4 = IPNetwork(str(netlf.network)) + elif netlf.ip_version == "v6": + IBGPToRLxLipv6 = IPNetwork(str(netlf.network)) + + id_vlt = [envconfig.get("VLT").get("id_vlt_lf1"), envconfig.get("VLT").get("id_vlt_lf2")] + priority_vlt = [envconfig.get("VLT").get("priority_vlt_lf1"), envconfig.get("VLT").get("priority_vlt_lf2")] + + IPSPINEipv4[numero_rack].append(CIDRBEipv4[0][0]) + IPSPINEipv4[numero_rack].append(CIDRBEipv4[1][0]) + IPSPINEipv4[numero_rack].append(CIDRBEipv4[2][0]) + IPSPINEipv4[numero_rack].append(CIDRBEipv4[3][0]) + # + IPLEAFipv4[numero_rack].append(CIDRBEipv4[0][1]) + IPLEAFipv4[numero_rack].append(CIDRBEipv4[1][1]) + IPLEAFipv4[numero_rack].append(CIDRBEipv4[2][1]) + IPLEAFipv4[numero_rack].append(CIDRBEipv4[3][1]) + # + IPSIBGPipv4[numero_rack].append(IBGPToRLxLipv4[0]) + IPSIBGPipv4[numero_rack].append(IBGPToRLxLipv4[1]) + # + IPSPINEipv6[numero_rack].append(CIDRBEipv6[0][0]) + IPSPINEipv6[numero_rack].append(CIDRBEipv6[1][0]) + IPSPINEipv6[numero_rack].append(CIDRBEipv6[2][0]) + IPSPINEipv6[numero_rack].append(CIDRBEipv6[3][0]) + # + IPLEAFipv6[numero_rack].append(CIDRBEipv6[0][1]) + IPLEAFipv6[numero_rack].append(CIDRBEipv6[1][1]) + IPLEAFipv6[numero_rack].append(CIDRBEipv6[2][1]) + IPLEAFipv6[numero_rack].append(CIDRBEipv6[3][1]) + # + IPSIBGPipv6[numero_rack].append(IBGPToRLxLipv6[0]) + IPSIBGPipv6[numero_rack].append(IBGPToRLxLipv6[1]) + # + log.debug("vlan subnet") + log.debug(vlanBE) + log.debug(BASE_RACK) + log.debug(numero_rack) + log.debug(vlanFE) + log.debug(vlanBO) + log.debug(vlanBOCA) + log.debug(vlanBOCAB) + log.debug(CIDRBEipv4) + log.debug(CIDRBEipv6) + + log.debug("as") + log.debug(BASE_AS_LFS) + log.debug(numero_rack) + ASLEAF[numero_rack].append(BASE_AS_LFS + numero_rack) + + for equip, spn, j in zip(equips_sorted[:2], [0, 2], [0, 1]): + variablestochangeleaf1["IPLEAFSP1IPV4"] = str(IPLEAFipv4[numero_rack][spn]) + variablestochangeleaf1["IPLEAFSP2IPV4"] = str(IPLEAFipv4[numero_rack][spn + 1]) + variablestochangeleaf1["IPIBGPIPV4"] = str(IPSIBGPipv4[numero_rack][j]) + variablestochangeleaf1["IPLEAFSP1IPV6"] = str(IPLEAFipv6[numero_rack][spn]) + variablestochangeleaf1["IPLEAFSP2IPV6"] = str(IPLEAFipv6[numero_rack][spn + 1]) + variablestochangeleaf1["IPIBGPIPV6"] = str(IPSIBGPipv6[numero_rack][j]) + log.debug("1") + variablestochangeleaf1["VLANBELEAFSP1"] = str(vlanBE[spn]) + variablestochangeleaf1["VLANBELEAFSP2"] = str(vlanBE[spn + 1]) + variablestochangeleaf1["VLANFELEAFSP1"] = str(vlanFE[spn]) + variablestochangeleaf1["VLANFELEAFSP2"] = str(vlanFE[spn + 1]) + variablestochangeleaf1["VLANBORDALEAFSP1"] = str(vlanBO[spn]) + variablestochangeleaf1["VLANBORDALEAFSP2"] = str(vlanBO[spn + 1]) + variablestochangeleaf1["VLANBORDACACHOSLEAFSP1"] = str(vlanBOCA[spn]) + variablestochangeleaf1["VLANBORDACACHOSLEAFSP2"] = str(vlanBOCA[spn + 1]) + variablestochangeleaf1["VLANBORDACACHOSBLEAFSP1"] = str(vlanBOCAB[spn]) + variablestochangeleaf1["VLANBORDACACHOSBLEAFSP2"] = str(vlanBOCAB[spn + 1]) + log.debug("2") + variablestochangeleaf1["ASLEAF"] = str(ASLEAF[numero_rack][0]) + + variablestochangeleaf1["IPNEIGHSPINE1IPV4"] = str(IPSPINEipv4[numero_rack][spn]) + variablestochangeleaf1["IPNEIGHSPINE2IPV4"] = str(IPSPINEipv4[numero_rack][spn + 1]) + variablestochangeleaf1["IPNEIGHSPINE1IPV6"] = str(IPSPINEipv6[numero_rack][spn]) + variablestochangeleaf1["IPNEIGHSPINE2IPV6"] = str(IPSPINEipv6[numero_rack][spn + 1]) + + if equip.get("nome")[-1] == "1": + log.debug("lf-name: %s. Ip: %s" % (equip.get("nome"), IPSIBGPipv4[numero_rack][1])) + variablestochangeleaf1["IPNEIGHIBGPIPV4"] = str(IPSIBGPipv4[numero_rack][1]) + variablestochangeleaf1["IPNEIGHIBGPIPV6"] = str(IPSIBGPipv6[numero_rack][1]) + else: + log.debug("lf-name: %s. Ip: %s" % (equip.get("nome"), IPSIBGPipv4[numero_rack][0])) + variablestochangeleaf1["IPNEIGHIBGPIPV4"] = str(IPSIBGPipv4[numero_rack][0]) + variablestochangeleaf1["IPNEIGHIBGPIPV6"] = str(IPSIBGPipv6[numero_rack][0]) + + try: + variablestochangeleaf1["NET_HOST_BE_IPV4"] = CIDRBEipv4interno + variablestochangeleaf1["NET_HOST_FE_IPV4"] = CIDRFEipv4interno + except Exception as e: + raise Exception("Error while getting IPv4 CIDR from BE or FE production environment. E: %s" % e) + + if CIDRBO_DSRipv4interno: + variablestochangeleaf1["NET_HOST_BO_DSR_IPV4"] = CIDRBO_DSRipv4interno + if CIDRBOCAAipv4interno: + variablestochangeleaf1["NET_HOST_BOCAA_IPV4"] = CIDRBOCAAipv4interno + if CIDRBOCABipv4interno: + variablestochangeleaf1["NET_HOST_BOCAB_IPV4"] = CIDRBOCABipv4interno + log.debug("3") + variablestochangeleaf1["NET_SPINE1_LF_IPV4"] = str(CIDRBEipv4[0]) + variablestochangeleaf1["NET_SPINE2_LF_IPV4"] = str(CIDRBEipv4[1]) + variablestochangeleaf1["NET_LF_LF_IPV4"] = str(IBGPToRLxLipv4) + + try: + variablestochangeleaf1["NET_HOST_BE_IPV6"] = CIDRBEipv6interno + variablestochangeleaf1["NET_HOST_FE_IPV6"] = CIDRFEipv6interno + except Exception as e: + raise Exception("Error while getting IPv6 CIDR from BE or FE production environment. E: %s" % e) + + if CIDRBO_DSRipv6interno: + variablestochangeleaf1["NET_HOST_BO_DSR_IPV6"] = CIDRBO_DSRipv6interno + if CIDRBOCAAipv6interno: + variablestochangeleaf1["NET_HOST_BOCAA_IPV6"] = CIDRBOCAAipv6interno + if CIDRBOCABipv6interno: + variablestochangeleaf1["NET_HOST_BOCAB_IPV6"] = CIDRBOCABipv6interno + log.debug("4") + variablestochangeleaf1["NET_SPINE1_LF_IPV6"] = str(CIDRBEipv6[0]) + variablestochangeleaf1["NET_SPINE2_LF_IPV6"] = str(CIDRBEipv6[1]) + variablestochangeleaf1["NET_LF_LF_IPV6"] = str(IBGPToRLxLipv6) + + variablestochangeleaf1["ID_LEAF"] = str(equip.get("sw")) # lf1 ou lf2 + variablestochangeleaf1["OWN_IP_MGMT"] = equip.get("ip_mngt") + variablestochangeleaf1["LF_HOSTNAME"] = equip.get("nome") + log.debug("5") + for i in equip.get("interfaces"): + if i.get("nome")[:3] == self.leaf_prefix: + variablestochangeleaf1["LFNEIGH_HOSTNAME"] = i.get("nome") + variablestochangeleaf1["LFNEIGH_IP_MGMT"] = i.get("ip_mngt") + elif i.get("nome")[:3] == self.spine_prefix: + spine_num = int(i.get("nome")[-1]) + variablestochangespine1["ASSPINE"] = str(BASE_AS_SPN + spine_num - 1) + variablestochangespine1["INTERFACE"] = i.get("interface") + variablestochangespine1["LEAFNAME"] = equip.get("nome") + variablestochangespine1["INT_LF_UPLINK"] = i.get("eq_interface") + log.debug("ok if spn") + variablestochangespine1["IPSPINEIPV4"] = str(IPSPINEipv4[numero_rack][spine_num - 1]) + variablestochangespine1["IPSPINEIPV6"] = str(IPSPINEipv6[numero_rack][spine_num - 1]) + variablestochangespine1["VLANBELEAF"] = str(vlanBE[spine_num - 1]) + variablestochangespine1["VLANFELEAF"] = str(vlanFE[spine_num - 1]) + variablestochangespine1["VLANBORDALEAF"] = str(vlanBO[spine_num - 1]) + variablestochangespine1["VLANBORDACACHOSLEAF"] = str(vlanBOCA[spine_num - 1]) + variablestochangespine1["VLANBORDACACHOSB"] = str(vlanBOCAB[spine_num - 1]) + variablestochangespine1["ASLEAF"] = str(ASLEAF[numero_rack][0]) + variablestochangespine1["IPNEIGHLEAFIPV4"] = str(IPLEAFipv4[numero_rack][spine_num - 1]) + variablestochangespine1["IPNEIGHLEAFIPV6"] = str(IPLEAFipv6[numero_rack][spine_num - 1]) + + if spine_num in [1, 3]: + variablestochangeleaf1["SP1_HOSTNAME"] = i.get("nome") + variablestochangeleaf1["INTERFACE_SP1"] = i.get("interface") + variablestochangeleaf1["ASSPINE1"] = str(BASE_AS_SPN + spine_num - 1) + else: + variablestochangeleaf1["SP2_HOSTNAME"] = i.get("nome") + variablestochangeleaf1["INTERFACE_SP2"] = i.get("interface") + variablestochangeleaf1["ASSPINE2"] = str(BASE_AS_SPN + spine_num - 1) + + fileinspine1 = path_to_guide + i.get("roteiro") + fileoutspine1 = path_to_add_config + i.get("nome") + "-ADD-" + rack.nome + ".cfg" + self.replace_file(fileinspine1, fileoutspine1, variablestochangespine1) + variablestochangespine1 = dict() + + elif i.get("nome")[:3] == self.oob_prefix: + variablestochangeleaf1["HOSTNAME_OOB"] = i.get("nome") + variablestochangeleaf1["INTERFACE_OOB"] = i.get("interface") + + variablestochangeleaf1["ID_VLT"] = str(id_vlt[j]) + variablestochangeleaf1["PRIORITY_VLT"] = str(priority_vlt[j]) + + fileinleaf1 = path_to_guide + equip.get("roteiro") + fileoutleaf1 = path_to_config + equip.get("nome") + ".cfg" + + self.replace_file(fileinleaf1, fileoutleaf1, variablestochangeleaf1) + log.debug(fileoutleaf1) + variablestochangeleaf1 = dict() + + return True + + def oob_provision(self, equips): + log.info("AutoprovisionOOB") + + variablestochangecore1 = dict() + variablestochangecore2 = dict() + variablestochangeoob = dict() + + fileincore1 = None + fileoutcore1 = None + fileincore2 = None + fileoutcore2 = None + + dcroom = model_to_dict(self.rack.dcroom) + log.debug("type: %s" % str(type(dcroom.get("config")))) + fabricconfig = dcroom.get("config") + + try: + fabricconfig = json.loads(fabricconfig) + log.debug("type -ast: %s" % str(type(fabricconfig))) + except: + pass + + try: + fabricconfig = ast.literal_eval(fabricconfig) + log.debug("config -ast: %s" % str(fabricconfig)) + except: + pass + + envconfig = fabricconfig + BASE_CHANNEL = int(envconfig.get("Channel").get("channel")) if envconfig.get("Channel") else 10 + + try: + path_to_guide = get_variable("path_to_guide") + path_to_add_config = get_variable("path_to_add_config") + path_to_config = get_variable("path_to_config") + except ObjectDoesNotExist: + raise var_exceptions.VariableDoesNotExistException("Erro buscando a variável PATH_TO_GUIDE") + + try: + vlan_name = "VLAN_GERENCIA_" + self.rack.nome + vlan = models_vlan.Vlan.objects.filter(nome=vlan_name).uniqueResult() + except Exception as e: + log.debug("Error while getting %s. Error: %s" % (vlan_name, e)) + vlan = False + + if not vlan: + try: + vlan_name = "OOB_SO_" + self.rack.nome + vlan = models_vlan.Vlan.objects.filter(nome=vlan_name).uniqueResult() + except Exception as e: + raise Exception("O rack não tem vlan de gerencia. Error: %s" % e) + + log.debug("Vlan OOB: %s" % vlan.nome) + log.debug("Rede OOB: %s" % IPNetwork(vlan.networks_ipv4[0].networkv4)) + log.debug("equips: %s" % str(equips)) + + if not vlan.networks_ipv4: + raise Exception("Vlan de OOB do rack não possui rede associada.") + + variablestochangeoob["VLAN_SO"] = str(vlan.num_vlan) + + equips_sorted = sorted(equips, key=operator.itemgetter('sw')) + oob = equips_sorted[-1] + + variablestochangeoob["OWN_IP_MGMT"] = oob.get("ip_mngt") + variablestochangeoob["HOSTNAME_OOB"] = oob.get("nome") + variablestochangeoob["HOSTNAME_RACK"] = self.rack.nome + + fileinoob = path_to_guide + oob.get("roteiro") + fileoutoob = path_to_config + oob.get("nome") + ".cfg" + + for equip in oob.get("interfaces"): + nome = equip.get("nome") + log.debug(str(nome)) + roteiro = equip.get("roteiro") + if nome[:3] == self.leaf_prefix: + if nome[-1] == "1": + variablestochangeoob["HOSTNAME_LF1"] = nome + else: + variablestochangeoob["HOSTNAME_LF2"] = nome + elif nome[:3] == self.oob_prefix: + intoob = equip.get("eq_interface") + intcore = equip.get("interface") + if nome[-1] == "1": + log.info(str(nome)) + variablestochangeoob["INT_OOBC1_UPLINK"] = intoob + variablestochangeoob["INTERFACE_CORE1"] = intcore + variablestochangeoob["HOSTNAME_CORE1"] = nome + variablestochangecore1["INT_OOB_UPLINK"] = intoob + variablestochangecore1["INTERFACE_CORE"] = intcore + variablestochangecore1["HOSTNAME_RACK"] = self.rack.nome + variablestochangecore1["SO_HOSTNAME_OOB"] = "SO_" + str(self.rack.nome) + variablestochangecore1["VLAN_SO"] = str(vlan.num_vlan) + variablestochangecore1['IPCORE'] = str(IPNetwork(vlan.networks_ipv4[0].networkv4).broadcast-2) + variablestochangecore1['IPHSRP'] = str(IPNetwork(vlan.networks_ipv4[0].networkv4).ip+1) + variablestochangecore1['NUM_CHANNEL'] = str(BASE_CHANNEL + int(self.rack.numero)) + if (1 + int(self.rack.numero)) % 2 == 0: + variablestochangecore1["HSRP_PRIORITY"] = "100" + else: + variablestochangecore1["HSRP_PRIORITY"] = "101" + fileincore1 = path_to_guide + roteiro + fileoutcore1 = path_to_add_config + nome + "-ADD-" + str(self.rack.nome) + ".cfg" + elif nome[-1] == "2": + log.info(str(nome)) + variablestochangeoob["INT_OOBC2_UPLINK"] = intoob + variablestochangeoob["INTERFACE_CORE2"] = intcore + variablestochangeoob["HOSTNAME_CORE2"] = nome + variablestochangecore2["INT_OOB_UPLINK"] = intoob + variablestochangecore2["INTERFACE_CORE"] = intcore + variablestochangecore2["HOSTNAME_RACK"] = self.rack.nome + variablestochangecore2["SO_HOSTNAME_OOB"] = "SO_" + str(self.rack.nome) + variablestochangecore2["VLAN_SO"] = str(vlan.num_vlan) + variablestochangecore2['IPCORE'] = str(IPNetwork(vlan.networks_ipv4[0].networkv4).broadcast-1) + variablestochangecore2['IPHSRP'] = str(IPNetwork(vlan.networks_ipv4[0].networkv4).ip+1) + variablestochangecore2['NUM_CHANNEL'] = str(BASE_CHANNEL + int(self.rack.numero)) + if (2 + int(self.rack.numero)) % 2 == 0: + variablestochangecore2["HSRP_PRIORITY"] = "100" + else: + variablestochangecore2["HSRP_PRIORITY"] = "101" + fileincore2 = path_to_guide + roteiro + fileoutcore2 = path_to_add_config + nome + "-ADD-" + str(self.rack.nome) + ".cfg" + + self.replace_file(fileincore1, fileoutcore1, variablestochangecore1) + self.replace_file(fileincore2, fileoutcore2, variablestochangecore2) + self.replace_file(fileinoob, fileoutoob, variablestochangeoob) + + return True diff --git a/networkapi/api_rack/rackenvironments.py b/networkapi/api_rack/rackenvironments.py new file mode 100644 index 000000000..c3d1d0f95 --- /dev/null +++ b/networkapi/api_rack/rackenvironments.py @@ -0,0 +1,521 @@ +# -*- coding: utf-8 -*- + +import ast +import json +import logging +import operator +from netaddr import IPNetwork +from networkapi.rack.models import Rack +from networkapi.ambiente import models as models_env +from networkapi.vlan import models as models_vlan +from networkapi.api_environment import facade as facade_env +from networkapi.api_vlan.facade import v3 as facade_vlan_v3 +from networkapi.api_network.facade.v3 import networkv4 as facade_redev4_v3 +from networkapi.api_network.facade.v3 import networkv6 as facade_redev6_v3 +from networkapi.equipamento.models import EquipamentoAmbiente +from networkapi.equipamento.models import EquipamentoAmbienteDuplicatedError + +log = logging.getLogger(__name__) + + +class RackEnvironment: + + def __init__(self, user, rack_id): + self.rack = Rack().get_by_pk(rack_id) + self.user = user + + @staticmethod + def save_environment(self, env): + pass + + @staticmethod + def save_vlan(self, vlan): + pass + + def allocate(self): + self.rack.__dict__.update( + id=self.rack.id, create_vlan_amb=True) + self.rack.save() + + def deallocate(self): + self.rack.__dict__.update( + id=self.rack.id, create_vlan_amb=False) + self.rack.save() + + def spines_environment_save(self): + log.debug("_create_spnlfenv") + + envfathers = models_env.Ambiente.objects.filter(dcroom=int(self.rack.dcroom.id), + father_environment__isnull=True, + grupo_l3__nome=str(self.rack.dcroom.name), + ambiente_logico__nome="SPINES") + log.debug("SPN environments" + str(envfathers)) + + environment_spn_lf_list = list() + spines = int(self.rack.dcroom.spines) + fabric = self.rack.dcroom.name + + try: + id_grupo_l3 = models_env.GrupoL3().get_by_name(fabric).id + except: + grupo_l3_dict = models_env.GrupoL3() + grupo_l3_dict.nome = fabric + grupo_l3_dict.save() + id_grupo_l3 = grupo_l3_dict.id + pass + + for env in envfathers: + config_subnet = list() + for net in env.configs: + # verificar se o ambiente possui range associado. + cidr = IPNetwork(net.network) + prefix = int(net.subnet_mask) + network = { + 'cidr': list(cidr.subnet(prefix)), + 'type': net.ip_version, + 'network_type': net.id_network_type.id + } + config_subnet.append(network) + for spn in range(spines): + amb_log_name = "SPINE0" + str(spn + 1) + "LEAF" + try: + id_amb_log = models_env.AmbienteLogico().get_by_name(amb_log_name).id + except: + amb_log_dict = models_env.AmbienteLogico() + amb_log_dict.nome = amb_log_name + amb_log_dict.save() + id_amb_log = amb_log_dict.id + pass + config = list() + for sub in config_subnet: + config_spn = { + 'subnet': str(sub.get("cidr")[spn]), + 'new_prefix': str(31) if str(sub.get("type"))[-1] is "4" else str(127), + 'type': str(sub.get("type")), + 'network_type': sub.get("network_type") + } + config.append(config_spn) + obj = { + 'grupo_l3': id_grupo_l3, + 'ambiente_logico': id_amb_log, + 'divisao_dc': env.divisao_dc.id, + 'acl_path': env.acl_path, + 'ipv4_template': env.ipv4_template, + 'ipv6_template': env.ipv6_template, + 'link': env.link, + 'min_num_vlan_2': env.min_num_vlan_2, + 'max_num_vlan_2': env.max_num_vlan_2, + 'min_num_vlan_1': env.min_num_vlan_1, + 'max_num_vlan_1': env.max_num_vlan_1, + 'vrf': env.vrf, + 'father_environment': env.id, + 'default_vrf': env.default_vrf.id, + 'configs': config, + 'fabric_id': self.rack.dcroom.id + } + + return environment_spn_lf_list + + def spines_environment_read(self): + pass + + def spine_leaf_vlans_save(self): + log.debug("_create_spnlfvlans") + + spn_lf_envs = models_env.Ambiente.objects.filter(dcroom=int(self.rack.dcroom.id), + grupo_l3__nome=str(self.rack.dcroom.name), + ambiente_logico__nome__in=["SPINE01LEAF", + "SPINE02LEAF", + "SPINE03LEAF", + "SPINE04LEAF"]) + log.debug("SPN environments" + str(spn_lf_envs)) + + tipo_rede = "Ponto a ponto" + try: + id_network_type = models_vlan.TipoRede().get_by_name(tipo_rede).id + except: + network_type = models_vlan.TipoRede() + network_type.tipo_rede = tipo_rede + network_type.save() + id_network_type = network_type.id + pass + + for env in spn_lf_envs: + + obj = { + 'name': "VLAN_" + env.divisao_dc.nome + "_" + env.ambiente_logico.nome + "_" + self.rack.nome, + 'environment': env.id, + 'default_vrf': env.default_vrf.id, + 'vrf': env.vrf, + 'create_networkv4': None, + 'create_networkv6': None, + 'description': "Vlan spinexleaf do rack " + self.rack.nome + + } + vlan = facade_vlan_v3.create_vlan(obj, self.user) + + log.debug("Vlan allocated: " + str(vlan)) + + for config in env.configs: + log.debug("Configs: " + str(config)) + network = dict(prefix=config.subnet_mask, + cluster_unit=None, + vlan=vlan.id, + network_type=id_network_type, + environmentvip=None) + log.debug("Network allocated: " + str(network)) + if str(config.ip_version)[-1] is "4": + facade_redev4_v3.create_networkipv4(network, self.user) + elif str(config.ip_version)[-1] is "6": + facade_redev6_v3.create_networkipv6(network, self.user) + + def spine_leaf_vlans_read(self): + pass + + def leaf_leaf_vlans_save(self): + log.debug("_create_lflf_vlans") + + env_lf = models_env.Ambiente.objects.filter(dcroom=int(self.rack.dcroom.id), + grupo_l3__nome=str(self.rack.dcroom.name), + ambiente_logico__nome="LEAF-LEAF") + log.debug("Leaf-leaf environments: " + str(env_lf)) + + tipo_rede = "Ponto a ponto" + try: + id_network_type = models_vlan.TipoRede().get_by_name(tipo_rede).id + except: + network_type = models_vlan.TipoRede() + network_type.tipo_rede = tipo_rede + network_type.save() + id_network_type = network_type.id + pass + + for env in env_lf: + env_id = env.id + vlan_number = int(env.min_num_vlan_1) + vlan_name = "VLAN_LFxLF_" + env.divisao_dc.nome + "_" + env.grupo_l3.nome + + try: + models_vlan.Vlan.objects.all().filter(nome=vlan_name).uniqueResult() + except: + log.debug("debug lfxlf") + for net in env.configs: + bloco = net.network + prefix = bloco.split('/')[-1] + network = { + 'prefix': prefix, + 'network_type': id_network_type + } + if str(net.ip_version)[-1] is "4": + create_networkv4 = network + elif str(net.ip_version)[-1] is "6": + create_networkv6 = network + obj = { + 'name': vlan_name, + 'num_vlan': vlan_number, + 'environment': env_id, + 'default_vrf': env.default_vrf.id, + 'vrf': env.vrf, + 'create_networkv4': create_networkv4 if create_networkv4 else None, + 'create_networkv6': create_networkv6 if create_networkv6 else None + } + facade_vlan_v3.create_vlan(obj, self.user) + + def leaf_leaf_envs_save(self): + log.debug("_create_lflf_envs") + + env_lf = models_env.Ambiente.objects.filter(dcroom=int(self.rack.dcroom.id), + grupo_l3__nome=str(self.rack.dcroom.name), + ambiente_logico__nome="LEAF-LEAF") + log.debug("Leaf-leaf environments: " + str(env_lf)) + + try: + id_l3 = models_env.GrupoL3().get_by_name(self.rack.nome).id + except: + l3_dict = models_env.GrupoL3() + l3_dict.nome = self.rack.nome + l3_dict.save() + id_l3 = l3_dict.id + pass + + for env in env_lf: + config_subnet = [] + for net in env.configs: + cidr = list(IPNetwork(net.network).subnet(int(net.subnet_mask)))[self.rack.numero] + network = { + 'network': str(cidr), + 'ip_version': str(net.ip_version), + 'network_type': int(net.id_network_type.id), + 'subnet_mask': int(net.subnet_mask) + } + config_subnet.append(network) + + obj = { + 'grupo_l3': id_l3, + 'ambiente_logico': env.ambiente_logico.id, + 'divisao_dc': env.divisao_dc.id, + 'acl_path': env.acl_path, + 'ipv4_template': env.ipv4_template, + 'ipv6_template': env.ipv6_template, + 'link': env.link, + 'min_num_vlan_2': env.min_num_vlan_1, + 'max_num_vlan_2': env.max_num_vlan_1, + 'min_num_vlan_1': env.min_num_vlan_1, + 'max_num_vlan_1': env.max_num_vlan_1, + 'vrf': env.vrf, + 'father_environment': env.id, + 'default_vrf': env.default_vrf.id, + 'configs': config_subnet, + 'fabric_id': self.rack.dcroom.id + } + environment = facade_env.create_environment(obj) + log.debug("Environment object: %s" % str(environment)) + + def prod_environment_save(self): + log.debug("_create_prod_envs") + + prod_envs = models_env.Ambiente.objects.filter(dcroom=int(self.rack.dcroom.id), + grupo_l3__nome=str(self.rack.dcroom.name), + ambiente_logico__nome="PRODUCAO" + ).exclude(divisao_dc__nome="BO_DMZ") + + log.debug("PROD environments: " + str(prod_envs)) + + try: + id_grupo_l3 = models_env.GrupoL3().get_by_name(self.rack.nome).id + except: + grupo_l3_dict = models_env.GrupoL3() + grupo_l3_dict.nome = self.rack.nome + grupo_l3_dict.save() + id_grupo_l3 = grupo_l3_dict.id + pass + + if self.rack.dcroom.config: + fabricconfig = self.rack.dcroom.config + else: + log.debug("sem configuracoes do fabric %s" % str(self.rack.dcroom.id)) + fabricconfig = list() + + try: + fabricconfig = json.loads(fabricconfig) + except: + pass + + try: + fabricconfig = ast.literal_eval(fabricconfig) + log.debug("config -ast: %s" % str(fabricconfig)) + except: + pass + + environment = list() + for env in prod_envs: + details = None + for fab in fabricconfig.get("Ambiente"): + if int(fab.get("id")) == env.id: + details = fab.get("details") + + config_subnet = list() + for net in env.configs: + + if isinstance(details, list) and len(details) > 0: + if details[0].get(str(net.ip_version)): + new_prefix = details[0].get(str(net.ip_version)).get("new_prefix") + else: + new_prefix = 27 if net.ip_version == "v4" else 64 + network = { + 'ip_version': net.ip_version, + 'network_type': net.id_network_type.id, + 'subnet_mask': new_prefix + } + config_subnet.append(network) + + obj = { + 'grupo_l3': id_grupo_l3, + 'ambiente_logico': env.ambiente_logico.id, + 'divisao_dc': env.divisao_dc.id, + 'acl_path': env.acl_path, + 'ipv4_template': env.ipv4_template, + 'ipv6_template': env.ipv6_template, + 'link': env.link, + 'min_num_vlan_2': env.min_num_vlan_1, + 'max_num_vlan_2': env.max_num_vlan_1, + 'min_num_vlan_1': env.min_num_vlan_1, + 'max_num_vlan_1': env.max_num_vlan_1, + 'vrf': env.vrf, + 'father_environment': env.id, + 'default_vrf': env.default_vrf.id, + 'configs': config_subnet, + 'fabric_id': self.rack.dcroom.id + } + obj_env = facade_env.create_environment(obj) + environment.append(obj_env) + log.debug("Environment Prod. object: %s" % str(obj_env)) + + for switch in [self.rack.id_sw1, self.rack.id_sw2]: + try: + equipamento_ambiente = EquipamentoAmbiente() + equipamento_ambiente.ambiente = obj_env + equipamento_ambiente.equipamento = switch + equipamento_ambiente.is_router = True + equipamento_ambiente.create(self.user) + except EquipamentoAmbienteDuplicatedError: + pass + + return environment + + def children_prod_environment_save(self): + log.debug("_create_prod_children") + + try: + env = models_env.Ambiente.objects.filter(dcroom=int(self.rack.dcroom.id), + divisao_dc__nome="BE", + grupo_l3__nome=str(self.rack.nome), + ambiente_logico__nome="PRODUCAO" + ).uniqueResult() + log.debug("BE environments: %s" % env) + except Exception as e: + raise Exception("Erro: %s" % e) + + if self.rack.dcroom.config: + fabricconfig = self.rack.dcroom.config + else: + log.debug("No fabric configurations %s" % str(self.rack.dcroom.id)) + fabricconfig = list() + + try: + fabricconfig = json.loads(fabricconfig) + fabricconfig = ast.literal_eval(fabricconfig) + log.debug("config -ast: %s" % str(fabricconfig)) + except: + log.debug("Error loading fabric json.") + + environment = None + father_id = env.id + fabenv = None + + for fab in fabricconfig.get("Ambiente"): + if int(fab.get("id")) == int(env.father_environment.id): + fabenv = fab.get("details") + + if not fabenv: + log.debug("No configurations for child environment of env id=%s" % ( + str(env.id))) + return False + + fabenv.sort(key=operator.itemgetter('min_num_vlan_1')) + log.debug("Order by min_num_vlan: %s" % str(fabenv)) + + for amb in fabenv: + log.debug("amb: %s" % amb) + try: + id_div = models_env.DivisaoDc().get_by_name(amb.get("name")).id + except: + div_dict = models_env.DivisaoDc() + div_dict.nome = amb.get("name") + div_dict.save() + id_div = div_dict.id + pass + + config_subnet = list() + for net_dict in amb.get("config"): + network = { + 'ip_version': net_dict.get("type"), + 'network_type': int(net_dict.get("network_type")), + 'subnet_mask': int(net_dict.get("new_prefix")), + 'network_mask': int(net_dict.get("mask")) + } + config_subnet.append(network) + log.debug("config: %s" % config_subnet) + obj = { + 'grupo_l3': env.grupo_l3.id, + 'ambiente_logico': env.ambiente_logico.id, + 'divisao_dc': id_div, + 'acl_path': env.acl_path, + 'ipv4_template': env.ipv4_template, + 'ipv6_template': env.ipv6_template, + 'link': env.link, + 'min_num_vlan_2': amb.get("min_num_vlan_1"), + 'max_num_vlan_2': amb.get("max_num_vlan_1"), + 'min_num_vlan_1': amb.get("min_num_vlan_1"), + 'max_num_vlan_1': amb.get("max_num_vlan_1"), + 'vrf': env.vrf, + 'father_environment': father_id, + 'default_vrf': env.default_vrf.id, + 'configs': config_subnet, + 'fabric_id': self.rack.dcroom.id + } + environment = facade_env.create_environment(obj) + log.debug("Environment object: %s" % str(environment)) + + for switch in [self.rack.id_sw1, self.rack.id_sw2]: + try: + equipamento_ambiente = EquipamentoAmbiente() + equipamento_ambiente.ambiente = environment + equipamento_ambiente.equipamento = switch + equipamento_ambiente.is_router = True + equipamento_ambiente.create(self.user) + except EquipamentoAmbienteDuplicatedError: + pass + except Exception as e: + log.debug("error %s" % e) + + return environment + + def manage_vlan_save(self): + log.debug("_create_oobvlans") + + env_oob = models_env.Ambiente.objects.filter(dcroom=int(self.rack.dcroom.id), + divisao_dc__nome="OOB", + grupo_l3__nome=str(self.rack.dcroom.name), + ambiente_logico__nome="GERENCIA").uniqueResult() + log.debug("OOB environments: " + str(env_oob)) + + for env in [env_oob]: + + obj = { + 'name': "VLAN_" + env.ambiente_logico.nome + "_" + self.rack.nome, + 'environment': env.id, + 'default_vrf': env.default_vrf.id, + 'vrf': env.vrf, + 'create_networkv4': None, + 'create_networkv6': None, + 'description': "Vlan de gerência do rack " + self.rack.nome + + } + vlan = facade_vlan_v3.create_vlan(obj, self.user) + + log.debug("Vlan allocated: " + str(vlan)) + + network = dict() + for config in env.configs: + log.debug("Configs: " + str(config)) + network = dict(prefix=config.subnet_mask, + cluster_unit=None, + vlan=vlan.id, + network_type=config.id_network_type.id, + environmentvip=None) + log.debug("Network allocated: " + str(network)) + facade_redev4_v3.create_networkipv4(network, self.user) + + return vlan + + def rack_environment_remove(self): + log.info("_remove_envs") + + envs = models_env.Ambiente.objects.filter(dcroom=int(self.rack.dcroom.id), + grupo_l3__nome=str(self.rack.nome)) + + for env in envs: + env.delete_v3() + + log.debug("PROD environments: %s. Total: %s" % (str(envs), len(envs))) + + def rack_vlans_remove(self): + log.info("remove_vlans") + + vlans = models_vlan.Vlan.objects.filter(nome__icontains="_"+self.rack.nome) + + for vlan in vlans: + vlan.delete_v3() + + log.debug("Vlans: %s. total: %s" % (vlans, len(vlans))) diff --git a/networkapi/api_rack/urls.py b/networkapi/api_rack/urls.py index 787223ad1..66b98549c 100644 --- a/networkapi/api_rack/urls.py +++ b/networkapi/api_rack/urls.py @@ -7,10 +7,12 @@ from networkapi.api_rack.views import RackDeployView +from networkapi.api_rack.views import RackForeman from networkapi.api_rack.views import RackView urlpatterns = patterns('', url(r'^rack/(?P\d+)/equipments/$', rack_views.RackDeployView.as_view()), + url(r'^rack/foreman/(?P\d+)/', rack_views.RackForeman.as_view()), url(r'^rack/fabric/(?P\d+)[/]$', rack_views.RackView.as_view()), url(r'^rack/$', rack_views.RackView.as_view()), url(r'^rack/(?P\d+)/$', rack_views.RackView.as_view()), @@ -19,7 +21,9 @@ url(r'^rack/list/all/$', rack_views.RackView.as_view()), url(r'^rack/next/', rack_facade.available_rack_number), + url(r'^dc/(?P\d+)/$', rack_views.DataCenterView.as_view()), url(r'^dc/$', rack_views.DataCenterView.as_view()), + url(r'^dcrooms/(?P\d+)/$', rack_views.FabricView.as_view()), url(r'^dcrooms/$', rack_views.FabricView.as_view()), url(r'^dcrooms/id/(?P\d+)/$', rack_views.FabricView.as_view()), url(r'^dcrooms/name/(?P\s+)/$', rack_views.FabricView.as_view()), diff --git a/networkapi/api_rack/views.py b/networkapi/api_rack/views.py index 7840280e4..602533c1d 100644 --- a/networkapi/api_rack/views.py +++ b/networkapi/api_rack/views.py @@ -16,30 +16,22 @@ import glob import logging -import re -import commands -from django.core.exceptions import ObjectDoesNotExist + from django.db.transaction import commit_on_success from django.core.exceptions import ObjectDoesNotExist from rest_framework import status -from rest_framework.decorators import api_view from rest_framework.decorators import permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView -from networkapi.api_rack.permissions import Read, Write + +from networkapi.api_rack.permissions import Write from networkapi.api_rack import facade, exceptions from networkapi.api_rack.serializers import RackSerializer, DCSerializer, DCRoomSerializer from networkapi.api_rest import exceptions as api_exceptions -from networkapi.equipamento.models import Equipamento, EquipamentoAmbiente -from networkapi.ip.models import Ip -from networkapi.ip.models import IpEquipamento -from networkapi.rack.models import Rack, Datacenter, DatacenterRooms -from networkapi.rest import RestResource -from networkapi.rest import UserNotAuthorizedError +from networkapi.equipamento.models import Equipamento from networkapi.system.facade import get_value as get_variable -from networkapi.system.facade import save_variable as save_variable from networkapi.system import exceptions as var_exceptions from networkapi.distributedlock import LOCK_EQUIPMENT_DEPLOY_CONFIG_USERSCRIPT @@ -71,7 +63,7 @@ def post(self, request, *args, **kwargs): exceptions.InvalidInputException) as exception: log.exception(exception) raise exception - except Exception, e: + except Exception as e: log.exception(e) raise api_exceptions.NetworkAPIException(e) @@ -93,10 +85,11 @@ def put(self, request, *args, **kwargs): data['rack'] = rack_serializer.data return Response(data, status=status.HTTP_200_OK) - except Exception, e: + except Exception as e: log.exception(e) raise api_exceptions.NetworkAPIException(e) + @commit_on_success def get(self, user, *args, **kwargs): """Handles GET requests to list all Racks""" @@ -117,10 +110,11 @@ def get(self, user, *args, **kwargs): return Response(data, status=status.HTTP_200_OK) - except Exception, e: + except Exception as e: log.exception(e) raise api_exceptions.NetworkAPIException(e) + @commit_on_success def delete(self, user, *args, **kwargs): """Handles DELETE requests to list all Racks URLs: /api/rack/ @@ -137,7 +131,7 @@ def delete(self, user, *args, **kwargs): return Response(data, status=status.HTTP_200_OK) - except Exception, e: + except Exception as e: log.exception(e) raise api_exceptions.NetworkAPIException(e) @@ -182,12 +176,10 @@ def post(self, *args, **kwargs): output = deploy_facade.deploy_config_in_equipment_synchronous(rel_filename, equip, lockvar) log.debug("equipment output: %s" % (output)) - except Exception, e: + except Exception as e: log.exception(e) raise exceptions.RackAplError(e) - - # Create Foreman entries for rack switches - facade.api_foreman(rack) + # SEPARAR AQUI! datas = dict() success_map = dict() @@ -197,18 +189,45 @@ def post(self, *args, **kwargs): return Response(datas, status=status.HTTP_201_CREATED) + except exceptions.RackNumberNotFoundError as e: + log.exception(e) + raise exceptions.NetworkAPIException(e) + except var_exceptions.VariableDoesNotExistException as e: + log.error(e) + raise api_exceptions.NetworkAPIException( + 'Erro buscando a variável PATH_TO_ADD_CONFIG ou REL_PATH_TO_ADD_CONFIG. Erro: %s' % e) + except Exception as e: + log.exception(e) + raise api_exceptions.NetworkAPIException(e) + + +class RackForeman (APIView): + def post(self, *args, **kwargs): + try: + log.info('RACK Foreman.') + + rack_id = kwargs.get('rack_id') + rack = facade.get_by_pk(rack_id) + # Create Foreman entries for rack switches + facade.api_foreman(rack) + raise api_exceptions.NetworkAPIException('chegou') + return Response(datas, status=status.HTTP_201_CREATED) + except exceptions.RackNumberNotFoundError, e: log.exception(e) raise exceptions.NetworkAPIException(e) + except var_exceptions.VariableDoesNotExistException, e: log.error(e) raise api_exceptions.NetworkAPIException( - 'Erro buscando a variável PATH_TO_ADD_CONFIG ou REL_PATH_TO_ADD_CONFIG. Erro: %s' % e) + 'Erro ao registrar o Switch no Foreman. Erro: %s' % e) + except Exception, e: log.exception(e) raise api_exceptions.NetworkAPIException(e) +#===============================================@==================================================== class RackConfigView(APIView): @commit_on_success @@ -221,23 +240,39 @@ def post(self, request, *args, **kwargs): data = dict() return Response(data, status=status.HTTP_200_OK) - except Exception, e: + except Exception as e: raise api_exceptions.NetworkAPIException(e) class RackEnvironmentView(APIView): + @permission_classes((IsAuthenticated, Write)) @commit_on_success def post(self, request, *args, **kwargs): try: logging.getLogger('Alocando ambientes e vlans do rack') rack_id = kwargs.get("rack_id") - facade.rack_environments_vlans(rack_id, request.user) + # facade.rack_environments_vlans(rack_id, request.user) + facade.allocate_env_vlan(request.user, rack_id) data = dict() return Response(data, status=status.HTTP_200_OK) - except Exception, e: + except Exception as e: + raise api_exceptions.NetworkAPIException(e) + + @permission_classes((IsAuthenticated, Write)) + @commit_on_success + def delete(self, request, *args, **kwargs): + try: + logging.getLogger('Remove environments and vlans.') + + rack_id = kwargs.get("rack_id") + facade.deallocate_env_vlan(request.user, rack_id) + + data = dict() + return Response(data, status=status.HTTP_200_OK) + except Exception as e: raise api_exceptions.NetworkAPIException(e) @@ -259,10 +294,9 @@ def post(self, request, *args, **kwargs): return Response(data, status=status.HTTP_201_CREATED) - except Exception, e: + except Exception as e: raise api_exceptions.NetworkAPIException(e) - @commit_on_success def get(self, request, *args, **kwargs): try: @@ -274,7 +308,25 @@ def get(self, request, *args, **kwargs): data['dc'] = dc return Response(data, status=status.HTTP_200_OK) - except Exception, e: + except Exception as e: + raise api_exceptions.NetworkAPIException(e) + + @commit_on_success + def delete(self, request, *args, **kwargs): + + try: + log.info('Delete DC') + + dc_id = kwargs.get("dc_id").split(";") + + facade.delete_dc(dc_id) + + data = dict() + + return Response(data, status=status.HTTP_200_OK) + + except Exception as e: + log.exception(e) raise api_exceptions.NetworkAPIException(e) @@ -295,7 +347,7 @@ def post(self, request, *args, **kwargs): data['dcroom'] = dcroom_serializer.data return Response(data, status=status.HTTP_201_CREATED) - except Exception, e: + except Exception as e: raise api_exceptions.NetworkAPIException(e) @commit_on_success @@ -320,10 +372,9 @@ def put(self, request, *args, **kwargs): data['fabric'] = fabric_serializer.data return Response(data, status=status.HTTP_200_OK) - except Exception, e: + except Exception as e: raise api_exceptions.NetworkAPIException(e) - @commit_on_success def get(self, request, *args, **kwargs): try: @@ -338,5 +389,23 @@ def get(self, request, *args, **kwargs): data['fabric'] = fabric return Response(data, status=status.HTTP_200_OK) - except Exception, e: - raise api_exceptions.NetworkAPIException(e) \ No newline at end of file + except Exception as e: + raise api_exceptions.NetworkAPIException(e) + + @commit_on_success + def delete(self, request, *args, **kwargs): + + try: + log.info('Delete Fabric') + + fabric_id = kwargs.get("fabric_id").split(";") + + facade.delete_dcrooms(fabric_id) + + data = dict() + + return Response(data, status=status.HTTP_200_OK) + + except Exception as e: + log.exception(e) + raise api_exceptions.NetworkAPIException(e) diff --git a/networkapi/api_vlan/tests/sanity/json/get/get_one_vlan.json b/networkapi/api_vlan/tests/sanity/json/get/get_one_vlan.json index 40a6258b4..9fa924b11 100644 --- a/networkapi/api_vlan/tests/sanity/json/get/get_one_vlan.json +++ b/networkapi/api_vlan/tests/sanity/json/get/get_one_vlan.json @@ -13,7 +13,8 @@ "id": 1, "name": "VLAN NUM 2 - RACK-1", "num_vlan": 2, - "vrf": null + "vrf": null, + "vxlan": false } ] } diff --git a/networkapi/api_vlan/tests/sanity/json/get/get_one_vlan_details.json b/networkapi/api_vlan/tests/sanity/json/get/get_one_vlan_details.json index e2ba9829a..7aecbcc0c 100644 --- a/networkapi/api_vlan/tests/sanity/json/get/get_one_vlan_details.json +++ b/networkapi/api_vlan/tests/sanity/json/get/get_one_vlan_details.json @@ -72,7 +72,8 @@ "id": 1, "name": "VLAN NUM 2 - RACK-1", "num_vlan": 2, - "vrf": null + "vrf": null, + "vxlan": false } ] } diff --git a/networkapi/api_vlan/tests/sanity/json/post/post_one_vlan.json b/networkapi/api_vlan/tests/sanity/json/post/post_one_vlan.json index 7d8d45806..60d047746 100644 --- a/networkapi/api_vlan/tests/sanity/json/post/post_one_vlan.json +++ b/networkapi/api_vlan/tests/sanity/json/post/post_one_vlan.json @@ -12,7 +12,8 @@ "environment": 1, "name": "VLAN 300 - AMBIENTE 1", "num_vlan": 300, - "vrf": null + "vrf": null, + "vxlan": false } ] } diff --git a/networkapi/api_vlan/tests/sanity/json/post/post_one_vlan_without_number.json b/networkapi/api_vlan/tests/sanity/json/post/post_one_vlan_without_number.json index 5a09a4c5a..b74b30a2a 100644 --- a/networkapi/api_vlan/tests/sanity/json/post/post_one_vlan_without_number.json +++ b/networkapi/api_vlan/tests/sanity/json/post/post_one_vlan_without_number.json @@ -11,7 +11,8 @@ "description": "", "environment": 1, "name": "VLAN AUTO - AMBIENTE 1", - "vrf": null + "vrf": null, + "vxlan": false } ] } diff --git a/networkapi/api_vlan/tests/sanity/json/put/put_one_change_env_vlan_with_nets.json b/networkapi/api_vlan/tests/sanity/json/put/put_one_change_env_vlan_with_nets.json index aac4797f9..5a83b65a9 100644 --- a/networkapi/api_vlan/tests/sanity/json/put/put_one_change_env_vlan_with_nets.json +++ b/networkapi/api_vlan/tests/sanity/json/put/put_one_change_env_vlan_with_nets.json @@ -13,7 +13,8 @@ "id": 4, "name": "VLAN NUM 4 - RACK-1", "num_vlan": 4, - "vrf": null + "vrf": null, + "vxlan": false } ] } diff --git a/networkapi/api_vlan/tests/sanity/json/put/put_one_vlan.json b/networkapi/api_vlan/tests/sanity/json/put/put_one_vlan.json index 40a6258b4..9fa924b11 100644 --- a/networkapi/api_vlan/tests/sanity/json/put/put_one_vlan.json +++ b/networkapi/api_vlan/tests/sanity/json/put/put_one_vlan.json @@ -13,7 +13,8 @@ "id": 1, "name": "VLAN NUM 2 - RACK-1", "num_vlan": 2, - "vrf": null + "vrf": null, + "vxlan": false } ] } diff --git a/networkapi/equipamento/resource/EquipmentFindResource.py b/networkapi/equipamento/resource/EquipmentFindResource.py index f31d3c0d3..cd0897c3b 100644 --- a/networkapi/equipamento/resource/EquipmentFindResource.py +++ b/networkapi/equipamento/resource/EquipmentFindResource.py @@ -102,27 +102,32 @@ def get_equips(equipments): Join all properties needed """ - itens = [] + itens = list() + logging.debug("get") + logging.debug(equipments) for equip in equipments: + logging.debug("eq") + logging.debug(equip) equip_dict = prepares_equips(equip) itens.append(equip_dict) return itens -@cache_function(EQUIPMENT_CACHE_TIME, True) +# @cache_function(EQUIPMENT_CACHE_TIME, True) def prepares_equips(equip): + logging.debug("20") - equip_dict = dict() equip_dict = model_to_dict(equip) equip_dict['tipo_equipamento'] = equip.tipo_equipamento.tipo_equipamento + logging.debug("21") group_list = [] for g in equip.grupos.all(): group_dict = dict() group_dict['nome'] = g.nome group_list.append(group_dict) - + logging.debug("22") ips_list = [] env_list = [] for ipe in equip.ipequipamento_set.all(): @@ -139,7 +144,7 @@ def prepares_equips(equip): env_list.append(ipp.networkipv4.vlan.ambiente.id) ips_list.append(ip_dict) - + logging.debug("23") for ipv6e in equip.ipv6equipament_set.all(): ipp = Ipv6.objects.select_related('ambiente').get(id=ipv6e.ip.id) @@ -155,7 +160,7 @@ def prepares_equips(equip): env_list.append(ipp.networkipv6.vlan.ambiente.id) ips_list.append(ipv6_dict) - + logging.debug("24") for env in equip.equipamentoambiente_set.all(): if env.ambiente.id not in env_list: @@ -172,7 +177,7 @@ def prepares_equips(equip): ip_dict['ambiente'] = amb.divisao_dc.nome + '-' + \ amb.ambiente_logico.nome + '-' + amb.grupo_l3.nome ips_list.append(ip_dict) - + logging.debug("25") equip_dict['grupos'] = group_list equip_dict['ips'] = ips_list @@ -180,12 +185,12 @@ def prepares_equips(equip): equip_dict['is_more'] = True else: equip_dict['is_more'] = False - + logging.debug("26") if len(group_list) > 3: equip_dict['is_more_group'] = True else: equip_dict['is_more_group'] = False - + logging.debug("27") return equip_dict @@ -228,21 +233,21 @@ def handle_post(self, request, user, *args, **kwargs): msg = u'There is no value to the equipment tag of XML request.' self.log.error(msg) return self.response_error(3, msg) - + logging.debug("1") # Get XML data start_record = equipment_map.get('start_record') end_record = equipment_map.get('end_record') asorting_cols = equipment_map.get('asorting_cols') searchable_columns = equipment_map.get('searchable_columns') custom_search = equipment_map.get('custom_search') - + logging.debug("2") name = equipment_map.get('nome') iexact = equipment_map.get('exato') environment = equipment_map.get('ambiente') equip_type = equipment_map.get('tipo_equipamento') group = equipment_map.get('grupo') ip = equipment_map.get('ip') - + logging.debug("3") # Business Rules # Start with alls @@ -264,7 +269,7 @@ def handle_post(self, request, user, *args, **kwargs): equip = equip.filter(nome=name) else: equip = equip.filter(nome__icontains=name) - + logging.debug("4") # If environment is valid, add to filter if environment is not None: if not is_valid_int_greater_zero_param(environment, False): @@ -272,7 +277,7 @@ def handle_post(self, request, user, *args, **kwargs): else: equip = equip.filter( equipamentoambiente__ambiente__pk=environment) - + logging.debug("5") if equip_type is not None: # If equip_type is valid, add to filter if not is_valid_int_greater_zero_param(equip_type, False): @@ -280,14 +285,14 @@ def handle_post(self, request, user, *args, **kwargs): None, 'tipo_equipamento', equip_type) else: equip = equip.filter(tipo_equipamento__pk=equip_type) - + logging.debug("6") if group is not None: # If equip_type is valid, add to filter if not is_valid_int_greater_zero_param(group, False): raise InvalidValueError(None, 'grupo', group) else: equip = equip.filter(grupos__pk=group) - + logging.debug("7") if ip is not None: # If ip is valid if not is_valid_string_minsize(ip, 1, False): @@ -345,19 +350,19 @@ def handle_post(self, request, user, *args, **kwargs): equip = equip.filter( oct1 & oct2 & oct3 & oct4 & oct5 & oct6 & oct7 & oct8) - + logging.debug("9") equip = equip.distinct() # Datatable paginator equip, total = build_query_to_datatable( equip, asorting_cols, custom_search, searchable_columns, start_record, end_record) - + logging.debug("10") itens = get_equips(equip) - + logging.debug("15") equipment_map = dict() equipment_map['equipamento'] = itens equipment_map['total'] = total - + logging.debug("17") return self.response(dumps_networkapi(equipment_map)) except InvalidValueError, e: diff --git a/networkapi/error_message_utils.py b/networkapi/error_message_utils.py index 41e9f441b..d65997a12 100644 --- a/networkapi/error_message_utils.py +++ b/networkapi/error_message_utils.py @@ -1,356 +1,358 @@ -# -*- 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 networkapi.infrastructure import xml_utils - -error_messages = { - 1: u'Falha ao acessar a fonte de dados', - 2: u'Falha ao executar o script. Causa: %s', - 3: u'Falha ao executar a leitura do XML de requisição. Causa: %s', - 4: u'Falha ao gerar o XML de resposta. Causa: %s', - 100: u'Tipo de equipamento não cadastrado', - 101: u'Model of equipment not registered', - 102: u'Group of equipment not registered', - 103: u'Identificador do tipo de equipamento é obrigatório', - 104: u'Identificador do modelo do equipamento é obrigatório', - 105: u'Nome do equipamento é obrigatório', - 106: u'Identificador do grupo do equipamento é obrigatório', - 107: u'Equipamento do grupo “Equipamentos Orquestração” somente poderá ser criado com tipo igual a “Servidor Virtual"', - 108: u'the VLAN name duplicated within an environment informed', - 109: u'Não existe número de VLAN disponível nos intervalos de %d até %d e de %d até %d para o ambiente informado', - 110: u'Ambiente com Divisão DC diferente de BE e FE', - 111: u'Type of network not registered', - 112: u'Environment not registered', - 113: u'O nome da VLAN é obrigatório', - 114: u'O identificador do ambiente é obrigatório', - 115: u'O identificador da VLAN é obrigatório', - 116: u'VLAN not registered', - 117: u'Equipment %s not registered', - 118: u'IP %s not registered for the equipment %s', - 119: u'IP not registered', - 120: u'IP already registered for the equipment', - 121: u'VLAN não validada', - 122: u'VLAN já ativada', - 123: u'The identifier of the IP is required', - 124: u'Healthcheck_expect não cadastrado', - 125: u'Invalid value of the finality', - 126: u'Invalid value of the client', - 127: u'Invalid value of the environment', - 128: u'Invalid value of the cache', - 129: u'Invalid value of the method_bal', - 130: u'Formato do valor do transbordo %s inválido', - 131: u'Valor do método de balanceamento inválido', - 132: u'Invalid value of the persistence', - 133: u'Valor do tipo do healthcheck inválido ou inconsistente em relação ao valor do healthcheck_expect', - 134: u'Valor do healthcheck inconsistente em relação ao valor do tipo do healthcheck', - 135: u'Invalid value of the timeout', - 136: u'Invalid value of the host', - 137: u'Invalid value of the maximum number of connections', - 138: u'Valor da variável porta_servico %s inválido', - 139: u'Não existe ligação no front cadastrada para a interface do equipamento', - 140: u'O sufixo do reals_name é obrigatório para criar ou alterar o vip %s do grupo virtual', - 141: u'Interface não cadastrada', - 142: u'Interface não está relacionada com o host', - 143: u'Interface do switch está com o campo protegida setado', - 144: u'A ligação no front da interface não tem nenhuma interface que representa um switch', - 145: u'O nome da interface é obrigatório', - 146: u'Equipamento já está cadastrado no grupo', - 147: u'O identificador do equipamento é obrigatório', - 148: u'Existe mais de um equipamento com o mesmo nome', - 149: u'Equipamento com nome duplicado', - 150: u'%s', - 151: u'Valor do real %s inválido', - 152: u'Request VIP is not registered.', - 153: u'IP %s.%s.%s.%s not registered for the environment %s', - 154: u'O valor da indicação de ativo do usuário é inválido', - 156: u'Equipamento %s já está cadastrado no ambiente %s', - 157: u'Equipamento %s não está cadastrado para o ambiente %s', - 158: u'Tipo de roteiro %s não cadastrado', - 159: u'O identificador do grupo layer 3 é obrigatório', - 160: u'Grupo layer 3 %s não cadastrado', - 161: u'O identificador do ambiente lógico é obrigatório', - 162: u'Ambiente lógico %s não cadastrado', - 163: u'O identificador da divisão DC é obrigatório', - 164: u'Divisão DC %s não cadastrada', - 165: u'Roteiro %s não cadastrado', - 166: u'O nome da marca é obrigatório', - 167: u'Marca %s não cadastrada', - 168: u'O nome do grupo layer 3 é obrigatório', - 169: u'Nome %s já cadastrado para outro grupo layer 3', - 170: u'O protocolo é obrigatório', - 171: u'Tipo de acesso %s não cadastrado', - 172: u'O nome do ambiente lógico é obrigatório', - 173: u'Nome %s já cadastrado para outro ambiente lógico', - 174: u'O nome da divisão DC é obrigatório', - 175: u'Nome %s já cadastrado para outra divisão DC', - 176: u'O nome do tipo de rede é obrigatório', - 177: u'User %s not registered', - 178: u'O user do usuário é obrigatório', - 179: u'User %s já está cadastrado para outro usuário', - 180: u'User Group %s not registered', - 181: u'Nome do grupo de usuário é obrigatório', - 182: u'Grupo de usuário com o nome %s já cadastrado', - 183: u'Usuário %s já está cadastrado no grupo %s', - 184: u'Usuário %s não pertence ao grupo %s', - 185: u'Equipamento %s não pertence ao grupo %s', - 186: u'The IP of the request VIP %s could not be changed because the VIP is already created', - 187: u'Interface com o nome %s já cadastrada para o equipamento %s', - 188: u'Interface %s não está associada ao equipamento %s', - 189: u'Permissão administrativa %s não cadastrada', - 190: u'Roteiro %s não associado ao equipamento %s', - 191: u'Requisição de VIP %s não validada', - 192: u'Requisição de VIP %s já criada', - 193: u'Tipo de roteiro com nome %s já cadastrado', - 194: u'O identificador do tipo de roteiro é obrigatório', - 195: u'O nome do roteiro é obrigatório', - 196: u'O tipo de roteiro %s não pôde ser excluído porque tem roteiro associado', - 197: u'O roteiro %s não pôde ser excluído porque tem equipamento associado', - 198: u'Roteiro %s já está associado ao equipamento %s', - 199: u'A marca %s não pôde ser excluída porque tem modelo associado', - 200: u'O nome do modelo é obrigatório', - 201: u'O identificador da marca é obrigatório', - 202: u'O modelo %s não pôde ser excluído porque tem equipamento associado', - 203: u'Tipo de acesso com o protocolo %s já cadastrado', - 204: u'O tipo de acesso %s não pôde ser excluído porque tem equipamento associado', - 205: u'The fqdn is required', - 206: u'The user is required', - 207: u'The password is required', - 208: u'O identificador do tipo de acesso é obrigatório', - 209: u'Equipamento %s não está associado ao tipo de acesso %s', - 210: u'O valor da indicação de protegida da interface é obrigatório', - 211: u'O valor da indicação de protegida da interface é inválido', - 212: u'Interface da ligação front não cadastrada', - 213: u'Interface da ligação back não cadastrada', - 214: u'Interface %s não pôde ser excluída porque tem outra interface associada', - 215: u'Tipo de rede %s não pôde ser excluído porque tem rede associada', - 216: u'Divisão DC %s não pôde ser excluída porque tem ambiente associado', - 217: u'Ambiente lógico %s não pôde ser excluído porque tem ambiente associado', - 218: u'Grupo layer 3 %s não pôde ser excluído porque tem ambiente associado', - 219: u'Ambiente com o mesmo grupo layer 3, ambiente lógico e divisão DC já cadastrado', - 220: u'Ambiente %s não pôde ser excluído porque tem vlan ou equipamento associado', - 221: u'O nome do usuário é obrigatório', - 222: u'O e-mail do usuário é obrigatório', - 223: u'O valor da indicação de ativo do usuário é obrigatório', - 224: u'O usuário %s não pôde ser excluído porque tem event_log ou grupo associado', - 225: u'A indicação de leitura do grupo do usuário é obrigatória', - 226: u'A indicação de escrita do grupo do usuário é obrigatória', - 227: u'A indicação de edição do grupo do usuário é obrigatória', - 228: u'A indicação de exclusão do grupo do usuário é obrigatória', - 229: u'O valor da indicação de leitura do grupo do usuário é inválido', - 230: u'O valor da indicação de escrita do grupo do usuário é inválido', - 231: u'O valor da indicação de edição do grupo do usuário é inválido', - 232: u'O valor da indicação de exclusão do grupo do usuário é inválido', - 233: u'O identificador do roteiro é obrigatório', - 234: u'O identificador do usuário é obrigatório', - 235: u'O identificador do grupo de usuário é obrigatório', - 236: u'O nome do grupo de equipamento é obrigatório', - 237: u'A função da permissão administrativa é obrigatória', - 238: u'A indicação de leitura da permissão administrativa é obrigatória', - 239: u'A indicação de escrita da permissão administrativa é obrigatória', - 240: u'O valor da indicação de leitura da permissão administrativa é inválido', - 241: u'O valor da indicação de escrita da permissão administrativa é inválido', - 242: u'Equipamento %s já está associado ao tipo de acesso %s', - 243: u'O identificador da requisição de VIP é obrigatório', - 244: u'O valor da indicação de validado da requisição de VIP é inválido', - 245: u'O valor da indicação de vip_criado da requisição de VIP é inválido', - 246: u'A indicação de validado da requisição de VIP é obrigatória', - 247: u'A indicação de vip_criado da requisição de VIP é obrigatória', - 248: u'O identificador da permissão administrativa é obrigatório', - 249: u'O nome do tipo de roteiro é obrigatório', - 250: u'Roteiro com o nome %s e tipo de roteiro %s já cadastrado', - 251: u'Marca com o nome %s já cadastrada', - 252: u'Modelo com o nome %s e a marca %s já cadastrado', - 253: u'Tipo de rede com o nome %s já cadastrado', - 254: u'Grupo de equipamento com o nome %s já cadastrado', - 255: u'O identificador da interface é obrigatório', - 256: u'O identificador do tipo de rede é obrigatório', - 257: u'Permissão administrativa com grupo de usuário %s e função %s já cadastrada', - 258: u'Rights Group Equipment %s not registered', - 259: u'A indicação de leitura do direito grupo equipamento é obrigatória', - 260: u'A indicação de escrita do direito grupo equipamento é obrigatória', - 261: u'A indicação de alterar_config do direito grupo equipamento é obrigatória', - 262: u'A indicação de exclusão do direito grupo equipamento é obrigatória', - 263: u'O valor da indicação de leitura do direito grupo equipamento é inválido', - 264: u'O valor da indicação de escrita do direito grupo equipamento é inválido', - 265: u'O valor da indicação de alterar_config do direito grupo equipamento é inválido', - 266: u'O valor da indicação de exclusão do direito grupo equipamento é inválido', - 267: u'Direitos Grupo Equipamento com o grupo de usuário %s e o grupo de equipamento %s já cadastrado', - 268: u'O identificador dos direitos grupo equipamento é obrigatório', - 269: u'Parameter %s is invalid. Value: %s', - 270: u'The VIP %s could not be changed because the VIP has not been created', - 271: u'Groups of equipment registered with the IP of the VIP request is not allowed of acess.', - 272: u'List the Reals_priority is higher or lower than list the real_server.', - 273: u'Lock wait timeout exceeded; try restarting transaction.', - 274: u'List the Reals_weight is higher or lower than list the real_server.', - 275: u'The healthcheck_type parameter not exist.', - 276: u'The healthcheck_type parameter is not HTTP, then healthcheck and id_healthcheck_expect must be None.', - 277: u'The healthcheck_type parameter is HTTP, then healthcheck and id_healthcheck_expect must NOT be None.', - 278: u'List the ports is higher or lower than list the real_server.', - 279: u'The VLAN name must be a string with a maximum of 50 characters and can not be empty.', - 280: u'The description of the VLAN must be a string with a maximum of 200 characters.', - 281: u'Network IPv4 is not registered.', - 282: u'The identifier RedeIPv4 is mandatory', - 283: u'Environment VIP not registered', - 284: u'There networkIPv4 associated with environment vip', - 285: u'There networkIPv6 associated with environment vip', - 286: u'Network IPv6 is not registered.', - 287: u'At least one of the parameters have to be informed to query', - 288: u'IP is not associated with the equipment', - 289: u'Option VIP is not registered.', - 290: u'Option vip is already associated with the environment vip', - 291: u'Option vip is not associated with the environment vip', - 292: u'IPv6 %s not registered for the environment %s', - 293: u'Vlan is currently in active/deployed state. It needs to be undeployed before deletion.', - 294: u'Invalid Environment Configuration or not registered', - 295: u'Unavailable address to create a NetworkIPv4', - 296: u'Unavailable address to create a NetworkIPv6', - 297: u'The Request VIP - IPv4 can not change to a Request VIP - IPv6', - 298: u'The Request VIP - IPv6 can not change to a Request VIP - IPv4', - 299: u'Network already activated', - 300: u'Invalid Request VIP IP version, try to use %s', - 301: u'IP Configuration is not registred.', - 302: u'Environment Configuration already exists', - 303: u'EquipmentAccess is not registred.', - 304: u'TypeAccess is not registred', - 305: u'Network %s don\'t have associate IPs', - 306: u'Vlan já cadastrada com o número %s', - 307: u'%s', - 308: u'Não existe associação de Ip e Equipamento para o IP %s', - 309: u'Failure to remove an association between an equipment and a group because the equipment is related only to one group.', - 310: u'Não foi possível excluir o grupo %s por alguns equipamentos estarem associados apenas a este grupo. Equipamentos: %s', - 311: u'Já existe uma Vlan com o arquivo_acl = %s', - 312: u'Tipo de Equipamento com nome %s, já cadastrado.', - 313: u'%s.', # Healthcheck já cadastrado - 314: u'%s', # Erro Vlan - 315: u'%s', # Erro Vlan - 316: u'Não existe Ambiente VIP cadastrado com os valores fornecidos: finalidade - %s ,cliente - %s, ambiente - %s.', - 317: u'Ip não encontrado para equipamento %s e ambiente vip %s.', - 318: u'O Ip %s e o Equipamento %s, não estão associados.', - 319: u'There is a request VIP pointing to this %s, the %s id = %s can not be excluded.', - 320: u'There are equipment related Ips, which are not part of the Environment Ip.', - 321: u'Não há rede %s no ambiente vip fornecido.', - 322: u'Requisição de VIP %s não criada', - 323: u'Ambiente %s não pôde ser excluído pois a rede %s da vlan %s tem um ip associado com a requisição vip %s.', - 324: u'Ambiente %s não pôde ser excluído pois a vlan %s está ativa.', - 325: u'Invalid value of the priority.', - # VipRequest Real server equipment error - 326: u'Não foi possível recuperar o equipamento %s associado a um real server.', - # VipRequest Real server equipment ip association error - 327: u'Não foi possível recuperar o ip %s e equipamento %s associados ao real server.', - # VipRequest Real server ip doesn't exist - 328: u'Não foi possível recuperar o IP %s associado ao real server %s.', - 329: u'Existe uma inconsistência de prioridade de real server no banco de dados.', - 330: u'Existe uma inconsistência de peso (weight) de real server no banco de dados.', - 331: u'Existe uma inconsistência de portas de real server no banco de dados.', - 332: u'Existe uma inconsistência na requisição vip, o parâmetro %s é inválido. Valor: %s.', - # 333:u'Alteração de real server realizada com sucesso, mas ocorreram - # erros de script com o(s) real(s) %s e ip(s) %s.', - 333: u'Alteração de real server concluída com falha, ocorreram erros de script com o(s) real(s) %s e ip(s) %s.', - 334: u'%s', - 335: u'Existe uma rede com mesma faixa relacionada com ambiente vip', - 336: u"Não foi possivel desassociar ambiente %s, pois existem ips sendo utilizados pelas requisições vip's. IPv4[ %s ] - IPV6[ %s ]", - 337: u'Valor do parâmetro %s inválido. Valor: %s.', - 338: u'Ocorreu um erro ao salvar o filtro no banco de dados. Verifique se o nome é único.', - 339: u'Não foi possível recuperar o filtro especificado do banco de dados.', - 340: u'Ocorreu um erro ao salvar o filtro editado no banco de dados.', - 341: u'Ocorreu um erro ao remover o filtro no banco de dados.', - 342: u'Não foi possível recuperar o tipo de equipamento especificado do banco de dados.', - 343: u'A associação entre o filtro %s e o tipo de equipamento %s já existe.', - 344: u'%s', - 345: u"Não foi possivel remover o equipamento %s, pois existem ips sendo utilizados por requisições vip's. IPv4[ %s ] - IPV6[ %s ]", - 346: u"Um dos equipamentos associados com o ambiente desta rede também está associado com outro ambiente que tem uma rede com essa mesma faixa, adicione filtros nos ambientes se necessário.", - 347: u"O equipamento que está sendo associado já possui um ip na mesma faixa em outra rede, se necessário adicione filtros nos ambientes.", - 348: u"O tipo de equipamento %s não pode ser desassociado do filtro %s.", - 349: u"O filtro %s não pode ser desassociado do ambiente pois está em uso.", - 350: u'Permissão %s não cadastrada.', - 351: u'Permissão Administrativa com função %s já cadastrada.', - 352: u"Não foi possível desassociar o ip %s do equipamento %s pois o ip está sendo utilizado na requisição vip %s e o equipamento é o único balanceador associado a este ip.", - 353: u'Valores duplicados para Porta Real, Porta Vip e IP do Real na mesma Requisição VIP.', - 354: u'Não foi possível excluir o ip de id %s pois ele está sendo usado em uma requisição VIP.', - 355: u'Não foi possível excluir a rede de id %s pois há um ip nela sendo usado em uma requisição VIP.', - 356: u'Não foi possível excluir a vlan de id %s pois há uma rede que possui um ip sendo usado em uma requisição VIP.', - 357: u'Esse ambiente já possui blocos cadastrados.', - 358: u'Regra inválida ou não cadastrada.', - 359: u'Bloco inválido ou não cadastrado.', - 360: u'Essa requisição vip não possui uma regra.', - 361: u'Esse bloco já está cadastrado na regra.', - 362: u'A regra relacionada a esse vip não possui blocos previamente cadastrados.', - 363: u'Não foi possível remover a rede pois ela está inativa.', - 364: u'Acl não foi criada', - 367: u'O ambiente desta Vlan já possui uma ACL com o nome = %s', - 368: u'Nao foi possivel remover a vlan pois ela esta inativa.', - 369: u'Nao foi possivel remover a vlan pois as seguintes redes nao puderam ser removidas: %s.', - 370: u'Nao foi possivel excluir o vip %s. Remova-o dos equipamentos primeiro.', - 371: u'Bloco não pode ser adicionado porque já existe uma regra para ser aplicada e o valor do parametro override é zero.', - 372: u'Server Pool Does Not Exists', - 373: u'Equipamento(s) do Server Pool: %s não pertence ao mesmo ambiente do Ambiente Vip: %s.', - 374: u'Está requisição vip não possui nenhum server pool cadastrado.', - 375: u'Pool can not be excluded because it is associated with a VIP', - 376: u'Numero de Rack %s ja existe.', - 377: u'Endereco MAC invalido', - 378: u'Rack nao pode ser incluido', - 379: u'Rack nao existe', - 380: u'Arquivo de configuracao do equipamento %s criado', - 381: u'Nome %s ja existe.', - 382: u'Os arquivos de configuracao do Rack %s nao podem ser gerados. %s', - 383: u'Nao foi possivel aplicar a configuracao do rack %s. %s', - 384: u'Erro ao editar ServerPool: %s', - 385: u'Não foi possível desassociar o ip %s do equipamento %s pois o ip está sendo utilizado nos server pools (id:identifier) %s.', - 386: u'Não foi possível excluir a rede %s pois o ip %s contido nela esta sendo usado nos Server Pools (id:identifier) %s.', - 387: u'Não foi possível excluir a vlan %s pois ela possui a rede %s e essa rede possui o ip %s contido nela, e esse ip esta sendo usado nos Server Pools (id:identifier) %s.', - 389: u'Não foi possível excluir o vip %s pois o ip %s do mesmo esta sendo usado nos Server Pools (id:identifier) %s.', - 390: u'Não foi possível excluir o vip %s pois os seguintes vips %s estão usando o mesmo ip %s.', - 391: u'Failure accessing Foreman server: %s', - 392: u'Environment is already associated with the environment vip', - 393: u'Environment is not associated with the environment vip', - 394: u'O ambiente %s não pode ser desvinculado pois existem server pools com reals vinculados a este ambiente.', - 396: u'A operação não pode ser realizada pois o ambiente "%s" do ip %s não possui permissão com um dos ambientes vips "%s".', - 397: u'O Rack, que o servidor está, não foi cadastrado.', - 400: u'Nao foi possivel adicionar o Rack', - 401: u'As mudancas nao foram salvas', - 405: u'Channel não pode ser criado. %s', - 406: u'Channel não pode ser editado. %s', - 407: u'Erro ao remover a variável.', - 410: u'Channel não pode ser deletado. %s', - 413: u'Interface não pode ser desconectada. Remova o Port Channel primeiro.', -} - - -def error_dumps(code, *args): - - if isinstance(code, tuple): - code = code[0] - - message = error_messages.get(code, '') - if len(args) > 0: - message = message % args - - error_map = dict() - error_map['codigo'] = '%04d' % code - error_map['descricao'] = message - - map = dict() - map['erro'] = error_map - - return xml_utils.dumps_networkapi(map) - - -if __name__ == '__main__': - print error_dumps(u'0001', u'Falha ao acessar a fonte de dados') - print error_dumps(1) - print error_dumps(3, 'Causa') - print error_messages[99] +# -*- 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 networkapi.infrastructure import xml_utils + +error_messages = { + 1: u'Falha ao acessar a fonte de dados', + 2: u'Falha ao executar o script. Causa: %s', + 3: u'Falha ao executar a leitura do XML de requisição. Causa: %s', + 4: u'Falha ao gerar o XML de resposta. Causa: %s', + 100: u'Tipo de equipamento não cadastrado', + 101: u'Model of equipment not registered', + 102: u'Group of equipment not registered', + 103: u'Identificador do tipo de equipamento é obrigatório', + 104: u'Identificador do modelo do equipamento é obrigatório', + 105: u'Nome do equipamento é obrigatório', + 106: u'Identificador do grupo do equipamento é obrigatório', + 107: u'Equipamento do grupo “Equipamentos Orquestração” somente poderá ser criado com tipo igual a “Servidor Virtual"', + 108: u'the VLAN name duplicated within an environment informed', + 109: u'Não existe número de VLAN disponível nos intervalos de %d até %d e de %d até %d para o ambiente informado', + 110: u'Ambiente com Divisão DC diferente de BE e FE', + 111: u'Type of network not registered', + 112: u'Environment not registered', + 113: u'O nome da VLAN é obrigatório', + 114: u'O identificador do ambiente é obrigatório', + 115: u'O identificador da VLAN é obrigatório', + 116: u'VLAN not registered', + 117: u'Equipment %s not registered', + 118: u'IP %s not registered for the equipment %s', + 119: u'IP not registered', + 120: u'IP already registered for the equipment', + 121: u'VLAN não validada', + 122: u'VLAN já ativada', + 123: u'The identifier of the IP is required', + 124: u'Healthcheck_expect não cadastrado', + 125: u'Invalid value of the finality', + 126: u'Invalid value of the client', + 127: u'Invalid value of the environment', + 128: u'Invalid value of the cache', + 129: u'Invalid value of the method_bal', + 130: u'Formato do valor do transbordo %s inválido', + 131: u'Valor do método de balanceamento inválido', + 132: u'Invalid value of the persistence', + 133: u'Valor do tipo do healthcheck inválido ou inconsistente em relação ao valor do healthcheck_expect', + 134: u'Valor do healthcheck inconsistente em relação ao valor do tipo do healthcheck', + 135: u'Invalid value of the timeout', + 136: u'Invalid value of the host', + 137: u'Invalid value of the maximum number of connections', + 138: u'Valor da variável porta_servico %s inválido', + 139: u'Não existe ligação no front cadastrada para a interface do equipamento', + 140: u'O sufixo do reals_name é obrigatório para criar ou alterar o vip %s do grupo virtual', + 141: u'Interface não cadastrada', + 142: u'Interface não está relacionada com o host', + 143: u'Interface do switch está com o campo protegida setado', + 144: u'A ligação no front da interface não tem nenhuma interface que representa um switch', + 145: u'O nome da interface é obrigatório', + 146: u'Equipamento já está cadastrado no grupo', + 147: u'O identificador do equipamento é obrigatório', + 148: u'Existe mais de um equipamento com o mesmo nome', + 149: u'Equipamento com nome duplicado', + 150: u'%s', + 151: u'Valor do real %s inválido', + 152: u'Request VIP is not registered.', + 153: u'IP %s.%s.%s.%s not registered for the environment %s', + 154: u'O valor da indicação de ativo do usuário é inválido', + 156: u'Equipamento %s já está cadastrado no ambiente %s', + 157: u'Equipamento %s não está cadastrado para o ambiente %s', + 158: u'Tipo de roteiro %s não cadastrado', + 159: u'O identificador do grupo layer 3 é obrigatório', + 160: u'Grupo layer 3 %s não cadastrado', + 161: u'O identificador do ambiente lógico é obrigatório', + 162: u'Ambiente lógico %s não cadastrado', + 163: u'O identificador da divisão DC é obrigatório', + 164: u'Divisão DC %s não cadastrada', + 165: u'Roteiro %s não cadastrado', + 166: u'O nome da marca é obrigatório', + 167: u'Marca %s não cadastrada', + 168: u'O nome do grupo layer 3 é obrigatório', + 169: u'Nome %s já cadastrado para outro grupo layer 3', + 170: u'O protocolo é obrigatório', + 171: u'Tipo de acesso %s não cadastrado', + 172: u'O nome do ambiente lógico é obrigatório', + 173: u'Nome %s já cadastrado para outro ambiente lógico', + 174: u'O nome da divisão DC é obrigatório', + 175: u'Nome %s já cadastrado para outra divisão DC', + 176: u'O nome do tipo de rede é obrigatório', + 177: u'User %s not registered', + 178: u'O user do usuário é obrigatório', + 179: u'User %s já está cadastrado para outro usuário', + 180: u'User Group %s not registered', + 181: u'Nome do grupo de usuário é obrigatório', + 182: u'Grupo de usuário com o nome %s já cadastrado', + 183: u'Usuário %s já está cadastrado no grupo %s', + 184: u'Usuário %s não pertence ao grupo %s', + 185: u'Equipamento %s não pertence ao grupo %s', + 186: u'The IP of the request VIP %s could not be changed because the VIP is already created', + 187: u'Interface com o nome %s já cadastrada para o equipamento %s', + 188: u'Interface %s não está associada ao equipamento %s', + 189: u'Permissão administrativa %s não cadastrada', + 190: u'Roteiro %s não associado ao equipamento %s', + 191: u'Requisição de VIP %s não validada', + 192: u'Requisição de VIP %s já criada', + 193: u'Tipo de roteiro com nome %s já cadastrado', + 194: u'O identificador do tipo de roteiro é obrigatório', + 195: u'O nome do roteiro é obrigatório', + 196: u'O tipo de roteiro %s não pôde ser excluído porque tem roteiro associado', + 197: u'O roteiro %s não pôde ser excluído porque tem equipamento associado', + 198: u'Roteiro %s já está associado ao equipamento %s', + 199: u'A marca %s não pôde ser excluída porque tem modelo associado', + 200: u'O nome do modelo é obrigatório', + 201: u'O identificador da marca é obrigatório', + 202: u'O modelo %s não pôde ser excluído porque tem equipamento associado', + 203: u'Tipo de acesso com o protocolo %s já cadastrado', + 204: u'O tipo de acesso %s não pôde ser excluído porque tem equipamento associado', + 205: u'The fqdn is required', + 206: u'The user is required', + 207: u'The password is required', + 208: u'O identificador do tipo de acesso é obrigatório', + 209: u'Equipamento %s não está associado ao tipo de acesso %s', + 210: u'O valor da indicação de protegida da interface é obrigatório', + 211: u'O valor da indicação de protegida da interface é inválido', + 212: u'Interface da ligação front não cadastrada', + 213: u'Interface da ligação back não cadastrada', + 214: u'Interface %s não pôde ser excluída porque tem outra interface associada', + 215: u'Tipo de rede %s não pôde ser excluído porque tem rede associada', + 216: u'Divisão DC %s não pôde ser excluída porque tem ambiente associado', + 217: u'Ambiente lógico %s não pôde ser excluído porque tem ambiente associado', + 218: u'Grupo layer 3 %s não pôde ser excluído porque tem ambiente associado', + 219: u'Ambiente com o mesmo grupo layer 3, ambiente lógico e divisão DC já cadastrado', + 220: u'Ambiente %s não pôde ser excluído porque tem vlan ou equipamento associado', + 221: u'O nome do usuário é obrigatório', + 222: u'O e-mail do usuário é obrigatório', + 223: u'O valor da indicação de ativo do usuário é obrigatório', + 224: u'O usuário %s não pôde ser excluído porque tem event_log ou grupo associado', + 225: u'A indicação de leitura do grupo do usuário é obrigatória', + 226: u'A indicação de escrita do grupo do usuário é obrigatória', + 227: u'A indicação de edição do grupo do usuário é obrigatória', + 228: u'A indicação de exclusão do grupo do usuário é obrigatória', + 229: u'O valor da indicação de leitura do grupo do usuário é inválido', + 230: u'O valor da indicação de escrita do grupo do usuário é inválido', + 231: u'O valor da indicação de edição do grupo do usuário é inválido', + 232: u'O valor da indicação de exclusão do grupo do usuário é inválido', + 233: u'O identificador do roteiro é obrigatório', + 234: u'O identificador do usuário é obrigatório', + 235: u'O identificador do grupo de usuário é obrigatório', + 236: u'O nome do grupo de equipamento é obrigatório', + 237: u'A função da permissão administrativa é obrigatória', + 238: u'A indicação de leitura da permissão administrativa é obrigatória', + 239: u'A indicação de escrita da permissão administrativa é obrigatória', + 240: u'O valor da indicação de leitura da permissão administrativa é inválido', + 241: u'O valor da indicação de escrita da permissão administrativa é inválido', + 242: u'Equipamento %s já está associado ao tipo de acesso %s', + 243: u'O identificador da requisição de VIP é obrigatório', + 244: u'O valor da indicação de validado da requisição de VIP é inválido', + 245: u'O valor da indicação de vip_criado da requisição de VIP é inválido', + 246: u'A indicação de validado da requisição de VIP é obrigatória', + 247: u'A indicação de vip_criado da requisição de VIP é obrigatória', + 248: u'O identificador da permissão administrativa é obrigatório', + 249: u'O nome do tipo de roteiro é obrigatório', + 250: u'Roteiro com o nome %s e tipo de roteiro %s já cadastrado', + 251: u'Marca com o nome %s já cadastrada', + 252: u'Modelo com o nome %s e a marca %s já cadastrado', + 253: u'Tipo de rede com o nome %s já cadastrado', + 254: u'Grupo de equipamento com o nome %s já cadastrado', + 255: u'O identificador da interface é obrigatório', + 256: u'O identificador do tipo de rede é obrigatório', + 257: u'Permissão administrativa com grupo de usuário %s e função %s já cadastrada', + 258: u'Rights Group Equipment %s not registered', + 259: u'A indicação de leitura do direito grupo equipamento é obrigatória', + 260: u'A indicação de escrita do direito grupo equipamento é obrigatória', + 261: u'A indicação de alterar_config do direito grupo equipamento é obrigatória', + 262: u'A indicação de exclusão do direito grupo equipamento é obrigatória', + 263: u'O valor da indicação de leitura do direito grupo equipamento é inválido', + 264: u'O valor da indicação de escrita do direito grupo equipamento é inválido', + 265: u'O valor da indicação de alterar_config do direito grupo equipamento é inválido', + 266: u'O valor da indicação de exclusão do direito grupo equipamento é inválido', + 267: u'Direitos Grupo Equipamento com o grupo de usuário %s e o grupo de equipamento %s já cadastrado', + 268: u'O identificador dos direitos grupo equipamento é obrigatório', + 269: u'Parameter %s is invalid. Value: %s', + 270: u'The VIP %s could not be changed because the VIP has not been created', + 271: u'Groups of equipment registered with the IP of the VIP request is not allowed of acess.', + 272: u'List the Reals_priority is higher or lower than list the real_server.', + 273: u'Lock wait timeout exceeded; try restarting transaction.', + 274: u'List the Reals_weight is higher or lower than list the real_server.', + 275: u'The healthcheck_type parameter not exist.', + 276: u'The healthcheck_type parameter is not HTTP, then healthcheck and id_healthcheck_expect must be None.', + 277: u'The healthcheck_type parameter is HTTP, then healthcheck and id_healthcheck_expect must NOT be None.', + 278: u'List the ports is higher or lower than list the real_server.', + 279: u'The VLAN name must be a string with a maximum of 50 characters and can not be empty.', + 280: u'The description of the VLAN must be a string with a maximum of 200 characters.', + 281: u'Network IPv4 is not registered.', + 282: u'The identifier RedeIPv4 is mandatory', + 283: u'Environment VIP not registered', + 284: u'There networkIPv4 associated with environment vip', + 285: u'There networkIPv6 associated with environment vip', + 286: u'Network IPv6 is not registered.', + 287: u'At least one of the parameters have to be informed to query', + 288: u'IP is not associated with the equipment', + 289: u'Option VIP is not registered.', + 290: u'Option vip is already associated with the environment vip', + 291: u'Option vip is not associated with the environment vip', + 292: u'IPv6 %s not registered for the environment %s', + 293: u'Vlan is currently in active/deployed state. It needs to be undeployed before deletion.', + 294: u'Invalid Environment Configuration or not registered', + 295: u'Unavailable address to create a NetworkIPv4', + 296: u'Unavailable address to create a NetworkIPv6', + 297: u'The Request VIP - IPv4 can not change to a Request VIP - IPv6', + 298: u'The Request VIP - IPv6 can not change to a Request VIP - IPv4', + 299: u'Network already activated', + 300: u'Invalid Request VIP IP version, try to use %s', + 301: u'IP Configuration is not registred.', + 302: u'Environment Configuration already exists', + 303: u'EquipmentAccess is not registred.', + 304: u'TypeAccess is not registred', + 305: u'Network %s don\'t have associate IPs', + 306: u'Vlan já cadastrada com o número %s', + 307: u'%s', + 308: u'Não existe associação de Ip e Equipamento para o IP %s', + 309: u'Failure to remove an association between an equipment and a group because the equipment is related only to one group.', + 310: u'Não foi possível excluir o grupo %s por alguns equipamentos estarem associados apenas a este grupo. Equipamentos: %s', + 311: u'Já existe uma Vlan com o arquivo_acl = %s', + 312: u'Tipo de Equipamento com nome %s, já cadastrado.', + 313: u'%s.', # Healthcheck já cadastrado + 314: u'%s', # Erro Vlan + 315: u'%s', # Erro Vlan + 316: u'Não existe Ambiente VIP cadastrado com os valores fornecidos: finalidade - %s ,cliente - %s, ambiente - %s.', + 317: u'Ip não encontrado para equipamento %s e ambiente vip %s.', + 318: u'O Ip %s e o Equipamento %s, não estão associados.', + 319: u'There is a request VIP pointing to this %s, the %s id = %s can not be excluded.', + 320: u'There are equipment related Ips, which are not part of the Environment Ip.', + 321: u'Não há rede %s no ambiente vip fornecido.', + 322: u'Requisição de VIP %s não criada', + 323: u'Ambiente %s não pôde ser excluído pois a rede %s da vlan %s tem um ip associado com a requisição vip %s.', + 324: u'Ambiente %s não pôde ser excluído pois a vlan %s está ativa.', + 325: u'Invalid value of the priority.', + # VipRequest Real server equipment error + 326: u'Não foi possível recuperar o equipamento %s associado a um real server.', + # VipRequest Real server equipment ip association error + 327: u'Não foi possível recuperar o ip %s e equipamento %s associados ao real server.', + # VipRequest Real server ip doesn't exist + 328: u'Não foi possível recuperar o IP %s associado ao real server %s.', + 329: u'Existe uma inconsistência de prioridade de real server no banco de dados.', + 330: u'Existe uma inconsistência de peso (weight) de real server no banco de dados.', + 331: u'Existe uma inconsistência de portas de real server no banco de dados.', + 332: u'Existe uma inconsistência na requisição vip, o parâmetro %s é inválido. Valor: %s.', + # 333:u'Alteração de real server realizada com sucesso, mas ocorreram + # erros de script com o(s) real(s) %s e ip(s) %s.', + 333: u'Alteração de real server concluída com falha, ocorreram erros de script com o(s) real(s) %s e ip(s) %s.', + 334: u'%s', + 335: u'Existe uma rede com mesma faixa relacionada com ambiente vip', + 336: u"Não foi possivel desassociar ambiente %s, pois existem ips sendo utilizados pelas requisições vip's. IPv4[ %s ] - IPV6[ %s ]", + 337: u'Valor do parâmetro %s inválido. Valor: %s.', + 338: u'Ocorreu um erro ao salvar o filtro no banco de dados. Verifique se o nome é único.', + 339: u'Não foi possível recuperar o filtro especificado do banco de dados.', + 340: u'Ocorreu um erro ao salvar o filtro editado no banco de dados.', + 341: u'Ocorreu um erro ao remover o filtro no banco de dados.', + 342: u'Não foi possível recuperar o tipo de equipamento especificado do banco de dados.', + 343: u'A associação entre o filtro %s e o tipo de equipamento %s já existe.', + 344: u'%s', + 345: u"Não foi possivel remover o equipamento %s, pois existem ips sendo utilizados por requisições vip's. IPv4[ %s ] - IPV6[ %s ]", + 346: u"Um dos equipamentos associados com o ambiente desta rede também está associado com outro ambiente que tem uma rede com essa mesma faixa, adicione filtros nos ambientes se necessário.", + 347: u"O equipamento que está sendo associado já possui um ip na mesma faixa em outra rede, se necessário adicione filtros nos ambientes.", + 348: u"O tipo de equipamento %s não pode ser desassociado do filtro %s.", + 349: u"O filtro %s não pode ser desassociado do ambiente pois está em uso.", + 350: u'Permissão %s não cadastrada.', + 351: u'Permissão Administrativa com função %s já cadastrada.', + 352: u"Não foi possível desassociar o ip %s do equipamento %s pois o ip está sendo utilizado na requisição vip %s e o equipamento é o único balanceador associado a este ip.", + 353: u'Valores duplicados para Porta Real, Porta Vip e IP do Real na mesma Requisição VIP.', + 354: u'Não foi possível excluir o ip de id %s pois ele está sendo usado em uma requisição VIP.', + 355: u'Não foi possível excluir a rede de id %s pois há um ip nela sendo usado em uma requisição VIP.', + 356: u'Não foi possível excluir a vlan de id %s pois há uma rede que possui um ip sendo usado em uma requisição VIP.', + 357: u'Esse ambiente já possui blocos cadastrados.', + 358: u'Regra inválida ou não cadastrada.', + 359: u'Bloco inválido ou não cadastrado.', + 360: u'Essa requisição vip não possui uma regra.', + 361: u'Esse bloco já está cadastrado na regra.', + 362: u'A regra relacionada a esse vip não possui blocos previamente cadastrados.', + 363: u'Não foi possível remover a rede pois ela está inativa.', + 364: u'Acl não foi criada', + 367: u'O ambiente desta Vlan já possui uma ACL com o nome = %s', + 368: u'Nao foi possivel remover a vlan pois ela esta inativa.', + 369: u'Nao foi possivel remover a vlan pois as seguintes redes nao puderam ser removidas: %s.', + 370: u'Nao foi possivel excluir o vip %s. Remova-o dos equipamentos primeiro.', + 371: u'Bloco não pode ser adicionado porque já existe uma regra para ser aplicada e o valor do parametro override é zero.', + 372: u'Server Pool Does Not Exists', + 373: u'Equipamento(s) do Server Pool: %s não pertence ao mesmo ambiente do Ambiente Vip: %s.', + 374: u'Está requisição vip não possui nenhum server pool cadastrado.', + 375: u'Pool can not be excluded because it is associated with a VIP', + 376: u'Numero de Rack %s ja existe.', + 377: u'Endereco MAC invalido', + 378: u'Rack nao pode ser incluido', + 379: u'Rack nao existe', + 380: u'Arquivo de configuracao do equipamento %s criado', + 381: u'Nome %s ja existe.', + 382: u'Os arquivos de configuracao do Rack %s nao podem ser gerados. %s', + 383: u'Nao foi possivel aplicar a configuracao do rack %s. %s', + 384: u'Erro ao editar ServerPool: %s', + 385: u'Não foi possível desassociar o ip %s do equipamento %s pois o ip está sendo utilizado nos server pools (id:identifier) %s.', + 386: u'Não foi possível excluir a rede %s pois o ip %s contido nela esta sendo usado nos Server Pools (id:identifier) %s.', + 387: u'Não foi possível excluir a vlan %s pois ela possui a rede %s e essa rede possui o ip %s contido nela, e esse ip esta sendo usado nos Server Pools (id:identifier) %s.', + 389: u'Não foi possível excluir o vip %s pois o ip %s do mesmo esta sendo usado nos Server Pools (id:identifier) %s.', + 390: u'Não foi possível excluir o vip %s pois os seguintes vips %s estão usando o mesmo ip %s.', + 391: u'Failure accessing Foreman server: %s', + 392: u'Environment is already associated with the environment vip', + 393: u'Environment is not associated with the environment vip', + 394: u'O ambiente %s não pode ser desvinculado pois existem server pools com reals vinculados a este ambiente.', + 396: u'A operação não pode ser realizada pois o ambiente "%s" do ip %s não possui permissão com um dos ambientes vips "%s".', + 397: u'O Rack, que o servidor está, não foi cadastrado.', + 400: u'Nao foi possivel adicionar o Rack', + 401: u'As mudancas nao foram salvas', + 405: u'Channel não pode ser criado. %s', + 406: u'Channel não pode ser editado. %s', + 407: u'Erro ao remover a variável.', + 410: u'Channel não pode ser deletado. %s', + 413: u'Interface não pode ser desconectada. Remova o Port Channel primeiro.', + 414: u'A rede a ser cadastrada não pertence a rede do ambiente. Cadastre o range desejado no ambiente', + 415: u'O ambiente não está configurado. É necessário efetuar a configuração.' +} + + +def error_dumps(code, *args): + + if isinstance(code, tuple): + code = code[0] + + message = error_messages.get(code, '') + if len(args) > 0: + message = message % args + + error_map = dict() + error_map['codigo'] = '%04d' % code + error_map['descricao'] = message + + map = dict() + map['erro'] = error_map + + return xml_utils.dumps_networkapi(map) + + +if __name__ == '__main__': + print error_dumps(u'0001', u'Falha ao acessar a fonte de dados') + print error_dumps(1) + print error_dumps(3, 'Causa') + print error_messages[99] diff --git a/networkapi/ip/models.py b/networkapi/ip/models.py index a97f79072..573ca5ba3 100644 --- a/networkapi/ip/models.py +++ b/networkapi/ip/models.py @@ -142,6 +142,32 @@ def __str__(self): return msg.encode('utf-8', 'replace') +class NetworkSubnetRange(NetworkIPvXError): + + """Exception for a network that does not be a subnet of de environment network.""" + + def __init__(self, cause, message=None): + self.cause = cause + self.message = message + + def __str__(self): + msg = u'Caused by: %s, Message: %s' % (self.cause, self.message) + return msg.encode('utf-8', 'replace') + + +class NetworkEnvironmentError(NetworkIPvXError): + + """Exception for a environment that does not have a network.""" + + def __init__(self, cause, message=None): + self.cause = cause + self.message = message + + def __str__(self): + msg = u'Caused by: %s, Message: %s' % (self.cause, self.message) + return msg.encode('utf-8', 'replace') + + class IpErrorV3(Exception): """Representa um erro ocorrido durante acesso à tabelas relacionadas com IP.""" @@ -509,6 +535,8 @@ def add_network_ipv4(self, user, id_vlan, network_type, evip, prefix=None): """ configenvironment = get_model('ambiente', 'ConfigEnvironment') vlan_model = get_model('vlan', 'Vlan') + models = get_model("ambiente", "EnvCIDR") + self.vlan = vlan_model().get_by_pk(id_vlan) network_found = None @@ -518,9 +546,9 @@ def add_network_ipv4(self, user, id_vlan, network_type, evip, prefix=None): try: - # Find all configs type v4 in environment - configs = configenvironment.get_by_environment( - self.vlan.ambiente.id).filter(ip_config__type=IP_VERSION.IPv4[0]) + env_id = self.vlan.ambiente.id + configs = models().get(env_id=env_id).filter( + ip_version=IP_VERSION.IPv4[0]) # If not found, an exception is thrown if len(configs) == 0: @@ -540,20 +568,19 @@ def add_network_ipv4(self, user, id_vlan, network_type, evip, prefix=None): # For each configuration founded in environment for config in configs: - # If already get a network stop this if stop: break # Need to be IPv4 - if config.ip_config.type == IP_VERSION.IPv4[0]: + if config.ip_version == IP_VERSION.IPv4[0]: - net4 = IPv4Network(config.ip_config.subnet) + net4 = IPv4Network(config.network) if prefix is not None: new_prefix = int(prefix) else: - new_prefix = int(config.ip_config.new_prefix) + new_prefix = int(config.subnet_mask) self.log.info( u'Prefix that will be used: %s' % new_prefix) @@ -580,8 +607,8 @@ def add_network_ipv4(self, user, id_vlan, network_type, evip, prefix=None): if network_type: internal_network_type = network_type - elif config.ip_config.network_type is not None: - internal_network_type = config.ip_config.network_type + elif config.id_network_type is not None: + internal_network_type = config.id_network_type else: self.log.error( u'Parameter tipo_rede is invalid. Value: %s', network_type) @@ -984,12 +1011,13 @@ def delete_v3(self, locks_used=[], force=False): def validate_v3(self): """Validate networkIPv4.""" - + models = get_model("ambiente", "EnvCIDR") if not self.network_type: raise NetworkIPv4ErrorV3('Network type can not null') # validate if network if allow in environment - configs = self.vlan.ambiente.configs.all() + env_id = self.vlan.ambiente.id + configs = models().get(env_id=env_id) self.vlan.allow_networks_environment(configs, [self], []) def activate_v3(self): @@ -1088,6 +1116,8 @@ def allocate_network_v3(self, id_vlan, prefix=None): """ vlan_model = get_model('vlan', 'Vlan') + cidr_model = get_model('ambiente', 'EnvCIDR') + self.vlan = vlan_model().get_by_pk(id_vlan) nets_envs, netv6 = network.get_networks_related( @@ -1099,19 +1129,19 @@ def allocate_network_v3(self, id_vlan, prefix=None): network_found = None try: - - configs = self.vlan.ambiente.configs.filter( - ip_config__type=IP_VERSION.IPv4[0]) + env_id = self.vlan.ambiente.id + configs = cidr_model().get(env_id=env_id).filter( + ip_version=IP_VERSION.IPv4[0]) # For each configuration founded in environment for config in configs: - net4 = IPNetwork(config.ip_config.subnet) + net4 = IPNetwork(config.network) if prefix is not None: new_prefix = int(prefix) else: - new_prefix = int(config.ip_config.new_prefix) + new_prefix = int(config.subnet_mask) self.log.info( u'Prefix that will be used: %s' % new_prefix) @@ -1139,7 +1169,7 @@ def allocate_network_v3(self, id_vlan, prefix=None): self.mask_oct4 = mask[3] if not self.network_type: - self.network_type = config.ip_config.network_type + self.network_type = config.id_network_type return @@ -2787,6 +2817,8 @@ def add_network_ipv6(self, user, id_vlan, network_type, evip, prefix=None): @raise InvalidValueError: Network type does not exist. """ configenvironment = get_model('ambiente', 'ConfigEnvironment') + models = get_model("ambiente", "EnvCIDR") + vlan_model = get_model('vlan', 'Vlan') self.vlan = vlan_model().get_by_pk(id_vlan) @@ -2797,9 +2829,9 @@ def add_network_ipv6(self, user, id_vlan, network_type, evip, prefix=None): try: - # Find all configs type v6 in environment - configs = configenvironment.get_by_environment( - self.vlan.ambiente.id).filter(ip_config__type=IP_VERSION.IPv6[0]) + env_id = self.vlan.ambiente.id + configs = models().get(env_id=env_id).filter( + ip_version=IP_VERSION.IPv6[0]) # If not found, an exception is thrown if len(configs) == 0: @@ -2825,14 +2857,14 @@ def add_network_ipv6(self, user, id_vlan, network_type, evip, prefix=None): break # Need to be IPv6 - if config.ip_config.type == IP_VERSION.IPv6[0]: + if config.ip_version == IP_VERSION.IPv6[0]: - net6 = IPv6Network(config.ip_config.subnet) + net6 = IPv6Network(config.network) if prefix is not None: new_prefix = int(prefix) else: - new_prefix = int(config.ip_config.new_prefix) + new_prefix = int(config.subnet_mask) self.log.info(u'Prefix that will be used: %s' % new_prefix) @@ -2852,8 +2884,8 @@ def add_network_ipv6(self, user, id_vlan, network_type, evip, prefix=None): if network_type: internal_network_type = network_type - elif config.ip_config.network_type is not None: - internal_network_type = config.ip_config.network_type + elif config.id_network_type is not None: + internal_network_type = config.id_network_type else: self.log.error( u'Parameter tipo_rede is invalid. Value: %s', network_type) @@ -3294,7 +3326,11 @@ def validate_v3(self): if not self.network_type: raise NetworkIPv6ErrorV3('Network type can not null') # validate if network if allow in environment - configs = self.vlan.ambiente.configs.all() + models = get_model("ambiente", "EnvCIDR") + + env_id = self.vlan.ambiente.id + configs = models().get(env_id=env_id) + self.vlan.allow_networks_environment(configs, [], [self]) def activate_v3(self): @@ -3392,6 +3428,8 @@ def allocate_network_v3(self, id_vlan, prefix=None): """ vlan_model = get_model('vlan', 'Vlan') + models = get_model("ambiente", "EnvCIDR") + self.vlan = vlan_model().get_by_pk(id_vlan) netv4, nets_envs = network.get_networks_related( @@ -3403,19 +3441,19 @@ def allocate_network_v3(self, id_vlan, prefix=None): network_found = None try: - - configs = self.vlan.ambiente.configs.filter( - ip_config__type=IP_VERSION.IPv6[0]) + env_id = self.vlan.ambiente.id + configs = models().get(env_id=env_id).filter( + ip_version=IP_VERSION.IPv6[0]) # For each configuration founded in environment for config in configs: - net6 = IPNetwork(config.ip_config.subnet) + net6 = IPNetwork(config.network) if prefix is not None: new_prefix = int(prefix) else: - new_prefix = int(config.ip_config.new_prefix) + new_prefix = int(config.subnet_mask) self.log.info( u'Prefix that will be used: %s' % new_prefix) @@ -3450,7 +3488,7 @@ def allocate_network_v3(self, id_vlan, prefix=None): self.mask7 = mask[6] self.mask8 = mask[7] if not self.network_type: - self.network_type = config.ip_config.network_type + self.network_type = config.network_type return # Checks if found any available network diff --git a/networkapi/ip/resource/NetworkAddResource.py b/networkapi/ip/resource/NetworkAddResource.py index bc95b680a..01bca0e4f 100644 --- a/networkapi/ip/resource/NetworkAddResource.py +++ b/networkapi/ip/resource/NetworkAddResource.py @@ -19,6 +19,7 @@ from networkapi.admin_permission import AdminPermission from networkapi.ambiente.models import ConfigEnvironmentInvalidError +from networkapi.ambiente.models import ConfigEnvironment from networkapi.ambiente.models import EnvironmentVip from networkapi.ambiente.models import IP_VERSION from networkapi.auth import has_perm @@ -43,6 +44,8 @@ from networkapi.ip.models import NetworkIPv4 from networkapi.ip.models import NetworkIPv4AddressNotAvailableError from networkapi.ip.models import NetworkIPv4Error +from networkapi.ip.models import NetworkEnvironmentError +from networkapi.ip.models import NetworkSubnetRange from networkapi.ip.models import NetworkIPv6 from networkapi.ip.models import NetworkIPv6AddressNotAvailableError from networkapi.ip.models import NetworkIPv6Error @@ -172,6 +175,50 @@ def handle_post(self, request, user, *args, **kwargs): u'Network cannot be allocated. %s already in use ' u'in this environment VIP.' % network_aux) + # Check if the new network is in the range of the Environment Network + try: + vlan = Vlan().get_by_pk(id_vlan) + vlan_env_id = vlan.ambiente + + try: + config_env = ConfigEnvironment() + environment_conf = config_env.get_by_environment(vlan_env_id) + + if environment_conf: + + is_valid_net = False + + for env_config in environment_conf: + + ipconfig = env_config.ip_config + subnet = ipconfig.subnet + + env_net = IPNetwork(subnet) + + if net in env_net: + self.log.debug('Network "%s" can be allocated because is in the ' + 'environment network(%s) subnets.' % (net, subnet)) + is_valid_net = True + break + + raise NetworkSubnetRange(None, 'A rede a ser cadastrada (%s) não pertence às ' + 'subredes do ambiente.' % net) if not is_valid_net else None + + else: + raise NetworkEnvironmentError(None, 'O ambiente não está configurado. ') + + except NetworkSubnetRange: + self.log.error('Network "%s" can not be allocated because is not in the ' + 'environment network(%s) subnets.' % (net, subnet)) + return self.response_error(414) + + except NetworkEnvironmentError: + self.log.error('The environment does not have a configuration') + return self.response_error(415) + + except Exception as ERROR: + self.log.error(ERROR) + # # Filter case 1 - Adding new network with same ip range to another network on other environment ## # Get environments with networks with the same ip range nets = NetworkIPv4.objects.filter(oct1=expl[0], oct2=expl[1], oct3=expl[2], diff --git a/networkapi/ip/resource/NetworkIPv6AddResource.py b/networkapi/ip/resource/NetworkIPv6AddResource.py index 48efd6d8b..daa717a55 100644 --- a/networkapi/ip/resource/NetworkIPv6AddResource.py +++ b/networkapi/ip/resource/NetworkIPv6AddResource.py @@ -246,7 +246,7 @@ def network_ipv6_add(self, user, vlan_id, network_type, environment_vip, prefix= else: for equip in list_equip_routers_ambient: - Ipv6Equipament().create(user, vlan_map['vlan']['id_network'], equip.equipamento.id) + Ipv6Equipament().create(user, ipv6_model.id, equip.equipamento.id) if multiple_ips: router_ip = Ipv6.get_first_available_ip6(vlan_map['vlan']['id_network'], True) @@ -264,7 +264,7 @@ def network_ipv6_add(self, user, vlan_id, network_type, environment_vip, prefix= ipv6_model2.save(user) Ipv6Equipament().create(user, ipv6_model2.id, - list_equip_routers_ambient[0].equipamento.id) + equip.equipamento.id) # Return XML return self.response(dumps_networkapi(vlan_map)) diff --git a/networkapi/plugins/Cisco/IOS/plugin.py b/networkapi/plugins/Cisco/IOS/plugin.py index f04ce79f3..eccb49623 100644 --- a/networkapi/plugins/Cisco/IOS/plugin.py +++ b/networkapi/plugins/Cisco/IOS/plugin.py @@ -71,7 +71,7 @@ def ensure_privilege_level(self, privilege_level=None): self.channel.send('show privilege\n') recv = self.waitString('Current privilege level is') level = re.search( - 'Current privilege level is ([0-9]+?).*', recv, re.DOTALL).group(1) + 'Current privilege level is ([0-9]+)?.*', recv, re.DOTALL).group(1) level = (level.split(' '))[-1] if int(level) < privilege_level: diff --git a/networkapi/plugins/Dell/FTOS/BGP/Cli.py b/networkapi/plugins/Dell/FTOS/BGP/Cli.py index 3c60153b9..7aa18f417 100644 --- a/networkapi/plugins/Dell/FTOS/BGP/Cli.py +++ b/networkapi/plugins/Dell/FTOS/BGP/Cli.py @@ -13,6 +13,7 @@ # 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. + import logging import os import re @@ -58,18 +59,20 @@ class Generic(BasePlugin): CURRENTLY_BUSY_WAIT = 'Currently busy with copying a file' INVALID_REGEX = '([Ii]nvalid)|overlaps with' WARNING_REGEX = 'config ignored|Warning' - ERROR_REGEX = '[Ee][Rr][Rr][Oo][Rr]|[Ff]ail|\%|utility is occupied' + ERROR_REGEX = '[Ee][Rr][Rr][Oo][Rr]|[Ff]ail|%|utility is occupied' admin_privileges = 15 VALID_TFTP_PUT_MESSAGE = 'bytes successfully copied' def _deploy_pre_req(self, neighbor): + log.debug("_deploy_pre_req") # Concatenate RouteMapEntries Lists route_map_in = neighbor.peer_group.route_map_in route_map_out = neighbor.peer_group.route_map_out rms = route_map_in.route_map_entries | \ route_map_out.route_map_entries + for rm_entry in rms: list_config_bgp = rm_entry.list_config_bgp if not list_config_bgp.equipments.filter(id=self.equipment.id): @@ -82,6 +85,7 @@ def _deploy_pre_req(self, neighbor): self.deploy_route_map(neighbor.peer_group.route_map_out) def _undeploy_pre_req(self, neighbor, ip_version): + log.debug("_undeploy_pre_req") # Concatenate RouteMapEntries Lists route_map_in = neighbor.peer_group.route_map_in route_map_out = neighbor.peer_group.route_map_out @@ -166,6 +170,7 @@ def _undeploy_pre_req(self, neighbor, ip_version): def deploy_neighbor(self, neighbor): """Deploy neighbor""" + log.debug("deploy_neighbor") self._deploy_pre_req(neighbor) @@ -175,10 +180,12 @@ def deploy_neighbor(self, neighbor): self.TEMPLATE_NEIGHBOR_V6_ADD config = self._generate_template_dict_neighbor(neighbor) + self._operate_equipment('neighbor', template_type, config) def undeploy_neighbor(self, neighbor): """Undeploy neighbor""" + log.debug("undeploy_neighbor") ip_version = IPAddress(str(neighbor.remote_ip)).version @@ -192,6 +199,7 @@ def undeploy_neighbor(self, neighbor): def deploy_list_config_bgp(self, list_config_bgp): """Deploy prefix list""" + log.debug("deploy_list_config_bgp") config = self._generate_template_dict_list_config_bgp(list_config_bgp) @@ -200,6 +208,7 @@ def deploy_list_config_bgp(self, list_config_bgp): def undeploy_list_config_bgp(self, list_config_bgp): """Undeploy prefix list""" + log.debug("undeploy_list_config_bgp") config = self._generate_template_dict_list_config_bgp(list_config_bgp) @@ -208,6 +217,7 @@ def undeploy_list_config_bgp(self, list_config_bgp): def deploy_route_map(self, route_map): """Deploy route map""" + log.debug("deploy_route_map") config = self._generate_template_dict_route_map(route_map) @@ -216,6 +226,7 @@ def deploy_route_map(self, route_map): def undeploy_route_map(self, route_map): """Undeploy route map""" + log.debug("undeploy_route_map") config = self._generate_template_dict_route_map(route_map) @@ -223,6 +234,7 @@ def undeploy_route_map(self, route_map): 'route_map', self.TEMPLATE_ROUTE_MAP_REMOVE, config) def _operate_equipment(self, type, template_type, config): + log.debug("_operate_equipment") self.connect() self._ensure_privilege_level() @@ -239,12 +251,13 @@ def _generate_config_file(self, type, template_type, config): Returns: filename with relative path to settings.TFTPBOOT_FILES_PATH """ - + log.debug("_generate_config_file") request_id = getattr(local, 'request_id', NO_REQUEST_ID) filename_out = 'bgp_{}_{}_config_{}'.format( type, self.equipment.id, request_id) + log.debug("filename_out %s" % filename_out) filename = BGP_CONFIG_FILES_PATH + filename_out rel_file_to_deploy = BGP_CONFIG_TOAPPLY_REL_PATH + filename_out @@ -255,11 +268,11 @@ def _generate_config_file(self, type, template_type, config): def _get_template_config(self, template_type, config): """Load template file and render values in VARs""" + log.debug("_get_template_config") try: template_file = self._load_template_file(template_type) config_to_be_saved = template_file.render(Context(config)) - except KeyError as err: log.error('Error: %s', err) raise deploy_exc.InvalidKeyException(err) @@ -277,28 +290,30 @@ def _load_template_file(self, template_type): Returns: template string """ - + log.debug("_load_template_file") equipment_template = self._get_equipment_template(template_type) filename = BGP_CONFIG_TEMPLATE_PATH + '/' + equipment_template.roteiro.roteiro + log.debug("template_path: %s" % filename) + template_file = self._read_config(filename) return template_file def _get_equipment_template(self, template_type): """Return a script by equipment and template_type""" - + log.debug("_get_equipment_template") try: return eqpt_models.EquipamentoRoteiro.search( None, self.equipment.id, template_type).uniqueResult() - except: - log.error('Template type %s not found.' % template_type) - raise plugin_exc.BGPTemplateException() + except Exception as e: + log.error('Template type %s not found. Error: %s' % (template_type, e)) + raise plugin_exc.BGPTemplateException(e) def _generate_template_dict_neighbor(self, neighbor): """Make a dictionary to use in template""" - + log.debug("_generate_template_dict_neighbor") key_dict = { 'AS_NUMBER': neighbor.local_asn.name, 'VRF_NAME': neighbor.remote_ip.networkipv4.vlan.ambiente.default_vrf.internal_name, @@ -315,23 +330,21 @@ def _generate_template_dict_neighbor(self, neighbor): 'REMOVE_PRIVATE_AS': neighbor.remove_private_as, 'COMMUNITY': neighbor.community } - return key_dict def _generate_template_dict_list_config_bgp(self, list_config_bgp): """Make a dictionary to use in template""" - + log.debug("_generate_template_dict_list_config_bgp") key_dict = { 'TYPE': self._get_type_list(list_config_bgp.type)['config_list'], 'NAME': list_config_bgp.name, 'CONFIG': list_config_bgp.config } - return key_dict def _generate_template_dict_route_map(self, route_map): """Make a dictionary to use in template""" - + log.debug("_generate_template_dict_route_map") entries = [] for entry_obj in route_map.route_map_entries: action = 'permit' if entry_obj.action == 'P' else 'deny' @@ -348,10 +361,10 @@ def _generate_template_dict_route_map(self, route_map): 'NAME': route_map.name, 'ENTRIES': entries } - return key_dict def _get_type_list(self, type): + log.debug("_get_type_list") types = { 'P': { 'config_list': 'prefix-list', @@ -366,7 +379,7 @@ def _get_type_list(self, type): def _read_config(self, filename): """Return content from template_file""" - + log.debug("_read_config") try: file_handle = open(filename, 'r') template_content = Template(file_handle.read()) @@ -382,7 +395,7 @@ def _read_config(self, filename): def _save_config(self, filename, config): """Write config in template file""" - + log.debug("_save_config") try: file_handle = open(filename, 'w') file_handle.write(config) @@ -395,7 +408,7 @@ def _save_config(self, filename, config): # DEPLOY # ########## def _deploy_config_in_equipment(self, rel_filename): - + log.debug("_deploy_config_in_equipment") path = os.path.abspath(TFTPBOOT_FILES_PATH + rel_filename) if not path.startswith(TFTPBOOT_FILES_PATH): raise deploy_exc.InvalidFilenameException(rel_filename) @@ -403,7 +416,7 @@ def _deploy_config_in_equipment(self, rel_filename): return self._apply_config(rel_filename) def _apply_config(self, filename): - + log.debug("_apply_config") if self.equipment.maintenance: raise AllEquipmentsAreInMaintenanceException() @@ -415,18 +428,19 @@ def _copy_script_file_to_config(self, filename, Copy file from TFTP server to destination By default, plugin should apply file in running configuration (active) """ - + log.debug("_copy_script_file_to_config") command = 'copy tftp://{}/{} {}\n\n'.format( self.tftpserver, filename, destination) file_copied = 0 retries = 0 - while(not file_copied and retries < self.MAX_TRIES): + recv = "" + + while not file_copied and retries < self.MAX_TRIES: if retries is not 0: sleep(self.RETRY_WAIT_TIME) - try: - log.info('try: %s - sending command: %s' % (retries, command)) + log.debug('try: %s - sending command: %s' % (retries, command)) self.channel.send('%s\n' % command) recv = self._wait_string(self.VALID_TFTP_PUT_MESSAGE) file_copied = 1 @@ -446,7 +460,7 @@ def _ensure_privilege_level(self, privilege_level=None): privilege_level = self.admin_privileges self.channel.send('\n') - recv = self._wait_string('>|#') + self._wait_string('>|#') self.channel.send('show privilege\n') recv = self._wait_string('Current privilege level is') level = re.search( @@ -455,9 +469,9 @@ def _ensure_privilege_level(self, privilege_level=None): level = (level.split(' '))[-1] if int(level) < privilege_level: self.channel.send('enable\n') - recv = self._wait_string('Password:') + self._wait_string('Password:') self.channel.send('%s\n' % self.equipment_access.enable_pass) - recv = self._wait_string('#') + self._wait_string('#') def _wait_string(self, wait_str_ok_regex='', wait_str_invalid_regex=None, wait_str_failed_regex=None): diff --git a/networkapi/plugins/SDN/ODL/Generic.py b/networkapi/plugins/SDN/ODL/Generic.py index f25f8b4fd..4b8ca28c4 100644 --- a/networkapi/plugins/SDN/ODL/Generic.py +++ b/networkapi/plugins/SDN/ODL/Generic.py @@ -304,7 +304,7 @@ def _request(self, **kwargs): return try: - return json.loads(request.text) + return request.json() except Exception as exception: log.error("Response received from uri '%s': \n%s", uri, request.text) diff --git a/networkapi/plugins/factory.py b/networkapi/plugins/factory.py index d13f607dd..80a1a589b 100644 --- a/networkapi/plugins/factory.py +++ b/networkapi/plugins/factory.py @@ -55,6 +55,9 @@ def get_plugin(cls, **kwargs): if re.search('ACE30', modelo.upper(), re.DOTALL): from .Cisco.ACE.plugin import ACE return ACE + if re.search('C9500', modelo.upper(), re.DOTALL): + from .Cisco.IOS.plugin import IOS + return IOS if 'marca' in kwargs: marca = kwargs.get('marca') diff --git a/networkapi/rack/models.py b/networkapi/rack/models.py index 72a399f9a..6ce5bd714 100644 --- a/networkapi/rack/models.py +++ b/networkapi/rack/models.py @@ -120,9 +120,9 @@ def get_dc(self, idt=None, dcname=None, address=None): if address: return Datacenter.objects.filter(address=address) return Datacenter.objects.all() - except ObjectDoesNotExist, e: + except ObjectDoesNotExist as e: raise Exception(u'Datacenter doesnt exist. %s' % e) - except Exception, e: + except Exception as e: self.log.error(u'Failure to get datacenter. %s' % e) raise Exception(e, u'Failure to get datacenter. %s' % e) @@ -132,17 +132,23 @@ def save_dc(self): try: self.save() - except Exception, e: + except Exception as e: self.log.error(u'Error trying to insert DatacenterRooms: %s.' %e) def del_dc(self): try: + self.check_fabric() self.delete() - except Exception, e: + except Exception as e: self.log.error(u'Error trying to remove Datacenter: %s.' %e) raise Exception(u'Error trying to remove Datacenter: %s.' %e) + def check_fabric(self): + if DatacenterRooms().get_dcrooms(id_dc=self.id): + raise Exception( + "The datacenter %s could not be deleted. There is a Fabric associated with it." % self.dcname) + class DatacenterRooms(BaseModel): @@ -156,12 +162,10 @@ class DatacenterRooms(BaseModel): leafs = models.IntegerField(blank=True, null=True) config = models.CharField(max_length=255) - class Meta(BaseModel.Meta): db_table = u'datacenterrooms' managed = True - def get_dcrooms(self, idt=None, id_dc=None, name=None): """ Find DatacenterRooms by id, name or datacenter. @@ -179,9 +183,9 @@ def get_dcrooms(self, idt=None, id_dc=None, name=None): return DatacenterRooms.objects.filter(dc=id_dc) return DatacenterRooms.objects.all() - except ObjectDoesNotExist, e: + except ObjectDoesNotExist as e: raise Exception(u'Datacenter Rooms doesnt exist. %s' % e) - except Exception, e: + except Exception as e: self.log.error(u'Failure to get datacenter room. %s' % e) raise Exception(u'Failure to get datacenter room. %s' % e) @@ -190,18 +194,33 @@ def save_dcrooms(self): ''' try: self.save() - except Exception, e: + except Exception as e: self.log.error(u'Error trying to insert DatacenterRooms: %s.' %e) raise Exception(u'Error trying to insert DatacenterRooms: %s.' %e) def del_dcrooms(self): try: + self.check_racks() + self.dissociate_environments() self.delete() - except Exception, e: + except Exception as e: self.log.error(u'Error trying to remove DatacenterRooms: %s.' %e) raise Exception(u'Error trying to remove DatacenterRooms: %s.' %e) + def dissociate_environments(self): + from networkapi.ambiente.models import Ambiente + + envs = Ambiente.objects.filter(dcroom=self.id) + for env in envs: + env.dcroom = None + env.save() + + def check_racks(self): + if Rack().get_rack(dcroom_id=self.id): + raise Exception( + "The Fabric %s could not be deleted. There is Racks associated with it." % self.name) + class Rack(BaseModel): @@ -241,34 +260,37 @@ def get_rack(cls, idt=None, number=None, name=None, dcroom_id=None, dc_id=None): if dc_id: return Rack.objects.filter(dcroom__dc__id=dc_id) return Rack.objects.all() - except ObjectDoesNotExist, e: + except ObjectDoesNotExist as e: raise Exception('Rack does not exist. %s.' % e) - except Exception, e: + except Exception as e: raise Exception('Failure to search the Rack. %s' % e) - def save_rack(self): if Rack.objects.filter(numero=self.numero, dcroom=self.dcroom): - raise Exception ('Numero de Rack %s ja existe na sala %s.' % (self.numero, self.dcroom.name)) + raise Exception('Numero de Rack %s ja existe na sala %s.' % (self.numero, self.dcroom.name)) if Rack.objects.filter(nome=self.nome, dcroom=self.dcroom): - raise Exception ('Já existe um rack com o nome %s na sala %s.' % (self.nome, self.dcroom.name)) + raise Exception('Já existe um rack com o nome %s na sala %s.' % (self.nome, self.dcroom.name)) try: - self.id_sw1 = networkapi.equipamento.Equipamento.get_by_pk(int(id_sw1)) if self.id_sw1 is int else self.id_sw1 - self.id_sw2 = networkapi.equipamento.Equipamento.get_by_pk(int(id_sw2)) if self.id_sw2 is int else self.id_sw2 - self.id_ilo = networkapi.equipamento.Equipamento.get_by_pk(int(id_sw3)) if self.id_sw3 is int else self.id_sw3 - self.dcroom = DatacenterRoom.get_dcrooms(int(dcroom)) if self.dcroom is int else self.dcroom + self.id_sw1 = networkapi.equipamento.Equipamento.get_by_pk(int(self.id_sw1)) \ + if self.id_sw1 is int else self.id_sw1 + self.id_sw2 = networkapi.equipamento.Equipamento.get_by_pk(int(self.id_sw2)) \ + if self.id_sw2 is int else self.id_sw2 + self.id_ilo = networkapi.equipamento.Equipamento.get_by_pk(int(self.id_sw3)) \ + if self.id_sw3 is int else self.id_sw3 + self.dcroom = DatacenterRoom().get_dcrooms(int(self.dcroom)) \ + if self.dcroom is int else self.dcroom return self.save() - except Exception, e: + except Exception as e: raise Exception('Falha ao inserir Rack. %s' % e) def del_rack(self): try: self.delete() - except Exception, e: + except Exception as e: raise Exception(u'Error trying to remove Rack: %s.' %e) def get_by_pk(cls, idt): @@ -281,10 +303,10 @@ def get_by_pk(cls, idt): """ try: return Rack.objects.filter(id=idt).uniqueResult() - except ObjectDoesNotExist, e: + except ObjectDoesNotExist as e: raise RackNumberNotFoundError( e, u'Dont there is a Rack by pk = %s.' % idt) - except Exception, e: + except Exception as e: cls.log.error(u'Failure to search the Rack.') raise RackError(e, u'Failure to search the Rack.') @@ -298,10 +320,10 @@ def get_by_name(cls, name): """ try: return Rack.objects.filter(nome=name).uniqueResult() - except ObjectDoesNotExist, e: + except ObjectDoesNotExist as e: raise RackNumberNotFoundError( e, u'Dont there is the Rack %s.' % name) - except Exception, e: + except Exception as e: cls.log.error(u'Failure to search the Rack.') raise RackError(e, u'Failure to search the Rack.') @@ -315,10 +337,10 @@ def get_by_id(cls, number): """ try: return Rack.objects.get(numero__iexact=number) - except ObjectDoesNotExist, e: + except ObjectDoesNotExist as e: raise RackNumberNotFoundError( - e, u'Dont there is a Rack by pk = %s.' % idt) - except Exception, e: + e, u'Dont there is a Rack by pk = %s.' % number) + except Exception as e: cls.log.error(u'Failure to search the Rack.') raise RackError(e, u'Failure to search the Rack.') @@ -326,20 +348,20 @@ def insert_new(self, authenticated_user): try: Rack.objects.get(numero__iexact=self.numero) raise RackNumberDuplicatedValueError( - None, u'Numero de Rack %s ja existe.' % (self.numero)) - except ObjectDoesNotExist, e: + None, u'Numero de Rack %s ja existe.' % self.numero) + except ObjectDoesNotExist as e: pass try: Rack.objects.get(nome__iexact=self.nome) raise RackNameDuplicatedError( - None, u'Nome %s ja existe.' % (self.nome)) - except ObjectDoesNotExist, e: + None, u'Nome %s ja existe.' % self.nome) + except ObjectDoesNotExist as e: pass try: return self.save() - except Exception, e: + except Exception as e: self.log.error(u'Falha ao inserir Rack.') raise RackError(e, u'Falha ao inserir Rack.') @@ -410,7 +432,7 @@ def create(self, authenticated_user): try: self.save() - except Exception, e: + except Exception as e: self.log.error(u'Error trying to insert EnvironmentRack: %s/%s.' % (self.rack.id, self.ambiente.id)) raise EnvironmentRackError( @@ -419,10 +441,10 @@ def create(self, authenticated_user): def get_by_rack_environment(self, rack_id, environment_id): try: return EnvironmentRack.objects.get(ambiente__id=environment_id, rack__id=rack_id) - except ObjectDoesNotExist, e: + except ObjectDoesNotExist as e: raise EnvironmentRackNotFoundError( e, u'There is no EnvironmentRack with rack = %s and environment = %s.' % (rack_id, environment_id)) - except Exception, e: + except Exception as e: self.log.error( u'Error trying to search EnvironmentRack %s/%s.' % (rack_id, environment_id)) raise EnvironmentRackError( @@ -435,9 +457,9 @@ def get_by_rack(cls, rack_id): """ try: return EnvironmentRack.objects.filter(rack=rack_id) - except ObjectDoesNotExist, e: + except ObjectDoesNotExist as e: raise RackError( e, u'Dont there is a Environment by rack = %s.' % rack_id) - except Exception, e: + except Exception as e: cls.log.error(u'Failure to search the Environment.') - raise AmbienteError(e, u'Failure to search the Environment.') + raise Exception(e, u'Failure to search the Environment.') diff --git a/networkapi/requisicaovips/models.py b/networkapi/requisicaovips/models.py index 8654a1c73..f93f39c02 100644 --- a/networkapi/requisicaovips/models.py +++ b/networkapi/requisicaovips/models.py @@ -2543,34 +2543,36 @@ def validate_v3(self, pool, permit_created=False): networkipv6__vlan__ambiente=pool['environment'] )) ).distinct() - - if member.get('ip', None) is not None: - amb = amb.filter( - vlan__networkipv4__ip=member['ip']['id'] - ) - # Ip not found environment - if not amb: - raise pool_exceptions.IpNotFoundByEnvironment( - 'Environment of IP:%s(%s) and different of ' - 'environment of server pool: %s' % - (member['ip']['ip_formated'], member['ip']['id'], - pool['identifier']) + self.log.debug("amb pool: %s" % amb) + if amb: + if member.get('ip', None) is not None: + amb = amb.filter( + vlan__networkipv4__ip=member['ip']['id'] ) - - if member.get('ipv6', None) is not None: - amb = amb.filter( - vlan__networkipv6__ipv6=member['ipv6']['id'] - ) - - # Ip not found environment - if not amb: - raise pool_exceptions.IpNotFoundByEnvironment( - 'Environment of IP:%s(%s) and different of ' - 'environment of server pool: %s' % - (member['ipv6']['ip_formated'], member['ipv6']['id'], - pool['identifier']) + self.log.debug("amb ip: %s" % amb) + # Ip not found environment + if not amb: + raise pool_exceptions.IpNotFoundByEnvironment( + 'Environment of IP:%s(%s) and different of ' + 'environment of server pool: %s' % + (member['ip']['ip_formated'], member['ip']['id'], + pool['identifier']) + ) + + if member.get('ipv6', None) is not None: + amb = amb.filter( + vlan__networkipv6__ipv6=member['ipv6']['id'] ) + # Ip not found environment + if not amb: + raise pool_exceptions.IpNotFoundByEnvironment( + 'Environment of IP:%s(%s) and different of ' + 'environment of server pool: %s' % + (member['ipv6']['ip_formated'], member['ipv6']['id'], + pool['identifier']) + ) + class ServerPoolMember(BaseModel): id = models.AutoField( diff --git a/networkapi/rest.py b/networkapi/rest.py index 6f5c1c6de..45bbaf2d2 100644 --- a/networkapi/rest.py +++ b/networkapi/rest.py @@ -204,6 +204,18 @@ def response_error(self, code, *args): return http_res + def not_found(self): + """Cria um HttpResponse com código HTTP 404 - Not Found.""" + http_res = HttpResponse( + u'404 - Chamada não encontrada.', + status=404, + content_type='text/plain') + + http_res['X-Request-Id'] = local.request_id + http_res['X-Request-Context'] = local.request_context + + return http_res + def response(self, content, status=200, content_type='text/plain'): """Cria um HttpResponse com os dados informados""" diff --git a/networkapi/settings.py b/networkapi/settings.py index a4770eb4d..80b496116 100644 --- a/networkapi/settings.py +++ b/networkapi/settings.py @@ -265,7 +265,7 @@ def local_files(path): ADMIN_MEDIA_PREFIX = '/media/' # Make this unique, and don't share it with anybody. -SECRET_KEY = 'ry@zgop%w80_nu83#!tbz)m&7*i@1)d-+ki@5^d#%6-&^216sg' +SECRET_KEY = os.getenv('DJANGO_SECRET_KEY', '') VLAN_CACHE_TIME = None EQUIPMENT_CACHE_TIME = None @@ -637,6 +637,18 @@ def local_files(path): 'simple_env_post': os.path.join( PROJECT_ROOT_PATH, 'api_environment/specs/simple_env_post.json' + ), + 'cidr_post': os.path.join( + PROJECT_ROOT_PATH, + 'api_environment/specs/cidr_post.json' + ), + 'cidr_post_auto': os.path.join( + PROJECT_ROOT_PATH, + 'api_environment/specs/cidr_post_auto.json' + ), + 'cidr_put': os.path.join( + PROJECT_ROOT_PATH, + 'api_environment/specs/cidr_put.json' ) } diff --git a/networkapi/usuario/models.py b/networkapi/usuario/models.py index 7c2e70dcc..cb133385a 100644 --- a/networkapi/usuario/models.py +++ b/networkapi/usuario/models.py @@ -17,6 +17,10 @@ import hashlib import logging +import requests +import socket +import tempfile +import os import ldap from django.core.exceptions import MultipleObjectsReturned @@ -27,6 +31,10 @@ from networkapi.system import exceptions from networkapi.system.facade import get_value from networkapi.util import convert_string_or_int_to_boolean +from networkapi.util.appcache import get_cache, set_cache +from networkapi.util.encrypt import encrypt_key, generate_key + +from base64 import b64encode class UsuarioError(Exception): @@ -82,6 +90,95 @@ def __init__(self, cause, message=None): UsuarioError.__init__(self, cause, message) +class CacheUser(object): + + log = logging.getLogger('CacheUser') + + def _generate_salt_key(self): + """"Generate salt_key for encrypt process in cache user. + @return: salt_key. + @raise VariableDoesNotExistException: time_cache_salt_key is not registered. + @raise Exception: Any different errors catch. + """ + try: + salt = get_cache('salt_key') + + if not salt: + salt_key = generate_key() + set_cache('salt_key', salt_key, int(get_value('time_cache_salt_key'))) + self.log.debug('The encrypt token was generated and cached successfully!') + return salt_key + + return salt + + except exceptions.VariableDoesNotExistException: + self.log.error(u'Error getting time_cache_salt_key variable.') + except Exception as ERROR: + self.log.error(ERROR) + + def _mount_hash(self, username, password): + """"Generate hash of username + password, then encrypt it for caching. + @return: hash encrypted. + @raise Exception: Any different errors catch. + """ + try: + salt = self._generate_salt_key() + + if salt: + self.log.debug('The encrypt key was taken successfully!') + hash_text = str(username + password) + encrypted_hash_text = encrypt_key(hash_text, salt) + self.log.debug('The encrypted_hash_text was generate successfully!') + + return encrypted_hash_text + + else: + self.log.error('Problems to take salt_key') + + except Exception as ERROR: + self.log.error(u'Error on mount hash for cache user: %s' % ERROR) + + def get(self, username, password): + """"Get the cached user. + @return: Hash of user cached. + @raise Exception: Any different errors catch. + """ + try: + encrypted_hash_text = self._mount_hash(username, password) + + if encrypted_hash_text: + self.log.debug('The encrypted_hash_text was taken successfully!') + cached_hash_text = get_cache(b64encode(encrypted_hash_text)) + + return cached_hash_text + + else: + self.log.error('Problems to take encrypted_hash_text') + + except Exception as ERROR: + self.log.error(u'Error on get cached user: %s' % ERROR) + + def set(self, username, password): + """"Set the cached user. + @raise VariableDoesNotExistException: time_cache_user is not registered. + @raise Exception: Any different errors catch. + """ + try: + encrypted_hash_text = self._mount_hash(username, password) + + if encrypted_hash_text: + set_cache(b64encode(encrypted_hash_text), True, int(get_value('time_cache_user'))) + self.log.debug('The user was cached successfully!') + + else: + self.log.error('Problems to take encrypted_hash_text') + + except exceptions.VariableDoesNotExistException: + self.log.error(u'Error getting time_cache_user variable.') + except Exception as ERROR: + self.log.error(ERROR) + + class Usuario(BaseModel): user = models.CharField(unique=True, max_length=45) @@ -96,6 +193,8 @@ class Usuario(BaseModel): log = logging.getLogger('Usuario') + cache_user = CacheUser() + class Meta(BaseModel.Meta): db_table = u'usuarios' managed = True @@ -122,9 +221,7 @@ def encode_password(cls, pwd): @classmethod def get_by_pk(cls, pk): """"Get User by pk. - @return: User. - @raise UsuarioNotFoundError: User is not registered. @raise UsuarioError: Failed to search for the User. """ @@ -140,9 +237,7 @@ def get_by_pk(cls, pk): @classmethod def get_by_user(cls, name): """"Get User by username. - @return: User. - @raise UsuarioNotFoundError: User is not registered. @raise UsuarioError: Failed to search for the User. """ @@ -155,12 +250,49 @@ def get_by_user(cls, name): cls.log.error(u'Failure to search the User.') raise UsuarioError(e, u'Failure to search the User.') + @classmethod + def get_by_authapi(cls, username, password): + """"Get User in AuthAPI by username and password. + @return: AuthAPI response. + @raise UsuarioNotFoundError: User is not registered + @raise VariableDoesNotExist: Feature Flag not found. + @raise Exception: For any different problem found. + """ + try: + user = Usuario.objects.prefetch_related('grupos').get(user=username, ativo=1) + authapi_info = dict( + mail=user.email, + password=password, + src=socket.gethostbyname(socket.gethostname()) + ) + + try: + ssl_cert = open(get_value('path_ssl_cert')) + + try: + response = requests.post(get_value('authapi_url'), json=authapi_info, verify=ssl_cert.name) + ssl_cert.close() + return response + + except exceptions.VariableDoesNotExistException: + cls.log.error(u'Error getting authapi_url variable.') + except Exception as ERROR: + raise Exception('Error uses AuthAPI. %s' % ERROR) + + except exceptions.VariableDoesNotExistException: + cls.log.error(u'Error getting path_ssl_cert variable.') + except Exception as ERROR: + raise Exception('Error to get SSL certificate. %s' % ERROR) + + except ObjectDoesNotExist as ERROR: + raise UsuarioNotFoundError(ERROR, u'There is no User with username = %s in AuthAPI.' % username) + except Exception as ERROR: + cls.log.error(u'Failure to search the User. Error: %s' % ERROR) + @classmethod def get_by_ldap_user(cls, ldap_usr, active=False): """Get User by ldap username. - @return: User. - @raise UsuarioNotFoundError: User is not registered. @raise UsuarioError: Failed to search for the User. """ @@ -179,11 +311,56 @@ def get_by_ldap_user(cls, ldap_usr, active=False): def get_enabled_user(self, username, password): """ Busca o usuário de acordo com o login e a senha. - Retorna apenas usuário ativo. """ bypass = 0 try: + # Cached User authentication + try: + if convert_string_or_int_to_boolean(get_value('use_cache_user')): + cached_hash_text = self.cache_user.get(username, password) + + if cached_hash_text: + self.log.debug('This authentication is using cached user') + return Usuario.objects.prefetch_related('grupos').get(user=username, ativo=1) + + else: + raise Exception('No cached user found with this credentials') + + except exceptions.VariableDoesNotExistException: + self.log.error( + u'Error getting cache user variable. Trying AuthAPI authentication') + except Exception as ERROR: + self.log.error(u'Error to get cached user. %s. Trying AuthAPI authentication. ' % ERROR) + + # AuthAPI authentication + try: + if convert_string_or_int_to_boolean(get_value('use_authapi')): + response = self.get_by_authapi(username, password) + + if response.status_code == 200: + self.log.debug('This authentication uses AuthAPI for user \'%s\'' % username) + + try: + if convert_string_or_int_to_boolean(get_value('use_cache_user')): + self.cache_user.set(username, password) + except exceptions.VariableDoesNotExistException: + self.log.debug(u'User will not be cached because cached user is disabled') + + return Usuario.objects.prefetch_related('grupos').get(user=username, ativo=1) + + elif response.status_code == 400: + raise Exception('No user founds in AuthAPI with this credentials') + + elif response.status_code == 500: + raise Exception('Error to connect with AuthAPI') + + except exceptions.VariableDoesNotExistException: + self.log.error( + u'Error getting AuthAPI variable. Trying ldap authentication') + except Exception as ERROR: + self.log.error(u'Error to get user from AuthAPI. %s. Trying ldap authentication. ' % ERROR) + try: use_ldap = convert_string_or_int_to_boolean( get_value('use_ldap')) @@ -204,6 +381,13 @@ def get_enabled_user(self, username, password): # local auth if bypass: + + try: + if convert_string_or_int_to_boolean(get_value('use_cache_user')): + self.cache_user.set(username, password) + except exceptions.VariableDoesNotExistException: + self.log.debug(u'User will not be cached because cached user is disabled') + password = Usuario.encode_password(password) return Usuario.objects.prefetch_related('grupos').get(user=username, pwd=password, ativo=1) @@ -212,7 +396,15 @@ def get_enabled_user(self, username, password): connect = ldap.open(ldap_server) user_dn = 'cn=' + username + ',' + ldap_param connect.simple_bind_s(user_dn, password) + + try: + if convert_string_or_int_to_boolean(get_value('use_cache_user')): + self.cache_user.set(username, password) + except exceptions.VariableDoesNotExistException: + self.log.debug(u'User will not be cached because cached user is disabled') + return return_user + except ldap.INVALID_CREDENTIALS, e: self.log.error('LDAP authentication error %s' % e) except exceptions.VariableDoesNotExistException, e: @@ -245,9 +437,7 @@ class Meta(BaseModel.Meta): @classmethod def list_by_user_id(cls, user_id): """"Get UserGroup by user. - @return: UserGroup. - @raise UsuarioNotFoundError: UserGroup is not registered. @raise UsuarioError: Failed to search for the UserGroup. """ @@ -263,9 +453,7 @@ def list_by_user_id(cls, user_id): @classmethod def get_by_user_group(cls, user_id, group_id): """"Get UserGroup by user and Group. - @return: UserGroup. - @raise UserGroupNotFoundError: UserGroup is not registered. @raise UsuarioError: Failed to search for the UserGroup. """ diff --git a/networkapi/util/__init__.py b/networkapi/util/__init__.py index ef026004e..e4b8f3f79 100644 --- a/networkapi/util/__init__.py +++ b/networkapi/util/__init__.py @@ -221,6 +221,23 @@ def is_valid_string_minsize(param, minsize=None, required=True): return True +def is_valid_vlan_name(vlan_name): + """Checks if the parameter is a valid string for Vlan's name, without special characters and breaklines + + @param vlan_name: Value to be validated. + + @return True if the parameter hasn't a special character, or False otherwise. + """ + + if vlan_name is None or vlan_name == '': + return False + + regex_for_breakline = re.compile('\r|\n\r|\n') + regex_for_special_characters = re.compile('[@!#$%^&*()<>?/\\\|}{~:]') + + return False if regex_for_breakline.search(vlan_name) or regex_for_special_characters.search(vlan_name) else True + + def is_valid_boolean_param(param, required=True): """Checks if the parameter is a valid boolean. @@ -286,7 +303,8 @@ def is_valid_uri(param): 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. + """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 @@ -305,7 +323,8 @@ def is_valid_text(param, required=True): 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. + """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 @@ -324,7 +343,8 @@ def is_valid_pool_identifier_text(param, required=True): 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. + """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. @@ -472,17 +492,21 @@ def cache_function(length, equipment=False): @param length: time in seconds to stay in cache """ def _decorated(func): - + logging.debug("30") def _cache(*args, **kwargs): - + logging.debug("31") if equipment is True: + logging.debug(equipment) + logging.debug(args) 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) - + logging.debug("32") # Search in cache if it exists + logging.debug("cache %s" % cache) + logging.debug("key %s" % key) if key in cache: # Get value in cache @@ -496,7 +520,7 @@ def _cache(*args, **kwargs): value = cache.get(key) # Return value of cache return value - + logging.debug("33") # If not exists in cache else: # Function can be called several times before it finishes and is put into the cache, @@ -517,9 +541,10 @@ def _cache(*args, **kwargs): # Set in cache the keys # key_list.append(key) # cache.set(sha1('key_networkapi_vlans').hexdigest(), key_list) + logging.debug("34") return result - + logging.debug("35") return _cache return _decorated diff --git a/networkapi/util/appcache.py b/networkapi/util/appcache.py index 7258684bb..1f4e043dd 100644 --- a/networkapi/util/appcache.py +++ b/networkapi/util/appcache.py @@ -19,9 +19,28 @@ def cache_enabled(): if int(get_value('use_cache')): return 1 return 0 - except Exception as e: + except Exception as ERROR: + log.error(ERROR) return 0 + +def set_cache(key, data, timeout): + try: + djangocache.set(key, data, timeout) + log.debug('Key cached successfully for key %s' % key) + except Exception as ERROR: + log.error(ERROR) + + +def get_cache(key): + try: + data = djangocache.get(key) + if data: + log.debug("Got cached data for key %s" % key) + return data + except Exception as ERROR: + log.error(ERROR) + def get_cached_search(prefix, search): @@ -29,9 +48,7 @@ def get_cached_search(prefix, search): try: search_md5 = hashlib.md5(str(search)).hexdigest() key = prefix+search_md5 - data = djangocache.get(key) - if data: - log.debug("Got cached data for key %s" % key) + data = get_cache(key) return data except Exception as e: log.error(e) @@ -47,7 +64,7 @@ def set_cache_search_with_list(prefix, search, data, timeout=DEFAULT_CACHE_TIMEO key = prefix+search_md5 djangocache.set(key, data, timeout) - cached_search_md5_list = djangocache.get(prefix) + cached_search_md5_list = get_cache(prefix) if not cached_search_md5_list: cached_search_md5_list = [] @@ -67,7 +84,7 @@ def delete_cached_searches_list(prefix): if cache_enabled(): with distributedlock(prefix): try: - cached_search_md5_list = djangocache.get(prefix) + cached_search_md5_list = get_cache(prefix) if cached_search_md5_list: for cached_search_md5 in cached_search_md5_list: key = str(prefix)+str(cached_search_md5) diff --git a/networkapi/util/cachenew.py b/networkapi/util/cachenew.py new file mode 100644 index 000000000..38beb2fac --- /dev/null +++ b/networkapi/util/cachenew.py @@ -0,0 +1,68 @@ +import hashlib +import logging + +from django.core.cache import cache as memcache + +from networkapi.distributedlock import distributedlock + +log = logging.getLogger(__name__) + + +DEFAULT_CACHE_TIMEOUT = 86400 + +ENVIRONMENT_CACHE_ENTRY = "CACHE_ENV_LIST" + + +def get_cached_search(prefix, search): + + try: + search_md5 = hashlib.md5(str(search)).hexdigest() + key = prefix+search_md5 + data = memcache.get(key) + if data: + log.debug("Got cached data for key %s" % key) + return data + except Exception as e: + log.error(e) + return None + + +def set_cache_search_with_list(prefix, search, data, timeout=DEFAULT_CACHE_TIMEOUT): + + with distributedlock(prefix): + try: + search_md5 = hashlib.md5(str(search)).hexdigest() + key = prefix+search_md5 + memcache.set(key, data, timeout) + + cached_search_md5_list = memcache.get(prefix) + if not cached_search_md5_list: + cached_search_md5_list = [] + + if search_md5 not in cached_search_md5_list: + cached_search_md5_list.append(search_md5) + + log.debug("Caching key %s in list %s ..." % (key, prefix)) + key = prefix + memcache.set(key, cached_search_md5_list, timeout) + except Exception as e: + log.error(e) + + +def delete_cached_searches_list(prefix): + + with distributedlock(prefix): + try: + cached_search_md5_list = memcache.get(prefix) + if cached_search_md5_list: + for cached_search_md5 in cached_search_md5_list: + key = str(prefix)+str(cached_search_md5) + log.debug("Deleting cache entry %s ... " % key) + memcache.delete(key) + log.debug("Deleting cache list entry %s ..." % prefix) + memcache.delete(prefix) + except Exception as e: + log.error(e) + raise e + + return True diff --git a/networkapi/util/encrypt.py b/networkapi/util/encrypt.py new file mode 100644 index 000000000..5c9430429 --- /dev/null +++ b/networkapi/util/encrypt.py @@ -0,0 +1,48 @@ +import hashlib +import logging +from Crypto.Cipher import Blowfish +from Crypto.Random import get_random_bytes + +log = logging.getLogger(__name__) + + +def encrypt_key(text, salt_key): + try: + bs = Blowfish.block_size + extra_bytes = len(text) % bs + padding_size = bs - extra_bytes + padding = chr(padding_size) * padding_size + padded_text = text + padding + + crypt_obj = Blowfish.new(salt_key, Blowfish.MODE_ECB) + + cipher = crypt_obj.encrypt(padded_text) + + return cipher + except Exception as ERROR: + log.error(ERROR) + + +def decrypt_key(cipher, salt_key): + try: + crypt_obj = Blowfish.new(salt_key, Blowfish.MODE_ECB) + decrypted_key = crypt_obj.decrypt(cipher) + + padding_size = ord(decrypted_key[-1]) + + text = decrypted_key[:-padding_size] + + log.debug("Decrypt key was made successfully") + return str(text) + + except Exception as ERROR: + log.error(ERROR) + + +def generate_key(): + try: + bs = Blowfish.block_size + return get_random_bytes(bs) + + except Exception as ERROR: + log.error(ERROR) diff --git a/networkapi/util/geral.py b/networkapi/util/geral.py index ad6b43123..d364f104f 100644 --- a/networkapi/util/geral.py +++ b/networkapi/util/geral.py @@ -153,9 +153,9 @@ def generate_return_json(obj_serializer, main_property, **kwargs): data.update({ 'total': obj_model.get('total'), - 'url_next_search': url_next_search, + 'url_next_search': str(url_next_search), 'next_search': obj_model.get('next_search'), - 'url_prev_search': url_prev_search, + 'url_prev_search': str(url_prev_search), 'prev_search': obj_model.get('prev_search') }) diff --git a/networkapi/util/network.py b/networkapi/util/network.py index 3310b6fc8..5d97926fa 100644 --- a/networkapi/util/network.py +++ b/networkapi/util/network.py @@ -228,14 +228,15 @@ def validate_network(envs, net_ip, version): """ models = get_app('ambiente', 'models') + cidr = models.EnvCIDR() # Filter network_ipv4 where environment has config permiting to insert # current network. nets_envs = list() for env in envs: # get configs v4 of environment - nts = [IPNetwork(config.ip_config.subnet) - for config in env.configs.filter(ip_config__type=version)] + nts = [IPNetwork(config.network) + for config in cidr.get(env_id=env.id).filter(ip_version=version)] # get networks that can be intersect with current network if verify_intersect(nts, net_ip)[0]: diff --git a/networkapi/util/timer.py b/networkapi/util/timer.py new file mode 100644 index 000000000..4f03c6049 --- /dev/null +++ b/networkapi/util/timer.py @@ -0,0 +1,39 @@ +import logging +from time import time + +log = logging.getLogger(__name__) + + +class Timer(): + def __init__(self, debug_msg=None): + self._start = time() + self._laps = [] + self._last_lap = 0 + self._lap_control = self._start + self._stopped = 0 + if debug_msg: + log.debug(debug_msg) + + def lap(self, debug_msg=None): + curr_time = time() + self._last_lap = curr_time-self._lap_control + self._lap_control = curr_time + self._laps.append(self._last_lap) + if debug_msg: + log.debug(debug_msg) + return self._last_lap + + def elapsed_time(self, debug_msg=None): + total_time = time()-self._start + if debug_msg: + log.debug(debug_msg) + return total_time + + def laps(self): + return self._laps + + def last_lap(self): + return self._last_lap + + def reset(self, debug_msg=None): + self.__init__(debug_msg) diff --git a/networkapi/vlan/models.py b/networkapi/vlan/models.py index e4eba5e0d..6ad88d656 100644 --- a/networkapi/vlan/models.py +++ b/networkapi/vlan/models.py @@ -2,6 +2,7 @@ from __future__ import with_statement import logging +import re from _mysql_exceptions import OperationalError from django.core.exceptions import ObjectDoesNotExist @@ -114,6 +115,14 @@ def __init__(self, cause, message=None): VlanError.__init__(self, cause, message) +class VlanNameInvalid(VlanError): + + """Retorna exceção porque o nome da VLAN tem caracter especial ou quebra de linha.""" + + def __init__(self, cause, message=None): + VlanError.__init__(self, cause, message) + + class VlanACLDuplicatedError(VlanError): """Retorna exceção porque já existe uma VLAN cadastrada com o mesmo nome de arquivo ACL.""" @@ -405,6 +414,16 @@ def search_vlan_numbers(self, environment_id, min_num, max_num): self.log.error(u'Failure to search the Vlans.') raise VlanError(e, u'Failure to search the Vlans.') + def valid_vlan_name(self, name): + + if name is None or name == '': + return False + + regex_for_breakline = re.compile('\r|\n\r|\n') + regex_for_special_characters = re.compile('[@!#$%^&*()<>?/\\\|}{~:]') + + return False if regex_for_breakline.search(name) or regex_for_special_characters.search(name) else True + def search(self, environment_id=None): try: v = Vlan.objects.all() @@ -567,6 +586,11 @@ def create_new(self, authenticated_user, min_num_01, max_num_01, min_num_02, max @return: nothing """ + + # Validate Name VLAN + if not self.valid_vlan_name(self.nome): + raise VlanNameInvalid(None, 'Name VLAN can not have special characters or breakline.') + if self.nome is not None: self.nome = self.nome.upper() @@ -626,6 +650,11 @@ def create(self, authenticated_user, min_num_01, max_num_01, min_num_02, max_num @raise VlanError: Erro não esperado ao executar o save. """ + + # Validate Name VLAN + if not self.valid_vlan_name(self.nome): + raise VlanNameInvalid(None, 'Name VLAN can not have special characters or breakline.') + if self.nome is not None: self.nome = self.nome.upper() @@ -804,6 +833,10 @@ def insert_vlan(self, authenticated_user): raise VlanNameDuplicatedError( None, 'Name VLAN can not be duplicated in the environment.') + # Validate Name VLAN + if not self.valid_vlan_name(self.nome): + raise VlanNameInvalid(None, 'Name VLAN can not have special characters or breakline.') + try: return self.save() @@ -1010,6 +1043,10 @@ def validate_v3(self): self.log.error(msg) raise VlanErrorV3(msg) + if not self.valid_vlan_name(self.nome): + msg = 'Name VLAN can not have special characters or breakline.' + raise VlanErrorV3(msg) + # Validate Number of vlan in environment related equips = self.get_eqpt() @@ -1481,10 +1518,10 @@ def allow_networks_environment(self, configs, netv4, netv6): for net in netv4: configsv4 = configs.filter( - ip_config__type='v4' + ip_version='v4' ) - nts = [IPNetwork(config.ip_config.subnet) for config in configsv4] + nts = [IPNetwork(config.network) for config in configsv4] net_ip = [IPNetwork(net.networkv4)] @@ -1498,10 +1535,10 @@ def allow_networks_environment(self, configs, netv4, netv6): for net in netv6: configsv6 = configs.filter( - ip_config__type='v6' + ip_version='v6' ) - nts = [IPNetwork(config.ip_config.subnet) for config in configsv6] + nts = [IPNetwork(config.network) for config in configsv6] net_ip = [IPNetwork(net.networkv6)] diff --git a/networkapi/vlan/resource/NetworkTypeResource.py b/networkapi/vlan/resource/NetworkTypeResource.py index 998c8e8ed..0c0f0d50c 100644 --- a/networkapi/vlan/resource/NetworkTypeResource.py +++ b/networkapi/vlan/resource/NetworkTypeResource.py @@ -30,6 +30,7 @@ from networkapi.util import is_valid_int_greater_zero_param from networkapi.util import is_valid_string_maxsize from networkapi.util import is_valid_string_minsize +from networkapi.util import is_valid_vlan_name from networkapi.vlan.models import NetTypeUsedByNetworkError from networkapi.vlan.models import NetworkTypeNameDuplicatedError from networkapi.vlan.models import NetworkTypeNotFoundError @@ -106,8 +107,18 @@ def handle_post(self, request, user, *args, **kwargs): u'Parameter %s is invalid. Value: %s.', 'name', name) raise InvalidValueError(None, 'name', name) + if not is_valid_vlan_name(name): + self.log.error( + u'Parameter %s is invalid because is using special characters and/or breaklines.', name) + raise InvalidValueError(None, 'name', name) + net_type = TipoRede(tipo_rede=name) + if not is_valid_vlan_name(name): + self.log.error( + u'Parameter %s is invalid because is using special characters and/or breaklines.', name) + raise InvalidValueError(None, 'name', name) + try: TipoRede.get_by_name(net_type.tipo_rede) raise NetworkTypeNameDuplicatedError( diff --git a/networkapi/vlan/resource/VlanAllocateIPv6Resorce.py b/networkapi/vlan/resource/VlanAllocateIPv6Resorce.py index 26c3bc613..18e0cd7f6 100644 --- a/networkapi/vlan/resource/VlanAllocateIPv6Resorce.py +++ b/networkapi/vlan/resource/VlanAllocateIPv6Resorce.py @@ -37,6 +37,7 @@ from networkapi.util import is_valid_int_greater_zero_param from networkapi.util import is_valid_string_maxsize from networkapi.util import is_valid_string_minsize +from networkapi.util import is_valid_vlan_name from networkapi.vlan.models import NetworkTypeNotFoundError from networkapi.vlan.models import TipoRede from networkapi.vlan.models import Vlan @@ -90,6 +91,11 @@ def handle_post(self, request, user, *args, **kwargs): self.log.error(u'Parameter name is invalid. Value: %s.', name) raise InvalidValueError(None, 'name', name) + if not is_valid_vlan_name(name): + self.log.error( + u'Parameter %s is invalid because is using special characters and/or breaklines.', name) + raise InvalidValueError(None, 'name', name) + # Description can NOT be greater than 200 if not is_valid_string_minsize(description, 3, False) or not is_valid_string_maxsize(description, 200, False): self.log.error( diff --git a/networkapi/vlan/resource/VlanAllocateResource.py b/networkapi/vlan/resource/VlanAllocateResource.py index 0aa228a36..d301ddbad 100644 --- a/networkapi/vlan/resource/VlanAllocateResource.py +++ b/networkapi/vlan/resource/VlanAllocateResource.py @@ -36,6 +36,7 @@ from networkapi.util import is_valid_int_greater_zero_param from networkapi.util import is_valid_string_maxsize from networkapi.util import is_valid_string_minsize +from networkapi.util import is_valid_vlan_name from networkapi.vlan.models import Vlan from networkapi.vlan.models import VlanError from networkapi.vlan.models import VlanNameDuplicatedError @@ -92,6 +93,11 @@ def handle_post(self, request, user, *args, **kwargs): self.log.error(u'Parameter name is invalid. Value: %s.', name) raise InvalidValueError(None, 'name', name) + if not is_valid_vlan_name(name): + self.log.error( + u'Parameter %s is invalid because is using special characters and/or breaklines.', name) + raise InvalidValueError(None, 'name', name) + # Description can NOT be greater than 200 if not is_valid_string_minsize(description, 3, False) or not is_valid_string_maxsize(description, 200, False): self.log.error( diff --git a/networkapi/vlan/resource/VlanEditResource.py b/networkapi/vlan/resource/VlanEditResource.py index 80060f227..4b62bd9ec 100644 --- a/networkapi/vlan/resource/VlanEditResource.py +++ b/networkapi/vlan/resource/VlanEditResource.py @@ -38,6 +38,7 @@ from networkapi.util import is_valid_int_greater_zero_param from networkapi.util import is_valid_string_maxsize from networkapi.util import is_valid_string_minsize +from networkapi.util import is_valid_vlan_name from networkapi.vlan.models import Vlan from networkapi.vlan.models import VlanACLDuplicatedError from networkapi.vlan.models import VlanError @@ -118,6 +119,11 @@ def handle_post(self, request, user, *args, **kwargs): self.log.error(u'Parameter name is invalid. Value: %s', name) raise InvalidValueError(None, 'name', name) + if not is_valid_vlan_name(name): + self.log.error( + u'Parameter %s is invalid because is using special characters and/or breaklines.', name) + raise InvalidValueError(None, 'name', name) + p = re.compile('^[A-Z0-9-_]+$') m = p.match(name) diff --git a/networkapi/vlan/resource/VlanInsertResource.py b/networkapi/vlan/resource/VlanInsertResource.py index c82da3895..09c5971c6 100644 --- a/networkapi/vlan/resource/VlanInsertResource.py +++ b/networkapi/vlan/resource/VlanInsertResource.py @@ -42,6 +42,7 @@ from networkapi.util import is_valid_int_greater_zero_param from networkapi.util import is_valid_string_maxsize from networkapi.util import is_valid_string_minsize +from networkapi.util import is_valid_vlan_name from networkapi.vlan.models import Vlan from networkapi.vlan.models import VlanACLDuplicatedError from networkapi.vlan.models import VlanError @@ -117,6 +118,11 @@ def handle_post(self, request, user, *args, **kwargs): self.log.error(u'Parameter name is invalid. Value: %s', name) raise InvalidValueError(None, 'name', name) + if not is_valid_vlan_name(name): + self.log.error( + u'Parameter %s is invalid because is using special characters and/or breaklines.', name) + raise InvalidValueError(None, 'name', name) + if not network_ipv4 or not str(network_ipv4).isdigit(): self.log.error( u'Parameter network_ipv4 is invalid. Value: %s.', network_ipv4) diff --git a/networkapi/vlan/resource/VlanResource.py b/networkapi/vlan/resource/VlanResource.py index 6045edaa6..7bfa64dac 100644 --- a/networkapi/vlan/resource/VlanResource.py +++ b/networkapi/vlan/resource/VlanResource.py @@ -49,6 +49,7 @@ from networkapi.util import is_valid_int_greater_zero_param from networkapi.util import is_valid_string_maxsize from networkapi.util import is_valid_string_minsize +from networkapi.util import is_valid_vlan_name from networkapi.vlan.models import NetworkTypeNotFoundError from networkapi.vlan.models import TipoRede from networkapi.vlan.models import Vlan @@ -114,6 +115,11 @@ def handle_post(self, request, user, *args, **kwargs): self.log.error(u'Parameter nome is invalid. Value: %s.', name) raise InvalidValueError(None, 'nome', name) + if not is_valid_vlan_name(name): + self.log.error( + u'Parameter %s is invalid because is using special characters and/or breaklines.', name) + raise InvalidValueError(None, 'name', name) + # Description can NOT be greater than 200 if not is_valid_string_minsize(description, 3, False) or not is_valid_string_maxsize(description, 200, False): self.log.error( diff --git a/requirements.txt b/requirements.txt index 80629d868..56cf99a05 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,6 +13,7 @@ graypy==0.2.14 gunicorn==19.9.0 httplib2==0.9.2 ipaddress==1.0.16 +ipaddr==2.1.11 ipython==5.3.0 json-delta==2.0 json-spec[ip]==0.10.1 diff --git a/scripts/docker/netapi.env b/scripts/docker/netapi.env index 7098f307e..81489385d 100644 --- a/scripts/docker/netapi.env +++ b/scripts/docker/netapi.env @@ -37,3 +37,5 @@ NETWORKAPI_LOG_FILE=/tmp/networkapi.log GUNICORN_DAEMONIZED=0 NETWORKAPI_SDN_CTRL=netapi_odl + +DJANGO_SECRET_KEY=ry@zgop%w80_nu83#!tbz)m&7*i@1)d-+ki@5^d#%6-&^216sg