Merge pull request #155 from GameServerPanel/copilot/hook-cron-scheduler-to-server-content
This commit is contained in:
commit
089051fecb
9 changed files with 593 additions and 31 deletions
2
.github/module-map.md
vendored
2
.github/module-map.md
vendored
|
|
@ -40,7 +40,7 @@ This file captures how the control panel, storefront, agents, and helper scripts
|
|||
| `extras`, `addonsmanager` | Workshop/add-on management. | Hooks into game homes after provisioning. |
|
||||
| `litefm`, `ftp`, `TS3Admin` | File managers and TeamSpeak controllers. | Depend on homes and remote server credentials set during provisioning. |
|
||||
| `news`, `circular`, `faq` | Content modules for panel UI. | Use standard MVC wrappers, share session/auth. |
|
||||
| `cron` | Scheduler UI feeding `scripts/` commands. | Maintains job metadata that OS cron reads. |
|
||||
| `cron` | Scheduler UI feeding `scripts/` commands. | Maintains job metadata that OS cron reads, including scheduler-triggered Server Content actions via `ogp_api.php?server_content/run_scheduled_action` and `modules/addonsmanager/server_content_actions.php`. |
|
||||
|
||||
## Storefront (`Panel/modules/billing` runtime + `Website/` compatibility wrappers)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# Changelog
|
||||
|
||||
## 2026-05-18
|
||||
- **Cron ↔ Server Content action hook integration:** Added scheduler-callable Server Content hooks in `modules/addonsmanager/server_content_actions.php`, exposed API route `server_content/run_scheduled_action`, and wired cron/user-cron action builders/parsing to support server content scheduled actions (check/install/queue/restart/validate/backup flows) without embedding game-specific install logic in the scheduler.
|
||||
- **Server Content Workshop Phase 1 in addonsmanager:** Added a new `Workshop Content` flow under Server Content with per-home Workshop ID storage, ID validation/deduplication, install/update/remove/update-all actions, manifest-based script handoff (`gsp_server_content/workshop_manifest.json`), safe placeholder workshop scripts for Linux/Cygwin, and schema support via `server_content_workshop` plus `addons.addon_type VARCHAR(32)`.
|
||||
- **Updater layout hardening + pre-update patch framework:** Reworked `modules/administration/panel_update.php` to resolve explicit GSP root/Panel/Website paths, run mandatory preflight checks, self-update updater files before main sync when drift is detected, and apply ordered required patches from `modules/update/patches/` with DB/local state tracking. Backup/rollback now includes both Panel + Website archives and root `version.json`, logs moved to root `logs/update_trace.log`, and the admin Update UI now exposes preflight, patch apply, Apache path scan/fix, backup, update, and rollback actions.
|
||||
- **Billing runtime relocation + portable path bootstrap:** Re-homed storefront runtime to `Panel/modules/billing`, added portable runtime helpers (`billing_bootstrap.php`, `site_config.php`, `site_config.example.php`) with env/local override support for base path and panel path, normalized critical storefront redirects/links to computed billing URLs, and added `Website` compatibility wrappers for key billing entrypoints.
|
||||
|
|
|
|||
|
|
@ -18,3 +18,4 @@
|
|||
- Add an automated deployment check that fails when `Website/timestamp.txt` and `modules/billing/timestamp.txt` diverge after storefront/content changes.
|
||||
- Add an admin preview/diff panel for Apache path repairs so staff can review exact vhost line changes before confirming `Fix Apache Paths`.
|
||||
- Add Phase 2 Workshop Content UX in `addonsmanager`: browse/search/select Workshop items with metadata while reusing the Phase 1 per-home saved-ID action pipeline.
|
||||
- Add localized language strings/tooltips for the new cron scheduler `server_content_*` action labels across all supported panel locales.
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ function get_function_args($main_request)
|
|||
|
||||
//______________ Steam Workshop
|
||||
$functions["steam_workshop/install"] = array("token" => true, "ip" => true, "port" => true, "mod_key" => false, "mods_list" => true);
|
||||
|
||||
//______________ Server Content
|
||||
$functions["server_content/run_scheduled_action"] = array("token" => true, "home_id" => true, "action" => true, "options" => false);
|
||||
|
||||
//______________ Settings
|
||||
$functions["setting/get"] = array("token" => true, "setting_name" => true);
|
||||
|
|
|
|||
472
Panel/modules/addonsmanager/server_content_actions.php
Normal file
472
Panel/modules/addonsmanager/server_content_actions.php
Normal file
|
|
@ -0,0 +1,472 @@
|
|||
<?php
|
||||
/*
|
||||
*
|
||||
* GSP - Server Content scheduler action hooks (addonsmanager)
|
||||
*
|
||||
*/
|
||||
|
||||
require_once("includes/lib_remote.php");
|
||||
require_once("modules/config_games/server_config_parser.php");
|
||||
require_once(dirname(__FILE__) . '/server_content_helpers.php');
|
||||
require_once(dirname(__FILE__) . '/workshop_action.php');
|
||||
|
||||
function server_content_get_home_info($home_id)
|
||||
{
|
||||
global $db;
|
||||
$home_id = (int)$home_id;
|
||||
if ($home_id <= 0) {
|
||||
return false;
|
||||
}
|
||||
return $db->getGameHome($home_id);
|
||||
}
|
||||
|
||||
function server_content_collect_workshop_ids($db, $home_id)
|
||||
{
|
||||
$rows = $db->resultQuery(
|
||||
"SELECT workshop_item_id FROM `".OGP_DB_PREFIX."server_content_workshop`
|
||||
WHERE home_id=".(int)$home_id." AND install_state<>'removed'"
|
||||
);
|
||||
$item_ids = array();
|
||||
if (is_array($rows)) {
|
||||
foreach ((array)$rows as $row) {
|
||||
$item_id = trim((string)$row['workshop_item_id']);
|
||||
if ($item_id !== '' && preg_match('/^[0-9]+$/', $item_id)) {
|
||||
$item_ids[$item_id] = $item_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array_values($item_ids);
|
||||
}
|
||||
|
||||
function server_content_collect_manifest_addon_rows($db, $home_id)
|
||||
{
|
||||
$rows = $db->resultQuery(
|
||||
"SELECT m.addon_id, m.install_method, m.content_version, m.install_state, a.name, a.url
|
||||
FROM `".OGP_DB_PREFIX."server_content_manifest` m
|
||||
LEFT JOIN `".OGP_DB_PREFIX."addons` a ON a.addon_id = m.addon_id
|
||||
WHERE m.home_id=".(int)$home_id."
|
||||
ORDER BY m.updated_at DESC, m.installed_at DESC"
|
||||
);
|
||||
return is_array($rows) ? $rows : array();
|
||||
}
|
||||
|
||||
function server_content_create_remote(array $home_info)
|
||||
{
|
||||
return new OGPRemoteLibrary(
|
||||
$home_info['agent_ip'],
|
||||
$home_info['agent_port'],
|
||||
$home_info['encryption_key'],
|
||||
$home_info['timeout']
|
||||
);
|
||||
}
|
||||
|
||||
function server_content_result($status, $message, array $details = array())
|
||||
{
|
||||
return array(
|
||||
'status' => (string)$status,
|
||||
'success' => ((string)$status === 'success' || (string)$status === 'no_updates' || (string)$status === 'restart_required'),
|
||||
'message' => (string)$message,
|
||||
'details' => $details,
|
||||
);
|
||||
}
|
||||
|
||||
function server_content_record_installed_content_state(array $home_info, array $state)
|
||||
{
|
||||
$home_path = rtrim(clean_path((string)$home_info['home_path']), '/');
|
||||
$file_path = clean_path($home_path . '/gsp_server_content/installed_content.json');
|
||||
if (!scm_path_is_under_home($home_path, $file_path)) {
|
||||
return false;
|
||||
}
|
||||
$json = json_encode($state);
|
||||
if ($json === false) {
|
||||
return false;
|
||||
}
|
||||
$remote = server_content_create_remote($home_info);
|
||||
$remote->exec("mkdir -p " . escapeshellarg(dirname($file_path)));
|
||||
return ((int)$remote->remote_writefile($file_path, $json) === 1);
|
||||
}
|
||||
|
||||
function server_content_log_action($home_id, $action, $status, $message = '', $details = array())
|
||||
{
|
||||
global $db;
|
||||
$payload = array(
|
||||
'home_id' => (int)$home_id,
|
||||
'action' => (string)$action,
|
||||
'status' => (string)$status,
|
||||
'message' => (string)$message,
|
||||
'details' => $details,
|
||||
);
|
||||
$db->logger("server_content_action " . json_encode($payload));
|
||||
return true;
|
||||
}
|
||||
|
||||
function server_content_build_manifest($home_id, $content_type, $action, $items = array(), $options = array())
|
||||
{
|
||||
$home_info = server_content_get_home_info($home_id);
|
||||
if ($home_info === false) {
|
||||
return false;
|
||||
}
|
||||
$home_path = rtrim(clean_path((string)$home_info['home_path']), '/');
|
||||
$manifest_dir = clean_path($home_path . '/gsp_server_content/manifests');
|
||||
$file_stub = preg_replace('/[^a-z0-9_\-]+/i', '_', (string)$content_type . '_' . (string)$action);
|
||||
if ($file_stub === '' || $file_stub === null) {
|
||||
$file_stub = 'manifest';
|
||||
}
|
||||
$manifest_path = clean_path($manifest_dir . '/' . $file_stub . '_' . date('Ymd_His') . '_' . mt_rand(1000, 9999) . '.json');
|
||||
if (!scm_path_is_under_home($home_path, $manifest_path)) {
|
||||
return false;
|
||||
}
|
||||
$manifest = array(
|
||||
'manifest_version' => 1,
|
||||
'home_id' => (int)$home_info['home_id'],
|
||||
'home_cfg_id' => (int)$home_info['home_cfg_id'],
|
||||
'remote_server_id' => (int)$home_info['remote_server_id'],
|
||||
'content_type' => (string)$content_type,
|
||||
'action' => (string)$action,
|
||||
'items' => is_array($items) ? array_values($items) : array(),
|
||||
'options' => is_array($options) ? $options : array(),
|
||||
'generated_at' => date('Y-m-d H:i:s'),
|
||||
);
|
||||
$manifest_json = json_encode($manifest);
|
||||
if ($manifest_json === false) {
|
||||
return false;
|
||||
}
|
||||
$remote = server_content_create_remote($home_info);
|
||||
$remote->exec("mkdir -p " . escapeshellarg($manifest_dir));
|
||||
if ((int)$remote->remote_writefile($manifest_path, $manifest_json) !== 1) {
|
||||
return false;
|
||||
}
|
||||
return $manifest_path;
|
||||
}
|
||||
|
||||
function server_content_resolve_script_path(array $home_info, $script_key, array $options = array())
|
||||
{
|
||||
$script_path = '';
|
||||
if (isset($options['script_path'])) {
|
||||
$script_path = trim((string)$options['script_path']);
|
||||
}
|
||||
$server_xml = read_server_config(SERVER_CONFIG_LOCATION . "/" . $home_info['home_cfg_file']);
|
||||
if ($server_xml === false) {
|
||||
return array(false, false);
|
||||
}
|
||||
if ($script_path === '' && $script_key === 'workshop') {
|
||||
$script_path = scm_get_workshop_script_path($home_info, $server_xml);
|
||||
}
|
||||
if ($script_path === '' && $script_key !== '' && isset($server_xml->$script_key)) {
|
||||
$script_path = trim((string)$server_xml->$script_key);
|
||||
}
|
||||
return array($server_xml, $script_path);
|
||||
}
|
||||
|
||||
function server_content_execute_manifest($home_id, $manifest_path, $script_key, $options = array())
|
||||
{
|
||||
$home_info = server_content_get_home_info($home_id);
|
||||
if ($home_info === false) {
|
||||
return server_content_result('failed', 'Invalid server home.', array('home_id' => (int)$home_id));
|
||||
}
|
||||
list($server_xml, $script_path) = server_content_resolve_script_path($home_info, $script_key, $options);
|
||||
if ($server_xml === false) {
|
||||
return server_content_result('failed', 'Unable to load server XML configuration.', array('home_id' => (int)$home_id));
|
||||
}
|
||||
$script_path = trim((string)$script_path);
|
||||
if ($script_path === '' || !preg_match('/^[^\r\n\0]+$/', $script_path)) {
|
||||
return server_content_result('failed', 'Configured server content script path is invalid.', array('script_key' => (string)$script_key));
|
||||
}
|
||||
$remote = server_content_create_remote($home_info);
|
||||
if ($remote->status_chk() !== 1) {
|
||||
return server_content_result('failed', 'Agent is offline.', array('remote_server_id' => (int)$home_info['remote_server_id']));
|
||||
}
|
||||
if ((int)$remote->rfile_exists($script_path) !== 1) {
|
||||
return server_content_result('failed', 'Server content script was not found on agent host.', array('script_path' => $script_path));
|
||||
}
|
||||
$command = "bash " . escapeshellarg($script_path) . " " . escapeshellarg((string)$manifest_path) . " ; echo __GSP_SERVER_CONTENT_EXIT:$?";
|
||||
$output = $remote->exec($command);
|
||||
if (!is_string($output) || $output === '') {
|
||||
return server_content_result('failed', 'Server content script did not return output.', array('script_path' => $script_path));
|
||||
}
|
||||
if (!preg_match('/__GSP_SERVER_CONTENT_EXIT:(\d+)/', $output, $matches)) {
|
||||
return server_content_result('failed', 'Server content script exit marker was not found.', array('output' => trim($output)));
|
||||
}
|
||||
$exit_code = (int)$matches[1];
|
||||
if ($exit_code !== 0) {
|
||||
return server_content_result('failed', 'Server content script failed.', array(
|
||||
'exit_code' => $exit_code,
|
||||
'output' => trim($output),
|
||||
'script_path' => $script_path,
|
||||
));
|
||||
}
|
||||
return server_content_result('success', 'Server content script executed successfully.', array(
|
||||
'exit_code' => $exit_code,
|
||||
'output' => trim($output),
|
||||
'script_path' => $script_path,
|
||||
'manifest_path' => (string)$manifest_path,
|
||||
));
|
||||
}
|
||||
|
||||
function server_content_check_updates($home_id, $options = array())
|
||||
{
|
||||
$options['check_only'] = true;
|
||||
return server_content_install_updates($home_id, $options);
|
||||
}
|
||||
|
||||
function server_content_update_workshop($home_id, $options = array())
|
||||
{
|
||||
$options['workshop_only'] = true;
|
||||
return server_content_install_updates($home_id, $options);
|
||||
}
|
||||
|
||||
function server_content_install_updates($home_id, $options = array())
|
||||
{
|
||||
global $db;
|
||||
$home_info = server_content_get_home_info($home_id);
|
||||
if ($home_info === false) {
|
||||
return server_content_result('failed', 'Invalid server home.');
|
||||
}
|
||||
scm_ensure_phase2_schema($db);
|
||||
scm_ensure_workshop_schema($db);
|
||||
|
||||
$workshop_action = isset($options['workshop_action']) ? (string)$options['workshop_action'] : '';
|
||||
if ($workshop_action === '') {
|
||||
$workshop_action = !empty($options['check_only']) ? 'check_updates' : 'update';
|
||||
}
|
||||
$workshop_ids = server_content_collect_workshop_ids($db, (int)$home_info['home_id']);
|
||||
$manifest_rows = server_content_collect_manifest_addon_rows($db, (int)$home_info['home_id']);
|
||||
if (empty($workshop_ids) && empty($manifest_rows)) {
|
||||
$result = server_content_result('no_updates', 'No installed server content records were found for this home.', array(
|
||||
'home_id' => (int)$home_info['home_id'],
|
||||
));
|
||||
server_content_record_installed_content_state($home_info, array(
|
||||
'home_id' => (int)$home_info['home_id'],
|
||||
'last_action' => 'no_updates',
|
||||
'last_updated_at' => date('Y-m-d H:i:s'),
|
||||
));
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (!empty($workshop_ids) && empty($options['check_only'])) {
|
||||
scm_workshop_update_rows_state($db, (int)$home_info['home_id'], $workshop_ids, 'installing', null, false, false);
|
||||
}
|
||||
|
||||
$manifest_items = array(
|
||||
'workshop_item_ids' => $workshop_ids,
|
||||
'manifest_addons' => $manifest_rows,
|
||||
);
|
||||
$manifest_path = server_content_build_manifest($home_info['home_id'], 'server_content', $workshop_action, $manifest_items, $options);
|
||||
if ($manifest_path === false) {
|
||||
if (!empty($workshop_ids) && empty($options['check_only'])) {
|
||||
scm_workshop_update_rows_state($db, (int)$home_info['home_id'], $workshop_ids, 'failed', 'Failed to build server content manifest.', false, false);
|
||||
}
|
||||
return server_content_result('failed', 'Failed to build server content manifest.');
|
||||
}
|
||||
|
||||
$execute = server_content_execute_manifest($home_info['home_id'], $manifest_path, 'workshop', $options);
|
||||
if (empty($execute['success'])) {
|
||||
if (!empty($workshop_ids) && empty($options['check_only'])) {
|
||||
$error_message = isset($execute['message']) ? $execute['message'] : 'Unknown failure.';
|
||||
scm_workshop_update_rows_state($db, (int)$home_info['home_id'], $workshop_ids, 'failed', $error_message, false, false);
|
||||
}
|
||||
return $execute;
|
||||
}
|
||||
|
||||
if (!empty($workshop_ids) && empty($options['check_only'])) {
|
||||
scm_workshop_update_rows_state($db, (int)$home_info['home_id'], $workshop_ids, 'installed', null, false, true);
|
||||
}
|
||||
server_content_record_installed_content_state($home_info, array(
|
||||
'home_id' => (int)$home_info['home_id'],
|
||||
'last_action' => (string)$workshop_action,
|
||||
'last_result' => 'success',
|
||||
'last_manifest' => $manifest_path,
|
||||
'last_updated_at' => date('Y-m-d H:i:s'),
|
||||
'installed_workshop_ids' => $workshop_ids,
|
||||
));
|
||||
|
||||
if (!empty($options['check_only'])) {
|
||||
return server_content_result('success', 'Server content update check completed.', array(
|
||||
'manifest_path' => $manifest_path,
|
||||
'workshop_items' => count($workshop_ids),
|
||||
));
|
||||
}
|
||||
return server_content_result('success', 'Server content updates were installed.', array(
|
||||
'manifest_path' => $manifest_path,
|
||||
'workshop_items' => count($workshop_ids),
|
||||
'manifest_rows' => count($manifest_rows),
|
||||
));
|
||||
}
|
||||
|
||||
function server_content_home_is_running(array $home_info)
|
||||
{
|
||||
$remote = server_content_create_remote($home_info);
|
||||
return ($remote->is_screen_running(OGP_SCREEN_TYPE_HOME, $home_info['home_id']) == 1);
|
||||
}
|
||||
|
||||
function server_content_install_updates_if_stopped($home_id, $options = array())
|
||||
{
|
||||
$home_info = server_content_get_home_info($home_id);
|
||||
if ($home_info === false) {
|
||||
return server_content_result('failed', 'Invalid server home.');
|
||||
}
|
||||
if (server_content_home_is_running($home_info)) {
|
||||
return server_content_result('restart_required', 'Server is running; update skipped until server is stopped.', array(
|
||||
'home_id' => (int)$home_info['home_id'],
|
||||
));
|
||||
}
|
||||
return server_content_install_updates($home_id, $options);
|
||||
}
|
||||
|
||||
function server_content_install_updates_next_restart($home_id, $options = array())
|
||||
{
|
||||
$home_info = server_content_get_home_info($home_id);
|
||||
if ($home_info === false) {
|
||||
return server_content_result('failed', 'Invalid server home.');
|
||||
}
|
||||
$options['queued_for_restart'] = true;
|
||||
$manifest_path = server_content_build_manifest($home_info['home_id'], 'server_content', 'install_next_restart', array(), $options);
|
||||
if ($manifest_path === false) {
|
||||
return server_content_result('failed', 'Failed to queue update manifest for next restart.');
|
||||
}
|
||||
server_content_record_installed_content_state($home_info, array(
|
||||
'home_id' => (int)$home_info['home_id'],
|
||||
'last_action' => 'install_next_restart',
|
||||
'last_result' => 'queued',
|
||||
'queued_manifest' => $manifest_path,
|
||||
'last_updated_at' => date('Y-m-d H:i:s'),
|
||||
));
|
||||
return server_content_result('restart_required', 'Server content updates were queued for next restart.', array(
|
||||
'manifest_path' => $manifest_path,
|
||||
));
|
||||
}
|
||||
|
||||
function server_content_restart_home($home_id, $options = array())
|
||||
{
|
||||
global $db, $user_info;
|
||||
$home_info = server_content_get_home_info($home_id);
|
||||
if ($home_info === false) {
|
||||
return server_content_result('failed', 'Invalid server home.');
|
||||
}
|
||||
$server_xml = read_server_config(SERVER_CONFIG_LOCATION . "/" . $home_info['home_cfg_file']);
|
||||
if ($server_xml === false) {
|
||||
return server_content_result('failed', 'Could not load server XML for restart.');
|
||||
}
|
||||
$remote = server_content_create_remote($home_info);
|
||||
$host_stat = $remote->status_chk();
|
||||
if ($host_stat !== 1) {
|
||||
return server_content_result('failed', 'Agent is offline; cannot restart server.');
|
||||
}
|
||||
|
||||
$ip_ports = $db->getHomeIpPorts($home_info['home_id']);
|
||||
if (!is_array($ip_ports) || !isset($ip_ports[0])) {
|
||||
return server_content_result('failed', 'No IP/port mapping found for server restart.');
|
||||
}
|
||||
$ip = $ip_ports[0]['ip'];
|
||||
$port = (int)$ip_ports[0]['port'];
|
||||
|
||||
$mod_id = key($home_info['mods']);
|
||||
$start_cmd = get_start_cmd($user_info, $remote, $server_xml, $home_info, $mod_id, $ip, $port, $db);
|
||||
$preStart = isset($server_xml->pre_start) ? trim((string)$server_xml->pre_start) : "";
|
||||
$envVars = isset($server_xml->environment_variables) ? trim((string)$server_xml->environment_variables) : "";
|
||||
|
||||
$delay = isset($options['restart_delay_seconds']) ? (int)$options['restart_delay_seconds'] : 0;
|
||||
if ($delay > 0) {
|
||||
if ($delay > 300) {
|
||||
$delay = 300;
|
||||
}
|
||||
sleep($delay);
|
||||
}
|
||||
|
||||
$remote_retval = $remote->remote_restart_server(
|
||||
$home_info['home_id'],
|
||||
$ip,
|
||||
$port,
|
||||
$server_xml->control_protocol,
|
||||
$home_info['control_password'],
|
||||
$server_xml->control_protocol_type,
|
||||
$home_info['home_path'],
|
||||
$server_xml->server_exec_name,
|
||||
$server_xml->exe_location,
|
||||
$start_cmd,
|
||||
$home_info['mods'][$mod_id]['cpu_affinity'],
|
||||
$home_info['mods'][$mod_id]['nice'],
|
||||
$preStart,
|
||||
$envVars,
|
||||
$server_xml->game_key,
|
||||
(isset($server_xml->console_log) ? $server_xml->console_log : "")
|
||||
);
|
||||
if ($remote_retval !== 1) {
|
||||
return server_content_result('restart_required', 'Update completed but automatic restart failed.', array(
|
||||
'restart_status' => $remote_retval,
|
||||
));
|
||||
}
|
||||
return server_content_result('success', 'Update completed and server restart was triggered.', array(
|
||||
'restart_status' => $remote_retval,
|
||||
));
|
||||
}
|
||||
|
||||
function server_content_install_updates_and_restart($home_id, $options = array())
|
||||
{
|
||||
$install_result = server_content_install_updates($home_id, $options);
|
||||
if (empty($install_result['success']) || $install_result['status'] === 'failed') {
|
||||
return $install_result;
|
||||
}
|
||||
$restart_result = server_content_restart_home($home_id, $options);
|
||||
$install_result['details']['restart'] = $restart_result;
|
||||
if ($restart_result['status'] === 'success') {
|
||||
$install_result['status'] = 'success';
|
||||
$install_result['message'] = 'Server content updates installed and server restart requested.';
|
||||
return $install_result;
|
||||
}
|
||||
$install_result['status'] = 'restart_required';
|
||||
$install_result['success'] = true;
|
||||
$install_result['message'] = 'Server content updates installed; restart is still required.';
|
||||
return $install_result;
|
||||
}
|
||||
|
||||
function server_content_run_scheduled_action($home_id, $action, $options = array())
|
||||
{
|
||||
$home_id = (int)$home_id;
|
||||
$action = trim((string)$action);
|
||||
if ($home_id <= 0) {
|
||||
return server_content_result('failed', 'Invalid server home id.');
|
||||
}
|
||||
$handlers = array(
|
||||
'server_content_check_updates' => 'server_content_check_updates',
|
||||
'server_content_check_workshop_updates' => 'server_content_update_workshop',
|
||||
'server_content_install_updates_if_stopped' => 'server_content_install_updates_if_stopped',
|
||||
'server_content_install_updates_next_restart' => 'server_content_install_updates_next_restart',
|
||||
'server_content_install_updates_now' => 'server_content_install_updates',
|
||||
'server_content_install_updates_and_restart' => 'server_content_install_updates_and_restart',
|
||||
'server_content_update_workshop' => 'server_content_update_workshop',
|
||||
'server_content_update_all' => 'server_content_install_updates',
|
||||
'server_content_notify_updates_only' => 'server_content_check_updates',
|
||||
'server_content_validate_files' => 'server_content_update_workshop',
|
||||
'server_content_backup_before_update' => 'server_content_install_updates',
|
||||
);
|
||||
if (!isset($handlers[$action]) || !function_exists($handlers[$action])) {
|
||||
$result = server_content_result('failed', 'Unsupported scheduled server content action.', array(
|
||||
'action' => $action,
|
||||
));
|
||||
server_content_log_action($home_id, $action, $result['status'], $result['message'], $result['details']);
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ($action === 'server_content_check_workshop_updates' || $action === 'server_content_validate_files') {
|
||||
$options['check_only'] = true;
|
||||
$options['workshop_action'] = ($action === 'server_content_validate_files') ? 'validate_files' : 'check_updates';
|
||||
}
|
||||
if ($action === 'server_content_backup_before_update') {
|
||||
$options['backup_before_update'] = true;
|
||||
}
|
||||
if ($action === 'server_content_install_updates_and_restart' && !isset($options['safe_restart'])) {
|
||||
$options['safe_restart'] = true;
|
||||
}
|
||||
if ($action === 'server_content_notify_updates_only') {
|
||||
$options['notify_only'] = true;
|
||||
$options['check_only'] = true;
|
||||
}
|
||||
|
||||
server_content_log_action($home_id, $action, 'started', 'Scheduled action started.', $options);
|
||||
$handler = $handlers[$action];
|
||||
$result = $handler($home_id, $options);
|
||||
server_content_log_action($home_id, $action, $result['status'], $result['message'], $result['details']);
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
|
@ -77,19 +77,12 @@ function exec_ogp_module()
|
|||
$mod_key = $game_home['mod_key'];
|
||||
$token = $db->getApiToken($_SESSION['user_id']);
|
||||
|
||||
switch ($_POST['action']) {
|
||||
case "stop":
|
||||
$command = "wget -qO- \"${panelURL}/ogp_api.php?gamemanager/stop&token=${token}&ip=${ip}&port=${port}&mod_key=${mod_key}\" --no-check-certificate > /dev/null 2>&1";
|
||||
break;
|
||||
case "start":
|
||||
$command = "wget -qO- \"${panelURL}/ogp_api.php?gamemanager/start&token=${token}&ip=${ip}&port=${port}&mod_key=${mod_key}\" --no-check-certificate > /dev/null 2>&1";
|
||||
break;
|
||||
case "restart":
|
||||
$command = "wget -qO- \"${panelURL}/ogp_api.php?gamemanager/restart&token=${token}&ip=${ip}&port=${port}&mod_key=${mod_key}\" --no-check-certificate > /dev/null 2>&1";
|
||||
break;
|
||||
case "steam_auto_update":
|
||||
$command = "wget -qO- \"${panelURL}/ogp_api.php?gamemanager/update&token=${token}&ip=${ip}&port=${port}&mod_key=${mod_key}&type=steam\" --no-check-certificate > /dev/null 2>&1";
|
||||
break;
|
||||
$command = build_cron_scheduler_command($panelURL, $token, $game_home, $_POST['action']);
|
||||
if($command === false)
|
||||
{
|
||||
print_failure(get_lang('bad_inputs'));
|
||||
$view->refresh('?m=cron&p=cron',2);
|
||||
return;
|
||||
}
|
||||
|
||||
$remote = new OGPRemoteLibrary( $game_home['agent_ip'], $game_home['agent_port'],
|
||||
|
|
|
|||
|
|
@ -47,10 +47,17 @@ function reloadJobs($server_homes, $remote_servers, $getAllJobs = true)
|
|||
list($wget,$wget_args,$url,$wget_nocert,$gt,$devnull,$err2out) = explode(" ", $command, 7);
|
||||
|
||||
parse_str(parse_url(trim($url,'"'), PHP_URL_QUERY), $url_query);
|
||||
|
||||
if(!isset($url_query['ip']) or !isset($url_query['port']))
|
||||
$home_info = false;
|
||||
if(isset($url_query['ip']) && isset($url_query['port']))
|
||||
{
|
||||
$home_info = $db->getGameHomeByIP($url_query['ip'], $url_query['port']);
|
||||
}
|
||||
elseif(isset($url_query['home_id']))
|
||||
{
|
||||
$home_info = $db->getGameHome((int)$url_query['home_id'], true);
|
||||
}
|
||||
if(!$home_info)
|
||||
continue;
|
||||
$home_info = $db->getGameHomeByIP($url_query['ip'], $url_query['port']);
|
||||
if(!$getAllJobs && !hasAccess($home_info))
|
||||
continue;
|
||||
|
||||
|
|
@ -63,6 +70,8 @@ function reloadJobs($server_homes, $remote_servers, $getAllJobs = true)
|
|||
$action = "start";
|
||||
}else if($action == "gamemanager/restart"){
|
||||
$action = "restart";
|
||||
}else if($action == "server_content/run_scheduled_action" && isset($url_query['action']) && $url_query['action'] != ""){
|
||||
$action = $url_query['action'];
|
||||
}
|
||||
|
||||
$jobsArray[$rhost_id][$jobId] = array( 'job' => $job,
|
||||
|
|
@ -76,7 +85,7 @@ function reloadJobs($server_homes, $remote_servers, $getAllJobs = true)
|
|||
'home_id' => $home_info['home_id'],
|
||||
'ip' => $home_info['ip'],
|
||||
'port' => $home_info['port'],
|
||||
'mod_key' => $url_query['mod_key']);
|
||||
'mod_key' => isset($url_query['mod_key']) ? $url_query['mod_key'] : '');
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -99,6 +108,50 @@ function reloadJobs($server_homes, $remote_servers, $getAllJobs = true)
|
|||
return array($jobsArray, $remote_servers_offline);
|
||||
}
|
||||
|
||||
function get_server_content_scheduled_actions() {
|
||||
return array(
|
||||
'server_content_check_updates',
|
||||
'server_content_check_workshop_updates',
|
||||
'server_content_install_updates_if_stopped',
|
||||
'server_content_install_updates_next_restart',
|
||||
'server_content_install_updates_now',
|
||||
'server_content_install_updates_and_restart',
|
||||
'server_content_notify_updates_only',
|
||||
'server_content_update_all',
|
||||
'server_content_validate_files',
|
||||
'server_content_backup_before_update',
|
||||
);
|
||||
}
|
||||
|
||||
function build_cron_scheduler_command($panelURL, $token, $game_home, $action) {
|
||||
$ip = $game_home['ip'];
|
||||
$port = $game_home['port'];
|
||||
$mod_key = isset($game_home['mod_key']) ? $game_home['mod_key'] : '';
|
||||
$home_id = isset($game_home['home_id']) ? (int)$game_home['home_id'] : 0;
|
||||
if(in_array($action, get_server_content_scheduled_actions()))
|
||||
{
|
||||
$options = array('triggered_by' => 'scheduler');
|
||||
if($action == 'server_content_install_updates_and_restart')
|
||||
{
|
||||
$options['safe_restart'] = true;
|
||||
$options['restart_delay_seconds'] = 60;
|
||||
}
|
||||
$options_json = urlencode(json_encode($options));
|
||||
return "wget -qO- \"${panelURL}/ogp_api.php?server_content/run_scheduled_action&token=${token}&home_id=${home_id}&action=${action}&options=${options_json}\" --no-check-certificate > /dev/null 2>&1";
|
||||
}
|
||||
switch ($action) {
|
||||
case "stop":
|
||||
return "wget -qO- \"${panelURL}/ogp_api.php?gamemanager/stop&token=${token}&ip=${ip}&port=${port}&mod_key=${mod_key}\" --no-check-certificate > /dev/null 2>&1";
|
||||
case "start":
|
||||
return "wget -qO- \"${panelURL}/ogp_api.php?gamemanager/start&token=${token}&ip=${ip}&port=${port}&mod_key=${mod_key}\" --no-check-certificate > /dev/null 2>&1";
|
||||
case "restart":
|
||||
return "wget -qO- \"${panelURL}/ogp_api.php?gamemanager/restart&token=${token}&ip=${ip}&port=${port}&mod_key=${mod_key}\" --no-check-certificate > /dev/null 2>&1";
|
||||
case "steam_auto_update":
|
||||
return "wget -qO- \"${panelURL}/ogp_api.php?gamemanager/update&token=${token}&ip=${ip}&port=${port}&mod_key=${mod_key}&type=steam\" --no-check-certificate > /dev/null 2>&1";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateCronJobTokens($old_token, $token){
|
||||
global $db;
|
||||
$remote_servers = $db->getRemoteServers();
|
||||
|
|
@ -152,6 +205,11 @@ function get_action_selector($action = false, $server_homes = false, $homeid_ip_
|
|||
if( $server_xml->installer == "steamcmd" )
|
||||
$server_actions[] = 'steam_auto_update';
|
||||
}
|
||||
global $db;
|
||||
if($db->isModuleInstalled('addonsmanager'))
|
||||
{
|
||||
$server_actions = array_merge($server_actions, get_server_content_scheduled_actions());
|
||||
}
|
||||
$select_action = '<select name="action" style="width: 100%;">';
|
||||
foreach ((array)$server_actions as $server_action)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -78,19 +78,12 @@ function exec_ogp_module()
|
|||
$mod_key = $game_home['mod_key'];
|
||||
$token = $db->getApiToken($_SESSION['user_id']);
|
||||
|
||||
switch ($_POST['action']) {
|
||||
case "stop":
|
||||
$command = "wget -qO- \"{$panelURL}/ogp_api.php?gamemanager/stop&token={$token}&ip={$ip}&port={$port}&mod_key={$mod_key}\" --no-check-certificate > /dev/null 2>&1";
|
||||
break;
|
||||
case "start":
|
||||
$command = "wget -qO- \"{$panelURL}/ogp_api.php?gamemanager/start&token={$token}&ip={$ip}&port={$port}&mod_key={$mod_key}\" --no-check-certificate > /dev/null 2>&1";
|
||||
break;
|
||||
case "restart":
|
||||
$command = "wget -qO- \"{$panelURL}/ogp_api.php?gamemanager/restart&token={$token}&ip={$ip}&port={$port}&mod_key={$mod_key}\" --no-check-certificate > /dev/null 2>&1";
|
||||
break;
|
||||
case "steam_auto_update":
|
||||
$command = "wget -qO- \"{$panelURL}/ogp_api.php?gamemanager/update&token={$token}&ip={$ip}&port={$port}&mod_key={$mod_key}&type=steam\" --no-check-certificate > /dev/null 2>&1";
|
||||
break;
|
||||
$command = build_cron_scheduler_command($panelURL, $token, $game_home, $_POST['action']);
|
||||
if($command === false)
|
||||
{
|
||||
print_failure(get_lang('bad_inputs'));
|
||||
$view->refresh('?m=cron&p=user_cron',2);
|
||||
return;
|
||||
}
|
||||
|
||||
$job = $_POST['minute']." ".
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ ogp_api.php?addonsmanager/install (POST/GET {token}{ip}{port}{mod_key}{addon_i
|
|||
|
||||
______________ Steam Workshop
|
||||
ogp_api.php?steam_workshop/install (POST/GET {token}{ip}{port}{mods_list})
|
||||
|
||||
______________ Server Content
|
||||
ogp_api.php?server_content/run_scheduled_action (POST/GET {token}{home_id}{action}{options})
|
||||
*
|
||||
______________ Panel Setting
|
||||
ogp_api.php?setting/get (POST/GET {token}{setting_name})
|
||||
|
|
@ -1474,6 +1477,44 @@ function api_addonsmanager()
|
|||
return array("status" => $status, "message" => $message);
|
||||
}
|
||||
|
||||
function api_server_content()
|
||||
{
|
||||
global $request, $db;
|
||||
if($db->isModuleInstalled('addonsmanager') === FALSE)
|
||||
return array("status" => '349', "message" => "This function is not available because the module is not installed.");
|
||||
|
||||
if($request[0] == "run_scheduled_action")
|
||||
{
|
||||
require_once(MODULES.'addonsmanager/server_content_actions.php');
|
||||
$home_id = (int)$_POST['home_id'];
|
||||
$action = isset($_POST['action']) ? trim((string)$_POST['action']) : '';
|
||||
$options = array();
|
||||
if(isset($_POST['options']))
|
||||
{
|
||||
$decoded_options = json_decode((string)$_POST['options'], true);
|
||||
if(is_array($decoded_options))
|
||||
$options = $decoded_options;
|
||||
}
|
||||
$passthrough_keys = array('triggered_by', 'cron_id', 'safe_restart', 'restart_delay_seconds', 'check_only', 'notify_only');
|
||||
foreach ((array)$passthrough_keys as $key)
|
||||
{
|
||||
if(isset($_POST[$key]))
|
||||
$options[$key] = $_POST[$key];
|
||||
}
|
||||
|
||||
$result = server_content_run_scheduled_action($home_id, $action, $options);
|
||||
$status = isset($result['status']) ? $result['status'] : 'failed';
|
||||
$http_status = ($status === 'failed') ? "500" : "200";
|
||||
return array(
|
||||
"status" => $http_status,
|
||||
"message" => isset($result['message']) ? $result['message'] : 'Server content scheduled action completed.',
|
||||
"result" => $result
|
||||
);
|
||||
}
|
||||
|
||||
return array("status" => "400", "message" => "BAD REQUEST");
|
||||
}
|
||||
|
||||
function api_steam_workshop()
|
||||
{
|
||||
global $request, $db, $user_info, $settings;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue