From: Marcin Haba Date: Sun, 22 Nov 2020 07:53:11 +0000 (+0100) Subject: baculum: Add json output option to show storages and show single storage endpoints X-Git-Tag: Release-9.6.7~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38fd271f9365a97d323523dedc526db97d68dfd6;p=thirdparty%2Fbacula.git baculum: Add json output option to show storages and show single storage endpoints --- diff --git a/gui/baculum/protected/API/Class/StatusStorage.php b/gui/baculum/protected/API/Class/StatusStorage.php index 085ef09e7..4a74b1e1c 100644 --- a/gui/baculum/protected/API/Class/StatusStorage.php +++ b/gui/baculum/protected/API/Class/StatusStorage.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2019 Kern Sibbald + * Copyright (C) 2013-2020 Kern Sibbald * * The main author of Baculum is Marcin Haba. * The original author of Bacula is Kern Sibbald, with contributions @@ -71,26 +71,62 @@ class StatusStorage extends ComponentStatusModule { * @return array array with parsed storage status values */ public function parseStatus(array $output, $type) { - $result = array(); + $result = []; $line = null; - $opts = array(); + $part = []; + $autochanger = null; + $autochangers = []; + $ach_dev = []; + $empty_lines = 0; for($i = 0; $i < count($output); $i++) { if (empty($output[$i])) { - if (count($opts) > 10) { - $result[] = $opts; + $empty_lines++; + if (count($part) > 10) { + $result[] = $part; + $part = []; } - if (count($opts) > 0) { - $opts = array(); + if (count($ach_dev) == 2) { + $autochangers[$autochanger]['devices'][] = $ach_dev; + $ach_dev = []; + } + if ($empty_lines == 4 && $autochanger) { + $autochanger = null; } } else { + $empty_lines = 0; $line = $this->parseLine($output[$i]); - if (is_array($line)) { - $opts[$line['key']] = $line['value']; + if (!is_array($line)) { + continue; + } + + if ($line['key'] == 'autochanger') { + $autochanger = $line['value']; + $autochangers[$autochanger] = ['devices' => []]; + } elseif ($autochanger) { + $ach_dev[$line['key']] = $line['value']; + } else { + $part[$line['key']] = $line['value']; } } } if ($type === self::OUTPUT_TYPE_HEADER) { $result = array_pop($result); + } elseif ($type === self::OUTPUT_TYPE_DEVICES) { + for ($i = 0; $i < count($result); $i++) { + $found = false; + foreach ($autochangers as $ach => $devs) { + for ($j = 0; $j < count($devs['devices']); $j++) { + if ($result[$i]['name'] === $devs['devices'][$j]['name']) { + $result[$i]['autochanger'] = $ach; + $found = true; + break 2; + } + } + } + if (!$found) { + $result[$i]['autochanger'] = null; + } + } } return $result; } diff --git a/gui/baculum/protected/API/Pages/API/StorageShow.php b/gui/baculum/protected/API/Pages/API/StorageShow.php index 918b8269a..4bfc4caf8 100644 --- a/gui/baculum/protected/API/Pages/API/StorageShow.php +++ b/gui/baculum/protected/API/Pages/API/StorageShow.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2019 Kern Sibbald + * Copyright (C) 2013-2020 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.ConsoleOutputPage'); + /** * Show storage command endpoint. * @@ -27,23 +29,27 @@ * @category API * @package Baculum API */ -class StorageShow extends BaculumAPIServer { +class StorageShow extends ConsoleOutputPage { public function get() { $storageid = $this->Request->contains('id') ? intval($this->Request['id']) : 0; + $out_format = $this->Request->contains('output') && $this->isOutputFormatValid($this->Request['output']) ? $this->Request['output'] : parent::OUTPUT_FORMAT_RAW; $result = $this->getModule('bconsole')->bconsoleCommand( $this->director, - array('.storage') + array('.storage'), + null, + true ); if ($result->exitcode === 0) { - array_shift($result->output); $storage = $this->getModule('storage')->getStorageById($storageid); if (is_object($storage) && in_array($storage->name, $result->output)) { - $result = $this->getModule('bconsole')->bconsoleCommand( - $this->director, - array('show', 'storage="' . $storage->name . '"') - ); - $this->output = $result->output; - $this->error = $result->exitcode; + $out = (object)['output' => [], 'exitcode' => 0]; + if ($out_format === parent::OUTPUT_FORMAT_RAW) { + $out = $this->getRawOutput(['storage' => $storage->name]); + } elseif($out_format === parent::OUTPUT_FORMAT_JSON) { + $out = $this->getJSONOutput(['storage' => $storage->name]); + } + $this->output = $out->output; + $this->error = $out->exitcode; } else { $this->output = StorageError::MSG_ERROR_STORAGE_DOES_NOT_EXISTS; $this->error = StorageError::ERROR_STORAGE_DOES_NOT_EXISTS; @@ -53,6 +59,52 @@ class StorageShow extends BaculumAPIServer { $this->error = $result->exitcode; } } + + /** + * Get show storage output from console in raw format. + * + * @param array $params command parameters + * @return StdClass object with output and exitcode + */ + protected function getRawOutput($params = []) { + $result = $this->getModule('bconsole')->bconsoleCommand( + $this->director, + array('show', 'storage="' . $params['storage'] . '"'), + null, + true + ); + return $result; + } + + /** + * Get show storage output in JSON format. + * + * @param array $params command parameters + * @return StdClass object with output and exitcode + */ + protected function getJSONOutput($params = []) { + $result = (object)['output' => [], 'exitcode' => 0]; + $output = $this->getRawOutput($params); + if ($output->exitcode === 0) { + for ($i = 0; $i < count($output->output); $i++) { + if (preg_match_all('/(?<=\s)\w+=.+?(?=\s+\w+=.+|$)/i', $output->output[$i], $matches) > 0) { + for ($j = 0; $j < count($matches[0]); $j++) { + list($key, $value) = explode('=', $matches[0][$j], 2); + if (key_exists($key, $result->output)) { + /* + * The most important options are in first lines. + * If keys are double skip the second ones + */ + continue; + } + $result->output[strtolower($key)] = $value; + } + } + } + } + $result->exitcode = $output->exitcode; + return $result; + } } ?> diff --git a/gui/baculum/protected/API/Pages/API/StoragesShow.php b/gui/baculum/protected/API/Pages/API/StoragesShow.php index 32bd3dd24..be449c645 100644 --- a/gui/baculum/protected/API/Pages/API/StoragesShow.php +++ b/gui/baculum/protected/API/Pages/API/StoragesShow.php @@ -3,7 +3,7 @@ * Bacula(R) - The Network Backup Solution * Baculum - Bacula web interface * - * Copyright (C) 2013-2019 Kern Sibbald + * Copyright (C) 2013-2020 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.ConsoleOutputPage'); + /** * Show storages command endpoint. * @@ -27,16 +29,18 @@ * @category API * @package Baculum API */ -class StoragesShow extends BaculumAPIServer { +class StoragesShow extends ConsoleOutputPage { public function get() { + $out_format = $this->Request->contains('output') && $this->isOutputFormatValid($this->Request['output']) ? $this->Request['output'] : parent::OUTPUT_FORMAT_RAW; $result = $this->getModule('bconsole')->bconsoleCommand( $this->director, - array('.storage') + array('.storage'), + null, + true ); $storage = null; if ($result->exitcode === 0) { - array_shift($result->output); if ($this->Request->contains('name')) { if (in_array($this->Request['name'], $result->output)) { $storage = $this->Request['name']; @@ -51,18 +55,76 @@ class StoragesShow extends BaculumAPIServer { $this->error = $result->exitcode; return; } + + $out = (object)['output' => [], 'exitcode' => 0]; + if ($out_format === parent::OUTPUT_FORMAT_RAW) { + $out = $this->getRawOutput(['storage' => $storage]); + } elseif($out_format === parent::OUTPUT_FORMAT_JSON) { + $out = $this->getJSONOutput(['storage' => $storage]); + } + + $this->output = $out->output; + $this->error = $out->exitcode; + } + + /** + * Get show storage output from console in raw format. + * + * @param array $params command parameters + * @return StdClass object with output and exitcode + */ + protected function getRawOutput($params = []) { $cmd = array('show'); - if (is_string($storage)) { - $cmd[] = 'storage="' . $storage . '"'; + if (is_string($params['storage'])) { + $cmd[] = 'storage="' . $params['storage'] . '"'; } else { $cmd[] = 'storages'; } $result = $this->getModule('bconsole')->bconsoleCommand( $this->director, - $cmd + $cmd, + true ); - $this->output = $result->output; - $this->error = $result->exitcode; + return $result; + } + + /** + * Get show storage output in JSON format. + * + * @param array $params command parameters + * @return StdClass object with output and exitcode + */ + protected function getJSONOutput($params = []) { + $result = (object)['output' => [], 'exitcode' => 0]; + $output = $this->getRawOutput($params); + if ($output->exitcode === 0) { + $part = []; + for ($i = 0; $i < count($output->output); $i++) { + if (preg_match_all('/(?<=\s)\w+=.+?(?=\s+\w+=.+|$)/i', $output->output[$i], $matches) > 0) { + for ($j = 0; $j < count($matches[0]); $j++) { + list($key, $value) = explode('=', $matches[0][$j], 2); + if (key_exists($key, $result->output)) { + /* + * The most important options are in first lines. + * If keys are double skip the second ones + */ + continue; + } + if ($key == 'name' && count($part) > 0) { + $result->output[] = $part; + $part = []; + } + $part[strtolower($key)] = $value; + } + } + } + if (count($part) > 0) { + $result->output[] = $part; + $part = []; + } + } + $result->exitcode = $output->exitcode; + return $result; } } ?> diff --git a/gui/baculum/protected/API/openapi_baculum.json b/gui/baculum/protected/API/openapi_baculum.json index 452273382..9d7046586 100644 --- a/gui/baculum/protected/API/openapi_baculum.json +++ b/gui/baculum/protected/API/openapi_baculum.json @@ -1981,9 +1981,14 @@ } } }, - "parameters": [{ - "$ref": "#/components/parameters/StorageId" - }] + "parameters": [ + { + "$ref": "#/components/parameters/StorageId" + }, + { + "$ref": "#/components/parameters/Output" + } + ] } }, "/api/v1/storages/{storageid}/status": { @@ -2198,6 +2203,9 @@ "type": "string", "pattern": "[a-zA-Z0-9:.-_ ]+" } + }, + { + "$ref": "#/components/parameters/Output" } ] }