]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
baculum: Add warning to running job status if job needs media
authorMarcin Haba <marcin.haba@bacula.pl>
Sat, 23 Oct 2021 15:45:48 +0000 (17:45 +0200)
committerEric Bollengier <eric@baculasystems.com>
Thu, 24 Mar 2022 08:03:26 +0000 (09:03 +0100)
14 files changed:
gui/baculum/protected/Web/Lang/en/messages.mo
gui/baculum/protected/Web/Lang/en/messages.po
gui/baculum/protected/Web/Lang/ja/messages.mo
gui/baculum/protected/Web/Lang/ja/messages.po
gui/baculum/protected/Web/Lang/pl/messages.mo
gui/baculum/protected/Web/Lang/pl/messages.po
gui/baculum/protected/Web/Lang/pt/messages.mo
gui/baculum/protected/Web/Lang/pt/messages.po
gui/baculum/protected/Web/Lang/ru/messages.mo
gui/baculum/protected/Web/Lang/ru/messages.po
gui/baculum/protected/Web/Pages/JobHistoryView.page
gui/baculum/protected/Web/Pages/JobHistoryView.php
gui/baculum/protected/Web/Portlets/LabelVolume.php
gui/baculum/protected/Web/Portlets/LabelVolume.tpl

index b9b82fc4a8a8a5bb4f4fc064da24a0866869bb42..f887bf649e6490eba35b9b9b4737d3253805fe2e 100644 (file)
Binary files a/gui/baculum/protected/Web/Lang/en/messages.mo and b/gui/baculum/protected/Web/Lang/en/messages.mo differ
index 7f2dee29ec2f535a85705cbf772ebaa8086cb839..0d430492ef8e07317a9793246144a9ab45ef0d82 100644 (file)
@@ -3805,3 +3805,15 @@ msgstr "New migrate job"
 
 msgid "Please select the criteria that will be used for selecting backup jobs to migrate."
 msgstr "Please select the criteria that will be used for selecting backup jobs to migrate."
+
+msgid "The job needs media."
+msgstr "The job needs media."
+
+msgid "Please mount volume %volume or label a new one for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please mount volume %volume or label a new one for storage: %storage, pool: %pool, media type: %mediatype."
+
+msgid "Please mount volume %volume for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please mount volume %volume for storage: %storage, pool: %pool, media type: %mediatype."
+
+msgid "Please create a new volume for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please create a new volume for storage: %storage, pool: %pool, media type: %mediatype."
index 5193c2fff903678956b03d2de913e5493292a3b2..fe34e3ece0c2fb9ba6bc9434708c3358e8b47215 100644 (file)
Binary files a/gui/baculum/protected/Web/Lang/ja/messages.mo and b/gui/baculum/protected/Web/Lang/ja/messages.mo differ
index c4e51893547e2511beff799573cd1d0114bfc4ea..d5df331527cf99a9dedfb81e32a39af6adfaad0a 100644 (file)
@@ -3891,3 +3891,15 @@ msgstr "New migrate job"
 
 msgid "Please select the criteria that will be used for selecting backup jobs to migrate."
 msgstr "Please select the criteria that will be used for selecting backup jobs to migrate."
+
+msgid "The job needs media."
+msgstr "The job needs media."
+
+msgid "Please mount volume %volume or label a new one for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please mount volume %volume or label a new one for storage: %storage, pool: %pool, media type: %mediatype."
+
+msgid "Please mount volume %volume for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please mount volume %volume for storage: %storage, pool: %pool, media type: %mediatype."
+
+msgid "Please create a new volume for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please create a new volume for storage: %storage, pool: %pool, media type: %mediatype."
index 6f143272673837ce8aee0b6f6ccc4524f8a96ca3..525bd0c107f1604ca009c7c66a9c560d83a8e3ba 100644 (file)
Binary files a/gui/baculum/protected/Web/Lang/pl/messages.mo and b/gui/baculum/protected/Web/Lang/pl/messages.mo differ
index 769f6117808ca820f5b71618d200323e06782f10..9aac429764c95185c95559282e7fa714ffaa6b7e 100644 (file)
@@ -3816,3 +3816,15 @@ msgstr "New migrate job"
 
 msgid "Please select the criteria that will be used for selecting backup jobs to migrate."
 msgstr "Please select the criteria that will be used for selecting backup jobs to migrate."
