diff --git a/include/nc_connector_system.inc.php b/include/nc_connector_system.inc.php index dda464e..caa2138 100644 --- a/include/nc_connector_system.inc.php +++ b/include/nc_connector_system.inc.php @@ -4,109 +4,13 @@ if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!'); } -function bratonien_tools_nc_connector_systemctl_value(array $args) -{ - if (!function_exists('proc_open')) - { - return ''; - } - - $command = array_merge(array('/usr/bin/systemctl'), $args); - $spec = array( - 0 => array('file', '/dev/null', 'r'), - 1 => array('pipe', 'w'), - 2 => array('pipe', 'w'), - ); - $environment = array_merge($_ENV, array('LC_ALL'=>'C', 'LANG'=>'C')); - $process = @proc_open($command, $spec, $pipes, null, $environment); - if (!is_resource($process)) - { - return ''; - } - $stdout = stream_get_contents($pipes[1]); - stream_get_contents($pipes[2]); - fclose($pipes[1]); - fclose($pipes[2]); - $exit = proc_close($process); - return $exit === 0 ? trim((string)$stdout) : ''; -} - -function bratonien_tools_nc_connector_parse_systemd_time($value) -{ - $value = trim((string)$value); - if ($value === '' || strtolower($value) === 'n/a') - { - return 0; - } - $parsed = strtotime($value); - return $parsed === false ? 0 : (int)$parsed; -} - -function bratonien_tools_nc_connector_monotonic_to_timestamp($value) -{ - $value = trim((string)$value); - if ($value === '' || $value === '0' || strtolower($value) === 'n/a') - { - return 0; - } - - if (preg_match('/^([0-9]+)(?:us)?$/', $value, $matches)) - { - $next_boot_seconds = ((float)$matches[1]) / 1000000; - } - else - { - return 0; - } - - $uptime_raw = @file_get_contents('/proc/uptime'); - if (!is_string($uptime_raw) || !preg_match('/^([0-9]+(?:\.[0-9]+)?)/', trim($uptime_raw), $uptime_match)) - { - return 0; - } - - $remaining = $next_boot_seconds - (float)$uptime_match[1]; - if ($remaining < -1) - { - return 0; - } - - return (int)round(time() + max(0, $remaining)); -} - -function bratonien_tools_nc_connector_next_from_timer_list($timer) -{ - $line = bratonien_tools_nc_connector_systemctl_value(array( - 'list-timers', '--all', '--no-pager', '--no-legend', $timer, - )); - if ($line === '') - { - return 0; - } - - $first_line = trim((string)strtok($line, "\n")); - if (preg_match('/^(\S+\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}\s+\S+)/', $first_line, $matches)) - { - $parsed = strtotime($matches[1]); - return $parsed === false ? 0 : (int)$parsed; - } - - return 0; -} +require_once(BRATONIEN_TOOLS_PATH . 'include/nc_connector_scheduler.inc.php'); function bratonien_tools_nc_connector_connection_last_status(array $connection) { $empty = array( - 'timestamp'=>0, - 'label'=>'Nicht verfügbar', - 'state'=>'', - 'message'=>'', - 'auth_mode'=>'', - 'api_state'=>'', - 'api_message'=>'', - 'fallback_state'=>'', - 'fallback_message'=>'', - 'error_detail'=>'', + 'timestamp'=>0,'label'=>'Nicht verfügbar','state'=>'','message'=>'','auth_mode'=>'', + 'api_state'=>'','api_message'=>'','fallback_state'=>'','fallback_message'=>'','error_detail'=>'', ); $connection_id = (int)($connection['id'] ?? 0); @@ -114,42 +18,25 @@ function bratonien_tools_nc_connector_connection_last_status(array $connection) if ($connection_id > 0) { $candidates[] = rtrim(PHPWG_ROOT_PATH, '/').'/_data/bratonien-tools/nc-connector-status/connection-'.$connection_id.'.json'; + $candidates[] = rtrim(PHPWG_ROOT_PATH, '/').'/_data/bratonien-tools/nc-connector-state/connection-'.$connection_id.'/connector-status.json'; } $config = isset($connection['config']) && is_array($connection['config']) ? $connection['config'] : array(); $state_dir = rtrim((string)($config['state_dir'] ?? ''), '/'); - if ($state_dir === '' && $connection_id > 0) - { - $state_dir = '/var/lib/bratonien-tools/nc-connector/connection-'.$connection_id; - } - if ($state_dir !== '') - { - $candidates[] = $state_dir.'/connector-status.json'; - } + if ($state_dir !== '') $candidates[] = $state_dir.'/connector-status.json'; $decoded = null; - foreach ($candidates as $candidate) + foreach (array_unique($candidates) as $candidate) { - if (!is_readable($candidate)) - { - continue; - } + if (!is_readable($candidate)) continue; $value = json_decode((string)@file_get_contents($candidate), true); - if (is_array($value)) - { - $decoded = $value; - break; - } - } - if (!is_array($decoded)) - { - return $empty; + if (is_array($value)) { $decoded = $value; break; } } + if (!is_array($decoded)) return $empty; $timestamp = (int)($decoded['timestamp'] ?? 0); $api = isset($decoded['api']) && is_array($decoded['api']) ? $decoded['api'] : array(); $fallback = isset($decoded['fallback']) && is_array($decoded['fallback']) ? $decoded['fallback'] : array(); - return array( 'timestamp'=>$timestamp, 'label'=>$timestamp > 0 ? date('d.m.Y H:i:s', $timestamp) : 'Nicht verfügbar', @@ -166,99 +53,69 @@ function bratonien_tools_nc_connector_connection_last_status(array $connection) function bratonien_tools_nc_connector_last_status(array $connections) { - $latest = array('timestamp'=>0, 'state'=>'', 'message'=>'', 'auth_mode'=>'', 'api_state'=>'', 'api_message'=>'', 'fallback_state'=>'', 'fallback_message'=>'', 'error_detail'=>''); - + $latest = array('timestamp'=>0,'state'=>'','message'=>'','auth_mode'=>'','api_state'=>'','api_message'=>'','fallback_state'=>'','fallback_message'=>'','error_detail'=>''); foreach ($connections as $connection) { - if (empty($connection['enabled'])) - { - continue; - } - + if (empty($connection['enabled'])) continue; $status = bratonien_tools_nc_connector_connection_last_status($connection); - if ((int)$status['timestamp'] >= (int)$latest['timestamp']) - { - $latest = $status; - } + if ((int)$status['timestamp'] >= (int)$latest['timestamp']) $latest = $status; } - return $latest; } function bratonien_tools_nc_connector_system_status(array $connections = array()) { - $timer = 'bratonien-nc-connector.timer'; - $service = 'bratonien-nc-connector.service'; - - $active = bratonien_tools_nc_connector_systemctl_value(array('is-active', $timer)); - $enabled = bratonien_tools_nc_connector_systemctl_value(array('is-enabled', $timer)); - $service_active_raw = bratonien_tools_nc_connector_systemctl_value(array('is-active', $service)); - $service_active = in_array($service_active_raw, array('active', 'activating'), true); - $service_started_raw = bratonien_tools_nc_connector_systemctl_value(array('show', $service, '--property=ActiveEnterTimestamp', '--value')); - $service_started_timestamp = bratonien_tools_nc_connector_parse_systemd_time($service_started_raw); - - $next_realtime_raw = bratonien_tools_nc_connector_systemctl_value(array('show', $timer, '--property=NextElapseUSecRealtime', '--value')); - $next_timestamp = bratonien_tools_nc_connector_parse_systemd_time($next_realtime_raw); - - if ($next_timestamp <= 0) - { - $next_monotonic_raw = bratonien_tools_nc_connector_systemctl_value(array('show', $timer, '--property=NextElapseUSecMonotonic', '--value')); - $next_timestamp = bratonien_tools_nc_connector_monotonic_to_timestamp($next_monotonic_raw); - } - - if ($next_timestamp <= 0) - { - $next_timestamp = bratonien_tools_nc_connector_next_from_timer_list($timer); - } - + $scheduler = bratonien_tools_nc_scheduler_read_state(); + $enabled = !isset($scheduler['enabled']) || !empty($scheduler['enabled']); + $running = (string)($scheduler['state'] ?? '') === 'running'; + $started = (int)($scheduler['started_at'] ?? 0); + $next = (int)($scheduler['next_due'] ?? 0); $last = bratonien_tools_nc_connector_last_status($connections); - if ($last['timestamp'] <= 0) - { - $last_raw = bratonien_tools_nc_connector_systemctl_value(array('show', $service, '--property=ExecMainExitTimestamp', '--value')); - $last['timestamp'] = bratonien_tools_nc_connector_parse_systemd_time($last_raw); - } - if ($next_timestamp > 0) + if ($next > 0) { - $next_label = date('d.m.Y H:i:s', $next_timestamp); - } - elseif ($service_active && $active === 'active' && $enabled === 'enabled') - { - $next_label = 'Nach Abschluss des aktuellen Laufs'; - } - elseif ($active === 'active' && $enabled === 'enabled') - { - $next_label = 'Wird von systemd neu geplant'; + $next_label = date('d.m.Y H:i:s', $next).' (beim nächsten Piwigo-Aufruf)'; } else { - $next_label = 'Nicht verfügbar'; + $next_label = 'Beim nächsten Piwigo-Aufruf'; + } + + if ((int)$last['timestamp'] <= 0 && !empty($scheduler['finished_at'])) + { + $last['timestamp'] = (int)$scheduler['finished_at']; + $last['state'] = (string)($scheduler['state'] ?? ''); + $last['message'] = (string)($scheduler['message'] ?? ''); + if ((string)$last['state'] === 'error') + { + $detail = trim((string)($scheduler['stderr'] ?? '')); + if ($detail === '') $detail = trim((string)($scheduler['stdout'] ?? '')); + $last['error_detail'] = $detail; + } } return array( - 'timer_name' => $timer, - 'timer_active' => $active === 'active', - 'timer_enabled' => $enabled === 'enabled', - 'service_active' => $service_active, - 'current_run_timestamp' => $service_started_timestamp, - 'current_run_label' => $service_active - ? ($service_started_timestamp > 0 ? 'Läuft seit '.date('d.m.Y H:i:s', $service_started_timestamp) : 'Läuft gerade') - : 'Kein Lauf aktiv', - 'last_run_timestamp' => (int)$last['timestamp'], - 'last_run_label' => $last['timestamp'] > 0 ? date('d.m.Y H:i:s', (int)$last['timestamp']) : 'Nicht verfügbar', - 'last_run_state' => (string)$last['state'], - 'last_run_message' => (string)$last['message'], - 'last_run_auth_mode' => (string)$last['auth_mode'], - 'last_run_api_state' => (string)$last['api_state'], - 'last_run_api_message' => (string)$last['api_message'], - 'last_run_fallback_state' => (string)$last['fallback_state'], - 'last_run_fallback_message' => (string)$last['fallback_message'], - 'last_run_error_detail' => (string)$last['error_detail'], - 'next_run_timestamp' => $next_timestamp, - 'next_run_label' => $next_label, - 'legacy_runtime_exists' => is_dir('/opt/piwigo-sync'), - 'legacy_config_exists' => is_dir('/etc/piwigo-sync'), - 'legacy_service_exists' => is_file('/etc/systemd/system/piwigo-sync.service'), - 'legacy_timer_exists' => is_file('/etc/systemd/system/piwigo-sync.timer'), + 'timer_name'=>'Piwigo nativer NC-Scheduler', + 'timer_active'=>$enabled, + 'timer_enabled'=>$enabled, + 'service_active'=>$running, + 'current_run_timestamp'=>$started, + 'current_run_label'=>$running ? ($started > 0 ? 'Läuft seit '.date('d.m.Y H:i:s', $started) : 'Läuft gerade') : 'Kein Lauf aktiv', + 'last_run_timestamp'=>(int)$last['timestamp'], + 'last_run_label'=>(int)$last['timestamp'] > 0 ? date('d.m.Y H:i:s', (int)$last['timestamp']) : 'Nicht verfügbar', + 'last_run_state'=>(string)$last['state'], + 'last_run_message'=>(string)$last['message'], + 'last_run_auth_mode'=>(string)$last['auth_mode'], + 'last_run_api_state'=>(string)$last['api_state'], + 'last_run_api_message'=>(string)$last['api_message'], + 'last_run_fallback_state'=>(string)$last['fallback_state'], + 'last_run_fallback_message'=>(string)$last['fallback_message'], + 'last_run_error_detail'=>(string)$last['error_detail'], + 'next_run_timestamp'=>$next, + 'next_run_label'=>$next_label, + 'legacy_runtime_exists'=>is_dir('/opt/piwigo-sync'), + 'legacy_config_exists'=>is_dir('/etc/piwigo-sync'), + 'legacy_service_exists'=>is_file('/etc/systemd/system/piwigo-sync.service'), + 'legacy_timer_exists'=>is_file('/etc/systemd/system/piwigo-sync.timer'), ); }