Example #1
0
    def delete(self, channel_id):
        """ tries to delete a channel and update equipments interfaces """

        try:
            interface = Interface.get_by_pk(int(channel_id))

            try:
                interface.channel.id
                channel = interface.channel
            except AtributeError:
                channel = interface.ligacao_front.channel

            try:
                interfaces = Interface.objects.all().filter(
                    channel__id=channel.id)
            except Exception as err:
                return {"error": str(err)}

            iface_type = TipoInterface.get_by_name('access')
            equip_dict = self._get_equipment_dict(interfaces)

            self._update_equipments(equip_dict, iface_type, self.user, channel)
            channel.delete(self.user)

            return {"channel": channel.id}

        except (InterfaceException, InvalidKeyException,
                InterfaceTemplateException) as err:
            return {"error": str(err)}
Example #2
0
    def update(self, data):

        try:
            id_channel = data.get('id_channel')
            nome = data.get('nome')

            if not is_valid_int_greater_zero_param(nome):
                raise InvalidValueError(None, 'Channel number',
                                        'must be integer.')

            lacp = data.get('lacp')
            int_type = data.get('int_type')
            vlan_nativa = data.get('vlan')
            envs_vlans = data.get('envs')
            ids_interface = data.get('ids_interface')

            if ids_interface is None:
                raise InterfaceError('No interfaces selected')

            if type(ids_interface) == list:
                interfaces_list = ids_interface
            else:
                interfaces_list = str(ids_interface).split('-')

            api_interface_facade.verificar_vlan_nativa(vlan_nativa)

            # verifica se o nome do port channel já existe no equipamento
            self.channel = PortChannel.get_by_pk(int(id_channel))

            if not nome == self.channel.nome:
                api_interface_facade.verificar_nome_channel(
                    nome, interfaces_list)

            # buscar interfaces do channel
            interfaces = Interface.objects.all().filter(channel__id=id_channel)
            ids_list = []
            for i in interfaces:
                ids_list.append(i.id)

            self._dissociate_interfaces_from_channel(ids_list, ids_interface)

            # update channel
            self.channel.nome = str(nome)
            self.channel.lacp = convert_string_or_int_to_boolean(lacp)
            self.channel.save()

            int_type = TipoInterface.get_by_name(str(int_type))

            self._update_interfaces_from_http_put(ids_interface, int_type,
                                                  vlan_nativa, envs_vlans)

        except Exception as err:
            return {"error": str(err)}

        return {"port_channel": self.channel}