+
+msgid "The job needs media."
+msgstr "The job needs media."
+
+msgid "Please mount volume %volume or label a new one for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please mount volume %volume or label a new one for storage: %storage, pool: %pool, media type: %mediatype."
+
+msgid "Please mount volume %volume for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please mount volume %volume for storage: %storage, pool: %pool, media type: %mediatype."
+
+msgid "Please create a new volume for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please create a new volume for storage: %storage, pool: %pool, media type: %mediatype."
index 17fa3db624ffbd165958e79b12b2550517861357..62d049175e24b1e6ff0214d1c82129069659d80e 100644 (file)
Binary files a/gui/baculum/protected/Web/Lang/pt/messages.mo and b/gui/baculum/protected/Web/Lang/pt/messages.mo differ
index 551b9744b34400cb2bf76cdcec96123dc10ecfce..30e182d2a5bbef6e8b1985d8b62b50a402bc4ebd 100644 (file)
@@ -3816,3 +3816,15 @@ msgstr "New migrate job"
 
 msgid "Please select the criteria that will be used for selecting backup jobs to migrate."
 msgstr "Please select the criteria that will be used for selecting backup jobs to migrate."
+
+msgid "The job needs media."
+msgstr "The job needs media."
+
+msgid "Please mount volume %volume or label a new one for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please mount volume %volume or label a new one for storage: %storage, pool: %pool, media type: %mediatype."
+
+msgid "Please mount volume %volume for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please mount volume %volume for storage: %storage, pool: %pool, media type: %mediatype."
+
+msgid "Please create a new volume for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please create a new volume for storage: %storage, pool: %pool, media type: %mediatype."
index 4fc1dfd01ac3e37e335d8f5854525d7044316c93..929ac449dc3dea697a4e8ec2a3915d29f6c8ace2 100644 (file)
Binary files a/gui/baculum/protected/Web/Lang/ru/messages.mo and b/gui/baculum/protected/Web/Lang/ru/messages.mo differ
index 1f2997886198a06ca4aa6dc89775fdb7043c4bb6..3e3871312242c2b0e896df8402b995c072703dcf 100644 (file)
@@ -3816,3 +3816,15 @@ msgstr "New migrate job"
 
 msgid "Please select the criteria that will be used for selecting backup jobs to migrate."
 msgstr "Please select the criteria that will be used for selecting backup jobs to migrate."
+
+msgid "The job needs media."
+msgstr "The job needs media."
+
+msgid "Please mount volume %volume or label a new one for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please mount volume %volume or label a new one for storage: %storage, pool: %pool, media type: %mediatype."
+
+msgid "Please mount volume %volume for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please mount volume %volume for storage: %storage, pool: %pool, media type: %mediatype."
+
+msgid "Please create a new volume for storage: %storage, pool: %pool, media type: %mediatype."
+msgstr "Please create a new volume for storage: %storage, pool: %pool, media type: %mediatype."
index cee5aae0692fe89f3ba496a8effd79fed58ef5f7..c0c513ceadc876e657ca51a41a38f4505c14ce1f 100644 (file)
                                ClientSide.OnComplete="oRunningJobStatus.init_refresh(); oRunningJobStatus.show_loader(false);"
                        />
                        <div class="w3-row">
