3 * Bacula(R) - The Network Backup Solution
4 * Baculum - Bacula web interface
6 * Copyright (C) 2013-2015 Marcin Haba
8 * The main author of Baculum is Marcin Haba.
9 * The original author of Bacula is Kern Sibbald, with contributions
10 * from many others, a complete list can be found in the file AUTHORS.
12 * You may use this file and others of this release according to the
13 * license defined in the LICENSE file, which includes the Affero General
14 * Public License, v3.0 ("AGPLv3") and some additional permissions and
15 * terms pursuant to its AGPLv3 Section 7.
17 * This notice must be preserved when any source code is
18 * conveyed and/or propagated.
20 * Bacula(R) is a registered trademark of Kern Sibbald.
23 Prado::using('Application.Class.ConfigurationManager');
24 Prado::using('Application.Class.Logging');
25 Prado::using('Application.Class.Errors');
27 class Bconsole extends TModule {
31 const BCONSOLE_COMMAND_PATTERN = "%s%s -c %s %s <<END_OF_DATA\n%s\nquit\nEND_OF_DATA";
33 const BCONSOLE_DIRECTORS_PATTERN = "%s%s -c %s -l";
35 const BCONSOLE_CFG_USER_KEYWORD = '{user}';
37 private $availableCommands = array('version', 'status', 'list', 'messages', 'show', 'mount', 'umount', 'release', 'prune', 'purge', 'update', 'estimate', 'run', '.bvfs_update', '.bvfs_lsdirs', '.bvfs_lsfiles', '.bvfs_versions', '.bvfs_get_jobids', '.bvfs_restore', '.bvfs_clear_cache', 'restore', 'cancel', 'delete', '.jobs', 'label', 'reload', '.fileset', '.storage', '.client', '.pool');
39 private $useSudo = false;
41 private $bconsoleCmdPath;
43 private $bconsoleCfgPath;
45 private $bconsoleCfgCustomPath;
47 public function init($config) {
48 if($this->Application->getModule('configuration')->isApplicationConfig() === true) {
49 $params = ConfigurationManager::getApplicationConfig();
50 $useSudo = ((integer)$params['bconsole']['use_sudo'] === 1);
51 $bconsoleCmdPath = $params['bconsole']['bin_path'];
52 $bconsoleCfgPath = $params['bconsole']['cfg_path'];
53 $bconsoleCfgCustomPath = array_key_exists('cfg_custom_path', $params['bconsole']) ? $params['bconsole']['cfg_custom_path'] : null;
54 $this->setEnvironmentParams($bconsoleCmdPath, $bconsoleCfgPath, $bconsoleCfgCustomPath, $useSudo);
58 private function setEnvironmentParams($bconsoleCmdPath, $bconsoleCfgPath, $bconsoleCfgCustomPath, $useSudo) {
59 $this->bconsoleCmdPath = $bconsoleCmdPath;
60 $this->bconsoleCfgPath = $bconsoleCfgPath;
61 $this->bconsoleCfgCustomPath = $bconsoleCfgCustomPath;
62 $this->useSudo = $useSudo;
65 private function isCommandValid($command) {
66 $command = trim($command);
67 return in_array($command, $this->availableCommands);
70 private function prepareResult(array $output, $exitcode, $bconsoleCommand) {
71 array_pop($output); // deleted 'quit' bconsole command
72 for($i = 0; $i < count($output); $i++) {
73 if(strstr($output[$i], $bconsoleCommand) == false) {
79 $output = count($output) > 1 ? array_values($output) : array_shift($output);
80 return (object)array('output' => $output, 'exitcode' => (integer)$exitcode);
83 public function bconsoleCommand($director, array $command, $user = null) {
84 $baseCommand = count($command) > 0 ? $command[0] : null;
85 if($this->isCommandValid($baseCommand) === true) {
86 $result = $this->execCommand($director, $command, $user);
88 $result = $this->prepareResult(array(BconsoleError::MSG_ERROR_INVALID_COMMAND, ''), BconsoleError::ERROR_INVALID_COMMAND, ' ');
93 private function execCommand($director, array $command, $user) {
95 if(!is_null($director) && $this->isValidDirector($director) === false) {
96 $output = array(BconsoleError::MSG_ERROR_INVALID_DIRECTOR, '');
97 $exitcode = BconsoleError::ERROR_INVALID_DIRECTOR;
98 $result = $this->prepareResult($output, $exitcode, ' ');
100 $dir = is_null($director) ? '': '-D ' . $director;
101 $sudo = ($this->useSudo === true) ? self::SUDO . ' ' : '';
102 $bconsoleCommand = implode(' ', $command);
103 if(!is_null($this->bconsoleCfgCustomPath) && !is_null($user)) {
104 $this->bconsoleCfgPath = str_replace(self::BCONSOLE_CFG_USER_KEYWORD, $user, $this->bconsoleCfgCustomPath);
106 $cmd = sprintf(self::BCONSOLE_COMMAND_PATTERN, $sudo, $this->bconsoleCmdPath, $this->bconsoleCfgPath, $dir, $bconsoleCommand);
107 exec($cmd, $output, $exitcode);
109 $output = array(BconsoleError::MSG_ERROR_BCONSOLE_CONNECTION_PROBLEM, '');
110 $exitcode = BconsoleError::ERROR_BCONSOLE_CONNECTION_PROBLEM;
111 $result = $this->prepareResult($output, $exitcode, ' ');
113 $result = $this->prepareResult($output, $exitcode, $bconsoleCommand);
116 $this->Application->getModule('logging')->log($cmd, $result, Logging::CATEGORY_EXECUTE, __FILE__, __LINE__);
121 public function getDirectors() {
122 $sudo = ($this->useSudo === true) ? self::SUDO . ' ' : '';
123 $cmd = sprintf(self::BCONSOLE_DIRECTORS_PATTERN, $sudo, $this->bconsoleCmdPath, $this->bconsoleCfgPath);
124 exec($cmd, $output, $exitcode);
126 $output = array(BconsoleError::MSG_ERROR_BCONSOLE_CONNECTION_PROBLEM, '');
127 $exitcode = BconsoleError::ERROR_BCONSOLE_CONNECTION_PROBLEM;
129 $result = (object)array('output' => $output, 'exitcode' => $exitcode);
133 private function isValidDirector($director) {
134 $ret = in_array($director, $this->getDirectors()->output);
138 public function testBconsoleCommand(array $command, $bconsoleCmdPath, $bconsoleCfgPath, $useSudo) {
139 $this->setEnvironmentParams($bconsoleCmdPath, $bconsoleCfgPath, null, $useSudo);
140 $director = array_shift($this->getDirectors()->output);
141 $result = $this->bconsoleCommand($director, $command);