#!/usr/bin/env php 0) { global $migration_log_file; print "Migration log written to: $migration_log_file" . PHP_EOL; print "Rollback data recorded in: $migration_log_file" . PHP_EOL; } } return true; } /** * Migrate devices from comma-separated host IDs * * @param string $host_ids_string Comma-separated list of host IDs * @param int $source_poller Source poller ID (for logging) * @param int $dest_poller Destination poller ID * @param bool $quietMode Whether to suppress output * * @return bool - False if there are problems */ function migrate_from_host_ids(string $host_ids_string, int $source_poller, int $dest_poller, bool $quietMode) : bool { // Parse comma-separated host IDs $host_id_array = array_map('trim', explode(',', $host_ids_string)); $host_id_array = array_filter($host_id_array, function ($id) { return is_numeric($id) && $id > 0; }); if (empty($host_id_array)) { print 'ERROR: No valid host IDs provided. Host IDs must be numeric and greater than 0.' . PHP_EOL; return false; } if (!$quietMode) { print 'Migration Mode: Specific host IDs' . PHP_EOL; print 'Host IDs to migrate: ' . implode(', ', $host_id_array) . PHP_EOL; print 'This will move ' . count($host_id_array) . " device(s) from any poller to Poller $dest_poller" . PHP_EOL . PHP_EOL; // Display devices to be migrated print 'Devices to be migrated:' . PHP_EOL; foreach ($host_id_array as $host_id) { $device = db_fetch_row_prepared('SELECT id, hostname, description, poller_id FROM host WHERE id = ?', [$host_id]); if (!empty($device)) { print " ID: {$device['id']} - {$device['hostname']} ({$device['description']}) [Current Poller: {$device['poller_id']}]" . PHP_EOL; } else { print " ID: $host_id - ERROR: Device not found" . PHP_EOL; } } print PHP_EOL; print 'Are you sure you want to continue? (y/N): '; $confirmation = trim((string) fgets(STDIN)); if (cacti_strtolower($confirmation) !== 'y') { print 'Migration cancelled by user' . PHP_EOL; return false; } print PHP_EOL; print 'Starting migration of ' . count($host_id_array) . ' device(s)...' . PHP_EOL; } $success_count = 0; $error_count = 0; foreach ($host_id_array as $host_id) { // Get full device record for api_device_save $device = db_fetch_row_prepared('SELECT * FROM host WHERE id = ?', [$host_id]); if (!empty($device)) { if (migrate_device($device, $dest_poller)) { $success_count++; if (!$quietMode) { print "Moved device: {$device['description']} (ID: {$device['id']}) from Poller {$device['poller_id']} to Poller $dest_poller" . PHP_EOL; } } else { $error_count++; print 'ERROR: Failed to migrate device ' . $device['id'] . ' (' . $device['description'] . ')' . PHP_EOL; } } else { $error_count++; print "ERROR: Could not find device with ID $host_id" . PHP_EOL; } } if (!$quietMode) { print PHP_EOL; print 'Migration completed!' . PHP_EOL; print "Successfully migrated: $success_count device(s)" . PHP_EOL; print "Failed migrations: $error_count device(s)" . PHP_EOL; if ($success_count > 0) { global $migration_log_file; print "Migration log written to: $migration_log_file" . PHP_EOL; print "Rollback data recorded in: $migration_log_file" . PHP_EOL; } } return true; } /** * display_version - displays version information * * @return void */ function display_version() : void { $version = get_cacti_cli_version(); print "Cacti Add Permissions Utility, Version $version, " . COPYRIGHT_YEARS . PHP_EOL; } /** * display_help - displays the usage of the function * * @return void */ function display_help() : void { display_version(); print PHP_EOL; print 'Purpose: This script is used to move devices off a given poller to another poller' . PHP_EOL . PHP_EOL; print 'Usage:' . PHP_EOL; print 'php ' . basename(__FILE__) . (' --source-poller=ID --dest-poller=ID [--all | --host-ids=ID1,ID2,...] ' . '[--quiet] [--help]') . PHP_EOL . PHP_EOL; print 'Required Arguments:' . PHP_EOL; print ' --source-poller=ID Source Poller ID to move devices from' . PHP_EOL; print ' --dest-poller=ID Destination Poller ID to move devices to' . PHP_EOL . PHP_EOL; print 'Migration Mode (choose exactly one):' . PHP_EOL; print ' --all Migrate all devices off the source poller' . PHP_EOL; print (' --host-ids=ID1,ID2,... Migrate specific devices by host ID ' . '(single ID or comma-separated list)') . PHP_EOL . PHP_EOL; print 'Optional Arguments:' . PHP_EOL; print ' --quiet Suppress verbose output (batch mode)' . PHP_EOL; print ' --help, -h Display this help message' . PHP_EOL; print ' --version, -v Display version information' . PHP_EOL . PHP_EOL; print 'Output Files:' . PHP_EOL; print ' migration_log.txt Timestamped log of all migration activities,' . PHP_EOL; print ' including rollback data with original poller assignments' . PHP_EOL . PHP_EOL; print 'Examples:' . PHP_EOL; print ' # Migrate all devices from poller 1 to poller 2:' . PHP_EOL; print ' php ' . basename(__FILE__) . ' --source-poller=1 --dest-poller=2 --all' . PHP_EOL . PHP_EOL; print ' # Migrate a single device by host ID:' . PHP_EOL; print ' php ' . basename(__FILE__) . ' --source-poller=1 --dest-poller=2 --host-ids=123' . PHP_EOL; print ' # Migrate multiple devices by host IDs:' . PHP_EOL; print ' php ' . basename(__FILE__) . ' --source-poller=1 --dest-poller=2 --host-ids=123,124,125' . PHP_EOL . PHP_EOL; print 'Note: You must specify exactly one migration option: --all or --host-ids' . PHP_EOL . PHP_EOL; }