├── .gitignore ├── README.md ├── ZabbixMap ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py ├── manage.py ├── mapmanager ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ └── __init__.py ├── models.py ├── templates │ ├── base.html │ ├── map_form.html │ └── map_result.html ├── tests.py ├── urls.py ├── views.py └── zabbix_api │ ├── __init__.py │ ├── config-example.py │ ├── createElements.py │ ├── createLinks.py │ ├── createMap.py │ ├── createSysmap.py │ ├── getCdpItems.py │ ├── getHosts.py │ ├── getMapID.py │ ├── mapLog.py │ └── zabbixApiAuth.py ├── requirements.txt └── static └── ZabbixMap └── image ├── favicon-16x16.png ├── favicon-32x32.png └── favicon.ico /.gitignore: -------------------------------------------------------------------------------- 1 | mapmanager/zabbix_api/config.py 2 | __pycache__/ 3 | venv/ 4 | .vscode/ 5 | db.sqlite3 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zabbix Map Manager 2 | 3 | Este projeto é uma aplicação Django para gerenciar mapas do Zabbix. 4 | 5 | ## Requisitos 6 | 7 | - Python 3.11 8 | - Pip 9 | 10 | ## Instalação 11 | 12 | 1. Clone o repositório: 13 | ```bash 14 | git clone 15 | cd zabbix_map_manager 16 | ``` 17 | 18 | 2. Crie um ambiente virtual usando `venv`: 19 | ```bash 20 | python3.11 -m venv venv 21 | ``` 22 | 23 | 3. Ative o ambiente virtual: 24 | 25 | - No Linux/Mac: 26 | ```bash 27 | source venv/bin/activate 28 | ``` 29 | 30 | 4. Instale as dependências: 31 | ```bash 32 | pip install -r requirements.txt 33 | ``` 34 | 35 | 5. Copie o arquivo de configuração: 36 | 37 | - Copie o arquivo `config-example.py` para `config.py`: 38 | ```bash 39 | cp zabbix_api/config-example.py zabbix_api/config.py 40 | ``` 41 | 42 | 5. Configure o banco de dados (SQLite por padrão): 43 | - Execute as migrações para recriar o banco de dados: 44 | ```bash 45 | python3 manage.py migrate 46 | ``` 47 | 48 | 6. Crie um superusuário para acessar a administração do Django: 49 | ```bash 50 | python3 manage.py createsuperuser 51 | ``` 52 | 53 | 7. Configure a aplicação: 54 | 55 | - Edite o arquivo `zabbix_api/config.py` para incluir as configurações de autenticação da API do Zabbix: 56 | ```python 57 | # URL para a API do Zabbix. 58 | ZABBIX_URL = 'https://localhost.com/' 59 | # URL com caminho da api. 60 | ZABBIX_API_URL = f"{ZABBIX_URL}api_jsonrpc.php" 61 | # Nome de usuário para autenticação na API do Zabbix. 62 | ZABBIX_USER = "user" 63 | # Senha para autenticação na API do Zabbix. 64 | ZABBIX_PASSWORD = "pass" 65 | # Token de API para autenticação segura. 66 | ZABBIX_API_TOKEN = "" 67 | ``` 68 | 69 | - Nesse mesmo arquivo, `config.py`, você encontrará configurações adicionais para a criação de mapas. 70 | 71 | 8. Inicie o servidor de desenvolvimento: 72 | ```bash 73 | python3 manage.py runserver 74 | ``` 75 | 76 | 9. Acesse a aplicação no navegador: 77 | ``` 78 | http://127.0.0.1:8000/mapmanager/create-map/ 79 | ``` 80 | 81 | ## Estrutura do Projeto 82 | 83 | - `mapmanager/`: Contém a aplicação principal. 84 | - `zabbix_api/`: Contém a integração com a API do Zabbix. 85 | - `ZabbixMap/`: Contém as configurações do projeto Django. 86 | - `static/ZabbixMap/image/`: Contém arquivos estáticos, como ícones. 87 | - `templates/`: Contém templates HTML. 88 | - `manage.py`: Script para executar comandos do Django. 89 | 90 | ## Dependências 91 | 92 | As dependências do projeto estão listadas no arquivo `requirements.txt`. -------------------------------------------------------------------------------- /ZabbixMap/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matheuskshn/Zabbix-Map-Manager/7abc1d69ca934e29cc286869a1e249b32f871cf7/ZabbixMap/__init__.py -------------------------------------------------------------------------------- /ZabbixMap/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for ZabbixMap project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ZabbixMap.settings") 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /ZabbixMap/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for ZabbixMap project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.2.4. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.2/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.2/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | import os 15 | 16 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 17 | BASE_DIR = Path(__file__).resolve().parent.parent 18 | 19 | 20 | # Quick-start development settings - unsuitable for production 21 | # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ 22 | 23 | # SECURITY WARNING: keep the secret key used in production secret! 24 | SECRET_KEY = "django-insecure-9v*nwz*gcl#7q-0-778k3r@_r()q=i579@y-+%g3nqoshg=a8o" 25 | 26 | # SECURITY WARNING: don't run with debug turned on in production! 27 | DEBUG = True 28 | 29 | ALLOWED_HOSTS = ['*'] 30 | 31 | 32 | # Application definition 33 | 34 | INSTALLED_APPS = [ 35 | "django.contrib.admin", 36 | "django.contrib.auth", 37 | "django.contrib.contenttypes", 38 | "django.contrib.sessions", 39 | "django.contrib.messages", 40 | "django.contrib.staticfiles", 41 | "mapmanager", 42 | "widget_tweaks", 43 | ] 44 | 45 | MIDDLEWARE = [ 46 | "django.middleware.security.SecurityMiddleware", 47 | "django.contrib.sessions.middleware.SessionMiddleware", 48 | "django.middleware.common.CommonMiddleware", 49 | "django.middleware.csrf.CsrfViewMiddleware", 50 | "django.contrib.auth.middleware.AuthenticationMiddleware", 51 | "django.contrib.messages.middleware.MessageMiddleware", 52 | "django.middleware.clickjacking.XFrameOptionsMiddleware", 53 | ] 54 | 55 | ROOT_URLCONF = "ZabbixMap.urls" 56 | 57 | TEMPLATES = [ 58 | { 59 | "BACKEND": "django.template.backends.django.DjangoTemplates", 60 | "DIRS": [], 61 | "APP_DIRS": True, 62 | "OPTIONS": { 63 | "context_processors": [ 64 | "django.template.context_processors.debug", 65 | "django.template.context_processors.request", 66 | "django.contrib.auth.context_processors.auth", 67 | "django.contrib.messages.context_processors.messages", 68 | ], 69 | }, 70 | }, 71 | ] 72 | 73 | WSGI_APPLICATION = "ZabbixMap.wsgi.application" 74 | 75 | 76 | # Database 77 | # https://docs.djangoproject.com/en/4.2/ref/settings/#databases 78 | 79 | DATABASES = { 80 | "default": { 81 | "ENGINE": "django.db.backends.sqlite3", 82 | "NAME": BASE_DIR / "db.sqlite3", 83 | } 84 | } 85 | 86 | 87 | # Password validation 88 | # https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators 89 | 90 | AUTH_PASSWORD_VALIDATORS = [ 91 | { 92 | "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", 93 | }, 94 | { 95 | "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", 96 | }, 97 | { 98 | "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", 99 | }, 100 | { 101 | "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", 102 | }, 103 | ] 104 | 105 | 106 | # Internationalization 107 | # https://docs.djangoproject.com/en/4.2/topics/i18n/ 108 | 109 | LANGUAGE_CODE = "en-us" 110 | 111 | TIME_ZONE = "UTC" 112 | 113 | USE_I18N = True 114 | 115 | USE_TZ = True 116 | 117 | 118 | # Static files (CSS, JavaScript, Images) 119 | # https://docs.djangoproject.com/en/4.2/howto/static-files/ 120 | 121 | STATIC_URL = '/static/' 122 | 123 | # Se ainda não tiver esta linha, adicione-a também: 124 | STATICFILES_DIRS = [os.path.join(BASE_DIR, "static"),] 125 | 126 | # Default primary key field type 127 | # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field 128 | 129 | DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" 130 | -------------------------------------------------------------------------------- /ZabbixMap/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | URL configuration for ZabbixMap project. 3 | 4 | The `urlpatterns` list routes URLs to views. For more information please see: 5 | https://docs.djangoproject.com/en/4.2/topics/http/urls/ 6 | Examples: 7 | Function views 8 | 1. Add an import: from my_app import views 9 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 10 | Class-based views 11 | 1. Add an import: from other_app.views import Home 12 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 13 | Including another URLconf 14 | 1. Import the include() function: from django.urls import include, path 15 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 16 | """ 17 | from django.contrib import admin 18 | from django.urls import path, include 19 | 20 | urlpatterns = [ 21 | path("admin/", admin.site.urls), 22 | path('mapmanager/', include('mapmanager.urls')), # Delega URLs que começam com "mapmanager/" para a aplicação mapmanager 23 | ] -------------------------------------------------------------------------------- /ZabbixMap/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for ZabbixMap project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ZabbixMap.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | def main(): 7 | """Run administrative tasks.""" 8 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ZabbixMap.settings") 9 | try: 10 | from django.core.management import execute_from_command_line 11 | except ImportError as exc: 12 | raise ImportError( 13 | "Couldn't import Django. Are you sure it's installed and " 14 | "available on your PYTHONPATH environment variable? Did you " 15 | "forget to activate a virtual environment?" 16 | ) from exc 17 | execute_from_command_line(sys.argv) 18 | 19 | if __name__ == "__main__": 20 | main() -------------------------------------------------------------------------------- /mapmanager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matheuskshn/Zabbix-Map-Manager/7abc1d69ca934e29cc286869a1e249b32f871cf7/mapmanager/__init__.py -------------------------------------------------------------------------------- /mapmanager/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /mapmanager/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | class MapmanagerConfig(AppConfig): 4 | default_auto_field = "django.db.models.BigAutoField" 5 | name = "mapmanager" 6 | -------------------------------------------------------------------------------- /mapmanager/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from .models import CreateMap 3 | 4 | class CreateMapForm(forms.ModelForm): 5 | class Meta: 6 | model = CreateMap 7 | fields = ['map_name', 'map_groups', 'map_hosts', 'map_ips', 'map_hosts_filter', 'create_link', 'add_trigger', 'unavailable_by_icmp', 'snmp_not_responding'] 8 | 9 | widgets = { 10 | 'map_name': forms.TextInput(attrs={'placeholder': 'Exemplo: CPD-DATACENTER'}), 11 | 'map_groups': forms.Textarea(attrs={'placeholder': 'Exemplo: DATACENTER1, DATACENTER2', 'style': 'resize: vertical;'}), 12 | 'map_hosts': forms.Textarea(attrs={'placeholder': 'Exemplo: SW009, SW019', 'style': 'resize: vertical;'}), 13 | 'map_ips': forms.Textarea(attrs={'placeholder': 'Exemplo: 192.168.99.227, 192.168.99.227', 'style': 'resize: vertical;'}), 14 | 'map_hosts_filter': forms.Textarea(attrs={'placeholder': 'Exemplo: DATASW0, DATASW2','style': 'resize: vertical;'}), 15 | 'create_link': forms.CheckboxInput(attrs={'class': 'form-check-input'}), 16 | 'add_trigger': forms.CheckboxInput(attrs={'class': 'form-check-input'}), 17 | 'unavailable_by_icmp': forms.CheckboxInput(attrs={'class': 'form-check-input'}), 18 | 'snmp_not_responding': forms.CheckboxInput(attrs={'class': 'form-check-input'}), 19 | } 20 | 21 | def __init__(self, *args, **kwargs): 22 | super(CreateMapForm, self).__init__(*args, **kwargs) 23 | self.fields['map_groups'].required = False 24 | self.fields['map_hosts'].required = False 25 | self.fields['map_ips'].required = False 26 | -------------------------------------------------------------------------------- /mapmanager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matheuskshn/Zabbix-Map-Manager/7abc1d69ca934e29cc286869a1e249b32f871cf7/mapmanager/migrations/__init__.py -------------------------------------------------------------------------------- /mapmanager/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | class CreateMap(models.Model): 4 | map_name = models.CharField(max_length=100) 5 | map_groups = models.TextField(max_length=99999, null=True, blank=True) 6 | map_hosts = models.TextField(max_length=99999, null=True, blank=True) 7 | map_ips = models.TextField(max_length=99999, null=True, blank=True) 8 | map_hosts_filter = models.TextField(max_length=99999, null=True, blank=True) 9 | create_link = models.BooleanField(default=False) 10 | add_trigger = models.BooleanField(default=False) 11 | unavailable_by_icmp = models.BooleanField(default=False) 12 | snmp_not_responding = models.BooleanField(default=False) 13 | -------------------------------------------------------------------------------- /mapmanager/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | {% load static %} 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Zabbix Map 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | {% block content %}{% endblock %} 22 |
23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /mapmanager/templates/map_form.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "base.html" %} 3 | {% load widget_tweaks %} 4 | 5 | {% block content %} 6 | 7 |
8 | {% csrf_token %} 9 | 10 |
11 | 12 | Informe o nome do mapa que deseja criar: 13 | {{ form.map_name.errors }} 14 | {{ form.map_name|add_class:"form-control" }} 15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 | 23 | 28 | 29 | 30 |
31 | 32 | 33 |
34 | 35 | 40 | 41 | 42 |
43 | 44 | 45 |
46 | 47 | 52 | 53 | 54 |
55 | 56 | 57 |
58 | 59 | 66 | 67 | 68 |
69 | {{ form.create_link|add_class:"form-check-input" }} 70 | 71 |
72 | 73 | 74 |
75 | {{ form.add_trigger|add_class:"form-check-input" }} 76 | 77 |
78 | 79 | 86 | 87 |
88 |
89 |
90 |
91 | 92 | 93 | 148 | 149 | 236 | 237 | {% endblock %} 238 | -------------------------------------------------------------------------------- /mapmanager/templates/map_result.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "base.html" %} 3 | {% block content %} 4 | {% if data.map_link %} 5 |