Example #3
0
    def create(self, data):
        """ Creates a new Port Channel """

        try:
            interfaces = data.get('interfaces')
            nome = data.get('nome')
            lacp = data.get('lacp')
            int_type = data.get('int_type')
            vlan_nativa = data.get('vlan')
            envs_vlans = data.get('envs')

            api_interface_facade.verificar_vlan_nativa(vlan_nativa)

            # Checks if Port Channel name already exists on equipment
            interfaces = str(interfaces).split('-')
            api_interface_facade.check_channel_name_on_equipment(
                nome, interfaces)

            self.channel = PortChannel()
            self.channel.nome = str(nome)
            self.channel.lacp = convert_string_or_int_to_boolean(lacp)
            self.channel.create(user)

            int_type = TipoInterface.get_by_name(str(int_type))

            ifaces_on_channel = []
            for interface in interfaces:

                if interface:
                    iface = Interface.get_by_pk(int(interface))

                    self._update_interfaces_from_a_channel(
                        iface, vlan_nativa, ifaces_on_channel, int_type)

                    if 'trunk' in int_type.tipo:
                        self._create_ifaces_on_trunks(sw_router, envs_vlans)

        except Exception as err:
            return {"error": str(err)}

        return {'port_channel': self.channel}
    def handle_post(self, request, user, *args, **kwargs):
        """Trata as requisições de POST para criar uma nova interface para o equipamento

        URL: /interface/ 

        """
        # Obtém dados do request e verifica acesso
        try:

            # Obtém os dados do xml do request
            xml_map, attrs_map = loads(request.raw_post_data)

            # Obtém o mapa correspondente ao root node do mapa do XML
            # (networkapi)
            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.')

            # Verifica a existência do node "interface"
            interface_map = networkapi_map.get('interface')
            if interface_map is None:
                return self.response_error(3, u'Não existe valor para a tag interface do XML de requisição.')

            # Valid id_equipamento value
            id_equipamento = interface_map.get('id_equipamento')
            if not is_valid_int_greater_zero_param(id_equipamento):
                self.log.error(
                    u'Parameter id_equipamento is invalid. Value: %s', id_equipamento)
                raise InvalidValueError(None, 'id_equipamento', id_equipamento)
            else:
                id_equipamento = int(id_equipamento)

            # Check existence
            Equipamento.get_by_pk(id_equipamento)

            # Verify permission
            if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION, None,
                            id_equipamento, AdminPermission.EQUIP_WRITE_OPERATION):
                return self.not_authorized()

            # Valid name value
            nome = interface_map.get('nome')
            if not is_valid_string_minsize(nome, 1) or not is_valid_string_maxsize(nome, 20):
                self.log.error(u'Parameter nome is invalid. Value: %s', nome)
                raise InvalidValueError(None, 'nome', nome)

            # Valid protegida value
            protegida = interface_map.get('protegida')
            if not is_valid_boolean_param(protegida):
                self.log.error(
                    u'Parameter protegida is invalid. Value: %s', protegida)
                raise InvalidValueError(None, 'protegida', protegida)
            else:
                protegida = convert_string_or_int_to_boolean(protegida)

            # Valid descricao value
            descricao = interface_map.get('descricao')
            if descricao is not None:
                if not is_valid_string_minsize(descricao, 3) or not is_valid_string_maxsize(descricao, 200):
                    self.log.error(
                        u'Parameter descricao is invalid. Value: %s', descricao)
                    raise InvalidValueError(None, 'descricao', descricao)

            # Valid "id_ligacao_front" value
            id_ligacao_front = interface_map.get('id_ligacao_front')
            if id_ligacao_front is not None:
                if not is_valid_int_greater_zero_param(id_ligacao_front):
                    self.log.error(
                        u'The id_ligacao_front parameter is not a valid value: %s.', id_ligacao_front)
                    raise InvalidValueError(
                        None, 'id_ligacao_front', id_ligacao_front)
                else:
                    id_ligacao_front = int(id_ligacao_front)
                    ligacao_front = Interface(id=id_ligacao_front)
            else:
                ligacao_front = None

            # Valid "id_ligacao_back" value
            id_ligacao_back = interface_map.get('id_ligacao_back')
            if id_ligacao_back is not None:
                if not is_valid_int_greater_zero_param(id_ligacao_back):
                    self.log.error(
                        u'The id_ligacao_back parameter is not a valid value: %s.', id_ligacao_back)
                    raise InvalidValueError(
                        None, 'id_ligacao_back', id_ligacao_back)
                else:
                    id_ligacao_back = int(id_ligacao_back)
                    ligacao_back = Interface(id=id_ligacao_back)
            else:
                ligacao_back = None

            tipo_interface = interface_map.get('tipo')
            if tipo_interface == None:
                tipo_interface = "Access"
            tipo_interface = TipoInterface.get_by_name(tipo_interface)

            vlan = interface_map.get('vlan')

            # Cria a interface conforme dados recebidos no XML
            interface = Interface(
                interface=nome,
                protegida=protegida,
                descricao=descricao,
                ligacao_front=ligacao_front,
                ligacao_back=ligacao_back,
                equipamento=Equipamento(id=id_equipamento),
                tipo=tipo_interface,
                vlan_nativa=vlan
            )

            interface.create(user)

            networkapi_map = dict()
            interface_map = dict()

            interface_map['id'] = interface.id
            networkapi_map['interface'] = interface_map

            return self.response(dumps_networkapi(networkapi_map))

        except InvalidValueError, e:
            return self.response_error(269, e.param, e.value)
    def handle_put(self, request, user, *args, **kwargs):
        """Trata uma requisição PUT para alterar informações de uma interface.

        URL: /interface/<id_interface>/
        """

        # Get request data and check permission
        try:
            # Valid Interface ID
            id_interface = kwargs.get('id_interface')
            if not is_valid_int_greater_zero_param(id_interface):
                self.log.error(
                    u'The id_interface parameter is not a valid value: %s.', id_interface)
                raise InvalidValueError(None, 'id_interface', id_interface)

            # Get interface and equipment to check permission
            interface = Interface.get_by_pk(id_interface)
            id_equipamento = interface.equipamento_id

            # Check permission
            if not has_perm(user,
                            AdminPermission.EQUIPMENT_MANAGEMENT,
                            AdminPermission.WRITE_OPERATION,
                            None,
                            id_equipamento,
                            AdminPermission.EQUIP_WRITE_OPERATION):
                return self.not_authorized()

            # Get XML data
            xml_map, attrs_map = loads(request.raw_post_data)

            networkapi_map = xml_map.get('networkapi')
            if networkapi_map is None:
                return self.response_error(3, u'There is no networkapi tag in XML request.')

            interface_map = networkapi_map.get('interface')
            if interface_map is None:
                return self.response_error(3, u'There is no interface tag in XML request.')

            # Valid name value
            nome = interface_map.get('nome')
            if not is_valid_string_minsize(nome, 1) or not is_valid_string_maxsize(nome, 20):
                self.log.error(u'Parameter nome is invalid. Value: %s', nome)
                raise InvalidValueError(None, 'nome', nome)

            # Valid protegida value
            protegida = interface_map.get('protegida')
            if not is_valid_boolean_param(protegida):
                self.log.error(
                    u'Parameter protegida is invalid. Value: %s', protegida)
                raise InvalidValueError(None, 'protegida', protegida)
            else:
                protegida = convert_string_or_int_to_boolean(protegida)

            # Valid descricao value
            descricao = interface_map.get('descricao')
            if descricao is not None:
                if not is_valid_string_minsize(descricao, 3) or not is_valid_string_maxsize(descricao, 200):
                    self.log.error(
                        u'Parameter descricao is invalid. Value: %s', descricao)
                    raise InvalidValueError(None, 'descricao', descricao)

            # Valid "id_ligacao_front" value
            id_ligacao_front = interface_map.get('id_ligacao_front')
            if id_ligacao_front is not None:
                if not is_valid_int_greater_zero_param(id_ligacao_front):
                    self.log.error(
                        u'The id_ligacao_front parameter is not a valid value: %s.', id_ligacao_front)
                    raise InvalidValueError(
                        None, 'id_ligacao_front', id_ligacao_front)
                else:
                    id_ligacao_front = int(id_ligacao_front)

            # Valid "id_ligacao_back" value
            id_ligacao_back = interface_map.get('id_ligacao_back')
            if id_ligacao_back is not None:
                if not is_valid_int_greater_zero_param(id_ligacao_back):
                    self.log.error(
                        u'The id_ligacao_back parameter is not a valid value: %s.', id_ligacao_back)
                    raise InvalidValueError(
                        None, 'id_ligacao_back', id_ligacao_back)
                else:
                    id_ligacao_back = int(id_ligacao_back)

            tipo = interface_map.get('tipo')
            tipo = TipoInterface.get_by_name(tipo)

            vlan = interface_map.get('vlan')

            with distributedlock(LOCK_INTERFACE % id_interface):

                # Update interface
                Interface.update(user,
                                 id_interface,
                                 interface=nome,
                                 protegida=protegida,
                                 descricao=descricao,
                                 ligacao_front_id=id_ligacao_front,
                                 ligacao_back_id=id_ligacao_back,
                                 tipo=tipo,
                                 vlan_nativa=vlan)

                return self.response(dumps_networkapi({}))

        except InvalidValueError, e:
            return self.response_error(269, e.param, e.value)
Example #6
0
    def handle_put(self, request, user, *args, **kwargs):
        """Treat requests POST to add Rack.

        URL: channel/editar/
        """
        try:
            self.log.info('Editar Channel')

            # User permission
            if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION):
                self.log.error(
                    u'User does not have permission to perform the operation.')
                raise UserNotAuthorizedError(None)

            # Load XML data
            xml_map, attrs_map = loads(request.raw_post_data)

            # XML data format
            networkapi_map = xml_map.get('networkapi')
            if networkapi_map is None:
                return self.response_error(3, u'There is no value to the networkapi tag  of XML request.')

            channel_map = networkapi_map.get('channel')
            if channel_map is None:
                return self.response_error(3, u'There is no value to the channel tag  of XML request.')

            # Get XML data
            id_channel = channel_map.get('id_channel')
            nome = channel_map.get('nome')
            if not is_valid_int_greater_zero_param(nome):
                raise InvalidValueError(
                    None, 'Numero do Channel', 'Deve ser um numero inteiro.')
            lacp = channel_map.get('lacp')
            int_type = channel_map.get('int_type')
            vlan_nativa = channel_map.get('vlan')
            envs_vlans = channel_map.get('envs')
            ids_interface = channel_map.get('ids_interface')
            if ids_interface is None:
                raise InterfaceError('Nenhuma interface selecionada')

            if type(ids_interface) == list:
                interfaces_list = ids_interface
            else:
                interfaces_list = str(ids_interface).split('-')

            port_channel = PortChannel()
            interface = Interface()
            amb = Ambiente()

            api_interface_facade.verificar_vlan_nativa(vlan_nativa)

            # verifica se o nome do port channel já existe no equipamento
            channel = port_channel.get_by_pk(int(id_channel))
            if not nome == channel.nome:
                api_interface_facade.verificar_nome_channel(
                    nome, interfaces_list)

            # buscar interfaces do channel
            interfaces = Interface.objects.all().filter(channel__id=id_channel)
            ids_list = []
            for i in interfaces:
                ids_list.append(i.id)

            ids_list = [int(y) for y in ids_list]
            if type(ids_interface) is list:
                ids_interface = [int(x) for x in ids_interface]
                desassociar = set(ids_list) - set(ids_interface)
                for item in desassociar:
                    item = interface.get_by_pk(int(item))
                    item.channel = None
                    item.save()
            else:
                if ids_interface is not None:
                    ids_interface = int(ids_interface)
                    if ids_interface is not None:
                        for item in ids_list:
                            item = interface.get_by_pk(int(item))
                            item.channel = None
                            item.save()
                    else:
                        for item in ids_list:
                            if not item == ids_interface:
                                item = interface.get_by_pk(int(item))
                                item.channel = None
                                item.save()

            # update channel
            channel.nome = str(nome)
            channel.lacp = convert_string_or_int_to_boolean(lacp)
            channel.save()

            int_type = TipoInterface.get_by_name(str(int_type))

            # update interfaces
            if type(ids_interface) is not list:
                i = ids_interface
                ids_interface = []
                ids_interface.append(i)
            for var in ids_interface:
                alterar_interface(var, interface, channel,
                                  int_type, vlan_nativa, user, envs_vlans, amb)
                interface = Interface()
                server_obj = Interface()
                interface_sw = interface.get_by_pk(int(var))
                interface_server = server_obj.get_by_pk(
                    interface_sw.ligacao_front.id)
                try:
                    front = interface_server.ligacao_front.id
                except:
                    front = None
                    pass
                try:
                    back = interface_server.ligacao_back.id
                except:
                    back = None
                    pass
                server_obj.update(user,
                                  interface_server.id,
                                  interface=interface_server.interface,
                                  protegida=interface_server.protegida,
                                  descricao=interface_server.descricao,
                                  ligacao_front_id=front,
                                  ligacao_back_id=back,
                                  tipo=int_type,
                                  vlan_nativa=int(vlan_nativa))

            port_channel_map = dict()
            port_channel_map['port_channel'] = port_channel

            return self.response(dumps_networkapi({'port_channel': port_channel_map}))

        except InvalidValueError, e:
            return self.response_error(269, e.param, e.value)
Example #7
0
    def handle_delete(self, request, user, *args, **kwargs):
        """Trata uma requisição DELETE para excluir um port channel
            URL: /channel/delete/<channel_name>/<interface_id>
        """
        try:
            self.log.info('Delete Channel')

            # User permission
            if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION):
                self.log.error(
                    u'User does not have permission to perform the operation.')
                raise UserNotAuthorizedError(None)

            interface_id = kwargs.get('channel_name')
            interface = Interface.get_by_pk(int(interface_id))
            equip_list = []

            try:
                interface.channel.id
                channel = interface.channel
            except:
                channel = interface.ligacao_front.channel
                pass
            try:
                interfaces = Interface.objects.all().filter(channel__id=channel.id)
            except:
                return self.response(dumps_networkapi({}))

            for i in interfaces:
                equip_list.append(i.equipamento.id)
            equip_list = set(equip_list)
            equip_dict = dict()
            for e in equip_list:
                equip_dict[str(e)] = interfaces.filter(equipamento__id=e)

            tipo = TipoInterface()
            tipo = tipo.get_by_name('access')

            for e in equip_dict:
                for i in equip_dict.get(e):
                    try:
                        front = i.ligacao_front.id
                    except:
                        front = None
                        pass
                    try:
                        back = i.ligacao_back.id
                    except:
                        back = None
                        pass
                    i.update(user,
                             i.id,
                             interface=i.interface,
                             protegida=i.protegida,
                             descricao=i.descricao,
                             ligacao_front_id=front,
                             ligacao_back_id=back,
                             tipo=tipo,
                             vlan_nativa='1')

                status = api_interface_facade.delete_channel(
                    user, e, equip_dict.get(e), channel)

            channel.delete(user)

            return self.response(dumps_networkapi({}))

        except api_interface_exceptions.InterfaceException, e:
            return self.response_error(410, e)
