Você está na página 1de 34

Programabilidade e automação de rede

Page 1 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Foreword
 Novos protocolos, tecnologias e modos de entrega e O&M estão surgindo no campo da
engenharia de rede. As redes convencionais enfrentam desafios de novos requisitos de conexão,
como requisitos para computação em nuvem e inteligência artificial (IA). As empresas também
estão buscando agilidade, flexibilidade e elasticidade de serviço. Nesse cenário, a automação de
rede se torna cada vez mais importante.
 A programação e a automação da rede visam simplificar a configuração, o gerenciamento, o
monitoramento e as operações da rede para engenheiros e melhorar a implantação e a eficiência
de O&M. Este curso é para ajudar os engenheiros de rede a entender a programação Python e
implementar a automação de rede.

Page 2 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Objectives
 Ao concluir este curso, você será capaz de:
▫ Descrever as dificuldades do O&M de rede convencional.

▫ Compreender a implementação da automação de rede.

▫ Compreender a classificação das linguagens de programação.

▫ Descrever o estilo do código Python.

▫ Descrever o uso básico do Python telnetlib.

Page 3 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Contents
1. Introdução à programação e automação de rede
2. Visão geral da linguagem de programação e do Python
3. Casos

Page 4 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Antecedentes: Dificuldades no O&M de Rede Convencional
 O&M de rede convencional exige que os engenheiros de rede efetuem login manualmente nos dispositivos de rede, consultem e
executem comandos de configuração e filtrem a saída do comando. Esse modo de trabalho altamente dependente de humanos é
demorado, ineficiente e difícil de auditar.
Cenários Típicos de O&M

Vários dispositivos As seguintes cenas de trabalho são familiares para você??


Operações complexas 1. Atualização do dispositivo: Milhares de dispositivos de rede residem em uma rede
Baixa eficiencia ativa. Você precisa atualizar periodicamente os dispositivos em lotes.
2. Auditoria de configuração: uma empresa precisa auditar a configuração dos
dispositivos todos os anos. Por exemplo, a empresa exige que o STelnet seja
habilitado em todos os dispositivos e que a segurança de spanning tree seja
configurada em switches Ethernet. Nesse caso, você precisa descobrir rapidamente
os dispositivos que não atendem aos requisitos.
3. Alteração de configuração: devido aos requisitos de segurança da rede, as contas e
senhas dos dispositivos precisam ser alteradas a cada três meses. Você tem que
excluir a conta original e criar uma conta em milhares de dispositivos de rede.

Dispositivo de rede

Page 5 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Automação de rede
 Automação de rede: são usadas ferramentas para implementar a implantação de rede automatizada, operações e O&M, reduzindo
gradualmente a dependência humana. Isso resolve os problemas convencionais de O&M da rede.
 Muitas ferramentas de código aberto, como Ansible, SaltStack, Puppet e Chef, estão disponíveis para automação de rede no setor.
Do ponto de vista da construção da capacidade de engenharia de rede, recomenda-se que os engenheiros adquiram a capacidade de
programação de código.

Palavras-chave de
Chef automação de rede SaltStack

Ferramen
ta NMS

Ansible Python scripts


Automatiza
do
Shell

Page 6 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Automação de rede baseada em programação
 Nos últimos anos, com o surgimento de tecnologias de automação de rede, os recursos de programação baseados em
Python tornaram-se um novo requisito de habilidade para engenheiros de rede.
 O script de automação escrito em Python pode executar operações repetidas, demoradas e baseadas em regras.
Exemplo: implementação da configuração automatizada do dispositivo
Python file usando Python

Configuration File • O que a automação de rede pode fazer? O exemplo mais intuitivo de
automação de rede é a configuração automatizada de dispositivos.
Sysname SW1 SSH/Telnet
Esse processo pode ser dividido em duas etapas: escrever um ficheiro
Vlan 10
description A de configuração e escrever código Python para enviar o ficheiro de
Vlan20 configuração para um dispositivo.
description B Dispositiv • Escreva o script de configuração no modo de interface de linha de
VLAN 30 o de rede comando (CLI) e, em seguida, carregue o script no dispositivo usando
description C
Telnet/SSH. Este método é fácil de entender para engenheiros de rede
que estão começando a aprender programabilidade e automação. Esta
apresentação descreve como implementar a automação de rede.

Page 7 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Contents
1. Introdução à rede Programabilidade e Automação
2. Visão geral de linguagem de programação e do Python
3. Casos

Page 8 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Linguagens de programação
 Uma linguagem de programação é usada para escrever um programa de computador e controlar o comportamento de um
