* Bacula(R) - The Network Backup Solution
* Baculum - Bacula web interface
*
- * Copyright (C) 2013-2016 Kern Sibbald
+ * Copyright (C) 2013-2019 Kern Sibbald
*
* The main author of Baculum is Marcin Haba.
* The original author of Bacula is Kern Sibbald, with contributions
const JSON_TOOL_FD_TYPE = 'fd';
const JSON_TOOL_BCONS_TYPE = 'bcons';
+ /**
+ * Action types
+ */
+ const ACTION_DIR_START = 'dir_start';
+ const ACTION_DIR_STOP = 'dir_stop';
+ const ACTION_DIR_RESTART = 'dir_restart';
+ const ACTION_SD_START = 'sd_start';
+ const ACTION_SD_STOP = 'sd_stop';
+ const ACTION_SD_RESTART = 'sd_restart';
+ const ACTION_FD_START = 'fd_start';
+ const ACTION_FD_STOP = 'fd_stop';
+ const ACTION_FD_RESTART = 'fd_restart';
+
/**
* These options are obligatory for API config.
*/
* @return boolean true if config valid, otherwise false
*/
private function validateConfig(array $config = array()) {
- $is_valid = $this->isConfigValid($this->required_options, $config, self::CONFIG_FILE_FORMAT, self::CONFIG_FILE_PATH);
- return $is_valid;
+ return $this->isConfigValid($this->required_options, $config, self::CONFIG_FILE_FORMAT, self::CONFIG_FILE_PATH);
}
private function getJSONToolTypes() {
- $types = array(
+ return array(
self::JSON_TOOL_DIR_TYPE,
self::JSON_TOOL_SD_TYPE,
self::JSON_TOOL_FD_TYPE,
self::JSON_TOOL_BCONS_TYPE
);
- return $types;
}
/**
}
return $tools;
}
+
+ /**
+ * Get action types.
+ *
+ * @return array action types
+ */
+ public function getActionTypes() {
+ return array(
+ self::ACTION_DIR_START,
+ self::ACTION_DIR_STOP,
+ self::ACTION_DIR_RESTART,
+ self::ACTION_SD_START,
+ self::ACTION_SD_STOP,
+ self::ACTION_SD_RESTART,
+ self::ACTION_FD_START,
+ self::ACTION_FD_STOP,
+ self::ACTION_FD_RESTART
+ );
+ }
+
+ /**
+ * Check if Actions are configured for application.
+ *
+ * @return boolean true if Actions are configured, otherwise false
+ */
+ public function isActionsConfigured() {
+ $config = $this->getConfig();
+ return key_exists('actions', $config);
+ }
+
+ /**
+ * Check if single action is configured for application.
+ *
+ * @return boolean true if single action is configured, otherwise false
+ */
+ public function isActionConfigured($action_type) {
+ $configured = false;
+ $config = $this->getActionsConfig();
+ return (key_exists($action_type, $config) && !empty($config[$action_type]));
+ }
+
+ /**
+ * Check if Actions support is enabled.
+ *
+ * @return boolean true if Actions support is enabled, otherwise false
+ */
+ public function isActionsEnabled() {
+ $enabled = false;
+ if ($this->isActionsConfigured() === true) {
+ $config = $this->getConfig();
+ $enabled = ($config['actions']['enabled'] == 1);
+ }
+ return $enabled;
+ }
+
+ /**
+ * Get Actions config parameters.
+ *
+ * @return array Actions config parameters
+ */
+ public function getActionsConfig() {
+ $cfg = array();
+ if ($this->isActionsConfigured() === true) {
+ $config = $this->getConfig();
+ $cfg = $config['actions'];
+ }
+ return $cfg;
+ }
+
+ /**
+ * Get single action command and sudo option.
+ *
+ * @param string $action_type action type (dir_start, dir_stop ...etc.)
+ * @return array command and sudo option state
+ */
+ public function getActionConfig($action_type) {
+ $action = array('cmd' => '', 'use_sudo' => false);
+ $actions = $this->getSupportedActions();
+ $config = $this->getActionsConfig();
+ if (in_array($action_type, $actions) && $this->isActionConfigured($action_type) === true) {
+ $action['cmd'] = $config[$action_type];
+ $action['use_sudo'] = ($config['use_sudo'] == 1);
+ }
+ return $action;
+ }
+
+ /**
+ * Get supported actions defined in API config.
+ *
+ * @return array supported actions
+ */
+ public function getSupportedActions() {
+ $actions = array();
+ $types = $this->getActionTypes();
+ for ($i = 0; $i < count($types); $i++) {
+ if ($this->isActionConfigured($types[$i]) === true) {
+ array_push($actions, $types[$i]);
+ }
+ }
+ return $actions;
+ }
}
if ($is_auth === false) {
// Authorization error.
header(OAuth2::HEADER_UNAUTHORIZED);
- $this->output = AuthorizationError::MSG_ERROR_AUTHORIZATION_TO_API_PROBLEM;
- $this->error = AuthorizationError::ERROR_AUTHORIZATION_TO_API_PROBLEM;
+ $this->output = AuthorizationError::MSG_ERROR_AUTHENTICATION_TO_API_PROBLEM;
+ $this->error = AuthorizationError::ERROR_AUTHENTICATION_TO_API_PROBLEM;
return;
}
try {
--- /dev/null
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum - Bacula web interface
+ *
+ * Copyright (C) 2013-2019 Kern Sibbald
+ *
+ * The main author of Baculum is Marcin Haba.
+ * The original author of Bacula is Kern Sibbald, with contributions
+ * from many others, a complete list can be found in the file AUTHORS.
+ *
+ * You may use this file and others of this release according to the
+ * license defined in the LICENSE file, which includes the Affero General
+ * Public License, v3.0 ("AGPLv3") and some additional permissions and
+ * terms pursuant to its AGPLv3 Section 7.
+ *
+ * This notice must be preserved when any source code is
+ * conveyed and/or propagated.
+ *
+ * Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+
+Prado::using('Application.API.Class.APIModule');
+Prado::using('Application.Common.Class.Errors');
+
+/**
+ * Module responsible for executing action commands.
+ */
+class ComponentActions extends APIModule {
+
+ /**
+ * Sudo command.
+ */
+ const SUDO = 'sudo';
+
+ /**
+ * Action command pattern used to execute command.
+ */
+ const ACTION_COMMAND_PATTERN = "%s%s 2>&1";
+
+ /**
+ * Get command pattern.
+ *
+ * @return string command pattern
+ */
+ private function getCmdPattern() {
+ // Default command pattern
+ return self::ACTION_COMMAND_PATTERN;
+ }
+
+ /**
+ * Get sudo command.
+ *
+ * @param boolean $use_sudo sudo option state
+ * @return string sudo command
+ */
+ private function getSudo($use_sudo) {
+ $sudo = '';
+ if ($use_sudo === true) {
+ $sudo = self::SUDO . ' ';
+ }
+ return $sudo;
+ }
+
+ /**
+ * Execute single action command.
+ *
+ * @param string $action_type action type (dir_start, dir_stop ...etc.)
+ * @return array result with output and exitcode
+ */
+ public function execAction($action_type) {
+ $result = null;
+ $output = array();
+ $exitcode = -1;
+ $api_config = $this->getModule('api_config');
+ if ($api_config->isActionConfigured($action_type) === true) {
+ if ($api_config->isActionsEnabled() === true) {
+ $action = $api_config->getActionConfig($action_type);
+ $result = $this->execCommand($action['cmd'], $action['use_sudo']);
+ if ($result->error !== 0) {
+ $emsg = PHP_EOL . ' Output:' . implode(PHP_EOL, $result->output);
+ $output = ActionsError::MSG_ERROR_ACTIONS_WRONG_EXITCODE . $emsg;
+ $exitcode = ActionsError::ERROR_ACTIONS_WRONG_EXITCODE;
+ $result = $this->prepareResult($output, $exitcode);
+ }
+ } else {
+ $output = ActionsError::MSG_ERROR_ACTIONS_DISABLED;
+ $exitcode = ActionsError::ERROR_ACTIONS_DISABLED;
+ $result = $this->prepareResult($output, $exitcode);
+ }
+ } else {
+ $output = ActionsError::MSG_ERROR_ACTIONS_NOT_CONFIGURED;
+ $exitcode = ActionsError::ERROR_ACTIONS_NOT_CONFIGURED;
+ $result = $this->prepareResult($output, $exitcode);
+ }
+ return $result;
+ }
+
+ /**
+ * Execute action command.
+ *
+ * @param string $bin command
+ * @param boolean $use_sudo use sudo
+ */
+ public function execCommand($bin, $use_sudo) {
+ $sudo = $this->getSudo($use_sudo);
+ $cmd_pattern = $this->getCmdPattern();
+ $cmd = sprintf($cmd_pattern, $sudo, $bin);
+ exec($cmd, $output, $exitcode);
+ $this->getModule('logging')->log($cmd, $output, Logging::CATEGORY_EXECUTE, __FILE__, __LINE__);
+ $result = $this->prepareResult($output, $exitcode);
+ return $result;
+ }
+
+ /**
+ * Prepare action command result.
+ *
+ * @param array $output output from command execution
+ * @param integer $exitcode command exit code
+ * @return array result with output and exitcode
+ */
+ public function prepareResult($output, $exitcode) {
+ $result = (object)array(
+ 'output' => $output,
+ 'error' => $exitcode
+ );
+ return $result;
+ }
+
+}
+?>
'filesets',
'schedules',
'config',
- 'status'
+ 'status',
+ 'actions'
];
var set_scopes = function(field_id) {
document.getElementById(field_id).value = OAuth2Scopes.join(' ');
msgid "Error"
msgstr "Error"
-msgid "Authorization"
-msgstr "Authorization"
-
msgid "Finish"
msgstr "Finish"
msgid "Do you want to setup and share the Bacula configuration interface to configure Bacula components via this API instance?"
msgstr "Do you want to setup and share the Bacula configuration interface to configure Bacula components via this API instance?"
-msgid "Step 5 - authorization to API"
-msgstr "Step 5 - authorization to API"
-
msgid "Administration login:"
msgstr "Administration login:"
msgid "Use sudo for bconsole requests:"
msgstr "Use sudo for bconsole requests:"
-msgid "Authorization to Baculum REST API"
-msgstr "Authorization to Baculum REST API"
-
msgid "Save"
msgstr "Save"
-msgid "Authorization type:"
-msgstr "Authorization type:"
-
-msgid "Step 6 - Finish"
-msgstr "Step 6 - Finish"
+msgid "Step 7 - Finish"
+msgstr "Step 7 - Finish"
msgid "Use sudo for Bacula JSON tools:"
msgstr "Use sudo for Bacula JSON tools:"
msgid "Version:"
msgstr "Version:"
+
+msgid "Authentication"
+msgstr "Authentication"
+
+msgid "Authentication to Baculum REST API"
+msgstr "Authentication to Baculum REST API"
+
+msgid "Authentication type:"
+msgstr "Authentication type:"
+
+msgid "Step 6 - authentication to API"
+msgstr "Step 6 - authentication to API"
+
+msgid "Actions"
+msgstr "Actions"
+
+msgid "Start"
+msgstr "Start"
+
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Restart"
+msgstr "Restart"
+
+msgid "Director start command:"
+msgstr "Director start command:"
+
+msgid "Director stop command:"
+msgstr "Director stop command:"
+
+msgid "Director restart command:"
+msgstr "Director restart command:"
+
+msgid "Storage Daemon start command:"
+msgstr "Storage Daemon start command:"
+
+msgid "Storage Daemon stop command:"
+msgstr "Storage Daemon stop command:"
+
+msgid "Storage Daemon restart command:"
+msgstr "Storage Daemon restart command:"
+
+msgid "File Daemon/Client start command:"
+msgstr "File Daemon/Client start command:"
+
+msgid "File Daemon/Client stop command:"
+msgstr "File Daemon/Client stop command:"
+
+msgid "File Daemon/Client restart command:"
+msgstr "File Daemon/Client restart command:"
+
+msgid "Do you want to setup start, stop and restart actions for Bacula components? If you define them, there will be possible to call these actions via API interface and by Baculum Web as well."
+msgstr "Do you want to setup start, stop and restart actions for Bacula components? If you define them, there will be possible to call these actions via API interface and by Baculum Web as well."
+
+msgid "Sudo configuration"
+msgstr "Sudo configuration"
+
+msgid "Example sudo configuration for Apache web server user (RHEL, CentOS and others):"
+msgstr "Example sudo configuration for Apache web server user (RHEL, CentOS and others):"
+
+msgid "Example sudo configuration for Lighttpd web server user (RHEL, CentOS and others):"
+msgstr "Example sudo configuration for Lighttpd web server user (RHEL, CentOS and others):"
+
+msgid "Example sudo configuration for Apache and Lighttpd web servers user (Debian, Ubuntu and others):"
+msgstr "Example sudo configuration for Apache and Lighttpd web servers user (Debian, Ubuntu and others):"
+
+msgid "Get sudo configuration"
+msgstr "Get sudo configuration"
+
+msgid "Please copy appropriate sudo configuration and put it to a new sudoers.d file for example /etc/sudoers.d/baculum-api"
+msgstr "Please copy appropriate sudo configuration and put it to a new sudoers.d file for example /etc/sudoers.d/baculum-api"
+
+msgid "Step 5 - enable actions for components"
+msgstr "Step 5 - enable actions for components"
+
+msgid "Directory path for new config files:"
+msgstr "Directory path for new config files:"
+
+msgid "Use sudo for actions:"
+msgstr "Use sudo for actions:"
+
+msgid "Actions setting:"
+msgstr "Actions setting:"
msgid "Error"
msgstr "Błąd"
-msgid "Authorization"
-msgstr "Autoryzacja"
-
msgid "Finish"
msgstr "Koniec"
msgid "Do you want to setup and share the Bacula configuration interface to configure Bacula components via this API instance?"
msgstr "Czy chcesz skonfigurować i udostępnić interfejs konfiguracyjny Bacula do konfiguracji komponentów Bacula poprzez tą instancję API?"
-msgid "Step 5 - authorization to API"
-msgstr "Krok 5 - autoryzacja do API"
-
msgid "Administration login:"
msgstr "Login administratora:"
msgid "Use sudo for bconsole requests:"
msgstr "Użyj sudo dla zapytań bconsole:"
-msgid "Authorization to Baculum REST API"
-msgstr "Autoryzacja do Baculum REST API"
-
msgid "Save"
msgstr "Zapisz"
-msgid "Authorization type:"
-msgstr "Typ autoryzacji:"
-
-msgid "Step 6 - Finish"
-msgstr "Krok 6 - Koniec"
+msgid "Step 7 - Finish"
+msgstr "Krok 7 - Koniec"
msgid "Use sudo for Bacula JSON tools:"
msgstr "Użyj sudo dla narzędzi JSON Bacula."
msgid "Version:"
msgstr "Wersja:"
+
+msgid "Authentication"
+msgstr "Uwierzytelnianie"
+
+msgid "Authentication to Baculum REST API"
+msgstr "Uwierzytelnianie do Baculum REST API"
+
+msgid "Authentication type:"
+msgstr "Typ uwierzytelniania:"
+
+msgid "Step 6 - authentication to API"
+msgstr "Krok 6 - uwierzytelnianie do API"
+
+msgid "Actions"
+msgstr "Actions"
+
+msgid "Start"
+msgstr "Start"
+
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Restart"
+msgstr "Restart"
+
+msgid "Director start command:"
+msgstr "Komenda uruchomenia Director:"
+
+msgid "Director stop command:"
+msgstr "Komenda zatrzymania Director:"
+
+msgid "Director restart command:"
+msgstr "Komenda restartu Director:"
+
+msgid "Storage Daemon start command:"
+msgstr "Komenda uruchomienia Storage Daemon:"
+
+msgid "Storage Daemon stop command:"
+msgstr "Komenda zatrzymania Storage Daemon:"
+
+msgid "Storage Daemon restart command:"
+msgstr "Komenda restartu Storage Daemon:"
+
+msgid "File Daemon/Client start command:"
+msgstr "Komenda uruchomienia klienta:"
+
+msgid "File Daemon/Client stop command:"
+msgstr "Komenda zatrzymania klienta:"
+
+msgid "File Daemon/Client restart command:"
+msgstr "Komenda restartu klienta:"
+
+msgid "Do you want to setup start, stop and restart actions for Bacula components? If you define them, there will be possible to call these actions via API interface and by Baculum Web as well."
+msgstr "Czy chcesz skonfigurować akcje uruchomienia, zatrzymania i restartu komponentów Bacula? Jeśli zdefiniujesz je, wtedy będzie możliwe wykonywanie tych akcji poprzez interfejs API i również przez Baculum Web."
+
+msgid "Sudo configuration"
+msgstr "Konfiguracja sudo"
+
+msgid "Example sudo configuration for Apache web server user (RHEL, CentOS and others):"
+msgstr "Przykładowa konfiguracja sudo dla użytkownika serwera web Apache (RHEL, CentOS i inne):"
+
+msgid "Example sudo configuration for Lighttpd web server user (RHEL, CentOS and others):"
+msgstr "Przykładowa konfiguracja sudo dla użytkownika serwera web Lighttpd (RHEL, CentOS i inne):"
+
+msgid "Example sudo configuration for Apache and Lighttpd web servers user (Debian, Ubuntu and others):"
+msgstr "Przykładowa konfiguracja sudo dla użytkownika serwerów web Apache i Lighttpd (Debian, Ubuntu i inne):"
+
+msgid "Get sudo configuration"
+msgstr "Weź konfigurację sudo"
+
+msgid "Please copy appropriate sudo configuration and put it to a new sudoers.d file for example /etc/sudoers.d/baculum-api"
+msgstr "Proszę skopiować odpowiednią konfigurację sudo i wpisać ją do nowego pliku sudoers.d na przykład /etc/sudoers.d/baculum-api"
+
+msgid "Step 5 - enable actions for components"
+msgstr "Krok 5 - włącz akcje dla komponentów"
+
+msgid "Directory path for new config files:"
+msgstr "Lokalizacja katalogu na nowe pliki konfiguracyjne:"
+
+msgid "Use sudo for actions:"
+msgstr "Użyj sudo dla akcji:"
+
+msgid "Actions setting:"
+msgstr "Ustawienie akcji:"
msgid "Error"
msgstr "Erro"
-msgid "Authorization"
-msgstr "Autorização"
-
msgid "Finish"
msgstr "Finalizar"
msgid "Do you want to setup and share the Bacula configuration interface to configure Bacula components via this API instance?"
msgstr "Deseja configurar e compartilhar a interface de configuração do Bacula para configurar os recursos através desta instância da API?"
-msgid "Step 5 - authorization to API"
-msgstr "Passo 5 - Autorização da API"
-
msgid "Administration login:"
msgstr "Usuário administrador:"
msgid "Use sudo for bconsole requests:"
msgstr "Utilizar sudo para executar bconsole:"
-msgid "Authorization to Baculum REST API"
-msgstr "Autorização para a API REST do Baculum"
-
msgid "Save"
msgstr "Salvar"
-msgid "Authorization type:"
-msgstr "Tipo de autorização:"
-
-msgid "Step 6 - Finish"
-msgstr "Passo 6 - Finalizar"
+msgid "Step 7 - Finish"
+msgstr "Passo 7 - Finalizar"
msgid "Use sudo for Bacula JSON tools:"
msgstr "Utilizar o sudo para os utilitários JSON:"
msgid "Version:"
msgstr "Version:"
+
+msgid "Authentication"
+msgstr "Authentication"
+
+msgid "Authentication to Baculum REST API"
+msgstr "Authentication to Baculum REST API"
+
+msgid "Authentication type:"
+msgstr "Authentication type:"
+
+msgid "Step 6 - authentication to API"
+msgstr "Step 6 - authentication to API"
+
+msgid "Actions"
+msgstr "Actions"
+
+msgid "Start"
+msgstr "Start"
+
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Restart"
+msgstr "Restart"
+
+msgid "Director start command:"
+msgstr "Director start command:"
+
+msgid "Director stop command:"
+msgstr "Director stop command:"
+
+msgid "Director restart command:"
+msgstr "Director restart command:"
+
+msgid "Storage Daemon start command:"
+msgstr "Storage Daemon start command:"
+
+msgid "Storage Daemon stop command:"
+msgstr "Storage Daemon stop command:"
+
+msgid "Storage Daemon restart command:"
+msgstr "Storage Daemon restart command:"
+
+msgid "File Daemon/Client start command:"
+msgstr "File Daemon/Client start command:"
+
+msgid "File Daemon/Client stop command:"
+msgstr "File Daemon/Client stop command:"
+
+msgid "File Daemon/Client restart command:"
+msgstr "File Daemon/Client restart command:"
+
+msgid "Do you want to setup start, stop and restart actions for Bacula components? If you define them, there will be possible to call these actions via API interface and by Baculum Web as well."
+msgstr "Do you want to setup start, stop and restart actions for Bacula components? If you define them, there will be possible to call these actions via API interface and by Baculum Web as well."
+
+msgid "Sudo configuration"
+msgstr "Sudo configuration"
+
+msgid "Example sudo configuration for Apache web server user (RHEL, CentOS and others):"
+msgstr "Example sudo configuration for Apache web server user (RHEL, CentOS and others):"
+
+msgid "Example sudo configuration for Lighttpd web server user (RHEL, CentOS and others):"
+msgstr "Example sudo configuration for Lighttpd web server user (RHEL, CentOS and others):"
+
+msgid "Example sudo configuration for Apache and Lighttpd web servers user (Debian, Ubuntu and others):"
+msgstr "Example sudo configuration for Apache and Lighttpd web servers user (Debian, Ubuntu and others):"
+
+msgid "Get sudo configuration"
+msgstr "Get sudo configuration"
+
+msgid "Please copy appropriate sudo configuration and put it to a new sudoers.d file for example /etc/sudoers.d/baculum-api"
+msgstr "Please copy appropriate sudo configuration and put it to a new sudoers.d file for example /etc/sudoers.d/baculum-api"
+
+msgid "Step 5 - enable actions for components"
+msgstr "Step 5 - enable actions for components"
+
+msgid "Directory path for new config files:"
+msgstr "Directory path for new config files:"
+
+msgid "Use sudo for actions:"
+msgstr "Use sudo for actions:"
+
+msgid "Actions setting:"
+msgstr "Actions setting:"
--- /dev/null
+<?php
+/*
+ * Bacula(R) - The Network Backup Solution
+ * Baculum - Bacula web interface
+ *
+ * Copyright (C) 2013-2019 Kern Sibbald
+ *
+ * The main author of Baculum is Marcin Haba.
+ * The original author of Bacula is Kern Sibbald, with contributions
+ * from many others, a complete list can be found in the file AUTHORS.
+ *
+ * You may use this file and others of this release according to the
+ * license defined in the LICENSE file, which includes the Affero General
+ * Public License, v3.0 ("AGPLv3") and some additional permissions and
+ * terms pursuant to its AGPLv3 Section 7.
+ *
+ * This notice must be preserved when any source code is
+ * conveyed and/or propagated.
+ *
+ * Bacula(R) is a registered trademark of Kern Sibbald.
+ */
+
+Prado::using('Application.API.Class.APIConfig');
+
+class Actions extends BaculumAPIServer {
+
+ public function get() {
+ $component = $this->Request->contains('component') ? $this->Request['component'] : '';
+ $action = $this->Request->contains('action') ? $this->Request['action'] : '';
+ $action_type = null;
+
+ switch ($component) {
+ case 'director':
+ if ($action === 'start') {
+ $action_type = APIConfig::ACTION_DIR_START;
+ } elseif ($action === 'stop') {
+ $action_type = APIConfig::ACTION_DIR_STOP;
+ } elseif ($action === 'restart') {
+ $action_type = APIConfig::ACTION_DIR_RESTART;
+ }
+ break;
+ case 'storage':
+ if ($action === 'start') {
+ $action_type = APIConfig::ACTION_SD_START;
+ } elseif ($action === 'stop') {
+ $action_type = APIConfig::ACTION_SD_STOP;
+ } elseif ($action === 'restart') {
+ $action_type = APIConfig::ACTION_SD_RESTART;
+ }
+ break;
+ case 'client':
+ if ($action === 'start') {
+ $action_type = APIConfig::ACTION_FD_START;
+ } elseif ($action === 'stop') {
+ $action_type = APIConfig::ACTION_FD_STOP;
+ } elseif ($action === 'restart') {
+ $action_type = APIConfig::ACTION_FD_RESTART;
+ }
+ break;
+ }
+
+ if (is_string($action_type)) {
+ $result = $this->getModule('comp_actions')->execAction($action_type);
+ if ($result->error === 0) {
+ $this->output = ActionsError::MSG_ERROR_NO_ERRORS;
+ $this->error = ActionsError::ERROR_NO_ERRORS;
+ } else {
+ $this->output = $result->output;
+ $this->error = $result->error;
+ }
+ } else {
+ $this->output = ActionsError::MSG_ERROR_ACTIONS_ACTION_DOES_NOT_EXIST;
+ $this->error = ActionsError::ERROR_ACTIONS_ACTION_DOES_NOT_EXIST;
+ }
+ }
+}
+?>
<div><com:TTranslate Text="Config API" /></div>
</div>
<div class="step step-<%=($this->Parent->ActiveStepIndex === 4) ? 'active' : (($this->Parent->ActiveStepIndex === 5) ? 'prev-active' : 'normal')%>">
- <div><com:TTranslate Text="Authorization" /></div>
+ <div><com:TTranslate Text="Actions" /></div>
</div>
- <div class="step step-<%=($this->Parent->ActiveStepIndex === 5) ? 'last-active' : (($this->Parent->ActiveStepIndex === 6) ? 'last-prev-active' : 'last')%>">
+ <div class="step step-<%=($this->Parent->ActiveStepIndex === 5) ? 'active' : (($this->Parent->ActiveStepIndex === 6) ? 'prev-active' : 'normal')%>">
+ <div><com:TTranslate Text="Authentication" /></div>
+ </div>
+ <div class="step step-<%=($this->Parent->ActiveStepIndex === 6) ? 'last-active' : (($this->Parent->ActiveStepIndex === 7) ? 'last-prev-active' : 'last')%>">
<div><com:TTranslate Text="Finish" /></div>
</div>
<div id="title"><%=$this->Parent->ActiveStep->Title%><div>
</div>
</div>
</com:TWizardStep>
- <com:TWizardStep ID="Step5" Title="<%[ Step 5 - authorization to API ]%>" StepType="Auto">
+ <com:TWizardStep ID="Step5" Title="<%[ Step 5 - enable actions for components ]%>" StepType="Auto">
+ <p><%[ Do you want to setup start, stop and restart actions for Bacula components? If you define them, there will be possible to call these actions via API interface and by Baculum Web as well. ]%></p>
+ <div class="line left">
+ <com:TRadioButton ID="ActionsNo" GroupName="SelectActions" Attributes.onclick="$('#configure_actions').hide();" /> <com:TLabel ForControl="ActionsNo" Text="<%[ No ]%>" />
+ </div>
+ <div class="line left">
+ <com:TRadioButton ID="ActionsYes" GroupName="SelectActions" Attributes.onclick="$('#configure_actions').show();" /> <com:TLabel ForControl="ActionsYes" Text="<%[ Yes ]%>" />
+ </div>
+ <div id="configure_actions" style="display: <%=($this->ActionsYes->Checked === true) ? 'block' : 'none';%>">
+ <div id="actions_fields">
+ <fieldset class="actions_field">
+ <legend><%[ General configuration ]%></legend>
+ <div class="actions_lines">
+ <div class="line left">
+ <div class="text"><com:TLabel ForControl="ActionsUseSudo" Text="<%[ Use sudo: ]%>" /></div>
+ <div class="field">
+ <com:TCheckBox ID="ActionsUseSudo" /> <a href="javascript:void(0)" onclick="get_sudo_config();"><%[ Get sudo configuration ]%></a>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ <fieldset class="actions_field">
+ <legend>Director</legend>
+ <div class="actions_lines">
+ <div class="line left">
+ <div class="text"><com:TLabel ForControl="DirStartAction" Text="<%[ Director start command: ]%>" /></div>
+ <div class="field">
+ <com:TTextBox ID="DirStartAction" CssClass="textbox" />
+ </div>
+ <div class="button">
+ <com:TActiveButton ID="TestDirStartActionCommand" ValidationGroup="ActionsGroup" Text="<%[ Start ]%>" OnCommand="testExecActionCommand" CommandParameter="dir_start">
+ <prop:ClientSide.OnLoading>
+ actions_hide_test_results('<%=$this->TestDirStartActionCommand->CommandParameter%>');
+ $('#actions_test_result_dir_start .action_test_loader').show();
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ $('#actions_test_result_dir_start .action_test_loader').hide();
+ </prop:ClientSide.OnComplete>
+ </com:TActiveButton>
+ </div>
+ <span id="actions_test_result_dir_start">
+ <span class="action_test_loader" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/ajax-loader.gif" alt="<%[ Loading... ]%>" /></span>
+ <span class="action_success" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_ok.png" alt="<%[ OK ]%>" /> <%[ OK ]%></span>
+ <span class="action_error" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_err.png" alt="<%[ Error ]%>" /> <%[ Error ]%></span>
+ <span class="action_result validator"></span>
+ </span>
+ </div>
+ <div class="line left">
+ <div class="text"><com:TLabel ForControl="DirStopAction" Text="<%[ Director stop command: ]%>" /></div>
+ <div class="field">
+ <com:TTextBox ID="DirStopAction" CssClass="textbox" />
+ </div>
+ <div class="button">
+ <com:TActiveButton ID="TestDirStopActionCommand" ValidationGroup="ActionsGroup" Text="<%[ Stop ]%>" OnCommand="testExecActionCommand" CommandParameter="dir_stop">
+ <prop:ClientSide.OnLoading>
+ actions_hide_test_results('<%=$this->TestDirStopActionCommand->CommandParameter%>');
+ $('#actions_test_result_dir_stop .action_test_loader').show();
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ $('#actions_test_result_dir_stop .action_test_loader').hide();
+ </prop:ClientSide.OnComplete>
+ </com:TActiveButton>
+ </div>
+ <span id="actions_test_result_dir_stop">
+ <span class="action_test_loader" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/ajax-loader.gif" alt="<%[ Loading... ]%>" /></span>
+ <span class="action_success" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_ok.png" alt="<%[ OK ]%>" /> <%[ OK ]%></span>
+ <span class="action_error" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_err.png" alt="<%[ Error ]%>" /> <%[ Error ]%></span>
+ <span class="action_result validator"></span>
+ </span>
+ </div>
+ <div class="line left">
+ <div class="text"><com:TLabel ForControl="DirRestartAction" Text="<%[ Director restart command: ]%>" /></div>
+ <div class="field">
+ <com:TTextBox ID="DirRestartAction" CssClass="textbox" />
+ </div>
+ <div class="button">
+ <com:TActiveButton ID="TestDirRestartActionCommand" ValidationGroup="ActionsGroup" Text="<%[ Restart ]%>" OnCommand="testExecActionCommand" CommandParameter="dir_restart">
+ <prop:ClientSide.OnLoading>
+ actions_hide_test_results('<%=$this->TestDirRestartActionCommand->CommandParameter%>');
+ $('#actions_test_result_dir_restart .action_test_loader').show();
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ $('#actions_test_result_dir_restart .action_test_loader').hide();
+ </prop:ClientSide.OnComplete>
+ </com:TActiveButton>
+ </div>
+ <span id="actions_test_result_dir_restart">
+ <span class="action_test_loader" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/ajax-loader.gif" alt="<%[ Loading... ]%>" /></span>
+ <span class="action_success" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_ok.png" alt="<%[ OK ]%>" /> <%[ OK ]%></span>
+ <span class="action_error" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_err.png" alt="<%[ Error ]%>" /> <%[ Error ]%></span>
+ <span class="action_result validator"></span>
+ </span>
+ </div>
+ </div>
+ </fieldset>
+ <fieldset class="actions_field">
+ <legend>Storage Daemon</legend>
+ <div class="actions_lines">
+ <div class="line left">
+ <div class="text"><com:TLabel ForControl="SdStartAction" Text="<%[ Storage Daemon start command: ]%>" /></div>
+ <div class="field">
+ <com:TTextBox ID="SdStartAction" CssClass="textbox" />
+ </div>
+ <div class="button">
+ <com:TActiveButton ID="TestSdStartActionCommand" ValidationGroup="ActionsGroup" Text="<%[ Start ]%>" OnCommand="testExecActionCommand" CommandParameter="sd_start">
+ <prop:ClientSide.OnLoading>
+ actions_hide_test_results('<%=$this->TestSdStartActionCommand->CommandParameter%>');
+ $('#actions_test_result_sd_start .action_test_loader').show();
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ $('#actions_test_result_sd_start .action_test_loader').hide();
+ </prop:ClientSide.OnComplete>
+ </com:TActiveButton>
+ </div>
+ <span id="actions_test_result_sd_start">
+ <span class="action_test_loader" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/ajax-loader.gif" alt="<%[ Loading... ]%>" /></span>
+ <span class="action_success" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_ok.png" alt="<%[ OK ]%>" /> <%[ OK ]%></span>
+ <span class="action_error" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_err.png" alt="<%[ Error ]%>" /> <%[ Error ]%></span>
+ <span class="action_result validator"></span>
+ </span>
+ </div>
+ <div class="line left">
+ <div class="text"><com:TLabel ForControl="SdStopAction" Text="<%[ Storage Daemon stop command: ]%>" /></div>
+ <div class="field">
+ <com:TTextBox ID="SdStopAction" CssClass="textbox" />
+ </div>
+ <div class="button">
+ <com:TActiveButton ID="TestSdStopActionCommand" ValidationGroup="ActionsGroup" Text="<%[ Stop ]%>" OnCommand="testExecActionCommand" CommandParameter="sd_stop">
+ <prop:ClientSide.OnLoading>
+ actions_hide_test_results('<%=$this->TestSdStopActionCommand->CommandParameter%>');
+ $('#actions_test_result_sd_stop .action_test_loader').show();
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ $('#actions_test_result_sd_stop .action_test_loader').hide();
+ </prop:ClientSide.OnComplete>
+ </com:TActiveButton>
+ </div>
+ <span id="actions_test_result_sd_stop">
+ <span class="action_test_loader" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/ajax-loader.gif" alt="<%[ Loading... ]%>" /></span>
+ <span class="action_success" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_ok.png" alt="<%[ OK ]%>" /> <%[ OK ]%></span>
+ <span class="action_error" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_err.png" alt="<%[ Error ]%>" /> <%[ Error ]%></span>
+ <span class="action_result validator"></span>
+ </span>
+ </div>
+ <div class="line left">
+ <div class="text"><com:TLabel ForControl="SdRestartAction" Text="<%[ Storage Daemon restart command: ]%>" /></div>
+ <div class="field">
+ <com:TTextBox ID="SdRestartAction" CssClass="textbox" />
+ </div>
+ <div class="button">
+ <com:TActiveButton ID="TestSdRestartActionCommand" ValidationGroup="ActionsGroup" Text="<%[ Restart ]%>" OnCommand="testExecActionCommand" CommandParameter="sd_restart">
+ <prop:ClientSide.OnLoading>
+ actions_hide_test_results('<%=$this->TestSdRestartActionCommand->CommandParameter%>');
+ $('#actions_test_result_sd_restart .action_test_loader').show();
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ $('#actions_test_result_sd_restart .action_test_loader').hide();
+ </prop:ClientSide.OnComplete>
+ </com:TActiveButton>
+ </div>
+ <span id="actions_test_result_sd_restart">
+ <span class="action_test_loader" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/ajax-loader.gif" alt="<%[ Loading... ]%>" /></span>
+ <span class="action_success" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_ok.png" alt="<%[ OK ]%>" /> <%[ OK ]%></span>
+ <span class="action_error" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_err.png" alt="<%[ Error ]%>" /> <%[ Error ]%></span>
+ <span class="action_result validator"></span>
+ </span>
+ </div>
+ </div>
+ </fieldset>
+ <fieldset class="actions_field">
+ <legend>File Daemon/Client</legend>
+ <div class="actions_lines">
+ <div class="line left">
+ <div class="text"><com:TLabel ForControl="FdStartAction" Text="<%[ File Daemon/Client start command: ]%>" /></div>
+ <div class="field">
+ <com:TTextBox ID="FdStartAction" CssClass="textbox" />
+ </div>
+ <div class="button">
+ <com:TActiveButton ID="TestFdStartActionCommand" ValidationGroup="ActionsGroup" Text="<%[ Start ]%>" OnCommand="testExecActionCommand" CommandParameter="fd_start">
+ <prop:ClientSide.OnLoading>
+ actions_hide_test_results('<%=$this->TestFdStartActionCommand->CommandParameter%>');
+ $('#actions_test_result_fd_start .action_test_loader').show();
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ $('#actions_test_result_fd_start .action_test_loader').hide();
+ </prop:ClientSide.OnComplete>
+ </com:TActiveButton>
+ </div>
+ <span id="actions_test_result_fd_start">
+ <span class="action_test_loader" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/ajax-loader.gif" alt="<%[ Loading... ]%>" /></span>
+ <span class="action_success" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_ok.png" alt="<%[ OK ]%>" /> <%[ OK ]%></span>
+ <span class="action_error" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_err.png" alt="<%[ Error ]%>" /> <%[ Error ]%></span>
+ <span class="action_result validator"></span>
+ </span>
+ </div>
+ <div class="line left">
+ <div class="text"><com:TLabel ForControl="FdStopAction" Text="<%[ File Daemon/Client stop command: ]%>" /></div>
+ <div class="field">
+ <com:TTextBox ID="FdStopAction" CssClass="textbox" />
+ </div>
+ <div class="button">
+ <com:TActiveButton ID="TestFdStopActionCommand" ValidationGroup="ActionsGroup" Text="<%[ Stop ]%>" OnCommand="testExecActionCommand" CommandParameter="fd_stop">
+ <prop:ClientSide.OnLoading>
+ actions_hide_test_results('<%=$this->TestFdStopActionCommand->CommandParameter%>');
+ $('#actions_test_result_fd_stop .action_test_loader').show();
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ $('#actions_test_result_fd_stop .action_test_loader').hide();
+ </prop:ClientSide.OnComplete>
+ </com:TActiveButton>
+ </div>
+ <span id="actions_test_result_fd_stop">
+ <span class="action_test_loader" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/ajax-loader.gif" alt="<%[ Loading... ]%>" /></span>
+ <span class="action_success" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_ok.png" alt="<%[ OK ]%>" /> <%[ OK ]%></span>
+ <span class="action_error" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_err.png" alt="<%[ Error ]%>" /> <%[ Error ]%></span>
+ <span class="action_result validator"></span>
+ </span>
+ </div>
+ <div class="line left">
+ <div class="text"><com:TLabel ForControl="FdRestartAction" Text="<%[ File Daemon/Client restart command: ]%>" /></div>
+ <div class="field">
+ <com:TTextBox ID="FdRestartAction" CssClass="textbox" />
+ </div>
+ <div class="button">
+ <com:TActiveButton ID="TestFdRestartActionCommand" ValidationGroup="ActionsGroup" Text="<%[ Restart ]%>" OnCommand="testExecActionCommand" CommandParameter="fd_restart">
+ <prop:ClientSide.OnLoading>
+ actions_hide_test_results('<%=$this->TestFdRestartActionCommand->CommandParameter%>');
+ $('#actions_test_result_fd_restart .action_test_loader').show();
+ </prop:ClientSide.OnLoading>
+ <prop:ClientSide.OnComplete>
+ $('#actions_test_result_fd_restart .action_test_loader').hide();
+ </prop:ClientSide.OnComplete>
+ </com:TActiveButton>
+ </div>
+ <span id="actions_test_result_fd_restart">
+ <span class="action_test_loader" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/ajax-loader.gif" alt="<%[ Loading... ]%>" /></span>
+ <span class="action_success" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_ok.png" alt="<%[ OK ]%>" /> <%[ OK ]%></span>
+ <span class="action_error" style="display: none"><img src="<%=$this->getPage()->getTheme()->getBaseUrl()%>/icon_err.png" alt="<%[ Error ]%>" /> <%[ Error ]%></span>
+ <span class="action_result validator"></span>
+ </span>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ </div>
+ </com:TWizardStep>
+ <com:TWizardStep ID="Step6" Title="<%[ Step 6 - authentication to API ]%>" StepType="Auto">
<div class="line left" style="width:500px; margin: 0 auto">
<com:TActiveRadioButton
ID="AuthOAuth2"
}
</script>
</com:TWizardStep>
- <com:TWizardStep ID="Step6" Title="<%[ Step 6 - Finish ]%>" StepType="Finish">
+ <com:TWizardStep ID="Step7" Title="<%[ Step 7 - Finish ]%>" StepType="Finish">
<fieldset>
<legend><%[ Catalog API ]%></legend>
<div style="display: <%=($this->DatabaseYes->Checked ? 'block' : 'none')%>">
</div>
</fieldset>
<fieldset>
- <legend><%[ Authorization to Baculum REST API ]%></legend>
+ <legend><%[ Actions ]%></legend>
+ <div style="display: <%=($this->ActionsYes->Checked ? 'block' : 'none')%>">
+ <div class="line">
+ <div class="text"><%[ Use sudo for actions: ]%></div>
+ <div class="field bold"><%=($this->ActionsUseSudo->Checked === true) ? 'yes' : 'no'%></div>
+ </div>
+ <div class="line">
+ <div class="text"><%[ Director start command: ]%></div>
+ <div class="field bold"><%=$this->DirStartAction->Text%></div>
+ </div>
+ <div class="line">
+ <div class="text"><%[ Director stop command: ]%></div>
+ <div class="field bold"><%=$this->DirStopAction->Text%></div>
+ </div>
+ <div class="line">
+ <div class="text"><%[ Director restart command: ]%></div>
+ <div class="field bold"><%=$this->DirRestartAction->Text%></div>
+ </div>
+ <div class="line">
+ <div class="text"><%[ Storage Daemon start command: ]%></div>
+ <div class="field bold"><%=$this->SdStartAction->Text%></div>
+ </div>
+ <div class="line">
+ <div class="text"><%[ Storage Daemon stop command: ]%></div>
+ <div class="field bold"><%=$this->SdStopAction->Text%></div>
+ </div>
+ <div class="line">
+ <div class="text"><%[ Storage Daemon restart command: ]%></div>
+ <div class="field bold"><%=$this->SdRestartAction->Text%></div>
+ </div>
+ <div class="line">
+ <div class="text"><%[ File Daemon/Client start command: ]%></div>
+ <div class="field bold"><%=$this->FdStartAction->Text%></div>
+ </div>
+ <div class="line">
+ <div class="text"><%[ File Daemon/Client stop command: ]%></div>
+ <div class="field bold"><%=$this->FdStopAction->Text%></div>
+ </div>
+ <div class="line">
+ <div class="text"><%[ File Daemon/Client restart command: ]%></div>
+ <div class="field bold"><%=$this->FdRestartAction->Text%></div>
+ </div>
+ </div>
+ <div style="display: <%=($this->ActionsNo->Checked ? 'block' : 'none')%>">
+ <div class="line">
+ <div class="text"><%[ Actions setting: ]%></div>
+ <div class="field bold"><%[ Disabled ]%></div>
+ </div>
+ </div>
+ </fieldset>
+ <fieldset>
+ <legend><%[ Authentication to Baculum REST API ]%></legend>
<div class="line">
- <div class="text"><%[ Authorization type: ]%></div>
+ <div class="text"><%[ Authentication type: ]%></div>
<div class="field bold">
<%=$this->AuthBasic->Checked ? 'HTTP Basic' : ''%>
<%=$this->AuthOAuth2->Checked ? 'OAuth2' : ''%>
</fieldset>
</com:TWizardStep>
</com:TWizard>
+<com:TJuiDialog
+ ID="SudoConfigPopup"
+ Options.title="<%[ Sudo configuration ]%>"
+ Options.autoOpen="false",
+ Options.minWidth="600"
+ Options.minHeight="200"
+>
+ <p><%[ Please copy appropriate sudo configuration and put it to a new sudoers.d file for example /etc/sudoers.d/baculum-api ]%></p>
+ <p><%[ Example sudo configuration for Apache web server user (RHEL, CentOS and others): ]%></p>
+ <pre id="sudo_config_apache"></pre>
+ <p><%[ Example sudo configuration for Lighttpd web server user (RHEL, CentOS and others): ]%></p>
+ <pre id="sudo_config_lighttpd"></pre>
+ <p><%[ Example sudo configuration for Apache and Lighttpd web servers user (Debian, Ubuntu and others): ]%></p>
+ <pre id="sudo_config_www_data"></pre>
+</com:TJuiDialog>
<script type="text/javascript">
var bjsontools_fields = {
General: {
}
}
};
+
+var set_action_command_output = function(action, result) {
+ var result_el = document.querySelector('#actions_test_result_' + action + ' .action_result');
+ if (result.error === 0) {
+ var success = document.querySelector('#actions_test_result_' + action + ' .action_success');
+ success.style.display = '';
+ result_el.textContent = '';
+ } else {
+ var error = document.querySelector('#actions_test_result_' + action + ' .action_error');
+ error.style.display = '';
+ result_el.innerHTML = '<br />' + result.output.join('<br />');
+ }
+};
+
+var actions_hide_test_results = function(action) {
+ var loader = document.querySelector('#actions_test_result_' + action + ' .action_test_loader');
+ var success = document.querySelector('#actions_test_result_' + action + ' .action_success');
+ var error = document.querySelector('#actions_test_result_' + action + ' .action_error');
+ var result = document.querySelector('#actions_test_result_' + action + ' .action_result');
+ loader.style.display = 'none';
+ success.style.display = 'none'
+ error.style.display = 'none';
+ result.textContent = '';
+};
+
+function get_sudo_config() {
+ var fields = [
+ '<%=$this->DirStartAction->ClientID%>',
+ '<%=$this->DirStopAction->ClientID%>',
+ '<%=$this->DirRestartAction->ClientID%>',
+ '<%=$this->SdStartAction->ClientID%>',
+ '<%=$this->SdStopAction->ClientID%>',
+ '<%=$this->SdRestartAction->ClientID%>',
+ '<%=$this->FdStartAction->ClientID%>',
+ '<%=$this->FdStopAction->ClientID%>',
+ '<%=$this->FdRestartAction->ClientID%>'
+ ];
+ var val, pre;
+ var cfg = '';
+ var users = ['apache', 'lighttpd', 'www-data'];
+ for (var i = 0; i < users.length; i++) {
+ var pre = document.getElementById('sudo_config_' + users[i].replace(/-/g, '_'));
+ pre.textContent = 'Defaults:' + users[i] + ' !requiretty' + "\n";
+ for (var j = 0; j < fields.length; j++) {
+ val = document.getElementById(fields[j]).value.trim();
+ if (val) {
+ pre.textContent += users[i] + ' ALL = (root) NOPASSWD: ' + val + "\n";
+ }
+ }
+ }
+ $('#<%=$this->SudoConfigPopup->ClientID%>').dialog('open');
+}
</script>
</com:TContent>
const DEFAULT_FD_CONF = '/etc/bacula/bacula-fd.conf';
const DEFAULT_BBCONJSON_BIN = '/usr/sbin/bbconsjson';
+ const DEFAULT_ACTION_DIR_START = '/usr/bin/systemctl start bacula-dir';
+ const DEFAULT_ACTION_DIR_STOP = '/usr/bin/systemctl stop bacula-dir';
+ const DEFAULT_ACTION_DIR_RESTART = '/usr/bin/systemctl restart bacula-dir';
+ const DEFAULT_ACTION_SD_START = '/usr/bin/systemctl start bacula-sd';
+ const DEFAULT_ACTION_SD_STOP = '/usr/bin/systemctl stop bacula-sd';
+ const DEFAULT_ACTION_SD_RESTART = '/usr/bin/systemctl restart bacula-sd';
+ const DEFAULT_ACTION_FD_START = '/usr/bin/systemctl start bacula-fd';
+ const DEFAULT_ACTION_FD_STOP = '/usr/bin/systemctl stop bacula-fd';
+ const DEFAULT_ACTION_FD_RESTART = '/usr/bin/systemctl restart bacula-fd';
+
public function onPreInit($param) {
parent::onPreInit($param);
if (isset($_SESSION['language'])) {
$this->FdCfgPath->Text = self::DEFAULT_FD_CONF;
$this->BBconsJSONPath->Text = self::DEFAULT_BBCONJSON_BIN;
$this->BconsCfgPath->Text = self::DEFAULT_BCONSOLE_CONF;
+
+ $this->DirStartAction->Text = self::DEFAULT_ACTION_DIR_START;
+ $this->DirStopAction->Text = self::DEFAULT_ACTION_DIR_STOP;
+ $this->DirRestartAction->Text = self::DEFAULT_ACTION_DIR_RESTART;
+ $this->SdStartAction->Text = self::DEFAULT_ACTION_SD_START;
+ $this->SdStopAction->Text = self::DEFAULT_ACTION_SD_STOP;
+ $this->SdRestartAction->Text = self::DEFAULT_ACTION_SD_RESTART;
+ $this->FdStartAction->Text = self::DEFAULT_ACTION_FD_START;
+ $this->FdStopAction->Text = self::DEFAULT_ACTION_FD_STOP;
+ $this->FdRestartAction->Text = self::DEFAULT_ACTION_FD_RESTART;
+
$this->DatabaseNo->Checked = true;
$this->ConsoleNo->Checked = true;
$this->ConfigNo->Checked = true;
+ $this->ActionsNo->Checked = true;
} else {
// Database param settings
if ($this->config['db']['enabled'] == 1) {
$this->BconsoleConfigPath->Text = $this->config['bconsole']['cfg_path'];
$this->UseSudo->Checked = $this->getPage()->config['bconsole']['use_sudo'] == 1;
+ $api_config = $this->getModule('api_config');
+
// JSONTools param settings
- if ($this->config['jsontools']['enabled'] == 1) {
+ if ($api_config->isJSONToolsEnabled() === true) {
$this->ConfigYes->Checked = true;
$this->ConfigNo->Checked = false;
} else {
$this->BBconsJSONPath->Text = $this->config['jsontools']['bbconsjson_path'];
$this->BconsCfgPath->Text = $this->config['jsontools']['bcons_cfg_path'];
+ if ($api_config->isActionsConfigured()) {
+ // Action params
+ if ($api_config->isActionsEnabled() === true) {
+ $this->ActionsYes->Checked = true;
+ $this->ActionsNo->Checked = false;
+ } else {
+ $this->ActionsYes->Checked = false;
+ $this->ActionsNo->Checked = true;
+ }
+
+ $this->ActionsUseSudo->Checked = ($this->config['actions']['use_sudo'] == 1);
+ $this->DirStartAction->Text = $this->config['actions']['dir_start'];
+ $this->DirStopAction->Text = $this->config['actions']['dir_stop'];
+ $this->DirRestartAction->Text = $this->config['actions']['dir_restart'];
+ $this->SdStartAction->Text = $this->config['actions']['sd_start'];
+ $this->SdStopAction->Text = $this->config['actions']['sd_stop'];
+ $this->SdRestartAction->Text = $this->config['actions']['sd_restart'];
+ $this->FdStartAction->Text = $this->config['actions']['fd_start'];
+ $this->FdStopAction->Text = $this->config['actions']['fd_stop'];
+ $this->FdRestartAction->Text = $this->config['actions']['fd_restart'];
+ } else {
+ $this->ActionsYes->Checked = false;
+ $this->ActionsNo->Checked = true;
+ $this->ActionsUseSudo->Checked = false;
+ $this->DirStartAction->Text = self::DEFAULT_ACTION_DIR_START;
+ $this->DirStopAction->Text = self::DEFAULT_ACTION_DIR_STOP;
+ $this->DirRestartAction->Text = self::DEFAULT_ACTION_DIR_RESTART;
+ $this->SdStartAction->Text = self::DEFAULT_ACTION_SD_START;
+ $this->SdStopAction->Text = self::DEFAULT_ACTION_SD_STOP;
+ $this->SdRestartAction->Text = self::DEFAULT_ACTION_SD_RESTART;
+ $this->FdStartAction->Text = self::DEFAULT_ACTION_FD_START;
+ $this->FdStopAction->Text = self::DEFAULT_ACTION_FD_STOP;
+ $this->FdRestartAction->Text = self::DEFAULT_ACTION_FD_RESTART;
+ }
+
if ($this->config['api']['auth_type'] === 'basic') {
// API basic auth data
$this->AuthBasic->Checked = true;
'api' => array(),
'db' => array(),
'bconsole' => array(),
- 'jsontools' => array()
+ 'jsontools' => array(),
+ 'actions' => array()
);
if ($this->AuthBasic->Checked) {
$cfg_data['api']['auth_type'] = 'basic';
$cfg_data['jsontools']['fd_cfg_path'] = $this->FdCfgPath->Text;
$cfg_data['jsontools']['bbconsjson_path'] = $this->BBconsJSONPath->Text;
$cfg_data['jsontools']['bcons_cfg_path'] = $this->BconsCfgPath->Text;
+ $cfg_data['actions']['enabled'] = (integer)($this->ActionsYes->Checked === true);
+ $cfg_data['actions']['use_sudo'] = (integer)($this->ActionsUseSudo->Checked === true);
+ $cfg_data['actions']['dir_start'] = $this->DirStartAction->Text;
+ $cfg_data['actions']['dir_stop'] = $this->DirStopAction->Text;
+ $cfg_data['actions']['dir_restart'] = $this->DirRestartAction->Text;
+ $cfg_data['actions']['sd_start'] = $this->SdStartAction->Text;
+ $cfg_data['actions']['sd_stop'] = $this->SdStopAction->Text;
+ $cfg_data['actions']['sd_restart'] = $this->SdRestartAction->Text;
+ $cfg_data['actions']['fd_start'] = $this->FdStartAction->Text;
+ $cfg_data['actions']['fd_stop'] = $this->FdStopAction->Text;
+ $cfg_data['actions']['fd_restart'] = $this->FdRestartAction->Text;
$ret = $this->getModule('api_config')->setConfig($cfg_data);
if ($ret) {
}
$param->setIsValid($valid);
}
+
+ public function testExecActionCommand($sender, $param) {
+ $action = $param->CommandParameter;
+ $cmd = '';
+ switch ($action) {
+ case 'dir_start': $cmd = $this->DirStartAction->Text; break;
+ case 'dir_stop': $cmd = $this->DirStopAction->Text; break;
+ case 'dir_restart': $cmd = $this->DirRestartAction->Text; break;
+ case 'sd_start': $cmd = $this->SdStartAction->Text; break;
+ case 'sd_stop': $cmd = $this->SdStopAction->Text; break;
+ case 'sd_restart': $cmd = $this->SdRestartAction->Text; break;
+ case 'fd_start': $cmd = $this->FdStartAction->Text; break;
+ case 'fd_stop': $cmd = $this->FdStopAction->Text; break;
+ case 'fd_restart': $cmd = $this->FdRestartAction->Text; break;
+ };
+ $result = $this->getModule('comp_actions')->execCommand($cmd, $this->ActionsUseSudo->Checked);
+ $this->getCallbackClient()->callClientFunction('set_action_command_output', array($action, (array)$result));
+ }
}
?>
<module id="status_dir" class="Application.API.Class.StatusDirector" />
<module id="status_sd" class="Application.API.Class.StatusStorage" />
<module id="status_fd" class="Application.API.Class.StatusClient" />
+ <!-- component actions modules -->
+ <module id="comp_actions" class="Application.API.Class.ComponentActions" />
<!-- misc modules -->
<module id="ls" class="Application.API.Class.Ls" />
</modules>
<url ServiceParameter="API.Config" pattern="api/v1/config/{component_type}/{resource_type}/{resource_name}/" parameters.component_type="[a-z]+" parameters.resource_type="[a-zA-Z]+" parameters.resource_name="[a-zA-Z0-9:.\-_ ]+" />
<!-- component status endpoints -->
<url ServiceParameter="API.ComponentStatus" pattern="api/v1/status/{component}/" parameters.component="(director|storage|client)" />
+ <!-- actions endpoints -->
+ <url ServiceParameter="API.Actions" pattern="api/v1/actions/{component}/{action}/" parameters.component="(director|storage|client)" parameters.action="(start|stop|restart)" />
class AuthorizationError extends GenericError {
- const ERROR_AUTHORIZATION_TO_API_PROBLEM = 6;
+ const ERROR_AUTHENTICATION_TO_API_PROBLEM = 6;
const ERROR_ACCESS_ATTEMPT_TO_NOT_ALLOWED_RESOURCE = 7;
- const MSG_ERROR_AUTHORIZATION_TO_API_PROBLEM = 'Problem with authorization to Baculum API.';
+ const MSG_ERROR_AUTHENTICATION_TO_API_PROBLEM = 'Problem with authentication to Baculum API.';
const MSG_ERROR_ACCESS_ATTEMPT_TO_NOT_ALLOWED_RESOURCE = 'Access attempt to not allowed resource. Permission denied.';
}
const MSG_ERROR_CONNECTION_TO_HOST_PROBLEM = 'Problem with connection to remote host.';
}
+
+class ActionsError extends GenericError {
+
+ const ERROR_ACTIONS_ACTION_DOES_NOT_EXIST = 110;
+ const ERROR_ACTIONS_DISABLED = 111;
+ const ERROR_ACTIONS_WRONG_EXITCODE = 112;
+ const ERROR_ACTIONS_NOT_CONFIGURED = 113;
+
+
+ const MSG_ERROR_ACTIONS_ACTION_DOES_NOT_EXIST = 'Action does not exist.';
+ const MSG_ERROR_ACTIONS_DISABLED = 'Actions support is disabled.';
+ const MSG_ERROR_ACTIONS_WRONG_EXITCODE = 'Action command returned wrong exitcode.';
+ const MSG_ERROR_ACTIONS_NOT_CONFIGURED = 'Action is not configured.';
+}
?>
private $runningJobStates = array('C', 'R');
private $components = array(
- 'dir' => array('full_name' => 'Director', 'main_resource' => 'Director'),
- 'sd' => array('full_name' => 'Storage Daemon', 'main_resource' => 'Storage'),
- 'fd' => array('full_name' => 'File Daemon', 'main_resource' => 'FileDaemon'),
- 'bcons' => array('full_name' => 'Console', 'main_resource' => 'Director')
+ 'dir' => array(
+ 'full_name' => 'Director',
+ 'url_name' => 'director',
+ 'main_resource' => 'Director'
+ ),
+ 'sd' => array(
+ 'full_name' => 'Storage Daemon',
+ 'url_name' => 'storage',
+ 'main_resource' => 'Storage'
+ ),
+ 'fd' => array(
+ 'full_name' => 'File Daemon',
+ 'url_name' => 'client',
+ 'main_resource' => 'FileDaemon'
+ ),
+ 'bcons' => array(
+ 'full_name' => 'Console',
+ 'url_name' => 'console',
+ 'main_resource' => 'Director'
+ )
);
private $replace_opts = array(
return $name;
}
+ public function getComponentUrlName($type) {
+ $name = '';
+ if (key_exists($type, $this->components)) {
+ $name = $this->components[$type]['url_name'];
+ }
+ return $name;
+ }
+
public function getJobStatesByType($type) {
$statesByType = array();
$states = array();
width: 590px;
float: left;
}
-
+.actions_lines {
+ width: 743px;
+}
.config_lines div.field {
width: 280px !important;
}
-#config_fields {
+.actions_lines div.field {
+ width: 332px !important;
+}
+
+#config_fields, #actions_fields {
width: 732px;
margin: 0 auto;
padding-top: 7px;
}
+#actions_fields {
+ width: 810px;
+}
+
+#actions_fields .button {
+ display: inline-block;
+ width: 50px;
+}
+
+#actions_fields .button input[type="submit"] {
+ min-width: 60px;
+}
+
+#actions_fields .action_test_loader, #actions_fields .action_success, #actions_fields .action_error {
+ margin-left: 11px;
+}
+
#config_fields div.button {
padding-left: 247px;
}
width: 667px;
}
-fieldset.config_field .line {
+fieldset.actions_field {
+ width: 745px;
+}
+
+fieldset.config_field .line, fieldset.actions_field .line {
height: auto;
min-height: 35px !important;
padding-top: 2px;