Example #8
0
    def handle_post(self, request, user, *args, **kwargs):
        """Treat requests POST to add Rack.
        URL: channel/inserir/
        """
        try:
            self.log.info('Inserir novo Channel')

            # User permission
            if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION):
                self.log.error(
                    u'User does not have permission to perform the operation.')
                raise UserNotAuthorizedError(None)

            # Load XML data
            xml_map, attrs_map = loads(request.raw_post_data)

            # XML data format
            networkapi_map = xml_map.get('networkapi')
            if networkapi_map is None:
                return self.response_error(3, u'There is no value to the networkapi tag  of XML request.')

            channel_map = networkapi_map.get('channel')
            if channel_map is None:
                return self.response_error(3, u'There is no value to the channel tag  of XML request.')

            # Get XML data
            interfaces = channel_map.get('interfaces')
            nome = channel_map.get('nome')
            lacp = channel_map.get('lacp')
            int_type = channel_map.get('int_type')
            vlan_nativa = channel_map.get('vlan')
            envs_vlans = channel_map.get('envs')

            port_channel = PortChannel()
            interface = Interface()
            amb = Ambiente()
            cont = []

            api_interface_facade.verificar_vlan_nativa(vlan_nativa)

            # verifica se o nome do port channel já existe no equipamento
            interfaces = str(interfaces).split('-')
            api_interface_facade.verificar_nome_channel(nome, interfaces)

            # cria o port channel
            port_channel.nome = str(nome)
            port_channel.lacp = convert_string_or_int_to_boolean(lacp)
            port_channel.create(user)

            int_type = TipoInterface.get_by_name(str(int_type))

            for var in interfaces:
                if not var == '' and not var is None:
                    interf = interface.get_by_pk(int(var))

                    try:
                        sw_router = interf.get_switch_and_router_interface_from_host_interface(
                            interf.protegida)
                    except:
                        raise InterfaceError('Interface não conectada')

                    if sw_router.channel is not None:
                        raise InterfaceError(
                            'Interface %s já está em um Channel' % sw_router.interface)

                    if cont is []:
                        cont.append(int(sw_router.equipamento.id))
                    elif not sw_router.equipamento.id in cont:
                        cont.append(int(sw_router.equipamento.id))
                        if len(cont) > 2:
                            raise InterfaceError(
                                'Mais de dois equipamentos foram selecionados')

                    if sw_router.ligacao_front is not None:
                        ligacao_front_id = sw_router.ligacao_front.id
                    else:
                        ligacao_front_id = None
                    if sw_router.ligacao_back is not None:
                        ligacao_back_id = sw_router.ligacao_back.id
                    else:
                        ligacao_back_id = None

                    Interface.update(user,
                                     sw_router.id,
                                     interface=sw_router.interface,
                                     protegida=sw_router.protegida,
                                     descricao=sw_router.descricao,
                                     ligacao_front_id=ligacao_front_id,
                                     ligacao_back_id=ligacao_back_id,
                                     tipo=int_type,
                                     vlan_nativa=vlan_nativa,
                                     channel=port_channel)

                    if 'trunk' in int_type.tipo:
                        interface_list = EnvironmentInterface.objects.all().filter(interface=sw_router.id)
                        for int_env in interface_list:
                            int_env.delete()
                        if type(envs_vlans) is not list:
                            d = envs_vlans
                            envs_vlans = []
                            envs_vlans.append(d)
                        for i in envs_vlans:
                            amb = amb.get_by_pk(int(i.get('env')))
                            amb_int = EnvironmentInterface()
                            amb_int.interface = sw_router
                            amb_int.ambiente = amb
                            try:
                                range_vlans = i.get('vlans')
                            except:
                                range_vlans = None
                                pass
                            if range_vlans:
                                api_interface_facade.verificar_vlan_range(
                                    amb, range_vlans)
                                amb_int.vlans = range_vlans
                            amb_int.create(user)

            port_channel_map = dict()
            port_channel_map['port_channel'] = port_channel

            return self.response(dumps_networkapi({'port_channel': port_channel_map}))

        except InvalidValueError, e:
            return self.response_error(269, e.param, e.value)
Example #9
0
    def handle_put(self, request, user, *args, **kwargs):
        """Trata uma requisição PUT para alterar informações de uma interface.

        URL: /interface/<id_interface>/
        """

        # Get request data and check permission
        try:
            # Valid Interface ID
            id_interface = kwargs.get('id_interface')
            if not is_valid_int_greater_zero_param(id_interface):
                self.log.error(
                    u'The id_interface parameter is not a valid value: %s.',
                    id_interface)
                raise InvalidValueError(None, 'id_interface', id_interface)

            # Get interface and equipment to check permission
            interface = Interface.get_by_pk(id_interface)
            id_equipamento = interface.equipamento_id

            # Check permission
            if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT,
                            AdminPermission.WRITE_OPERATION, None,
                            id_equipamento,
                            AdminPermission.EQUIP_WRITE_OPERATION):
                return self.not_authorized()

            # Get XML data
            xml_map, attrs_map = loads(request.raw_post_data)

            networkapi_map = xml_map.get('networkapi')
            if networkapi_map is None:
                return self.response_error(
                    3, u'There is no networkapi tag in XML request.')

            interface_map = networkapi_map.get('interface')
            if interface_map is None:
                return self.response_error(
                    3, u'There is no interface tag in XML request.')

            # Valid name value
            nome = interface_map.get('nome')
            if not is_valid_string_minsize(
                    nome, 1) or not is_valid_string_maxsize(nome, 20):
                self.log.error(u'Parameter nome is invalid. Value: %s', nome)
                raise InvalidValueError(None, 'nome', nome)

            # Valid protegida value
            protegida = interface_map.get('protegida')
            if not is_valid_boolean_param(protegida):
                self.log.error(u'Parameter protegida is invalid. Value: %s',
                               protegida)
                raise InvalidValueError(None, 'protegida', protegida)
            else:
                protegida = convert_string_or_int_to_boolean(protegida)

            # Valid descricao value
            descricao = interface_map.get('descricao')
            if descricao is not None:
                if not is_valid_string_minsize(
                        descricao, 3) or not is_valid_string_maxsize(
                            descricao, 200):
                    self.log.error(
                        u'Parameter descricao is invalid. Value: %s',
                        descricao)
                    raise InvalidValueError(None, 'descricao', descricao)

            # Valid "id_ligacao_front" value
            id_ligacao_front = interface_map.get('id_ligacao_front')
            if id_ligacao_front is not None:
                if not is_valid_int_greater_zero_param(id_ligacao_front):
                    self.log.error(
                        u'The id_ligacao_front parameter is not a valid value: %s.',
                        id_ligacao_front)
                    raise InvalidValueError(None, 'id_ligacao_front',
                                            id_ligacao_front)
                else:
                    id_ligacao_front = int(id_ligacao_front)

            # Valid "id_ligacao_back" value
            id_ligacao_back = interface_map.get('id_ligacao_back')
            if id_ligacao_back is not None:
                if not is_valid_int_greater_zero_param(id_ligacao_back):
                    self.log.error(
                        u'The id_ligacao_back parameter is not a valid value: %s.',
                        id_ligacao_back)
                    raise InvalidValueError(None, 'id_ligacao_back',
                                            id_ligacao_back)
                else:
                    id_ligacao_back = int(id_ligacao_back)

            tipo = interface_map.get('tipo')
            if tipo is not None:
                tipo = TipoInterface.get_by_name(tipo)

            vlan = interface_map.get('vlan')
            with distributedlock(LOCK_INTERFACE % id_interface):

                # Update interface
                Interface.update(user,
                                 id_interface,
                                 interface=nome,
                                 protegida=protegida,
                                 descricao=descricao,
                                 ligacao_front_id=id_ligacao_front,
                                 ligacao_back_id=id_ligacao_back,
                                 tipo=tipo,
                                 vlan_nativa=vlan)

                return self.response(dumps_networkapi({}))

        except InvalidValueError, e:
            return self.response_error(269, e.param, e.value)