computador.
 Dependendo se a compilação é necessária antes da execução de uma linguagem, a linguagem de programação pode ser classificada
na linguagem compilada e na linguagem interpretada que não precisa ser compilada.

Linguagem compilada Linguagem interpretada


(Código fonte) (Código fonte)

Compilador
Intérprete: Interpreta o
código-fonte linha por
linha.
Arquivo executável

Sistema operacional (Windows/Linux/Mac OS)

CPU (arquitetura x86/ARM)

Page 9 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Pilha de Tecnologia de Computação e Processo de
Execução do Programa
Pilha de Tecnologia de Processo de Execução do Programa
Computação
Aplicação
temp = v [k]; TEMP = V[K]
Algoritmo Linguagem de v[k] = v[k+1]; V[K] = V[K+1]
programação de v[k+1] = temp; V[K+1] = TEMP
Ordem crescente de complexidade

Programas
Linguagem de alto nível alto nível C/C++ Fortran
Ordem crescente de abstração

compiler compiler
Linguagem assembly
lw $t0, 0($2)
lw $t1, 4($2)
Código de máquina Linguagem sw $t1, 0($2)
assembly sw $t0, 4($2)
Arquitetura do conjunto de instruções
Assembler
Microarquitetura

Hardware
0000 1001 1100 0110 1010 1111 0101 1000
1010 1111 0101 1000 0000 1001 1100 0110
Portas/Registros Código de 1100 0110 1010 1111 0101 1000 0000 1001
máquina 0101 1000 0000 1001 1100 0110 1010 1111
Transistores
Conjunto de
Física Instrução 1 Dado 1
instruções

Page 10 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Linguagem de Programação de Alto Nível -
Linguagem Compilada
 Linguagem compilada: Antes de um programa em uma linguagem compilada ser executado, um processo de compilação é
executado para compilar o programa em um arquivo de linguagem de máquina. O resultado da compilação pode ser usado
diretamente sem retradução durante a execução. As linguagens compiladas típicas incluem C/C++ e Go.
 Do código-fonte ao programa: O código-fonte precisa ser traduzido em instruções de máquina pelo compilador e pelo assembler
(montador) e, em seguida, o linker (vinculador) usa a função de biblioteca de links para gerar o programa em linguagem de máquina.
A linguagem de máquina deve corresponder ao conjunto de instruções da CPU, que é carregado na memória pelo loader (carregador)
durante a execução e executado pela CPU.
Módulo de objeto: Código executável:
Programa em
Código fonte módulo de programa em
Compilador linguagem assembler Links loader Memória
C/C++ linguagem de linguagem de
assembly
máquina máquina

Biblioteca de destino:
função de biblioteca
(linguagem de máquina)

Page 11 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Linguagem de Programação de Alto Nível -
Linguagem Interpretada
 Linguagem interpretada: programas em linguagem interpretada não precisam ser compilados antes de serem executados. Eles são
traduzidos linha por linha durante a execução. Normalmente, Java e Python são linguagens interpretadas.
 Processo do código-fonte ao programa: O código-fonte de uma linguagem interpretada é gerado pelo compilador e depois
interpretado e executado por uma máquina virtual (VM) (por exemplo, JVM/PVM). A VM protege as diferenças entre os conjuntos
de instruções da CPU. Portanto, a portabilidade da linguagem interpretada é relativamente boa.

programa em linguagem Java Programa Python

Compilador Compilador

Funções da biblioteca
Arquivo de classe Função de biblioteca Java Python (linguagem arquivo .pyc
(código de bytes) (linguagem de máquina) de máquina) (código de bytes)

JVM PVM

Page 12 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
O que é Python?
 Python é uma linguagem de programação de alto nível totalmente de código aberto. Seu autor é Guido Van Rossum.

Vantagens do Python: Desvantagens do Python:


• É uma linguagem interpretada tipada dinamicamente com sintaxe • Execução lenta. É uma linguagem
elegante. Ele permite que os alunos se concentrem na lógica do programa interpretada que roda sem ser compilada. O
em vez do aprendizado de detalhes de sintaxe. código é traduzido linha por linha em tempo
• Suporta programação orientada a processos e a objetos. de execução em código de máquina que a
• Fornece bibliotecas abundantes de terceiros. CPU possa entender, o que consome tempo.
• É apelidada de linguagem cola porque pode chamar código escrito em
outras linguagens.

Com suporte para inúmeras bibliotecas de terceiros e vantagens da linguagem Python, o Python pode ser usado em
muitos campos, como IA, ciência de dados, aplicações e scripts para O&M automatizado.

Page 13 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Processo de execução do código Python
Processo de compilação e
execução de um programa Operação
Python