+                               <div id="status_running_job_warning_container" class="w3-panel w3-pale-yellow w3-border" style="display: none">
+                                       <h3><%[ Warning ]%></h3>
+                                       <p id="status_running_job_warning_msg"></p>
+                                       <div id="status_running_job_warning_label_btn" class="w3-section" style="display: none">
+                                               <com:Application.Web.Portlets.LabelVolume ID="LabelMedia" />
+                                       </div>
+                               </div>
                                <a href="javascript:void(0)" onclick="W3SubTabs.open('status_running_job_subtab_graphical', 'status_running_job_graphical_output');"<%=!$this->allow_graph_mode ? ' style="display: none"' : ''%>>
                                        <div id="status_running_job_subtab_graphical" class="subtab_btn w3-half w3-bottombar w3-hover-light-grey w3-border-red w3-padding">
                                                <%[ Running job status ]%>
@@ -117,6 +124,11 @@ var oRunningJobStatus = {
                refresh_interval: 'status_running_job_refresh_interval',
                status_not_supported: 'status_running_job_status_not_supported',
                graphical_container: 'status_running_job_graphical_container',
+               warning: {
+                       container: 'status_running_job_warning_container',
+                       msg: 'status_running_job_warning_msg',
+                       label_btn: 'status_running_job_warning_label_btn'
+               },
                header: {
                        version: 'status_client_version',
                        uname: 'status_client_uname',
@@ -390,6 +402,37 @@ var oRunningJobStatus = {
        },
        show_loader: function(show) {
                document.getElementById(this.ids.loader).style.display = (show === true ? '' : 'none');
+       },
+       show_warning: function(show) {
+               var warning = document.getElementById(oRunningJobStatus.ids.warning.container);
+               warning.style.display = show ? 'block' : 'none';
+       },
+       set_media_request_msg: function(data) {
+               if (data.waiting) {
+                       var msg;
+                       var label_btn = document.getElementById(oRunningJobStatus.ids.warning.label_btn);
+                       label_btn.style.display = 'none';
+                       if (data.volume) {
+                               if (data.write) {
+                                       msg = '<%[ The job needs media. ]%> <%[ Please mount volume %volume or label a new one for storage: %storage, pool: %pool, media type: %mediatype. ]%>';
+                                       label_btn.style.display = '';
+                               } else {
+                                       msg = '<%[ The job needs media. ]%> <%[ Please mount volume %volume for storage: %storage, pool: %pool, media type: %mediatype. ]%>';
+                               }
+                               msg = msg.replace('%volume', '<strong>' + data.volume + '</strong>');
+                       } else {
+                               msg = '<%[ The job needs media. ]%> <%[ Please create a new volume for storage: %storage, pool: %pool, media type: %mediatype. ]%>';
+                               label_btn.style.display = '';
+                       }
+                       msg = msg.replace('%storage', '<strong>' + data.storage + '</strong>');
+                       msg = msg.replace('%pool', '<strong>' + data.pool + '</strong>');
+                       msg = msg.replace('%mediatype', '<strong>' + data.mediatype + '</strong>');
+                       var message = document.getElementById(oRunningJobStatus.ids.warning.msg);
+                       message.innerHTML = msg;
+                       oRunningJobStatus.show_warning(true);
+               } else {
+                       oRunningJobStatus.show_warning(false);
+               }
        }
 }
 
index bcc6c20ef10eec0b10c3edd088fbba4d56635012..0ede0534eb7f8a9247044ccbcd23ba4d49588211 100644 (file)
@@ -43,6 +43,7 @@ class JobHistoryView extends BaculumWebPage {
        const JOB_TYPE = 'JobType';
        const CLIENTID = 'ClientId';
        const JOB_INFO = 'JobInfo';
+       const STORAGE_INFO = 'StorageInfo';
 
        const USE_CACHE = true;
 
@@ -296,6 +297,31 @@ class JobHistoryView extends BaculumWebPage {
                return $this->getViewState(self::JOB_INFO, []);
        }
 
+       /**
+        * Set all storage information.
+        *
+        * @return none
+        */
+       public function setStorageInfo() {
+               $storages_show = $this->getModule('api')->get(
+                       ['storages', 'show', '?output=json'],
+                       null,
+                       true,
+                       false
+               );
+               if ($storages_show->error == 0) {
+                       $this->setViewState(self::STORAGE_INFO, $storages_show->output);
+               }
+       }
+
+       /**
+        * Get storage information.
+        *
+        * @return array storage information
+        */
+       public function getStorageInfo() {
+               return $this->getViewState(self::STORAGE_INFO, []);
+       }
 
        /**
         * Reload job information.
@@ -327,12 +353,23 @@ class JobHistoryView extends BaculumWebPage {
                }
                $log = $this->getModule('api')->get($params);
 
+               $joblog = [];
                if (!is_array($log->output) || count($log->output) == 0) {
                        $msg = Prado::localize("Output for selected job is not available yet or you do not have enabled logging job logs to the catalog database.\n\nTo watch job log you need to add to the job Messages resource the following directive:\n\nCatalog = all, !debug, !skipped, !saved");
-                       $joblog = array($msg);
+                       $joblog = [$msg];
 
                } else {
                        $joblog = $log->output;
+
+                       if ($this->is_running) {
+                               // search for media requests to display warning
+                               $this->findLogMediaRequest($joblog);
+                       } else {
+                               $this->getCallbackClient()->callClientFunction(
+                                       'oRunningJobStatus.show_warning',
+                                       [false]
+                               );
+                       }
                }
                if ($this->is_running) {
                        $this->RunningIcon->Display = 'Dynamic';
@@ -355,6 +392,77 @@ class JobHistoryView extends BaculumWebPage {
                $this->JobLog->Text = implode(PHP_EOL, $joblog);
        }
 
+       private function findLogMediaRequest($joblog) {
+               $waiting = false;
+               $needed = [
+                       'storage' => '',
+                       'volume' => '',
+                       'pool' => '',
+                       'mediatype' => '',
+                       'write' => true,
+                       'waiting' => $waiting
+               ];
+               $joblog = array_reverse($joblog);
+               for ($i = 0; $i < count($joblog); $i++) {
+                       if (preg_match('/Cannot find any appendable volumes/i', $joblog[$i]) === 1) {
+                               $waiting = true;
+                       } elseif (preg_match('/Please mount read Volume "(?P<volume>[a-zA-Z0-9:.\-_]+)" for:/i', $joblog[$i], $match) === 1) {
+                               $needed['volume'] = $match['volume'];
+                               $needed['write'] = false;
+                               $waiting = true;
+                       } elseif (preg_match('/Please mount append Volume "(?P<volume>[a-zA-Z0-9:.\-_]+)" or label a new one for:/i', $joblog[$i], $match) === 1) {
+                               $needed['volume'] = $match['volume'];
+                               $waiting = true;
+                       } elseif (preg_match('/(New volume "[a-zA-Z0-9:.\-_]+" mounted on device|Ready to append to end of Volume|Ready to read from volume|Recycled volume.+all previous data lost|Wrote label to prelabeled Volume)/i', $joblog[$i]) === 1) {
+                               // stop checking, new volume provided
+                               break;
+                       }
+                       if ($waiting) {
+                               $log = explode(PHP_EOL, $joblog[$i]);
+                               for ($j = 0; $j < count($log); $j++) {
+                                       if (preg_match('/\s+(?P<key>Storage|Pool|Media type):\s*(?P<value>.+)/i', $log[$j], $match) === 1) {
+                                               $key = strtolower($match['key']);
+                                               $key = str_replace(' ', '', $key);
+                                               $needed[$key] = $match['value'];
+                                       }
+                               }
+                               if ($needed['storage'] && $needed['pool'] && $needed['mediatype']) {
+                                       // everything what needed, so stop
+                                       break;
+                               }
+                       }
+               }
+               if ($waiting && $needed['write']) {
+                       if (!empty($needed['pool'])) {
+                               // Set pool for labeling
+                               $this->LabelMedia->setPool($needed['pool']);
+                       }
+                       if (!empty($needed['storage'])) {
+                               // Set storage for labeling
+                               if (count($this->StorageInfo) == 0) {
+                                       $this->setStorageInfo();
+                               }
+                               $storage = '';
+                               if (preg_match('/^"(?P<storage>[a-zA-Z0-9:.\-_ ]+)"/', $needed['storage'], $match) === 1) {
+                                       $storage = $match['storage'];
+                               }
+                               for ($i = 0; $i < count($this->StorageInfo); $i++) {
+                                       if ($this->StorageInfo[$i]->devicename == $storage) {
+                                               // Set storage for labeling
+                                               $this->LabelMedia->setStorage($this->StorageInfo[$i]->name);
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               $needed['waiting'] = $waiting;
+
+               $this->getCallbackClient()->callClientFunction(
+                       'oRunningJobStatus.set_media_request_msg',
+                       [$needed]
+               );
+       }
+
        private function isShowRestoreBtn() {
                $type = $this->getJobType();
                return in_array($type, $this->show_restore_types);
index 27f3d3320eee2a0330e304dc7c94ed44fbf1d1c9..94f78284d1ba28368a2d2144dc98c8d76866dba7 100644 (file)
@@ -39,6 +39,7 @@ class LabelVolume extends Portlets {
        const SHOW_BUTTON = 'ShowButton';
        const BARCODE_LABEL = 'BarcodeLabel';
        const STORAGE = 'Storage';
+       const POOL = 'Pool';
 
        public function loadValues() {
                $storages = $this->getModule('api')->get(array('storages'));
@@ -50,8 +51,10 @@ class LabelVolume extends Portlets {
                }
                $this->StorageLabel->DataSource = $storage_list;
                if ($this->Storage) {
-                       $storage_list_flip =array_flip($storage_list);
-                       $this->StorageLabel->SelectedValue = $storage_list_flip[$this->Storage];
+                       $storage_list_flip = array_flip($storage_list);
+                       if (key_exists($this->Storage, $storage_list_flip)) {
+                               $this->StorageLabel->SelectedValue = $storage_list_flip[$this->Storage];
+                       }
                }
                $this->StorageLabel->dataBind();
 
@@ -63,6 +66,12 @@ class LabelVolume extends Portlets {
                        }
                }
                $this->PoolLabel->dataSource = $pool_list;
+               if ($this->Pool) {
+                       $pool_list_flip = array_flip($pool_list);
+                       if (key_exists($this->Pool, $pool_list_flip)) {
+                               $this->PoolLabel->SelectedValue = $pool_list_flip[$this->Pool];
+                       }
+               }
                $this->PoolLabel->dataBind();
        }
 
@@ -194,5 +203,13 @@ class LabelVolume extends Portlets {
        public function getStorage() {
                return $this->getViewState(self::STORAGE);
        }
+
+       public function setPool($pool) {
+               $this->setViewState(self::POOL, $pool);
+       }
+
+       public function getPool() {
+               return $this->getViewState(self::POOL);
+       }
 }
 ?>
index c8ecd2ff9c4c5db7fda2118bbcd3e1331969cce0..6da2e6cfa83c835da72c4d1e79eee203c486d139 100644 (file)
@@ -13,7 +13,7 @@
        <div class="w3-modal-content w3-animate-top w3-card-4">
                <header class="w3-container w3-teal"> 
                        <span onclick="show_label_volume_window(false);" class="w3-button w3-display-topright">&times;</span>
-                       <h2><%[ Label volume(s) ]%></h2>
+                       <h2><%[ Label volume(s) ]%> <%=$this->Storage ? Prado::localize('Storage:') . ' ' . $this->Storage : ''%></h2>
                </header>
                <div class="w3-padding">
                        <com:TValidationSummary