Novo Mapa Criado com sucesso:

6 |

Acessar o Mapa ID: {{ data.sysmapid }}

7 | {% else %} 8 |

{{ data.mensagem }}

9 | {% endif %} 10 | 11 |

Entradas do Mapa

12 | 23 | 24 | 29 |

Elementos do mapa encontrados:

30 | 35 | 43 | 44 | 45 | {% endblock %} -------------------------------------------------------------------------------- /mapmanager/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /mapmanager/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | 4 | urlpatterns = [ 5 | path('create-map/', views.create_map_view, name='create_map_view'), 6 | path('map-result/', views.map_result_view, name='map_result'), 7 | # ... outras URLs 8 | ] 9 | -------------------------------------------------------------------------------- /mapmanager/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from .forms import CreateMapForm 3 | from .zabbix_api import createMap 4 | 5 | def create_map_view(request): 6 | if request.method == 'POST': 7 | form = CreateMapForm(request.POST) 8 | if form.is_valid(): 9 | data = form.cleaned_data 10 | result = createMap.main( 11 | data['map_name'], data['map_groups'], data['map_hosts'], data['map_ips'], 12 | data['map_hosts_filter'], data['create_link'], data['add_trigger'], 13 | data['unavailable_by_icmp'], data['snmp_not_responding'] 14 | ) 15 | print(request.POST) 16 | 17 | request.session['map_result'] = result 18 | 19 | return redirect('map_result') 20 | else: 21 | form = CreateMapForm() 22 | 23 | return render(request, 'map_form.html', {'form': form}) 24 | 25 | def map_result_view(request): 26 | result = request.session.get('map_result', {}) 27 | return render(request, 'map_result.html', {'data': result}) 28 | -------------------------------------------------------------------------------- /mapmanager/zabbix_api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matheuskshn/Zabbix-Map-Manager/7abc1d69ca934e29cc286869a1e249b32f871cf7/mapmanager/zabbix_api/__init__.py -------------------------------------------------------------------------------- /mapmanager/zabbix_api/config-example.py: -------------------------------------------------------------------------------- 1 | # URL para a API do Zabbix. 2 | ZABBIX_URL = 'https://localhost.com/' 3 | ZABBIX_API_URL = f"{ZABBIX_URL}api_jsonrpc.php" 4 | # Nome de usuário para autenticação na API do Zabbix. 5 | ZABBIX_USER = "user" 6 | # Senha para autenticação na API do Zabbix. 7 | ZABBIX_PASSWORD = "pass" 8 | # Token de API para autenticação segura. 9 | ZABBIX_API_TOKEN = "" 10 | 11 | # Configurações padrões do mapa: 12 | USERID=1 # Usuário admin 13 | BACKGROUNDID=323 14 | EXPANDPROBLEM=0 15 | EXPANDMACROS=1 16 | MARKELEMENTS=1 17 | SHOW_SUPPRESSED=1 18 | SEVERITY_MIN=2 19 | HIGHLIGHT=0 20 | LABEL_TYPE=0 21 | PRIVATE=0 22 | 23 | # Mapeamento de icones por de tipos de host, definido pelo nome do equipamento. 24 | ICON_MAP = { 25 | # A chave é o filtro de pesquisa (hostname) que determina o conjunto de icones. 26 | # Caso necessário adicione um novo filtro abaixo, seguindo o padrão: 27 | # "FILTRO": ["iconid_off", "iconid_on", "iconid_disabled", "iconid_maintenance"] 28 | # 29 | # ORDEM: "ICONID_OFF", "ICONID_ON", "ICONID_DISABLED", "ICONID_MAINTENANCE" 30 | "CORESW": ["371", "372", "0", "370"], # sw-l3-64 31 | "SW-CORE": ["371", "372", "0", "370"], # sw-l3-64 32 | "PYYZ": ["371", "372", "0", "370"], # sw-l3-64 33 | "RS0": ["371", "372", "0", "370"], # sw-l3-64 34 | "RS1": ["371", "372", "0", "370"], # sw-l3-64 35 | "ACCSSW": ["368", "369", "0", "367"], # sw-l2-64 36 | "SW0": ["368", "369", "0", "367"], # sw-l2-64 37 | "SW1": ["368", "369", "0", "367"], # sw-l2-64 38 | "WAN": ["401", "402", "0", "400"], # service-router-64 39 | "WA0": ["401", "402", "0", "400"], # service-router-64 40 | "RT0": ["401", "402", "0", "400"], # service-router-64 41 | "GK0": ["401", "402", "0", "400"], # service-router-64 42 | "AP": ["329", "330", "0", "328"], # ap-64 43 | "WP": ["329", "330", "0", "328"], # ap-64 44 | "CAMERA": ["188", "189", "0", "535"], # cam-64 45 | "CFTV": ["188", "189", "0", "535"], # cam-64 46 | "VOIP": ["423", "421", "0", "422"], # voice-gateway-64 47 | "FW0": ["542", "541", "0", "540"], # firewall-64 48 | "VALEVA": ["542", "541", "0", "540"], # firewall-64 49 | "WC0": ["354", "353", "0", "352"], # control-wireless-64 50 | "WC1": ["354", "353", "0", "352"], # control-wireless-64 51 | "MGMTP": ["160", "160", "0", "160"], # UPS_64 52 | "HF-DCA-VD": ["419", "420", "0", "418"], # virtual_server64 53 | "HF-DCA-VS": ["419", "420", "0", "418"], # virtual_server64 54 | "HF-DTO-VD": ["419", "420", "0", "418"], # virtual_server64 55 | "HF-DTO-VS": ["419", "420", "0", "418"], # virtual_server64 56 | } 57 | 58 | # IDs de ícones padrão 59 | DEFAULT_ICONS = ["594", "593", "0", "595"] # ip-device-64 60 | -------------------------------------------------------------------------------- /mapmanager/zabbix_api/createElements.py: -------------------------------------------------------------------------------- 1 | from mapmanager.zabbix_api.config import * 2 | import math 3 | 4 | def create_elements(hosts_elements, qt_elements): 5 | # Define o tamanho do mapa 6 | map_width = 80 * qt_elements 7 | map_height = map_width 8 | 9 | max_hosts = 600 10 | 11 | if qt_elements > max_hosts: 12 | mensagem = f"Parando a execução do script porque o número de hosts para adicionar ao mapa '{qt_elements}' excede o máximo permitido.\n-> Máximo permitido: '{max_hosts} hosts'" 13 | exit() 14 | 15 | num_columns = int(math.sqrt(qt_elements)) 16 | num_rows = math.ceil(qt_elements / num_columns) 17 | 18 | x_spacing = map_width // num_columns 19 | y_spacing = map_height // num_rows 20 | 21 | elements = [] 22 | hosts_dict = {host['host']: host for host in hosts_elements} 23 | hosts_elements = list(hosts_dict.values()) 24 | 25 | for index, host in enumerate(hosts_elements): 26 | x = (index % num_columns) * x_spacing + x_spacing // 2 27 | y = (index // num_columns) * y_spacing + y_spacing // 2 28 | 29 | host_type = next((key for key in ICON_MAP if key in host['host']), None) 30 | 31 | icon_ids = ICON_MAP[host_type] if host_type else DEFAULT_ICONS 32 | 33 | element = { 34 | "selementid": str(len(elements) + 1), 35 | "elements": [{"hostid": host['hostid']}], 36 | "elementtype": 0, 37 | "label": "{HOST.HOST}\r\n{HOST.IP}\r\n{INVENTORY.MODEL}", 38 | "x": x, 39 | "y": y, 40 | "iconid_off": icon_ids[0], 41 | "iconid_on": icon_ids[1], 42 | "iconid_disabled": icon_ids[2], 43 | "iconid_maintenance": icon_ids[3] 44 | } 45 | 46 | elements.append(element) 47 | 48 | mensagem = "Elementos criados" 49 | 50 | return elements, map_width, map_height, mensagem 51 | -------------------------------------------------------------------------------- /mapmanager/zabbix_api/createLinks.py: -------------------------------------------------------------------------------- 1 | def get_trigger(zapi, hostid, trigger_icmp, trigger_snmp): 2 | TRIGGER_DESCRIPTION1 = 'is unavailable by ICMP' 3 | TRIGGER_DESCRIPTION2 = 'SNMP not responding' 4 | 5 | trigger_data = zapi.trigger.get(hostids=hostid) 6 | triggerids = [] 7 | 8 | if trigger_icmp: 9 | filtered_triggers = [trigger for trigger in trigger_data if TRIGGER_DESCRIPTION1 in trigger['description']] 10 | triggerids.append(filtered_triggers[0]['triggerid'] if filtered_triggers else None) 11 | 12 | if trigger_snmp: 13 | filtered_triggers = [trigger for trigger in trigger_data if TRIGGER_DESCRIPTION2 in trigger['description']] 14 | triggerids.append(filtered_triggers[0]['triggerid'] if filtered_triggers else None) 15 | 16 | return triggerids 17 | 18 | def create_linktriggers(zapi, hostid1, hostid2, trigger_icmp, trigger_snmp): 19 | triggerids1 = get_trigger(zapi, hostid1, trigger_icmp, trigger_snmp) 20 | triggerids2 = get_trigger(zapi, hostid2, trigger_icmp, trigger_snmp) 21 | 22 | linktriggers = [] 23 | 24 | for triggerid in triggerids1 + triggerids2: 25 | if triggerid: 26 | linktriggers.append({ 27 | "triggerid": triggerid, 28 | "color": "DD0000", 29 | "drawtype": 0 30 | }) 31 | 32 | return linktriggers 33 | 34 | def create_links(elements, neighbors, zapi, trigger_icmp=False, trigger_snmp=False): 35 | element_dict = {str(element['elements'][0]['hostid']): element['selementid'] for element in elements} 36 | 37 | links = [] 38 | 39 | for neighbor in neighbors: 40 | localHostID = neighbor['localHostID'] 41 | neighborHostID = neighbor['neighborHostID'] 42 | 43 | if localHostID in element_dict and neighborHostID in element_dict: 44 | selementid1 = element_dict[localHostID] 45 | selementid2 = element_dict[neighborHostID] 46 | 47 | linktriggers = [] 48 | if trigger_icmp or trigger_snmp: 49 | linktriggers = create_linktriggers(zapi, localHostID, neighborHostID, trigger_icmp, trigger_snmp) 50 | 51 | link = { 52 | "selementid1": selementid1, 53 | "selementid2": selementid2, 54 | "color": "00CC00", 55 | 'label': f"{neighbor['neighborPort']} - {neighbor['localPortName']}", 56 | "linktriggers": linktriggers 57 | } 58 | 59 | links.append(link) 60 | 61 | return links 62 | -------------------------------------------------------------------------------- /mapmanager/zabbix_api/createMap.py: -------------------------------------------------------------------------------- 1 | from mapmanager.zabbix_api.config import * 2 | from mapmanager.zabbix_api.createSysmap import create_sysmap 3 | from mapmanager.zabbix_api.getHosts import get_hosts 4 | from mapmanager.zabbix_api.createElements import create_elements 5 | from mapmanager.zabbix_api.getCdpItems import * 6 | from mapmanager.zabbix_api.createLinks import create_links 7 | from mapmanager.zabbix_api.zabbixApiAuth import authenticate 8 | 9 | zbx_url = ZABBIX_URL if ZABBIX_URL else '' 10 | zbx_api_url = ZABBIX_API_URL if ZABBIX_API_URL else '' 11 | zbx_user = ZABBIX_USER if ZABBIX_USER else '' 12 | zbx_pass = ZABBIX_PASSWORD if ZABBIX_PASSWORD else '' 13 | zbx_api_token = ZABBIX_API_TOKEN if ZABBIX_API_TOKEN else '' 14 | 15 | def main(map_name, map_groups, map_hosts, map_ips, map_hosts_filter, create_link, add_trigger, trigger_icmp, trigger_snmp): 16 | zapi = authenticate(zbx_api_url, zbx_user, zbx_pass, zbx_api_token) 17 | mensagem = "" 18 | new_map = None 19 | links = [] 20 | 21 | if map_name: 22 | if map_groups or map_hosts or map_ips or map_hosts_filter: 23 | hosts_elements = get_hosts(zapi, map_groups, map_hosts, map_ips, map_hosts_filter) 24 | elements, map_width, map_height, mensagem = create_elements(hosts_elements[0], hosts_elements[6]) 25 | map_params = create_sysmap(map_name, map_width, map_height) 26 | map_params['selements'] = elements 27 | 28 | if create_link: 29 | neighbors = get_neighbors(zapi, hosts_elements[0]) 30 | links = create_links(elements, neighbors, zapi, trigger_icmp, trigger_snmp) 31 | map_params['links'] = links 32 | 33 | create_result = zapi.map.create(map_params) 34 | print(create_result) 35 | sysmapid = create_result['sysmapids'][0] 36 | new_map = map_params 37 | map_link = f"{zbx_url}zabbix.php?action=map.view&sysmapid={sysmapid}" 38 | new_map = map_params 39 | else: 40 | mensagem = 'Criando mapa sem elementos' 41 | map_params = create_sysmap(map_name) 42 | create_result = zapi.map.create(map_params) 43 | print(create_result) 44 | sysmapid = create_result['sysmapids'][0] 45 | new_map = map_params 46 | map_link = f"{zbx_url}zabbix.php?action=map.view&sysmapid={sysmapid}" 47 | else: 48 | mensagem = "Nome do mapa não fornecido" 49 | 50 | # Retorno para map_result.html: 51 | return { 52 | 'sysmapid': sysmapid, 53 | 'map_link': map_link, 54 | 'map_name': map_name, 55 | 'map_groups': map_groups, 56 | 'map_hosts': map_hosts, 57 | 'map_ips': map_ips, 58 | 'map_hosts_filter': map_hosts_filter, 59 | 'create_link': create_link, 60 | 'add_trigger': add_trigger, 61 | 'trigger_icmp': trigger_icmp, 62 | 'trigger_snmp': trigger_snmp, 63 | 'mensagem': mensagem, 64 | 'host_elements': hosts_elements[0] if 'hosts_elements' in locals() else None, 65 | 'qt_found_group': hosts_elements[1] if 'hosts_elements' in locals() else None, 66 | 'qt_found_host': hosts_elements[2] if 'hosts_elements' in locals() else None, 67 | 'qt_found_ip': hosts_elements[3] if 'hosts_elements' in locals() else None, 68 | 'qt_found_host_filter': hosts_elements[4] if 'hosts_elements' in locals() else None, 69 | 'qt_duplicate_host': hosts_elements[5] if 'hosts_elements' in locals() else None, 70 | 'qt_all_hosts': hosts_elements[6] if 'hosts_elements' in locals() else None, 71 | 'new_map': new_map if 'new_map' in locals() else None 72 | } 73 | -------------------------------------------------------------------------------- /mapmanager/zabbix_api/createSysmap.py: -------------------------------------------------------------------------------- 1 | from mapmanager.zabbix_api.config import * 2 | 3 | def create_sysmap(map_name, map_width=500, map_height=500): 4 | map_params = { 5 | "name": map_name, 6 | "userid": USERID, 7 | "width": map_width, 8 | "height": map_height, 9 | "backgroundid": BACKGROUNDID, 10 | "expandproblem": EXPANDPROBLEM, 11 | "expand_macros": EXPANDMACROS, 12 | "markelements": MARKELEMENTS, 13 | "show_suppressed": SHOW_SUPPRESSED, 14 | "severity_min": SEVERITY_MIN, 15 | "highlight": HIGHLIGHT, 16 | "label_type": LABEL_TYPE, 17 | "private": PRIVATE, 18 | } 19 | 20 | return map_params -------------------------------------------------------------------------------- /mapmanager/zabbix_api/getCdpItems.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | INTERFACE_ABBREVIATIONS = { 4 | 'FastEthernet': 'Fa', 5 | 'GigabitEthernet': 'Gi', 6 | 'TenGigabitEthernet': 'Te', 7 | 'Wlan-GigabitEthernet': 'Wlan-Gi' 8 | } 9 | 10 | def get_items(zapi, hostids): 11 | cdp_items = zapi.item.get( 12 | output=['hostid', 'name', 'key_'], 13 | hostids=hostids, 14 | search={ 15 | 'key_': ['cdp.local.if.name.index','cdp.neighbor.name.index'] 16 | }, 17 | searchByAny= True, 18 | ) 19 | 20 | return cdp_items 21 | 22 | def get_neighbors(zapi, hosts_elements): 23 | hostids = [host['hostid'] for host in hosts_elements] 24 | cdp_items = get_items(zapi, hostids) 25 | 26 | host_dict = {host['host']: host['hostid'] for host in hosts_elements} 27 | 28 | data_dict = {} 29 | 30 | for host in cdp_items: 31 | localportindex_match = re.search(r'index\[([\d.]+)\]', host['key_']) 32 | if localportindex_match: 33 | localportindex = int(localportindex_match.group(1).split('.')[0]) 34 | composite_key = f"{host['hostid']}-{localportindex}" 35 | 36 | if composite_key not in data_dict: 37 | data_dict[composite_key] = { 38 | 'localHostID': host['hostid'], 39 | 'localPortIndex': localportindex 40 | } 41 | 42 | if 'cdp.neighbor.name.index' in host['key_']: 43 | neighhost_match = re.search(r'neighborName\(([^)]+)\)', host['name']) 44 | neighport_match = re.search(r'DevicePort\(([^)]+)\)', host['name']) 45 | 46 | if neighhost_match: 47 | neighbor_host_name_full = neighhost_match.group(1) 48 | neighbor_host_name = re.match(r'^([^\.]+)', neighbor_host_name_full).group(1) 49 | data_dict[composite_key]['neighborHost'] = neighbor_host_name 50 | data_dict[composite_key]['neighborHostID'] = host_dict.get(neighbor_host_name, 'N/A') 51 | 52 | if neighport_match: 53 | neighport_full = neighport_match.group(1) 54 | for abbreviation, abbreviation_short in INTERFACE_ABBREVIATIONS.items(): 55 | if abbreviation in neighport_full: 56 | data_dict[composite_key]['neighborPort'] = neighport_full.replace(abbreviation, abbreviation_short) 57 | break 58 | else: 59 | data_dict[composite_key]['neighborPort'] = neighport_full 60 | 61 | elif 'cdp.local.if.name.index' in host['key_']: 62 | localportname_match = re.search(r'ifName\(([^)]+)\)', host['name']) 63 | if localportname_match: 64 | localportname_full = localportname_match.group(1) 65 | for abbreviation, abbreviation_short in INTERFACE_ABBREVIATIONS.items(): 66 | if abbreviation in localportname_full: 67 | data_dict[composite_key]['localPortName'] = localportname_full.replace(abbreviation, abbreviation_short) 68 | break 69 | else: 70 | data_dict[composite_key]['localPortName'] = localportname_full 71 | 72 | print (f"LOCALPORTNAME: {data_dict[composite_key]['localPortName']}") 73 | 74 | result_data = [] 75 | 76 | for localportindex, data in data_dict.items(): 77 | if data.get('neighborHost', 'N/A') != 'N/A': 78 | print(f"localHostID: {data['localHostID']}, neighborHost: {data.get('neighborHost', 'N/A')}, neighborHostID: {data.get('neighborHostID', 'N/A')}, neighborPort: {data.get('neighborPort', 'N/A')}, localPortIndex: {localportindex}, localPortName: {data.get('localPortName', 'N/A')}") 79 | result_data.append(data) 80 | # print(result_data) 81 | return result_data 82 | -------------------------------------------------------------------------------- /mapmanager/zabbix_api/getHosts.py: -------------------------------------------------------------------------------- 1 | def get_hosts(zapi, map_groups, map_hosts, map_ips, map_hosts_filter): 2 | 3 | add_groups = [] 4 | add_hosts = [] 5 | add_ips = [] 6 | add_filter_hosts = [] 7 | 8 | get_all_hosts = zapi.host.get(output=['hostid', 'host'], selectInterfaces=['ip'], selectGroups=['groupid']) 9 | 10 | if map_groups: 11 | hosts_groups = zapi.hostgroup.get(filter={"name": map_groups}) 12 | group_ids = {group['groupid'] for group in hosts_groups} 13 | add_groups = [host for host in get_all_hosts if any(group['groupid'] in group_ids for group in host['groups'])] 14 | else: 15 | add_groups = [] 16 | 17 | count_groups = len(add_groups) 18 | 19 | if map_hosts: 20 | host_names_set = set(map_hosts.split(", ")) if isinstance(map_hosts, str) else set(map_hosts) 21 | add_hosts = [host for host in get_all_hosts if host['host'] in host_names_set] 22 | else: 23 | add_hosts = [] 24 | 25 | count_hosts = len(add_hosts) 26 | 27 | if map_ips: 28 | ip_set = set(map_ips.split(", ")) if isinstance(map_ips, str) else set(map_ips) 29 | add_ips = [host for host in get_all_hosts if any(interface['ip'] in ip_set for interface in host['interfaces'])] 30 | else: 31 | add_ips = [] 32 | 33 | count_ips = len(add_ips) 34 | 35 | if map_hosts_filter: 36 | if isinstance(map_hosts_filter, list): 37 | map_hosts_filter = ", ".join(map_hosts_filter) 38 | host_filters_set = set(map_hosts_filter.split(", ")) 39 | add_filter_hosts = [host for host in get_all_hosts if any(host['host'].startswith(filter_str) for filter_str in host_filters_set)] 40 | else: 41 | add_filter_hosts = [] 42 | 43 | count_filter_hosts = len(add_filter_hosts) 44 | 45 | seen = set() 46 | all_hosts = [] 47 | for host in add_groups + add_hosts + add_ips + add_filter_hosts: 48 | host_id = host['hostid'] 49 | if host_id not in seen: 50 | host.pop('groups', None) 51 | host.pop('interfaces', None) 52 | all_hosts.append(host) 53 | seen.add(host_id) 54 | 55 | count_map_all_hosts = len(all_hosts) 56 | 57 | count_duplicates_hosts = (count_groups + count_hosts + count_ips + count_filter_hosts) - count_map_all_hosts 58 | 59 | return all_hosts, count_groups, count_hosts, count_ips, count_filter_hosts, count_duplicates_hosts, count_map_all_hosts 60 | -------------------------------------------------------------------------------- /mapmanager/zabbix_api/getMapID.py: -------------------------------------------------------------------------------- 1 | from .mapLog import log 2 | 3 | def get_id(zapi, map_id=None, map_name=None): 4 | log("Iniciando busca pelo ID do mapa...") 5 | 6 | if map_id: 7 | existing_map_by_id = zapi.map.get(sysmapids=[map_id]) 8 | if existing_map_by_id: 9 | log(f"Usando map_id fornecido: {map_id}") 10 | return map_id 11 | else: 12 | log( 13 | f"map_id fornecido {map_id} não encontrado. Procurando pelo nome do mapa..." 14 | ) 15 | 16 | if map_name: 17 | existing_maps_by_name = zapi.map.get(filter={"name": map_name}) 18 | if existing_maps_by_name: 19 | log( 20 | f"Mapa encontrado com o nome {map_name}. ID: {existing_maps_by_name[0]['sysmapid']}" 21 | ) 22 | return existing_maps_by_name[0]["sysmapid"] 23 | 24 | log(f"Nenhum mapa encontrado com o nome {map_name}.") 25 | return None 26 | -------------------------------------------------------------------------------- /mapmanager/zabbix_api/mapLog.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | 3 | def log(message): 4 | """Função auxiliar para logar mensagens com a tag da função atual.""" 5 | caller_name = inspect.stack()[1].function.upper() 6 | print(f"[{caller_name}] {message}") 7 | -------------------------------------------------------------------------------- /mapmanager/zabbix_api/zabbixApiAuth.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from pyzabbix import ZabbixAPI, ZabbixAPIException 3 | 4 | def authenticate(zbx_url, zbx_user, zbx_pass, zbx_api_token=None): 5 | requests.packages.urllib3.disable_warnings() 6 | 7 | zapi = ZabbixAPI(zbx_url) 8 | zapi.session.verify = False 9 | 10 | if zbx_api_token: 11 | print("\nTentando autenticação com token...\n") 12 | zapi.auth = zbx_api_token 13 | try: 14 | zapi.host.get(output=["hostid"], limit=1) 15 | print("Autenticado com sucesso via token!\n") 16 | return zapi 17 | except ZabbixAPIException: 18 | print("Token inválido. Tentando autenticação com login e senha...\n") 19 | 20 | try: 21 | zapi.login(user=zbx_user, password=zbx_pass) 22 | zapi.check_authentication() 23 | print("Autenticado com sucesso via usuário e senha!\n") 24 | except ZabbixAPIException as e: 25 | print(f"Não foi possível conectar na API do Zabbix. Erro: {e}\n") 26 | exit() 27 | 28 | return zapi -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django== 4.2 2 | pyzabbix 3 | djangorestframework 4 | django-cors-headers 5 | django-widget-tweaks -------------------------------------------------------------------------------- /static/ZabbixMap/image/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matheuskshn/Zabbix-Map-Manager/7abc1d69ca934e29cc286869a1e249b32f871cf7/static/ZabbixMap/image/favicon-16x16.png -------------------------------------------------------------------------------- /static/ZabbixMap/image/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matheuskshn/Zabbix-Map-Manager/7abc1d69ca934e29cc286869a1e249b32f871cf7/static/ZabbixMap/image/favicon-32x32.png -------------------------------------------------------------------------------- /static/ZabbixMap/image/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matheuskshn/Zabbix-Map-Manager/7abc1d69ca934e29cc286869a1e249b32f871cf7/static/ZabbixMap/image/favicon.ico --------------------------------------------------------------------------------