From: Marcin Haba Date: Thu, 9 May 2019 14:40:06 +0000 (+0200) Subject: baculum: Add API endpoints to label volume with and without barcodes X-Git-Tag: Release-9.6.0~237 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6e2ca83ae24634d3ce36052ce4a49eac7002101c;p=thirdparty%2Fbacula.git baculum: Add API endpoints to label volume with and without barcodes --- diff --git a/gui/baculum/protected/API/Class/Bconsole.php b/gui/baculum/protected/API/Class/Bconsole.php index f1c801384a..be1e04cf8d 100644 --- a/gui/baculum/protected/API/Class/Bconsole.php +++ b/gui/baculum/protected/API/Class/Bconsole.php @@ -28,8 +28,17 @@ class Bconsole extends APIModule { const SUDO = 'sudo'; + /** + * Pattern types used to prepare command. + */ + const PTYPE_REG_CMD = 0; + const PTYPE_API_CMD = 1; + const PTYPE_CONFIRM_YES_CMD = 2; + const BCONSOLE_COMMAND_PATTERN = "%s%s -c %s %s 2>&1 < $output, 'exitcode' => (integer)$exitcode); } - public function bconsoleCommand($director, array $command, $api = false) { + public function bconsoleCommand($director, array $command, $ptype = null) { if (count($this->config) > 0 && $this->config['enabled'] !== '1') { throw new BConsoleException( BconsoleError::MSG_ERROR_BCONSOLE_DISABLED, @@ -158,7 +167,7 @@ class Bconsole extends APIModule { } $base_command = count($command) > 0 ? $command[0] : null; if($this->isCommandValid($base_command) === true) { - $result = $this->execCommand($director, $command, $api); + $result = $this->execCommand($director, $command, $ptype); } else { throw new BConsoleException( BconsoleError::MSG_ERROR_INVALID_COMMAND, @@ -168,7 +177,7 @@ class Bconsole extends APIModule { return $result; } - private function execCommand($director, array $command, $api = false) { + private function execCommand($director, array $command, $ptype = null) { $cmd = ''; $result = null; if(!is_null($director) && $this->isValidDirector($director) === false) { @@ -180,7 +189,12 @@ class Bconsole extends APIModule { $dir = is_null($director) ? '': '-D ' . $director; $sudo = ($this->getUseSudo() === true) ? self::SUDO . ' ' : ''; $bconsole_command = implode(' ', $command); - $pattern = ($api === true) ? self::BCONSOLE_API_COMMAND_PATTERN : self::BCONSOLE_COMMAND_PATTERN; + $pattern = null; + switch ($ptype) { + case self::PTYPE_API_CMD: $pattern = self::BCONSOLE_API_COMMAND_PATTERN; break; + case self::PTYPE_CONFIRM_YES_CMD: $pattern = self::BCONSOLE_CONFIRM_YES_COMMAND_PATTERN; break; + default: $pattern = self::BCONSOLE_COMMAND_PATTERN; + } $cmd = sprintf( $pattern, $sudo, diff --git a/gui/baculum/protected/API/Pages/API/ComponentStatus.php b/gui/baculum/protected/API/Pages/API/ComponentStatus.php index d813cb5e44..c809eaba7c 100644 --- a/gui/baculum/protected/API/Pages/API/ComponentStatus.php +++ b/gui/baculum/protected/API/Pages/API/ComponentStatus.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2018 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 @@ -20,6 +20,8 @@ * Bacula(R) is a registered trademark of Kern Sibbald. */ +Prado::using('Application.API.Class.Bconsole'); + /** * Component status module. */ @@ -36,7 +38,7 @@ class ComponentStatus extends BaculumAPIServer { $result = $this->getModule('bconsole')->bconsoleCommand( $this->director, array('status', 'director'), - true + Bconsole::PTYPE_API_CMD ); if ($result->exitcode === 0) { $output = $this->getModule('status_dir')->getStatus($result->output); @@ -62,7 +64,7 @@ class ComponentStatus extends BaculumAPIServer { $result = $this->getModule('bconsole')->bconsoleCommand( $this->director, array('.status', $storage, $type), - true + Bconsole::PTYPE_API_CMD ); if ($result->exitcode === 0) { $this->output = $this->getModule('status_sd')->getStatus($result->output); diff --git a/gui/baculum/protected/API/Pages/API/ScheduleStatus.php b/gui/baculum/protected/API/Pages/API/ScheduleStatus.php index 4b8acf9525..b5e2283cf2 100644 --- a/gui/baculum/protected/API/Pages/API/ScheduleStatus.php +++ b/gui/baculum/protected/API/Pages/API/ScheduleStatus.php @@ -20,6 +20,8 @@ * Bacula(R) is a registered trademark of Kern Sibbald. */ +Prado::using('Application.API.Class.Bconsole'); + class ScheduleStatus extends BaculumAPIServer { public function get() { @@ -44,7 +46,7 @@ class ScheduleStatus extends BaculumAPIServer { $cmd[] = 'time="' . $this->Request['time'] . '"'; } - $result = $this->getModule('bconsole')->bconsoleCommand($this->director, $cmd, true); + $result = $this->getModule('bconsole')->bconsoleCommand($this->director, $cmd, Bconsole::PTYPE_API_CMD); if ($result->exitcode === 0) { array_shift($result->output); $this->output = $this->formatSchedules($result->output); diff --git a/gui/baculum/protected/API/Pages/API/VolumeLabel.php b/gui/baculum/protected/API/Pages/API/VolumeLabel.php new file mode 100644 index 0000000000..7c991ea828 --- /dev/null +++ b/gui/baculum/protected/API/Pages/API/VolumeLabel.php @@ -0,0 +1,136 @@ +volume : 0; + $slot = property_exists($params, 'slot') ? $params->slot : 0; + $drive = property_exists($params, 'drive') ? intval($params->drive) : 0; + $poolid = property_exists($params, 'poolid') ? intval($params->poolid) : 0; + $misc = $this->getModule('misc'); + + if (!$misc->isValidName($volume)) { + $this->output = VolumeError::ERROR_INVALID_VOLUME; + $this->error = VolumeError::MSG_ERROR_INVALID_VOLUME; + return; + } + + if (!$misc->isValidInteger($slot)) { + $this->output = VolumeError::ERROR_INVALID_SLOT; + $this->error = VolumeError::MSG_ERROR_INVALID_SLOT; + return; + } + + $storage = null; + if (property_exists($params, 'storageid')) { + $storageid = intval($params->storageid); + $result = $this->getModule('storage')->getStorageById($storageid); + if (is_object($result)) { + $storage = $result->name; + } + } elseif (property_exists($params, 'storage') && $misc->isValidName($params->storage)) { + $storage = $params->storage; + } + + $pool = null; + if (property_exists($params, 'poolid')) { + $poolid = intval($params->poolid); + $result = $this->getModule('pool')->getPoolById($poolid); + if (is_object($result)) { + $pool = $result->name; + } + } elseif (property_exists($params, 'pool') && $misc->isValidName($params->pool)) { + $pool = $params->pool; + } + + if (!is_null($storage)) { + $result = $this->getModule('bconsole')->bconsoleCommand( + $this->director, + array('.storage') + ); + if ($result->exitcode === 0) { + array_shift($result->output); + if (!in_array($storage, $result->output)) { + $this->output = StorageError::MSG_ERROR_STORAGE_DOES_NOT_EXISTS; + $this->error = StorageError::ERROR_STORAGE_DOES_NOT_EXISTS; + return; + } + } else { + $this->output = $result->output; + $this->error = $result->exitcode; + return; + } + } else { + $this->output = StorageError::MSG_ERROR_STORAGE_DOES_NOT_EXISTS; + $this->error = StorageError::ERROR_STORAGE_DOES_NOT_EXISTS; + return; + } + + if (!is_null($pool)) { + $result = $this->getModule('bconsole')->bconsoleCommand( + $this->director, + array('.pool') + ); + if ($result->exitcode === 0) { + array_shift($result->output); + if (!in_array($pool, $result->output)) { + $this->output = PoolError::MSG_ERROR_POOL_DOES_NOT_EXISTS; + $this->error = PoolError::ERROR_POOL_DOES_NOT_EXISTS; + return; + } + } else { + $this->output = $result->output; + $this->error = $result->exitcode; + return; + } + } else { + $this->output = PoolError::MSG_ERROR_POOL_DOES_NOT_EXISTS; + $this->error = PoolError::ERROR_POOL_DOES_NOT_EXISTS; + return; + } + + $cmd = array( + 'label', + 'volume="' . $volume . '"', + 'storage="' . $storage . '"', + 'drive="' . $drive . '"', + 'slot="' . $slot . '"', + 'pool="' . $pool . '"' + ); + $result = $this->getModule('bconsole')->bconsoleCommand( + $this->director, + $cmd + ); + if ($result->exitcode === 0) { + $this->output = $result->output; + $this->error = VolumeError::ERROR_NO_ERRORS; + } else { + $this->output = $result->output; + $this->error = $result->exitcode; + } + } +} + +?> diff --git a/gui/baculum/protected/API/Pages/API/VolumeLabelBarcodes.php b/gui/baculum/protected/API/Pages/API/VolumeLabelBarcodes.php new file mode 100644 index 0000000000..f7124f590c --- /dev/null +++ b/gui/baculum/protected/API/Pages/API/VolumeLabelBarcodes.php @@ -0,0 +1,124 @@ +slots : 0; + $drive = property_exists($params, 'drive') ? intval($params->drive) : 0; + $poolid = property_exists($params, 'poolid') ? intval($params->poolid) : 0; + $misc = $this->getModule('misc'); + + $storage = null; + if (property_exists($params, 'storageid')) { + $storageid = intval($params->storageid); + $result = $this->getModule('storage')->getStorageById($storageid); + if (is_object($result)) { + $storage = $result->name; + } + } elseif (property_exists($params, 'storage') && $misc->isValidName($params->storage)) { + $storage = $params->storage; + } + + $pool = null; + if (property_exists($params, 'poolid')) { + $poolid = intval($params->poolid); + $result = $this->getModule('pool')->getPoolById($poolid); + if (is_object($result)) { + $pool = $result->name; + } + } elseif (property_exists($params, 'pool') && $misc->isValidName($params->pool)) { + $pool = $params->pool; + } + + if (!is_null($storage)) { + $result = $this->getModule('bconsole')->bconsoleCommand( + $this->director, + array('.storage') + ); + if ($result->exitcode === 0) { + array_shift($result->output); + if (!in_array($storage, $result->output)) { + $this->output = StorageError::MSG_ERROR_STORAGE_DOES_NOT_EXISTS; + $this->error = StorageError::ERROR_STORAGE_DOES_NOT_EXISTS; + return; + } + } else { + $this->output = $result->output; + $this->error = $result->exitcode; + return; + } + } else { + $this->output = StorageError::MSG_ERROR_STORAGE_DOES_NOT_EXISTS; + $this->error = StorageError::ERROR_STORAGE_DOES_NOT_EXISTS; + return; + } + + if (!is_null($pool)) { + $result = $this->getModule('bconsole')->bconsoleCommand( + $this->director, + array('.pool') + ); + if ($result->exitcode === 0) { + array_shift($result->output); + if (!in_array($pool, $result->output)) { + $this->output = PoolError::MSG_ERROR_POOL_DOES_NOT_EXISTS; + $this->error = PoolError::ERROR_POOL_DOES_NOT_EXISTS; + return; + } + } else { + $this->output = $result->output; + $this->error = $result->exitcode; + return; + } + } else { + $this->output = PoolError::MSG_ERROR_POOL_DOES_NOT_EXISTS; + $this->error = PoolError::ERROR_POOL_DOES_NOT_EXISTS; + return; + } + + $cmd = array ( + 'label', + 'barcodes', + 'slots="' . $slots . '"', + 'storage="' . $storage . '"', + 'drive="' . $drive . '"', + 'pool="' . $pool . '"' + ); + $result = $this->getModule('bconsole')->bconsoleCommand( + $this->director, + $cmd, + Bconsole::PTYPE_CONFIRM_YES_CMD + ); + if ($result->exitcode === 0) { + $this->output = $result->output; + $this->error = VolumeError::ERROR_NO_ERRORS; + } else { + $this->output = $result->output; + $this->error = $result->exitcode; + } + } +} + +?> diff --git a/gui/baculum/protected/API/endpoints.xml b/gui/baculum/protected/API/endpoints.xml index 4dbb0d8b3f..31ea654edf 100644 --- a/gui/baculum/protected/API/endpoints.xml +++ b/gui/baculum/protected/API/endpoints.xml @@ -42,6 +42,8 @@ + + diff --git a/gui/baculum/protected/Common/Class/Errors.php b/gui/baculum/protected/Common/Class/Errors.php index dfaf702d84..87c3c32f8b 100644 --- a/gui/baculum/protected/Common/Class/Errors.php +++ b/gui/baculum/protected/Common/Class/Errors.php @@ -74,8 +74,12 @@ class StorageError extends GenericError { class VolumeError extends GenericError { const ERROR_VOLUME_DOES_NOT_EXISTS = 30; + const ERROR_INVALID_VOLUME = 31; + const ERROR_INVALID_SLOT = 32; const MSG_ERROR_VOLUME_DOES_NOT_EXISTS = 'Volume does not exist.'; + const MSG_ERROR_INVALID_VOLUME = 'Invalid volume.'; + const MSG_ERROR_INVALID_SLOT = 'Invalid slot.'; } class PoolError extends GenericError { diff --git a/gui/baculum/protected/Common/Class/Miscellaneous.php b/gui/baculum/protected/Common/Class/Miscellaneous.php index 8a9ded6329..ad3d65cbce 100644 --- a/gui/baculum/protected/Common/Class/Miscellaneous.php +++ b/gui/baculum/protected/Common/Class/Miscellaneous.php @@ -239,6 +239,11 @@ class Miscellaneous extends TModule { return (preg_match('/^\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2}$/', $time) === 1); } + public function isValidRange($range) { + return (preg_match('/^[\d\-\,]+$/', $range) === 1); + } + + /** * Writing INI-style configuration file. *