Código-fonte Python Instale o Python e o ambiente de execução em um


sistema operacional.

2. Compile o código-fonte do Python.


Compilador
3. O compilador executa o código-fonte Python e gera
um ficheiro .pyc (byte code).
.pyc file (byte code)
4. Uma VM Python converte o código de byte na
linguagem de máquina.
Execução da VM Python 5. O hardware executa a linguagem de máquina.

Page 14 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Introdução ao código Python - Execução
interativa
 Python é executado no modo interativo ou de script.
 A programação interativa não requer a criação do ficheiro de script e o código é escrito no modo interativo do
interpretador Python.

C:\Users\Richard>python
Python 3.7.4 (default, Aug 9 2019, 18:34:13) [MSC v.1915 64 bit (AMD64)] :: Anaconda,
Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
1. Input -- >>> print ("hello world")
2. Output -- hello world
3. Input -- >>> a = 1
4. Input -- >>> b = 2
5. Input -- >>> print ( a + b )
6. Output -- 3
>>>

Page 15 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Introdução ao código Python- Execução baseada
em script
 O código no modo de script pode ser executado em vários compiladores Python ou em ambientes de desenvolvimento
integrados. Por exemplo, IDLE, Atom, Visual Studio, Pycharm e Anaconda fornecidos pelo Python podem ser usados.

demo.py

print ("hello world") 1. Input -- C:\Users\Richard>python demo.py


a=1 2. Output -- hello world
b=2 3. Output -- 3
print ( a + b )

1 Escreva um ficheiro de script Python (.py). 2 Execute o ficheiro de script.

Page 16 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Guia de estilo do código para Python
 As regras de estilo do código referem-se a regras de nomenclatura, recuo do código e modos de segmentação do código e instrução
que devem ser cumpridos quando o Python é usado para escrever código. Boas regras de estilo ajudam a melhorar a legibilidade do
código e facilitam a manutenção e modificação do código.
 Por exemplo, as seguintes regras para usar ponto e vírgula, parênteses, linhas em branco e espaços são recomendadas:

Ponto e vírgula Linha em branco


• Um ponto e vírgula pode ser adicionado no final de uma • Diferentes funções ou blocos de instruções podem ser
linha em Python, mas não é recomendado para separar separados por espaços. Uma linha em branco ajuda a
instruções. diferenciar dois segmentos de código, melhorando a
• Recomenda-se que cada frase esteja em uma linha legibilidade do código.
separada.

Parênteses Espaço
• Parênteses podem ser usados ​para a continuação de • Espaços não são recomendados entre parênteses.
declarações longas. Evite parênteses desnecessários. • Você pode determinar se deseja adicionar espaços em
ambas as extremidades de um operador.

Page 17 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Guia de estilo do código para Python -Nomeação do
identificador
• Um identificador Python representa o nome de uma constante, variável, função ou outro objeto.

• Um identificador geralmente é composto por letras, dígitos e sublinhados, mas não pode começar com um dígito. Os identificadores
diferenciam maiúsculas de minúsculas e devem ser exclusivos. Se um identificador não estiver em conformidade com as regras, o
compilador produzirá uma mensagem de Erro de sintaxe ao executar o código.

1. Atribua um valor - User_ID = 10 print ( User_ID )


2. Atribua um valor - user_id = 20 print ( user_id )
3. Atribua uma string - User_Name = ‘Richard’ print ( User_Name )
4. Atribua um valor - Count = 1 + 1 print ( Count )
5. Identificar incorreto - 4_passwd = "Huawei" print ( 4_passwd )

print() é uma função interna do Python e é usada para gerar conteúdo entre parênteses.

Pergunta: Qual é a saída do comando print à direita?

Page 18 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Guia de estilo do código para Python - recuo do código
 Em programas Python, o recuo do código representa o escopo de um bloco de código. Se um bloco de código contém
duas ou mais instruções, as instruções devem ter o mesmo recuo. Para Python, o recuo de código é uma regra de
sintaxe que usa recuo de código e dois pontos para distinguir entre camadas de código.
 Ao escrever o código, é aconselhável usar quatro espaços para recuo. Se o recuo incorreto for usado no código do
programa, uma mensagem de erro IndentationError será exibida durante a execução do código.

if True:
Recuo correto- print ("Hello")
else:
Recuo correto- print (0)

a = “Python”
Recuo incorreto - print (a)

Page 19 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Guia de estilo do código para Python - Usando comentários
 Os comentários são explicações adicionadas aos programas para melhorar a legibilidade do programa. No programa
