181 lines
6.6 KiB
Python
181 lines
6.6 KiB
Python
import requests
|
||
import json
|
||
import sys
|
||
import argparse
|
||
from datetime import datetime
|
||
|
||
# ==============================================================================
|
||
# 🛠️ CONFIGURAÇÕES DO USUÁRIO - EDITE AQUI
|
||
# ==============================================================================
|
||
# URL do seu Zabbix antigo (ex: http://192.168.1.100/zabbix/api_jsonrpc.php)
|
||
ZABBIX_URL = "http://172.16.254.11/zabbix/api_jsonrpc.php"
|
||
|
||
# Credenciais de um usuário com permissão de leitura total (Admin ou Super Admin)
|
||
ZABBIX_USER = "Admin"
|
||
ZABBIX_PASS = "M@dC@tMK11"
|
||
|
||
# Nome do arquivo de saída
|
||
OUTPUT_FILE = "zabbix_hosts_export.json"
|
||
|
||
# ==============================================================================
|
||
# 🚀 INÍCIO DO SCRIPT (Não precisa editar abaixo, a menos que saiba o que faz)
|
||
# ==============================================================================
|
||
|
||
def print_header():
|
||
print("="*60)
|
||
print(" 📦 EXPORTADOR DE HOSTS ZABBIX - BASEADO NO PADRÃO ARTHUR")
|
||
print("="*60)
|
||
print(f"📅 Data: {datetime.now().strftime('%d/%m/%Y %H:%M:%S')}")
|
||
print(f"🎯 Alvo: {ZABBIX_URL}")
|
||
print("="*60 + "\n")
|
||
|
||
def zabbix_api_call(method, params, auth_token=None, request_id=1):
|
||
"""
|
||
Faz uma chamada JSON-RPC para a API do Zabbix.
|
||
"""
|
||
headers = {'Content-Type': 'application/json-rpc'}
|
||
payload = {
|
||
"jsonrpc": "2.0",
|
||
"method": method,
|
||
"params": params,
|
||
"id": request_id
|
||
}
|
||
|
||
if auth_token:
|
||
# Padrão: Auth no corpo. O main() pode alterar isso se detectar 6.4+
|
||
# Se o token começar com 'Bearer', usamos via header (adaptação dinâmica)
|
||
if str(auth_token).startswith("USE_HEADER:"):
|
||
real_token = auth_token.split(":", 1)[1]
|
||
headers["Authorization"] = f"Bearer {real_token}"
|
||
else:
|
||
payload["auth"] = auth_token
|
||
|
||
try:
|
||
# verify=False é crucial para Zabbix legados com certificados inválidos
|
||
response = requests.post(ZABBIX_URL, data=json.dumps(payload), headers=headers, verify=False, timeout=30)
|
||
response.raise_for_status()
|
||
decoded = response.json()
|
||
|
||
if 'error' in decoded:
|
||
# Se for erro de "Unexpected parameter 'auth'", tentamos retry sem auth no body?
|
||
# Melhor garantir na detecção de versão.
|
||
print(f"\n❌ ERRO NA API ZABBIX ({method}):")
|
||
print(f" Mensagem: {decoded['error'].get('message', 'Sem mensagem')}")
|
||
print(f" Detalhes: {decoded['error'].get('data', 'Sem detalhes')}")
|
||
sys.exit(1)
|
||
|
||
return decoded['result']
|
||
|
||
except requests.exceptions.ConnectionError:
|
||
print(f"\n❌ ERRO DE CONEXÃO:")
|
||
print(f" Não foi possível conectar em: {ZABBIX_URL}")
|
||
print(" Verifique se a URL está correta e se o servidor está acessível.")
|
||
sys.exit(1)
|
||
except requests.exceptions.Timeout:
|
||
print(f"\n❌ ERRO DE TIMEOUT:")
|
||
print(" O servidor demorou muito para responder.")
|
||
sys.exit(1)
|
||
except Exception as e:
|
||
print(f"\n❌ ERRO INESPERADO: {e}")
|
||
sys.exit(1)
|
||
|
||
def main():
|
||
# Desabilita warnings chatos de SSL inseguro
|
||
requests.packages.urllib3.disable_warnings()
|
||
|
||
print_header()
|
||
|
||
# 1. Autenticação
|
||
print("🔐 1. Autenticando no Zabbix...", end=" ")
|
||
try:
|
||
# Tenta conectar usando 'username' (padrão 5.4+)
|
||
try:
|
||
auth_token = zabbix_api_call("user.login", {"username": ZABBIX_USER, "password": ZABBIX_PASS})
|
||
except SystemExit:
|
||
# Se falhar (ex: Zabbix antigo < 5.4), tenta com 'user'
|
||
print("⚠️ Falha com 'username', tentando com método legado 'user'...")
|
||
auth_token = zabbix_api_call("user.login", {"user": ZABBIX_USER, "password": ZABBIX_PASS})
|
||
print(f"✅ Sucesso!\n 🔑 Token: {auth_token[:10]}...")
|
||
except SystemExit:
|
||
raise
|
||
except Exception as e:
|
||
print(f"❌ Falha: {e}")
|
||
sys.exit(1)
|
||
|
||
# 2. Obter versão da API (opcional, mas bom pra debug)
|
||
print("\n🔍 2. Verificando versão da API...", end=" ")
|
||
api_info = zabbix_api_call("apiinfo.version", {}, auth_token=None)
|
||
print(f"✅ Versão detectada: {api_info}")
|
||
|
||
# DECISÃO DE AUTH: Zabbix 6.4+ prefere Bearer Token no Header
|
||
use_header_auth = False
|
||
try:
|
||
major_minor = float(api_info[:3]) # Pega "6.0", "7.0"
|
||
if major_minor >= 6.4:
|
||
print(f" ℹ️ Zabbix moderno (>6.4) detectado. Usando Auth via Header.")
|
||
# Marcamos o token para ser usado via header
|
||
auth_token = f"USE_HEADER:{auth_token}"
|
||
use_header_auth = True
|
||
except ValueError:
|
||
pass # Versão estranha, mantém legado
|
||
|
||
# 3. Listar Hosts
|
||
print("\n📋 3. Buscando lista de hosts...", end=" ")
|
||
hosts = zabbix_api_call("host.get", {
|
||
"output": ["hostid", "name"],
|
||
"preservekeys": True
|
||
}, auth_token)
|
||
|
||
host_ids = list(hosts.keys())
|
||
count = len(host_ids)
|
||
print(f"✅ Encontrados: {count} hosts.")
|
||
|
||
if count == 0:
|
||
print("\n⚠️ Nenhum host encontrado para exportar. Encerrando.")
|
||
return
|
||
|
||
# 4. Exportar (O Heavy Lifting)
|
||
print(f"\n📦 4. Iniciando exportação completa (Configuration Export)...")
|
||
print(" Isso pode demorar um pouco dependendo do tamanho da base. Aguarde...")
|
||
|
||
export_params = {
|
||
"options": {
|
||
"hosts": host_ids
|
||
},
|
||
"format": "json"
|
||
}
|
||
|
||
try:
|
||
export_data = zabbix_api_call("configuration.export", export_params, auth_token)
|
||
except SystemExit:
|
||
print("\n❌ Falha na exportação. Verifique se o usuário tem permissão para exportar hosts.")
|
||
sys.exit(1)
|
||
|
||
# 5. Salvar Arquivo
|
||
print(f"\n💾 5. Salvando arquivo '{OUTPUT_FILE}'...", end=" ")
|
||
try:
|
||
with open(OUTPUT_FILE, 'w', encoding='utf-8') as f:
|
||
if isinstance(export_data, str):
|
||
f.write(export_data)
|
||
else:
|
||
json.dump(export_data, f, indent=4, ensure_ascii=False)
|
||
print("✅ Sucesso!")
|
||
except Exception as e:
|
||
print(f"\n❌ Erro ao salvar arquivo: {e}")
|
||
sys.exit(1)
|
||
|
||
# Conclusão
|
||
print("\n" + "="*60)
|
||
print("🎉 PROCESSO CONCLUÍDO COM SUCESSO!")
|
||
print(f" Arquivo gerado: {OUTPUT_FILE}")
|
||
print(" Total de hosts: ", count)
|
||
print("="*60)
|
||
print("\n👉 COMO IMPORTAR:")
|
||
print(" 1. Vá no seu novo Zabbix > Configuration > Hosts")
|
||
print(" 2. Clique em 'Import'")
|
||
print(f" 3. Selecione o arquivo '{OUTPUT_FILE}'")
|
||
print(" 4. Marque 'Create new' e 'Update existing'")
|
||
|
||
if __name__ == "__main__":
|
||
main()
|