import os import sys import json from pyzabbix import ZabbixAPI, ZabbixAPIException import getpass # For secure password input # --- Paths to the files created by the Nagios export script --- ZABBIX_HOSTGROUPS_FILE = 'zabbix_hostgroups.txt' ZABBIX_HOSTS_FILE = 'zabbix_hosts.txt' ZABBIX_COMMANDS_FILE = 'zabbix_commands.txt' # Now contains JSON ZABBIX_SERVICES_RAW_FILE = 'zabbix_services_raw.txt' # --- Main script --- def main(): print("--- Zabbix Automatic Import Script ---") # Ask user for Zabbix API Configuration print("\nPlease provide your Zabbix API connection details:") zabbix_server = input("Zabbix Server URL (e.g., http://your_zabbix_server/api_jsonrpc.php): ").strip() zabbix_user = input("Zabbix API Login Name: ").strip() zabbix_password = getpass.getpass("Zabbix API Password: ").strip() # Validate inputs if not zabbix_server or not zabbix_user or not zabbix_password: print("Error: All Zabbix connection details must be provided.", file=sys.stderr) sys.exit(1) # Connect to Zabbix API try: zapi = ZabbixAPI(zabbix_server) zapi.login(zabbix_user, zabbix_password) print(f"Connected to Zabbix API at {zabbix_server} as user {zabbix_user}") except ZabbixAPIException as e: print(f"Error connecting to Zabbix API: {e}", file=sys.stderr) print("Please check the provided server URL, login name, and password.", file=sys.stderr) sys.exit(1) # 1. Import Hostgroups print("\n--- Importing Hostgroups ---") created_hostgroups = {} # To store mapping of Nagios group name to Zabbix group ID if not os.path.exists(ZABBIX_HOSTGROUPS_FILE): print(f"Warning: Hostgroups file not found: {ZABBIX_HOSTGROUPS_FILE}. Skipping hostgroup import.") else: with open(ZABBIX_HOSTGROUPS_FILE, 'r') as f: lines = f.readlines() lines = [line for line in lines if not line.startswith("--- Hostgroups ---")] for i in range(0, len(lines), 2): name_alias_line = lines[i].strip() if not name_alias_line.startswith("Name:"): print(f"Warning: Skipping malformed hostgroup line: {name_alias_line}", file=sys.stderr) continue try: name = name_alias_line.split("Name: ")[1].split(",")[0].strip() alias = name_alias_line.split("Alias: ")[1].strip() except IndexError: print(f"Warning: Could not parse hostgroup name/alias from: {name_alias_line}", file=sys.stderr) continue print(f" Processing hostgroup: {name}") try: existing_groups = zapi.hostgroup.get(filter={'name': name}, output=['groupid']) if existing_groups: group_id = existing_groups[0]['groupid'] print(f" Hostgroup '{name}' already exists with ID: {group_id}") created_hostgroups[name] = group_id else: new_group = zapi.hostgroup.create(name=name) group_id = new_group['groupids'][0] print(f" Created hostgroup '{name}' with ID: {group_id}") created_hostgroups[name] = group_id except ZabbixAPIException as e: print(f" Error creating hostgroup '{name}': {e}", file=sys.stderr) # 2. Import Hosts print("\n--- Importing Hosts ---") if not os.path.exists(ZABBIX_HOSTS_FILE): print(f"Warning: Hosts file not found: {ZABBIX_HOSTS_FILE}. Skipping host import.") else: with open(ZABBIX_HOSTS_FILE, 'r') as f: lines = f.readlines() lines = [line for line in lines if not line.startswith("--- Hosts ---")] host_data_buffer = [] for line in lines: line = line.strip() if line.startswith(" Host:"): if host_data_buffer: process_host_entry(zapi, host_data_buffer, created_hostgroups) host_data_buffer = [] host_data_buffer.append(line) elif host_data_buffer: host_data_buffer.append(line) if host_data_buffer: process_host_entry(zapi, host_data_buffer, created_hostgroups) # 3. Process Commands (for manual item creation/templating review) print("\n--- Commands (for manual item creation/templating review) ---") if not os.path.exists(ZABBIX_COMMANDS_FILE): print(f"Warning: Commands file not found: {ZABBIX_COMMANDS_FILE}.") else: try: with open(ZABBIX_COMMANDS_FILE, 'r') as f: commands_json_str = "" for line in f: if not line.startswith("--- Commands (JSON Data) ---"): commands_json_str += line commands_data = json.loads(commands_json_str) print(" Review the following Nagios commands for Zabbix Item conversion:") for cmd_name, cmd_info in commands_data.items(): print(f" Command Name: {cmd_name}") print(f" Command Line: {cmd_info.get('command_line', 'N/A')}") print(f" Raw Attributes: {json.dumps(cmd_info.get('raw_attributes', {}), indent=6)}") except FileNotFoundError: print(f"Error: {ZABBIX_COMMANDS_FILE} not found.", file=sys.stderr) except json.JSONDecodeError as e: print(f"Error parsing JSON from {ZABBIX_COMMANDS_FILE}: {e}", file=sys.stderr) print(f"Content that caused error (first 200 chars): {commands_json_str[:200]}", file=sys.stderr) except Exception as e: print(f"An unexpected error occurred while processing commands: {e}", file=sys.stderr) # 4. Handle Services (as potential Zabbix Items/Templates) - For information only print("\n--- Services (for manual item/trigger/template creation review) ---") if not os.path.exists(ZABBIX_SERVICES_RAW_FILE): print(f"Warning: Services raw file not found: {ZABBIX_SERVICES_RAW_FILE}.") else: with open(ZABBIX_SERVICES_RAW_FILE, 'r') as f: print(" Review the following Nagios services for Zabbix Item/Trigger/Template conversion:") service_block = [] for line in f: line = line.strip() if line == "Service_Block_Start": service_block = [] elif line == "Service_Block_End": if service_block: try: full_attrs_line = next((s for s in service_block if s.startswith("All attributes:")), None) if full_attrs_line: json_str = full_attrs_line.split("All attributes: ")[1] service_info = json.loads(json_str) print(f" Service Name: {service_info.get('service_description', 'N/A')}") print(f" Host Name(s): {service_info.get('host_name', 'N/A')}") print(f" Check Command: {service_info.get('check_command', 'N/A')}") else: print(f" Could not parse service block for full attributes: {service_block}") except json.JSONDecodeError as e: print(f" Error parsing service JSON: {e} in block: {service_block}", file=sys.stderr) service_block = [] else: service_block.append(line) print("\nZabbix import script finished. Please review logs for any errors or warnings.") print("Manual mapping will still be required for complex Nagios commands and services.") def process_host_entry(zapi, host_lines, created_hostgroups): """Processes a buffered host entry and attempts to create it in Zabbix.""" host_name = "" alias = "" address = "" nagios_hostgroups = [] for line in host_lines: if line.startswith(" Host:"): parts = line.split("|") host_name = parts[0].split("Host:")[1].strip() alias = parts[1].split("Name:")[1].strip() elif line.startswith(" Interfaces:"): try: interfaces_str = line.split("Interfaces:")[1].strip() interfaces_list = json.loads(interfaces_str) if interfaces_list: address = interfaces_list[0].get('ip', '') except json.JSONDecodeError as e: print(f"Warning: Could not parse interfaces for {host_name}: {e} - {line}", file=sys.stderr) elif line.startswith(" Groups:"): groups_str = line.split("Groups:")[1].strip() nagios_hostgroups = [g.strip().strip("'") for g in groups_str.strip('[]').split(',') if g.strip()] if not host_name: print(f"Warning: Skipping host due to missing name in block: {host_lines}", file=sys.stderr) return print(f" Processing host: {host_name} (IP: {address})") zabbix_groups_payload = [] for hg_name in nagios_hostgroups: if hg_name in created_hostgroups: zabbix_groups_payload.append({'groupid': created_hostgroups[hg_name]}) else: try: existing_groups = zapi.hostgroup.get(filter={'name': hg_name}, output=['groupid']) if existing_groups: group_id = existing_groups[0]['groupid'] created_hostgroups[hg_name] = group_id zabbix_groups_payload.append({'groupid': group_id}) print(f" Found existing group '{hg_name}' for host '{host_name}'.") else: new_group = zapi.hostgroup.create(name=hg_name) group_id = new_group['groupids'][0] created_hostgroups[hg_name] = group_id zabbix_groups_payload.append({'groupid': group_id}) print(f" Created missing hostgroup '{hg_name}' for host '{host_name}'.") except ZabbixAPIException as e: print(f" Error ensuring hostgroup '{hg_name}' for host '{host_name}': {e}", file=sys.stderr) continue zabbix_interfaces_payload = [] if address: zabbix_interfaces_payload.append({ "type": 1, "main": 1, "useip": 1, "ip": address, "dns": "", "port": "10050" }) else: print(f" Warning: Host '{host_name}' has no address. Skipping interface creation.", file=sys.stderr) existing_hosts = zapi.host.get(filter={'host': host_name}, output=['hostid']) if existing_hosts: host_id = existing_hosts[0]['hostid'] print(f" Host '{host_name}' already exists with ID: {host_id}. Skipping creation.") try: zapi.host.update(hostid=host_id, groups=zabbix_groups_payload, interfaces=zabbix_interfaces_payload) print(f" Updated host '{host_name}'.") except ZabbixAPIException as e: print(f" Error updating host '{host_name}': {e}", file=sys.stderr) else: if not zabbix_interfaces_payload: print(f" Skipping creation of host '{host_name}' as no valid interfaces could be determined.", file=sys.stderr) return try: new_host = zapi.host.create( host=host_name, name=alias if alias else host_name, interfaces=zabbix_interfaces_payload, groups=zabbix_groups_payload ) host_id = new_host['hostids'][0] print(f" Created host '{host_name}' with ID: {host_id}") except ZabbixAPIException as e: print(f" Error creating host '{host_name}': {e}", file=sys.stderr) if __name__ == '__main__': main()