Python, os comentários são classificados em comentários de linha única e comentários de várias linhas.
 Um comentário de linha única começa com um sinal de libra (#).
 Um comentário de várias linhas pode conter várias linhas, que são colocadas entre um par de três aspas ('''...''' ou
'''''' ... '''''').

Comentário de linha única - # Assign a string to a.


a = “Python”
print (a)

“””
Comentário de várias linhas - The output is Python.
“””

Page 20 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Guia de estilo do código para Python - Estrutura do
arquivo do código-fonte
 Um arquivo de código-fonte Python completo geralmente consiste em declaração do interpretador e formato de
codificação, string do documento, importação do módulo e código em execução.
 Se você precisar chamar uma classe de uma biblioteca padrão ou de terceiros em um programa, use a instrução
"import" ou "from ... import" para importar módulos relacionados. A instrução de importação está sempre após o
comentário do módulo ou a string do documento (docstring) no topo do arquivo.
Declaração do intérpretador - #!/usr/bin/env python
Declaração do formato de codificação- #-*- coding:utf-8 -*-

Comentário do módulo ou string do documento - Description of a document (docstring)

This document is intended for...


“””

Momento em que um módulo é importado- import time


O código está em execução - …

Page 21 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Funções e módulos do Python
 Uma função é um bloco de código organizado e reutilizável que é usado para executar uma única ação relacionada. Pode melhorar a
modularidade do programa e a utilização do código. A função é definida usando a palavra-chave def.
 Um módulo é um arquivo Python salvo. Os módulos podem conter definições de funções, classes e variáveis ​que podem ser
utilizadas em outros programas Python. A única diferença entre um módulo e um programa Python comum é que o módulo é usado
para importação por outros programas. Portanto, um módulo geralmente não possui uma função principal.

demo.py test.py
def sit(): #Definir uma função. import demo #Importar um módulo.
print ('A dog is now sitting’)
demo.sit() #Chamar uma função.
sit() #Chamar uma função.
Resultado da execução:
Resultado da execução:
A dog is now sitting.
A dog is now sitting. A dog is now sitting.

1 Escrever um arquivo Python (.py). 2 Importar um módulo.

Page 22 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Classes e métodos do Python
 Uma classe é uma coleção de propriedades e métodos que são iguais. A palavra-chave class é usada para definir uma
classe.
 A função de uma classe instanciada é chamada de método. Quando você define um método, uma classe deve carregar
a palavra-chave self, que indica a instância da classe.
demo.py

class Dog(): #Definir uma classe. test.py


def sit(self): #definir um método.
print(“A dog is now sitting.") import demo

Richard = Dog() #A classe é instanciada. demo.Dog.sit


print (type(Richard.sit)) #A função de um tipo instanciado é chamada de
método.
print (type(Dog.sit)) # O tipo é função.
Resultado da execução:

Resultado da execução: A dog is now sitting.


<class 'method'>
<class 'method'> <class 'function'>
<class 'function'>

1 Escrever um arquivo Python (.py). 2 Importar um módulo.


Page 23 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Introdução ao telnetlib
 telnetlib é um módulo na biblioteca padrão do Python. Ele fornece a classe telnetlib.Telnet para implementar a função Telnet.
 Diferentes métodos na classe telnetlib.Telnet são chamados para implementar diferentes funções.

Importa a classe Telnet do módulo telnetlib. - from telnetlib import Telnet


Cria uma conexão Telnet com um servidor especificado.- tn = Telnet(host=None, port=0[, timeout])
Invoque o método read_all(). - tn.read_all()

Método Função
Leia os dados até uma determinada string de bytes, expected, é encontrado ou até segundos de timeout
Telnet.read_until(expected, timeout=None)
tenham passado.
Telnet.read_all() Leia todos os dados até EOF como bytes; bloquear até que a conexão seja fechada.
Leia tudo o que puder ser sem bloqueio no I/O (eager). Aumente EOFError se a conexão for fechada e não
Telnet.read_very_eager() houver dados preparados disponíveis. Retorna b'' se não houver dados preparados disponíveis de outra forma.
Não bloqueie a menos que esteja no meio de uma sequência IAC.

Telnet.write(Parachoque) Escreva uma string de bytes no soquete, dobrando quaisquer caracteres IAC.

Telnet.close() Feche a conexão.

Page 24 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Contents
1. Introdução à redeProgramabilidade e Automação
2. Visão geral da linguagem de programação e do Python
3. Casos

Page 25 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Caso: Fazendo login em um dispositivo usando
telnetlib
 Descrição do caso:
 Um dispositivo de rede funciona como um servidor Telnet, e o Python telnetlib precisa ser usado como um cliente Telnet para efetuar
login no dispositivo.
Verifique o procedimento de Escreva o código Verifique o
Configurar Telnet.
login do Telnet. Python. resultado.

192.168.10.10 192.168.10.20

GE1/0/10
Servidor Cliente Telnet
Telnet

 O processo de implementação é o seguinte:


 Configure o serviço Telnet.
 Verifique e visualize manualmente o procedimento de login do Telnet como referência para implementação de código.
 Compile e execute o código Python.
 Verifique o resultado.
Page 26 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Caso: Fazendo login em um dispositivo usando
telnetlib
Configurar Telnet. Verifique o procedimento de Escreva o código Verifique o
login do Telnet. Python. resultado.

192.168.10.10 192.168.10.20

GE1/0/10
Servidor Cliente Telnet
Telnet

Configurar o endereço IP da interface


no dispositivo : Configurar o serviço Telnet :

[Huawei] interface GE 1/0/0 [Huawei] user-interface vty 0 4


[Huawei -GE1/0/0] ip add 192.168.10.10 24 [Huawei-ui-vty0-4] authentication-mode password
[Huawei -GE1/0/0] quit [Huawei-ui-vty0-4] set authentication password simple Huawei@123
[Huawei-ui-vty0-4] protocol inbound telnet
[Huawei-ui-vty0-4] user privilege level 15
[Huawei-ui-vty0-4] quit
[Huawei] telnet server enable

Page 27 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Caso: Fazendo login em um dispositivo usando
telnetlib
Verifique o procedimento de login do Escreva o código
Configurar Telnet. Verifique o resultado.
Telnet. Python.

192.168.10.10 192.168.10.20

GE1/0/10
Servidor Cliente Telnet
Telnet

Login Telnet:

1 Execute o comando de C:\Users\Richard>telnet 192.168.10.10


login.
Saída do comando Login authentication

2 Introduza uma senha. Password:


Saída do comando
Info: The max number of VTY users is 5, and the number of current VTY users on line is 1.
The current login time is 2020-01-15 21:12:57.
<Huawei>

Page 28 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Caso: Fazendo login em um dispositivo usando
telnetlib
Verifique o procedimento de Escreva o código
Configurar Telnet. Verifique o resultado.
login do Telnet. Python.

Importa o módulo. - import telnetlib


Define o endereço IP do host. -
Define a senha para fazer login no dispositivo.- host = '192.168.10.10'
password = 'Huawei@123'
Efetua login no host por meio do Telnet. -
Imprime dados até que Password: seja exibida.- tn = telnetlib.Telnet(host)
-
Define uma senha ASCII e inicia uma nova linha. tn.read_until(b'Password:')
Imprime dados até que <Huawei> seja exibido.- tn.write(password.encode('ascii') + b"\n")
Fecha a conexão Telnet. - print (tn.read_until(b'<Huawei>').decode('ascii’))
tn.close()
Page 29 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Caso: Comparação de resultados em execução
Verifique o procedimento de Escreva o código Verifique o
Configurar Telnet.
login do Telnet. Python. resultado.

C:\Users\Richard>telnet 192.168.10.10
Login authentication
Resultado do login Telnet
manual: Password:
Info: The max number of VTY users is 5, and the number of current VTY users on line is 1. The
current login time is 2020-01-15 21:12:57.
<Huawei>

#Run Python code in the compiler.


Resultado da execução do Info: The max number of VTY users is 5, and the number
código Python: of current VTY users on line is 1.
The current login time is 2020-01-15 22:12:57.
<Huawei>

Page 30 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Quiz
1. Python é uma linguagem compilada. ()
A. Verdadeiro

B. Falso

2. Como criar VLAN 10 usando telnetlib?

Page 31 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Summary
 A automação de rede usa ferramentas para implementar a implantação de rede automatizada,
operação e O&M, reduzindo gradualmente a dependência de pessoas. Você pode usar uma
linguagem de programação ou ferramenta para implementar a automação de rede.
 Python é uma linguagem de programação de alto nível de código totalmente aberto, com sintaxe
simples e fácil de aprender. Possui bibliotecas padrão ricas e bibliotecas de terceiros, que são
aplicáveis ​ao campo de engenharia de rede.
 O módulo telnetlib do Python fornece a classe telnetlib.Telnet para implementar a função Telnet.
Ele ajuda você a entrar no mundo da programação e automação da rede!

Page 32 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
More Information
 Para obter mais informações sobre Python, visite https://www.python.org/.

Page 33 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.
Thank You
www.huawei.com

Page 34 Copyright © 2020 Huawei Technologies Co., Ltd. All rights reserved.

Você também pode gostar