Example #10
0
    def handle_post(self, request, user, *args, **kwargs):
        """Trata as requisições de POST para criar uma nova interface para o equipamento

        URL: /interface/

        """
        # Obtém dados do request e verifica acesso
        try:

            # Obtém os dados do xml do request
            xml_map, attrs_map = loads(request.raw_post_data)

            # Obtém o mapa correspondente ao root node do mapa do XML
            # (networkapi)
            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.'
                )

            # Verifica a existência do node "interface"
            interface_map = networkapi_map.get('interface')
            if interface_map is None:
                return self.response_error(
                    3,
                    u'Não existe valor para a tag interface do XML de requisição.'
                )

            # Valid id_equipamento value
            id_equipamento = interface_map.get('id_equipamento')
            if not is_valid_int_greater_zero_param(id_equipamento):
                self.log.error(
                    u'Parameter id_equipamento is invalid. Value: %s',
                    id_equipamento)
                raise InvalidValueError(None, 'id_equipamento', id_equipamento)
            else:
                id_equipamento = int(id_equipamento)

            # Check existence
            Equipamento.get_by_pk(id_equipamento)

            # Verify permission
            if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT,
                            AdminPermission.WRITE_OPERATION, None,
                            id_equipamento,
                            AdminPermission.EQUIP_WRITE_OPERATION):
                return self.not_authorized()

            # Valid name value
            nome = interface_map.get('nome')
            if not is_valid_string_minsize(
                    nome, 1) or not is_valid_string_maxsize(nome, 20):
                self.log.error(u'Parameter nome is invalid. Value: %s', nome)
                raise InvalidValueError(None, 'nome', nome)

            # Valid protegida value
            protegida = interface_map.get('protegida')
            if not is_valid_boolean_param(protegida):
                self.log.error(u'Parameter protegida is invalid. Value: %s',
                               protegida)
                raise InvalidValueError(None, 'protegida', protegida)
            else:
                protegida = convert_string_or_int_to_boolean(protegida)

            # Valid descricao value
            descricao = interface_map.get('descricao')
            if descricao is not None:
                if not is_valid_string_minsize(
                        descricao, 3) or not is_valid_string_maxsize(
                            descricao, 200):
                    self.log.error(
                        u'Parameter descricao is invalid. Value: %s',
                        descricao)
                    raise InvalidValueError(None, 'descricao', descricao)

            # Valid "id_ligacao_front" value
            id_ligacao_front = interface_map.get('id_ligacao_front')
            if id_ligacao_front is not None:
                if not is_valid_int_greater_zero_param(id_ligacao_front):
                    self.log.error(
                        u'The id_ligacao_front parameter is not a valid value: %s.',
                        id_ligacao_front)
                    raise InvalidValueError(None, 'id_ligacao_front',
                                            id_ligacao_front)
                else:
                    id_ligacao_front = int(id_ligacao_front)
                    ligacao_front = Interface(id=id_ligacao_front)
            else:
                ligacao_front = None

            # Valid "id_ligacao_back" value
            id_ligacao_back = interface_map.get('id_ligacao_back')
            if id_ligacao_back is not None:
                if not is_valid_int_greater_zero_param(id_ligacao_back):
                    self.log.error(
                        u'The id_ligacao_back parameter is not a valid value: %s.',
                        id_ligacao_back)
                    raise InvalidValueError(None, 'id_ligacao_back',
                                            id_ligacao_back)
                else:
                    id_ligacao_back = int(id_ligacao_back)
                    ligacao_back = Interface(id=id_ligacao_back)
            else:
                ligacao_back = None

            tipo_interface = interface_map.get('tipo')
            if tipo_interface is None:
                tipo_interface = 'Access'
            tipo_interface = TipoInterface.get_by_name(tipo_interface)

            vlan = interface_map.get('vlan')

            # Cria a interface conforme dados recebidos no XML
            interface = Interface(interface=nome,
                                  protegida=protegida,
                                  descricao=descricao,
                                  ligacao_front=ligacao_front,
                                  ligacao_back=ligacao_back,
                                  equipamento=Equipamento(id=id_equipamento),
                                  tipo=tipo_interface,
                                  vlan_nativa=vlan)

            interface.create(user)

            networkapi_map = dict()
            interface_map = dict()

            interface_map['id'] = interface.id
            networkapi_map['interface'] = interface_map

            return self.response(dumps_networkapi(networkapi_map))

        except InvalidValueError, e:
            return self.response_error(269, e.param, e.value)
    def handle_post(self, request, user, *args, **kwargs):
        """Treat requests POST to add Rack.
        URL: channel/inserir/
        """
        try:
            self.log.info("Inserir novo Channel")

            # User permission
            if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION):
                self.log.error(u'User does not have permission to perform the operation.')
                raise UserNotAuthorizedError(None)

            # Load XML data
            xml_map, attrs_map = loads(request.raw_post_data)

            # XML data format
            networkapi_map = xml_map.get('networkapi')
            if networkapi_map is None:
                return self.response_error(3, u'There is no value to the networkapi tag  of XML request.')

            channel_map = networkapi_map.get('channel')
            if channel_map is None:
                return self.response_error(3, u'There is no value to the channel tag  of XML request.')

            # Get XML data
            interfaces = channel_map.get('interfaces')
            nome = channel_map.get('nome')
            lacp = channel_map.get('lacp')
            int_type = channel_map.get('int_type')
            vlans = channel_map.get('vlan')
            envs = channel_map.get('envs')

            port_channel = PortChannel()
            interface = Interface()
            amb = Ambiente()

            cont = []

            interfaces = str(interfaces).split('-')
            interface_id = None

            # verifica a vlan_nativa
            vlan = vlans.get('vlan_nativa')
            if vlan is not None:
                if int(vlan) < 1 or int(vlan) > 4096:
                    raise InvalidValueError(None, "Vlan Nativa", "Range valido: 1 - 4096.")
                if int(vlan) < 1 or 3967 < int(vlan) < 4048 or int(vlan)==4096:
                    raise InvalidValueError(None, "Vlan Nativa" ,"Range reservado: 3968-4047;4094.")

            # verifica se o nome do port channel já existe no equipamento
            channels = PortChannel.objects.filter(nome=nome)
            channels_id = []
            for ch in channels:
                channels_id.append(int(ch.id))
            if channels_id:
                for var in interfaces:
                    if not var=="" and not var==None:
                        interface_id = int(var)
                interface_id = interface.get_by_pk(interface_id)
                equip_id = interface_id.equipamento.id
                equip_interfaces = interface.search(equip_id)
                for i in equip_interfaces:
                    try:
                        sw = i.get_switch_and_router_interface_from_host_interface(i.protegida)
                    except:
                        sw = None
                        pass
                    if sw.channel is not None:
                        if sw.channel.id in channels_id:
                            raise InterfaceError("O nome do port channel ja foi utilizado no equipamento")

            #cria o port channel
            port_channel.nome = str(nome)
            port_channel.lacp = convert_string_or_int_to_boolean(lacp)
            port_channel.create(user)

            int_type = TipoInterface.get_by_name(str(int_type))

            for var in interfaces:
                if not var=="" and not var==None:
                    interf = interface.get_by_pk(int(var))

                    try:
                        sw_router = interf.get_switch_and_router_interface_from_host_interface(interf.protegida)
                    except:
                        raise InterfaceError("Interface não conectada")

                    if sw_router.channel is not None:
                        raise InterfaceError("Interface %s já está em um Channel" % sw_router.interface)

                    if cont is []:
                        cont.append(int(sw_router.equipamento.id))
                    elif not sw_router.equipamento.id in cont:
                        cont.append(int(sw_router.equipamento.id))
                        if len(cont) > 2:
                            raise InterfaceError("Mais de dois equipamentos foram selecionados")

                    if sw_router.ligacao_front is not None:
                        ligacao_front_id = sw_router.ligacao_front.id
                    else:
                        ligacao_front_id = None
                    if sw_router.ligacao_back is not None:
                        ligacao_back_id = sw_router.ligacao_back.id
                    else:
                        ligacao_back_id = None

                    Interface.update(user,
                                     sw_router.id,
                                     interface=sw_router.interface,
                                     protegida=sw_router.protegida,
                                     descricao=sw_router.descricao,
                                     ligacao_front_id=ligacao_front_id,
                                     ligacao_back_id=ligacao_back_id,
                                     tipo=int_type,
                                     vlan_nativa=vlans.get('vlan_nativa'),
                                     channel=port_channel)

                    if "trunk" in int_type.tipo:
                        interface_list = EnvironmentInterface.objects.all().filter(interface=sw_router.id)
                        for int_env in interface_list:
                            int_env.delete()
                        if envs is not None:
                            amb = amb.get_by_pk(int(envs))
                            amb_int = EnvironmentInterface()
                            amb_int.interface = sw_router
                            amb_int.ambiente = amb
                            try:
                                range_vlans = vlans.get('range')
                            except:
                                range_vlans = None
                                pass
                            if range_vlans:
                                api_interface_facade.verificar_vlan_range(amb, range_vlans)
                                amb_int.vlans = range_vlans
                            amb_int.create(user)

            port_channel_map = dict()
            port_channel_map['port_channel'] = port_channel

            return self.response(dumps_networkapi({'port_channel': port_channel_map}))

        except InvalidValueError, e:
            return self.response_error(269, e.param, e.value)
    def handle_put(self, request, user, *args, **kwargs):
        """Treat requests POST to add Rack.

        URL: channel/editar/
        """
        try:
            self.log.info("Editar Channel")

            # User permission
            if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION):
                self.log.error(u'User does not have permission to perform the operation.')
                raise UserNotAuthorizedError(None)

            # Load XML data
            xml_map, attrs_map = loads(request.raw_post_data)

            # XML data format
            networkapi_map = xml_map.get('networkapi')
            if networkapi_map is None:
                return self.response_error(3, u'There is no value to the networkapi tag  of XML request.')

            channel_map = networkapi_map.get('channel')
            if channel_map is None:
                return self.response_error(3, u'There is no value to the channel tag  of XML request.')

            # Get XML data
            id_channel = channel_map.get('id_channel')
            nome = channel_map.get('nome')
            if not is_valid_int_greater_zero_param(nome):
                raise InvalidValueError(None, "Numero do Channel", "Deve ser um numero inteiro.")
            lacp = channel_map.get('lacp')
            int_type = channel_map.get('int_type')
            vlans = channel_map.get('vlan')
            envs = channel_map.get('envs')
            ids_interface = channel_map.get('ids_interface')


            if ids_interface is None:
                raise InterfaceError("Nenhuma interface selecionada")

            # verifica a vlan_nativa
            vlan = vlans.get('vlan_nativa')
            if vlan is not None:
                if int(vlan) < 1 or int(vlan) > 4096:
                    raise InvalidValueError(None, "Vlan Nativa", "Range valido: 1 - 4096.")
                if int(vlan) < 1 or 3967 < int(vlan) < 4048 or int(vlan)==4096:
                    raise InvalidValueError(None, "Vlan Nativa" ,"Range reservado: 3968-4047;4094.")

            port_channel = PortChannel()
            interface = Interface()
            amb = Ambiente()

            # verifica se o nome do port channel está sendo usado no equipamento
            channels = PortChannel.objects.filter(nome=nome)
            channels_id = []
            for ch in channels:
                channels_id.append(int(ch.id))
            if len(channels_id)>1:
                if type(ids_interface) is list:
                    for var in ids_interface:
                        if not var=="" and not var==None:
                            interface_id = int(var)
                else:
                    interface_id = int(ids_interface)
                interface_id = interface.get_by_pk(interface_id)
                equip_id = interface_id.equipamento.id
                equip_interfaces = interface.search(equip_id)
                for i in equip_interfaces:
                    try:
                        sw = i.get_switch_and_router_interface_from_host_interface(i.protegida)
                    except:
                        sw = None
                        pass
                    if sw is not None:
                        if sw.channel is not None:
                            if sw.channel.id in channels_id and sw.channel.id is not id_channel:
                                raise InterfaceError("O nome do port channel ja foi utilizado no equipamento")

            #buscar interfaces do channel
            interfaces = Interface.objects.all().filter(channel__id=id_channel)
            ids_list = []
            for i in interfaces:
                ids_list.append(i.id)

            ids_list = [ int(y) for y in ids_list ]
            if type(ids_interface) is list:
                ids_interface = [ int(x) for x in ids_interface ]
                desassociar = set(ids_list) - set(ids_interface)
                for item in desassociar:
                    item = interface.get_by_pk(int(item))
                    item.channel = None
                    item.save()
            else:
                if ids_interface is not None:
                    ids_interface = int(ids_interface)
                    if ids_interface is not None:
                        for item in ids_list:
                            item = interface.get_by_pk(int(item))
                            item.channel = None
                            item.save()
                    else:
                        for item in ids_list:
                            if not item== ids_interface:
                                item = interface.get_by_pk(int(item))
                                item.channel = None
                                item.save()


            #update channel
            port_channel = port_channel.get_by_pk(id_channel)
            port_channel.nome = str(nome)
            port_channel.lacp = convert_string_or_int_to_boolean(lacp)
            port_channel.save()

            int_type = TipoInterface.get_by_name(str(int_type))

            #update interfaces
            if type(ids_interface) is not list:
                i = ids_interface
                ids_interface = []
                ids_interface.append(i)
            for var in ids_interface:
                alterar_interface(var, interface, port_channel, int_type, vlans, user, envs, amb)
                interface = Interface()
                server_obj = Interface()
                interface_sw = interface.get_by_pk(int(var))
                interface_server = server_obj.get_by_pk(interface_sw.ligacao_front.id)
                try:
                    front = interface_server.ligacao_front.id
                except:
                    front = None
                    pass
                try:
                    back = interface_server.ligacao_back.id
                except:
                    back = None
                    pass
                server_obj.update(user,
                                  interface_server.id,
                                  interface=interface_server.interface,
                                  protegida=interface_server.protegida,
                                  descricao=interface_server.descricao,
                                  ligacao_front_id=front,
                                  ligacao_back_id=back,
                                  tipo=int_type,
                                  vlan_nativa=int(vlan))

            port_channel_map = dict()
            port_channel_map['port_channel'] = port_channel

            return self.response(dumps_networkapi({'port_channel': port_channel_map}))

        except InvalidValueError, e:
            return self.response_error(269, e.param, e.value)
    def handle_delete(self, request, user, *args, **kwargs):
        """Trata uma requisição DELETE para excluir um port channel
            URL: /channel/delete/<channel_name>/<interface_id>
        """
        try:
            self.log.info("Delete Channel")

            # User permission
            if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION):
                self.log.error(u'User does not have permission to perform the operation.')
                raise UserNotAuthorizedError(None)

            interface_id = kwargs.get('channel_name')
            interface = Interface.get_by_pk(int(interface_id))
            equip_list = []

            try:
                interface.channel.id
                channel = interface.channel
            except:
                channel = interface.ligacao_front.channel
                pass
            try:
                interfaces = Interface.objects.all().filter(channel__id=channel.id)
            except:
                return self.response(dumps_networkapi({}))

            for i in interfaces:
                equip_list.append(i.equipamento.id)
            equip_list = set(equip_list)
            equip_dict = dict()
            for e in equip_list:
                equip_dict[str(e)] = interfaces.filter(equipamento__id=e)

            tipo = TipoInterface()
            tipo = tipo.get_by_name("access")

            for e in equip_dict:
                for i in equip_dict.get(e):
                    try:
                        front = i.ligacao_front.id
                    except:
                        front = None
                        pass
                    try:
                        back = i.ligacao_back.id
                    except:
                        back = None
                        pass
                    i.update(user,
                                  i.id,
                                  interface=i.interface,
                                  protegida=i.protegida,
                                  descricao=i.descricao,
                                  ligacao_front_id=front,
                                  ligacao_back_id=back,
                                  tipo=tipo,
                                  vlan_nativa="1")

                status = api_interface_facade.delete_channel(user, e, equip_dict.get(e), channel)

            channel.delete(user)

            return self.response(dumps_networkapi({}))

        except api_interface_exceptions.InterfaceException, e:
            return api_interface_exceptions.InterfaceException(e)
    def handle_post(self, request, user, *args, **kwargs):
        """Treat requests POST to add Rack.

        URL: channel/inserir/
        """
        try:
            self.log.info("Inserir novo Channel")

            # User permission
            if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION):
                self.log.error(
                    u'User does not have permission to perform the operation.')
                raise UserNotAuthorizedError(None)

            # Load XML data
            xml_map, attrs_map = loads(request.raw_post_data)

            # XML data format
            networkapi_map = xml_map.get('networkapi')
            if networkapi_map is None:
                return self.response_error(3, u'There is no value to the networkapi tag  of XML request.')

            channel_map = networkapi_map.get('channel')
            if channel_map is None:
                return self.response_error(3, u'There is no value to the channel tag  of XML request.')

            # Get XML data
            interfaces = channel_map.get('interfaces')
            nome = channel_map.get('nome')
            lacp = channel_map.get('lacp')
            int_type = channel_map.get('int_type')
            vlan = channel_map.get('vlan')
            envs = channel_map.get('envs')
            port_channel = PortChannel()
            interface = Interface()
            amb = Ambiente()

            cont = []

            port_channel.nome = str(nome)
            port_channel.lacp = convert_string_or_int_to_boolean(lacp)
            port_channel.create(user)

            interfaces = str(interfaces).split('-')

            int_type = TipoInterface.get_by_name(str(int_type))
            for var in interfaces:
                if not var=="" and not var==None:
                    interf = interface.get_by_pk(int(var))
                    try:
                        sw_router = interf.get_switch_and_router_interface_from_host_interface(interf.protegida)
                    except:
                        raise InterfaceError("Interface não conectada")

                    if sw_router.channel is not None:
                        raise InterfaceError("Interface %s já está em um Channel" % sw_router.interface)

                    for i in interface.search(sw_router.equipamento.id):
                        if i.channel is not None:
                            raise InterfaceError("Equipamento %s já possui um Channel" % sw_router.equipamento.nome)

                    if cont is []:
                        cont.append(int(sw_router.equipamento.id))
                    elif not sw_router.equipamento.id in cont:
                        cont.append(int(sw_router.equipamento.id))
                        if len(cont) > 2:
                            raise InterfaceError("Mais de dois equipamentos foram selecionados")

                    if sw_router.ligacao_front is not None:
                        ligacao_front_id = sw_router.ligacao_front.id
                    else:
                        ligacao_front_id = None
                    if sw_router.ligacao_back is not None:
                        ligacao_back_id = sw_router.ligacao_back.id
                    else:
                        ligacao_back_id = None

                    Interface.update(user,
                                     sw_router.id,
                                     interface=sw_router.interface,
                                     protegida=sw_router.protegida,
                                     descricao=sw_router.descricao,
                                     ligacao_front_id=ligacao_front_id,
                                     ligacao_back_id=ligacao_back_id,
                                     tipo=int_type,
                                     vlan_nativa=vlan,
                                     channel=port_channel)

                    if "trunk" in int_type.tipo:
                        interface_list = EnvironmentInterface.objects.all().filter(interface=sw_router.id)
                        for int_env in interface_list:
                            int_env.delete(user)
                        if envs is not None:
                            if not type(envs)==unicode:
                                for env in envs:
                                    amb_int = EnvironmentInterface()
                                    amb_int.interface = sw_router
                                    amb_int.ambiente = amb.get_by_pk(int(env))
                                    amb_int.create(user)
                            else:
                                amb_int = EnvironmentInterface()
                                amb_int.interface = sw_router
                                amb_int.ambiente = amb.get_by_pk(int(envs))
                                amb_int.create(user)

            port_channel_map = dict()
            port_channel_map['port_channel'] = port_channel

            return self.response(dumps_networkapi({'port_channel': port_channel_map}))

        except InvalidValueError, e:
            return self.response_error(269, e.param, e.value)
    def handle_put(self, request, user, *args, **kwargs):
        """Treat requests POST to add Rack.

        URL: channel/editar/
        """
        try:
            self.log.info("Editar Channel")

            # User permission
            if not has_perm(user, AdminPermission.EQUIPMENT_MANAGEMENT, AdminPermission.WRITE_OPERATION):
                self.log.error(
                    u'User does not have permission to perform the operation.')
                raise UserNotAuthorizedError(None)

            # Load XML data
            xml_map, attrs_map = loads(request.raw_post_data)

            # XML data format
            networkapi_map = xml_map.get('networkapi')
            if networkapi_map is None:
                return self.response_error(3, u'There is no value to the networkapi tag  of XML request.')

            channel_map = networkapi_map.get('channel')
            if channel_map is None:
                return self.response_error(3, u'There is no value to the channel tag  of XML request.')

            # Get XML data
            id_channel = channel_map.get('id_channel')
            nome = channel_map.get('nome')
            lacp = channel_map.get('lacp')
            int_type = channel_map.get('int_type')
            vlan = channel_map.get('vlan')
            envs = channel_map.get('envs')
            ids_interface = channel_map.get('ids_interface')


            if ids_interface is None:
                raise InterfaceError("Nenhuma interface selecionada")

            if vlan is not None:
                if int(vlan) < 1 or int(vlan) > 4096:
                    raise InvalidValueError(None, "Vlan" , vlan)
                if int(vlan) < 1 or 3967 < int(vlan) < 4048 or int(vlan)==4096:
                    raise InvalidValueError(None, "Vlan Nativa" ,"Range reservado: 3968-4047;4094.")

            port_channel = PortChannel()
            interface = Interface()
            amb = Ambiente()
            cont = []

            #buscar interfaces do channel
            interfaces = Interface.objects.all().filter(channel__id=id_channel)
            ids_list = []
            for i in interfaces:
                ids_list.append(i.id)

            ids_list = [ int(y) for y in ids_list ]
            if type(ids_interface) is list:
                ids_interface = [ int(x) for x in ids_interface ]
                desassociar = set(ids_list) - set(ids_interface)
                for item in desassociar:
                    item = interface.get_by_pk(int(item))
                    item.channel = None
                    item.save(user)
            else:
                if ids_interface is not None:
                    ids_interface = int(ids_interface)
                    if ids_interface is not None:
                        for item in ids_list:
                            item = interface.get_by_pk(int(item))
                            item.channel = None
                            item.save(user)
                    else:
                        for item in ids_list:
                            if not item== ids_interface:
                                item = interface.get_by_pk(int(item))
                                item.channel = None
                                item.save(user)




            #update channel
            port_channel = port_channel.get_by_pk(id_channel)
            port_channel.nome = str(nome)
            port_channel.lacp = convert_string_or_int_to_boolean(lacp)
            port_channel.save(user)

            int_type = TipoInterface.get_by_name(str(int_type))

            #update interfaces
            if type(ids_interface) is list:
                for var in ids_interface:
                    alterar_interface(var, interface, port_channel, int_type, vlan, user, envs, amb)
            else:
                var = ids_interface
                alterar_interface(var, interface, port_channel, int_type, vlan, user, envs, amb)


            port_channel_map = dict()
            port_channel_map['port_channel'] = port_channel

            return self.response(dumps_networkapi({'port_channel': port_channel_map}))

        except InvalidValueError, e:
            return self.response_error(269, e.param, e.value)