From e39a29ebc6a86570ed20bd25cdc1ba2be1783445 Mon Sep 17 00:00:00 2001 From: Simone Caronni Date: Jul 18 2017 09:30:28 +0000 Subject: Update to 9.0.1 --- diff --git a/.gitignore b/.gitignore index ace74f0..73744f0 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ bacula-docs-5.0.3.tar.bz2 /bacula-7.4.6.tar.gz /bacula-7.4.7.tar.gz /bacula-9.0.0.tar.gz +/bacula-9.0.1.tar.gz diff --git a/0001-Add-new-tray-monitor-files-that-were-omitted-in-the-.patch b/0001-Add-new-tray-monitor-files-that-were-omitted-in-the-.patch deleted file mode 100644 index 7e31d8f..0000000 --- a/0001-Add-new-tray-monitor-files-that-were-omitted-in-the-.patch +++ /dev/null @@ -1,3617 +0,0 @@ -From a34f61be3e65120b8b22d306c0718d7a5aec7bc1 Mon Sep 17 00:00:00 2001 -From: Kern Sibbald -Date: Mon, 10 Jul 2017 17:50:29 +0200 -Subject: [PATCH 1/4] Add new tray-monitor files that were omitted in the - backport from Enterprise - ---- - .../tray-monitor/bacula-tray-monitor.conf.in | 32 + - bacula/src/qt-console/tray-monitor/conf.h | 85 ++ - .../qt-console/tray-monitor/install_conf_file.in | 3 + - bacula/src/qt-console/tray-monitor/main-conf.ui | 350 ++++++++ - bacula/src/qt-console/tray-monitor/res-conf.ui | 565 ++++++++++++ - bacula/src/qt-console/tray-monitor/run.ui | 379 ++++++++ - bacula/src/qt-console/tray-monitor/runjob.cpp | 515 +++++++++++ - bacula/src/qt-console/tray-monitor/runjob.h | 118 +++ - bacula/src/qt-console/tray-monitor/sd-monitor.ui | 162 ++++ - bacula/src/qt-console/tray-monitor/sdstatus.cpp | 125 +++ - bacula/src/qt-console/tray-monitor/sdstatus.h | 42 + - bacula/src/qt-console/tray-monitor/status.cpp | 42 + - bacula/src/qt-console/tray-monitor/status.h | 44 + - bacula/src/qt-console/tray-monitor/task.cpp | 951 +++++++++++++++++++++ - .../qt-console/tray-monitor/tray-monitor.conf.in | 3 + - .../qt-console/tray-monitor/tray-monitor.pro.in | 3 + - .../tray-monitor/tray-monitor.pro.mingw32.in | 9 +- - .../tray-monitor/tray-monitor.pro.mingw64.in | 9 +- - 18 files changed, 3433 insertions(+), 4 deletions(-) - create mode 100644 bacula/src/qt-console/tray-monitor/bacula-tray-monitor.conf.in - create mode 100644 bacula/src/qt-console/tray-monitor/conf.h - create mode 100644 bacula/src/qt-console/tray-monitor/main-conf.ui - create mode 100644 bacula/src/qt-console/tray-monitor/res-conf.ui - create mode 100644 bacula/src/qt-console/tray-monitor/run.ui - create mode 100644 bacula/src/qt-console/tray-monitor/runjob.cpp - create mode 100644 bacula/src/qt-console/tray-monitor/runjob.h - create mode 100644 bacula/src/qt-console/tray-monitor/sd-monitor.ui - create mode 100644 bacula/src/qt-console/tray-monitor/sdstatus.cpp - create mode 100644 bacula/src/qt-console/tray-monitor/sdstatus.h - create mode 100644 bacula/src/qt-console/tray-monitor/status.cpp - create mode 100644 bacula/src/qt-console/tray-monitor/status.h - create mode 100644 bacula/src/qt-console/tray-monitor/task.cpp - -diff --git a/bacula/src/qt-console/tray-monitor/bacula-tray-monitor.conf.in b/bacula/src/qt-console/tray-monitor/bacula-tray-monitor.conf.in -new file mode 100644 -index 000000000..4a9eff7b1 ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/bacula-tray-monitor.conf.in -@@ -0,0 +1,32 @@ -+# -+# Bacula Tray Monitor Configuration File -+# -+# Copyright (C) 2000-2017 Kern Sibbald -+# License: BSD 2-Clause; see file LICENSE-FOSS -+# -+ -+Monitor { -+ Name = @basename@-mon -+ RefreshInterval = 120 seconds -+} -+ -+Client { -+ Name = @basename@-fd -+ Password = "@mon_fd_password@" # password for FileDaemon -+ Address = @hostname@ -+ Port = @fd_port@ -+} -+ -+#Storage { -+# Name = @basename@-sd -+# Address = @hostname@ -+# Port = @sd_port@ -+# Password = "@mon_sd_password@" # password for StorageDaemon -+#} -+# -+#Director { -+# Name = @basename@-dir -+# Address = @hostname@ -+# Port = @dir_port@ -+# Password = "@mon_dir_password@" # password for the Directors -+#} -diff --git a/bacula/src/qt-console/tray-monitor/conf.h b/bacula/src/qt-console/tray-monitor/conf.h -new file mode 100644 -index 000000000..e2cb52802 ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/conf.h -@@ -0,0 +1,85 @@ -+/* -+ Bacula(R) - The Network Backup Solution -+ -+ Copyright (C) 2000-2017 Kern Sibbald -+ -+ 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. -+*/ -+ -+#ifndef CONF_H -+#define CONF_H -+ -+#include "common.h" -+#include "ui_main-conf.h" -+#include "ui_res-conf.h" -+#include "tray_conf.h" -+ -+class Conf: public QDialog -+{ -+ Q_OBJECT -+ -+private: -+ CONFIG *config; -+ RES_HEAD **rhead; -+public: -+ int items; -+ QLineEdit::EchoMode passtype; -+ Ui::Conf UIConf; -+ Conf(); -+ ~Conf(); -+ bool parse_config(); -+ void addResource(RESMON *res, const char *title); -+ void addRes(int type, const char *title); /* create the resource */ -+public slots: -+ void accept(); -+ void selectCommandDir(); -+ void addDir(); -+ void addStore(); -+ void addClient(); -+ void togglePassword(); -+}; -+ -+class ConfTab: public QWidget -+{ -+ Q_OBJECT -+ -+public: -+ Ui::ResConf ui; -+ RESMON *res; -+ int type; -+ bool new_resource; -+ ConfTab(RESMON *r): QWidget() { -+ res = r; -+ type = r->type; -+ new_resource = r->new_resource; -+ ui.setupUi(this); -+ connect(ui.bpDelete, SIGNAL(clicked()), this, SLOT(disable())); -+ }; -+ ~ConfTab() { -+ if (new_resource && res) { -+ free_resource((RES*) res, res->type); -+ res = NULL; -+ } -+ }; -+public slots: -+ void disable() { -+ setEnabled(false); -+ }; -+ void selectCaCertificateFile(); -+ void selectCaCertificateDir(); -+ void selectCertificate(); -+ void selectKey(); -+}; -+ -+#endif -diff --git a/bacula/src/qt-console/tray-monitor/install_conf_file.in b/bacula/src/qt-console/tray-monitor/install_conf_file.in -index 6b9d27823..3698afb44 100755 ---- a/bacula/src/qt-console/tray-monitor/install_conf_file.in -+++ b/bacula/src/qt-console/tray-monitor/install_conf_file.in -@@ -1,4 +1,7 @@ - #!/bin/sh -+# Copyright (C) 2000-2017 Kern Sibbald -+# License: BSD 2-Clause; see file LICENSE-FOSS -+# - - sbindir=@sbindir@ - sysconfdir=@sysconfdir@ -diff --git a/bacula/src/qt-console/tray-monitor/main-conf.ui b/bacula/src/qt-console/tray-monitor/main-conf.ui -new file mode 100644 -index 000000000..4e023ab6b ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/main-conf.ui -@@ -0,0 +1,350 @@ -+ -+ -+ Conf -+ -+ -+ -+ 0 -+ 0 -+ 556 -+ 337 -+ -+ -+ -+ Configuration -+ -+ -+ -+ -+ -+ 0 -+ -+ -+ -+ Monitor Configuration -+ -+ -+ -+ -+ -+ QFormLayout::AllNonFixedFieldsGrow -+ -+ -+ -+ -+ The Monitor name will be used during the authentication phase. -+ -+ -+ Name: -+ -+ -+ -+ -+ -+ -+ The Monitor name will be used during the authentication phase. -+ -+ -+ 127 -+ -+ -+ -+ -+ -+ -+ Refresh Interval: -+ -+ -+ -+ -+ -+ -+ 5 -+ -+ -+ 9999 -+ -+ -+ 120 -+ -+ -+ -+ -+ -+ -+ Specify the "Command Directory" where the tray-monitor program will check regularly for jobs to run -+ -+ -+ Command Directory: -+ -+ -+ -+ -+ -+ -+ -+ -+ Specify the "Command Directory" where the tray-monitor program will check regularly for jobs to run -+ -+ -+ -+ -+ -+ -+ ... -+ -+ -+ -+ -+ -+ -+ -+ -+ Display or Hide advanced options in the "Run Job" window -+ -+ -+ Display Advanced Options: -+ -+ -+ -+ -+ -+ -+ Display or Hide advanced options in the "Run Job" window -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Save and Apply the changes -+ -+ -+ Save -+ -+ -+ -+ :/images/label.png:/images/label.png -+ -+ -+ -+ -+ -+ -+ Cancel -+ -+ -+ -+ :/images/A.png:/images/A.png -+ -+ -+ -+ -+ -+ -+ Qt::Vertical -+ -+ -+ -+ 20 -+ 40 -+ -+ -+ -+ -+ -+ -+ -+ Show/Hide Passwords -+ -+ -+ Password -+ -+ -+ -+ :/images/zoom.png:/images/zoom.png -+ -+ -+ -+ -+ -+ -+ Add Client resource to monitor -+ -+ -+ Client -+ -+ -+ -+ :/images/mark.png:/images/mark.png -+ -+ -+ -+ -+ -+ -+ Add Storage resource to monitor -+ -+ -+ Storage -+ -+ -+ -+ :/images/mark.png:/images/mark.png -+ -+ -+ -+ -+ -+ -+ Add Director resource to monitor -+ -+ -+ Director -+ -+ -+ -+ :/images/mark.png:/images/mark.png -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ bpSave -+ clicked() -+ Conf -+ accept() -+ -+ -+ 511 -+ 30 -+ -+ -+ 521 -+ 46 -+ -+ -+ -+ -+ bpCancel -+ clicked() -+ Conf -+ close() -+ -+ -+ 511 -+ 76 -+ -+ -+ 521 -+ 159 -+ -+ -+ -+ -+ bpStrip -+ clicked() -+ Conf -+ togglePassword() -+ -+ -+ 511 -+ 178 -+ -+ -+ 496 -+ 142 -+ -+ -+ -+ -+ bpAddClient -+ clicked() -+ Conf -+ addClient() -+ -+ -+ 511 -+ 239 -+ -+ -+ 521 -+ 245 -+ -+ -+ -+ -+ bpAddStorage -+ clicked() -+ Conf -+ addStore() -+ -+ -+ 511 -+ 272 -+ -+ -+ 521 -+ 289 -+ -+ -+ -+ -+ bpAddDir -+ clicked() -+ Conf -+ addDir() -+ -+ -+ 511 -+ 313 -+ -+ -+ 521 -+ 331 -+ -+ -+ -+ -+ bpCommandDir -+ clicked() -+ Conf -+ selectCommandDir() -+ -+ -+ 405 -+ 135 -+ -+ -+ 466 -+ 112 -+ -+ -+ -+ -+ -+ togglePassword() -+ addClient() -+ addStore() -+ addDir() -+ selectCommandDir() -+ -+ -diff --git a/bacula/src/qt-console/tray-monitor/res-conf.ui b/bacula/src/qt-console/tray-monitor/res-conf.ui -new file mode 100644 -index 000000000..7cf21a783 ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/res-conf.ui -@@ -0,0 +1,565 @@ -+ -+ -+ ResConf -+ -+ -+ -+ 0 -+ 0 -+ 417 -+ 541 -+ -+ -+ -+ Form -+ -+ -+ -+ -+ -+ General -+ -+ -+ -+ QFormLayout::AllNonFixedFieldsGrow -+ -+ -+ -+ -+ The Name will be used only in the Tray Monitor interface -+ -+ -+ Name: -+ -+ -+ -+ -+ -+ -+ The Name will be used only in the Tray Monitor interface -+ -+ -+ 127 -+ -+ -+ -+ -+ -+ -+ Description: -+ -+ -+ -+ -+ -+ -+ 512 -+ -+ -+ -+ -+ -+ -+ Password: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ 127 -+ -+ -+ QLineEdit::PasswordEchoOnEdit -+ -+ -+ -+ -+ -+ -+ Address: -+ -+ -+ -+ -+ -+ -+ 1024 -+ -+ -+ -+ -+ -+ -+ Port: -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 100 -+ 16777215 -+ -+ -+ -+ 5 -+ -+ -+ -+ -+ -+ -+ Timeout: -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 100 -+ 16777215 -+ -+ -+ -+ 5 -+ -+ -+ -+ -+ -+ -+ Use Client Initiated backup/restore feature -+ -+ -+ Remote -+ -+ -+ -+ -+ -+ -+ Use Client Initiated backup/restore feature -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Update the tray monitor icon with the status of this component -+ -+ -+ Monitor: -+ -+ -+ -+ -+ -+ -+ Update the tray monitor icon with the status of this component -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Use SetIp: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ TLS -+ -+ -+ -+ -+ -+ ... -+ -+ -+ -+ -+ -+ -+ CA Certificate File: -+ -+ -+ -+ -+ -+ -+ Enabled -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ ... -+ -+ -+ -+ -+ -+ -+ Key File: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ ... -+ -+ -+ -+ -+ -+ -+ Certificate File: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ CA Certificate Directory: -+ -+ -+ -+ -+ -+ -+ ... -+ -+ -+ -+ -+ cbTLSEnabled -+ editCaCertificateFile -+ label_5 -+ label_6 -+ editCaCertificateDir -+ label_7 -+ editCertificate -+ label_8 -+ editKey -+ bpCaCertificateFile -+ bpCaCertificateDir -+ bpCertificate -+ bpKey -+ -+ -+ -+ -+ -+ -+ 64 -+ 16777215 -+ -+ -+ -+ -+ 64 -+ 0 -+ -+ -+ -+ -+ -+ -+ -+ :/images/purge.png:/images/purge.png -+ -+ -+ false -+ -+ -+ -+ -+ -+ -+ Qt::Horizontal -+ -+ -+ -+ 40 -+ 20 -+ -+ -+ -+ -+ -+ -+ -+ editName -+ editDescription -+ editPassword -+ editAddress -+ editPort -+ editTimeout -+ cbRemote -+ cbTLSEnabled -+ editCaCertificateFile -+ bpCaCertificateFile -+ editCaCertificateDir -+ bpCaCertificateDir -+ editCertificate -+ bpCertificate -+ editKey -+ bpKey -+ -+ -+ -+ -+ -+ -+ bpCaCertificateFile -+ clicked() -+ ResConf -+ selectCaCertificateFile() -+ -+ -+ 461 -+ 294 -+ -+ -+ 521 -+ 247 -+ -+ -+ -+ -+ bpCaCertificateDir -+ clicked() -+ ResConf -+ selectCaCertificateDir() -+ -+ -+ 452 -+ 334 -+ -+ -+ 501 -+ 355 -+ -+ -+ -+ -+ bpCertificate -+ clicked() -+ ResConf -+ selectCertificate() -+ -+ -+ 459 -+ 364 -+ -+ -+ 495 -+ 384 -+ -+ -+ -+ -+ bpKey -+ clicked() -+ ResConf -+ selectKey() -+ -+ -+ 461 -+ 395 -+ -+ -+ 481 -+ 410 -+ -+ -+ -+ -+ cbTLSEnabled -+ toggled(bool) -+ editCaCertificateFile -+ setEnabled(bool) -+ -+ -+ 132 -+ 271 -+ -+ -+ 249 -+ 291 -+ -+ -+ -+ -+ cbTLSEnabled -+ toggled(bool) -+ editCaCertificateDir -+ setEnabled(bool) -+ -+ -+ 120 -+ 274 -+ -+ -+ 203 -+ 325 -+ -+ -+ -+ -+ cbTLSEnabled -+ toggled(bool) -+ editCertificate -+ setEnabled(bool) -+ -+ -+ 68 -+ 271 -+ -+ -+ 220 -+ 360 -+ -+ -+ -+ -+ cbTLSEnabled -+ toggled(bool) -+ editKey -+ setEnabled(bool) -+ -+ -+ 51 -+ 275 -+ -+ -+ 288 -+ 392 -+ -+ -+ -+ -+ cbTLSEnabled -+ toggled(bool) -+ bpCaCertificateFile -+ setEnabled(bool) -+ -+ -+ 161 -+ 267 -+ -+ -+ 449 -+ 291 -+ -+ -+ -+ -+ cbTLSEnabled -+ toggled(bool) -+ bpCaCertificateDir -+ setEnabled(bool) -+ -+ -+ 145 -+ 271 -+ -+ -+ 455 -+ 329 -+ -+ -+ -+ -+ cbTLSEnabled -+ toggled(bool) -+ bpCertificate -+ setEnabled(bool) -+ -+ -+ 140 -+ 266 -+ -+ -+ 459 -+ 358 -+ -+ -+ -+ -+ cbTLSEnabled -+ toggled(bool) -+ bpKey -+ setEnabled(bool) -+ -+ -+ 118 -+ 272 -+ -+ -+ 458 -+ 389 -+ -+ -+ -+ -+ -+ selectCaCertificateFile() -+ selectCaCertificateDir() -+ selectCertificate() -+ selectKey() -+ -+ -diff --git a/bacula/src/qt-console/tray-monitor/run.ui b/bacula/src/qt-console/tray-monitor/run.ui -new file mode 100644 -index 000000000..4ed29af13 ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/run.ui -@@ -0,0 +1,379 @@ -+ -+ -+ runForm -+ -+ -+ -+ 0 -+ 0 -+ 568 -+ 407 -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ Run job -+ -+ -+ -+ -+ -+ -+ 16777215 -+ 30 -+ -+ -+ -+ -+ 11 -+ -+ -+ -+ <h3>Run a Job</h3> -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 0 -+ 5 -+ -+ -+ -+ Qt::Horizontal -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ :/images/runit.png -+ -+ -+ -+ -+ -+ -+ 0 -+ -+ -+ -+ Properties -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ QFormLayout::AllNonFixedFieldsGrow -+ -+ -+ -+ -+ Job: -+ -+ -+ jobCombo -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ QComboBox::AdjustToContents -+ -+ -+ -+ -+ -+ -+ When: -+ -+ -+ dateTimeEdit -+ -+ -+ -+ -+ -+ -+ QDateTimeEdit::YearSection -+ -+ -+ yyyy-MM-dd hh:mm:ss -+ -+ -+ true -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ <html><head/><body><p>Job statistics computed from the Catalog with previous jobs.</p><p>For accurate information, it is possible to use the bconsole &quot;estimate&quot; command.</p></body></html> -+ -+ -+ Estimate: -+ -+ -+ -+ -+ -+ Job Bytes: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Job Files: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Level: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Advanced -+ -+ -+ -+ -+ -+ Level: -+ -+ -+ levelCombo -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Client: -+ -+ -+ clientCombo -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ FileSet: -+ -+ -+ filesetCombo -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Pool: -+ -+ -+ poolCombo -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Storage: -+ -+ -+ storageCombo -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Catalog: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Priority: -+ -+ -+ prioritySpin -+ -+ -+ -+ -+ -+ -+ -+ 60 -+ 0 -+ -+ -+ -+ -+ 60 -+ 16777215 -+ -+ -+ -+ -+ 60 -+ 0 -+ -+ -+ -+ 1 -+ -+ -+ 10000 -+ -+ -+ 10 -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ 0 -+ 0 -+ -+ -+ -+ -+ 0 -+ 5 -+ -+ -+ -+ Qt::Horizontal -+ -+ -+ -+ -+ -+ -+ -+ -+ Qt::Horizontal -+ -+ -+ -+ 40 -+ 20 -+ -+ -+ -+ -+ -+ -+ -+ OK -+ -+ -+ -+ -+ -+ -+ Cancel -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/bacula/src/qt-console/tray-monitor/runjob.cpp b/bacula/src/qt-console/tray-monitor/runjob.cpp -new file mode 100644 -index 000000000..e6204ee45 ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/runjob.cpp -@@ -0,0 +1,515 @@ -+/* -+ Bacula(R) - The Network Backup Solution -+ -+ Copyright (C) 2000-2017 Kern Sibbald -+ -+ 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. -+*/ -+ -+#include "runjob.h" -+#include -+ -+static void fillcombo(QComboBox *cb, alist *lst, bool addempty=true) -+{ -+ if (lst && lst->size() > 0) { -+ QStringList list; -+ char *str; -+ if (addempty) { -+ list << QString(""); -+ } -+ foreach_alist(str, lst) { -+ list << QString(str); -+ } -+ cb->addItems(list); -+ } else { -+ cb->setEnabled(false); -+ } -+} -+ -+RunJob::RunJob(RESMON *r): QDialog(), res(r), tabAdvanced(NULL) -+{ -+ int nbjob; -+ if (res->jobs->size() == 0) { -+ QMessageBox msgBox; -+ msgBox.setText(_("This restricted console does not have access to Backup jobs")); -+ msgBox.setIcon(QMessageBox::Warning); -+ msgBox.exec(); -+ deleteLater(); -+ return; -+ -+ } -+ -+ ui.setupUi(this); -+ setModal(true); -+ connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(close_cb())); -+ connect(ui.okButton, SIGNAL(clicked()), this, SLOT(runjob())); -+ connect(ui.jobCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(jobChanged(int))); -+ connect(ui.levelCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(levelChanged(int))); -+ ui.dateTimeEdit->setMinimumDate(QDate::currentDate()); -+ ui.dateTimeEdit->setMaximumDate(QDate::currentDate().addDays(7)); -+ ui.dateTimeEdit->setDate(QDate::currentDate()); -+ ui.dateTimeEdit->setTime(QTime::currentTime()); -+ ui.boxEstimate->setVisible(false); -+ -+ res->mutex->lock(); -+ nbjob = res->jobs->size(); -+ fillcombo(ui.jobCombo, res->jobs, (nbjob > 1)); -+ fillcombo(ui.clientCombo, res->clients); -+ fillcombo(ui.filesetCombo,res->filesets); -+ fillcombo(ui.poolCombo, res->pools); -+ fillcombo(ui.storageCombo,res->storages); -+ fillcombo(ui.catalogCombo,res->catalogs); -+ res->mutex->unlock(); -+ connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChange(int))); -+ QStringList levels; -+ levels << "" << "Incremental" << "Differential" << "Full"; -+ ui.levelCombo->addItems(levels); -+ -+ MONITOR *m = (MONITOR*) GetNextRes(R_MONITOR, NULL); -+ if (!m->display_advanced_options) { -+ tabAdvanced = ui.tabWidget->widget(1); -+ ui.tabWidget->removeTab(1); -+ } -+ -+ show(); -+}; -+ -+void RunJob::tabChange(int idx) -+{ -+ QString q = ui.tabWidget->tabText(idx); -+ if (q.contains("Advanced")) { -+ if (ui.jobCombo->currentText().compare("") == 0) { -+ pm_strcpy(curjob, ""); -+ ui.tab2->setEnabled(false); -+ -+ } else if (ui.jobCombo->currentText().compare(curjob.c_str()) != 0) { -+ task *t = new task(); -+ char *job = bstrdup(ui.jobCombo->currentText().toUtf8().data()); -+ pm_strcpy(curjob, job); // Keep the job name to not refresh the Advanced tab the next time -+ -+ Dmsg1(10, "get defaults for %s\n", job); -+ res->mutex->lock(); -+ bfree_and_null(res->defaults.job); -+ res->defaults.job = job; -+ res->mutex->unlock(); -+ -+ ui.tab2->setEnabled(false); -+ connect(t, SIGNAL(done(task *)), this, SLOT(fill_defaults(task *)), Qt::QueuedConnection); -+ t->init(res, TASK_DEFAULTS); -+ res->wrk->queue(t); -+ } -+ } -+} -+ -+void RunJob::runjob() -+{ -+ POOL_MEM tmp; -+ char *p; -+ -+ p = ui.jobCombo->currentText().toUtf8().data(); -+ if (!p || !*p) { -+ QMessageBox msgBox; -+ msgBox.setText(_("Nothing selected")); -+ msgBox.setIcon(QMessageBox::Warning); -+ msgBox.exec(); -+ return; -+ } -+ -+ Mmsg(command, "run job=\"%s\" yes", p); -+ -+ if (strcmp(p, NPRTB(res->defaults.job)) == 0 || strcmp("", NPRTB(res->defaults.job)) == 0) { -+ p = ui.storageCombo->currentText().toUtf8().data(); -+ if (p && *p && strcmp(p, NPRTB(res->defaults.storage)) != 0) { -+ Mmsg(tmp, " storage=\"%s\"", p); -+ pm_strcat(command, tmp.c_str()); -+ } -+ -+ p = ui.clientCombo->currentText().toUtf8().data(); -+ if (p && *p && strcmp(p, NPRTB(res->defaults.client)) != 0) { -+ Mmsg(tmp, " client=\"%s\"", p); -+ pm_strcat(command, tmp.c_str()); -+ } -+ -+ p = ui.levelCombo->currentText().toUtf8().data(); -+ if (p && *p && strcmp(p, NPRTB(res->defaults.level)) != 0) { -+ Mmsg(tmp, " level=\"%s\"", p); -+ pm_strcat(command, tmp.c_str()); -+ } -+ -+ p = ui.poolCombo->currentText().toUtf8().data(); -+ if (p && *p && strcmp(p, NPRTB(res->defaults.pool)) != 0) { -+ Mmsg(tmp, " pool=\"%s\"", p); -+ pm_strcat(command, tmp.c_str()); -+ } -+ -+ p = ui.filesetCombo->currentText().toUtf8().data(); -+ if (p && *p && strcmp(p, NPRTB(res->defaults.fileset)) != 0) { -+ Mmsg(tmp, " fileset=\"%s\"", p); -+ pm_strcat(command, tmp.c_str()); -+ } -+ -+ if (res->defaults.priority && res->defaults.priority != ui.prioritySpin->value()) { -+ Mmsg(tmp, " priority=\"%d\"", res->defaults.priority); -+ pm_strcat(command, tmp.c_str()); -+ } -+ } -+ -+ QDate dnow = QDate::currentDate(); -+ QTime tnow = QTime::currentTime(); -+ QDate dval = ui.dateTimeEdit->date(); -+ QTime tval = ui.dateTimeEdit->time(); -+ -+ if (dval > dnow || (dval == dnow && tval > tnow)) { -+ Mmsg(tmp, " when=\"%s %s\"", dval.toString("yyyy-MM-dd").toUtf8().data(), tval.toString("hh:mm:00").toUtf8().data()); -+ pm_strcat(command, tmp.c_str()); -+ } -+ -+ if (res->type == R_CLIENT) { -+ pm_strcat(command, " fdcalled=1"); -+ } -+ -+ // Build the command and run it! -+ task *t = new task(); -+ connect(t, SIGNAL(done(task *)), this, SLOT(jobStarted(task *)), Qt::QueuedConnection); -+ t->arg = command.c_str(); -+ t->init(res, TASK_RUN); -+ res->wrk->queue(t); -+} -+ -+void RunJob::jobStarted(task *t) -+{ -+ Dmsg1(10, "%s\n", command.c_str()); -+ Dmsg1(10, "-> jobid=%d\n", t->result.i); -+ deleteLater(); -+ delete t; -+} -+ -+void RunJob::close_cb(task *t) -+{ -+ deleteLater(); -+ delete t; -+} -+ -+void RunJob::close_cb() -+{ -+ task *t = new task(); -+ connect(t, SIGNAL(done(task *)), this, SLOT(close_cb(task *)), Qt::QueuedConnection); -+ t->init(res, TASK_DISCONNECT); -+ res->wrk->queue(t); -+} -+ -+void RunJob::jobChanged(int) -+{ -+ char *p; -+ ui.levelCombo->setCurrentIndex(0); -+ ui.storageCombo->setCurrentIndex(0); -+ ui.filesetCombo->setCurrentIndex(0); -+ ui.clientCombo->setCurrentIndex(0); -+ ui.storageCombo->setCurrentIndex(0); -+ ui.poolCombo->setCurrentIndex(0); -+ ui.catalogCombo->setCurrentIndex(0); -+ -+ p = ui.jobCombo->currentText().toUtf8().data(); -+ if (p && *p) { -+ task *t = new task(); -+ pm_strcpy(info, p); -+ connect(t, SIGNAL(done(task *)), this, SLOT(jobInfo(task *)), Qt::QueuedConnection); -+ t->arg = info.c_str(); // Jobname -+ t->arg2 = NULL; // Level -+ t->init(res, TASK_INFO); -+ res->wrk->queue(t); -+ } -+} -+ -+void RunJob::levelChanged(int) -+{ -+ char *p; -+ p = ui.jobCombo->currentText().toUtf8().data(); -+ if (p && *p) { -+ pm_strcpy(info, p); -+ p = ui.levelCombo->currentText().toUtf8().data(); -+ if (p && *p) { -+ task *t = new task(); -+ pm_strcpy(level, p); -+ connect(t, SIGNAL(done(task *)), this, SLOT(jobInfo(task *)), Qt::QueuedConnection); -+ t->arg = info.c_str(); // Jobname -+ t->arg2 = level.c_str(); // Level -+ t->init(res, TASK_INFO); -+ res->wrk->queue(t); -+ } -+ } -+} -+ -+void RunJob::jobInfo(task *t) -+{ -+ char ed1[50]; -+ res->mutex->lock(); -+ if (res->infos.CorrNbJob == 0) { -+ ui.boxEstimate->setVisible(false); -+ } else { -+ QString t; -+ edit_uint64_with_suffix(res->infos.JobBytes, ed1); -+ strncat(ed1, "B", sizeof(ed1)); -+ ui.labelJobBytes->setText(QString(ed1)); -+ ui.labelJobFiles->setText(QString(edit_uint64_with_commas(res->infos.JobFiles, ed1))); -+ ui.labelJobLevel->setText(QString(job_level_to_str(res->infos.JobLevel))); -+ t = tr("Computed over %1 job%2, the correlation is %3/100.").arg(res->infos.CorrNbJob).arg(res->infos.CorrNbJob>1?"s":"").arg(res->infos.CorrJobBytes); -+ ui.labelJobBytes_2->setToolTip(t); -+ t = tr("Computed over %1 job%2, The correlation is %3/100.").arg(res->infos.CorrNbJob).arg(res->infos.CorrNbJob>1?"s":"").arg(res->infos.CorrJobFiles); -+ ui.labelJobFiles_2->setToolTip(t); -+ ui.boxEstimate->setVisible(true); -+ } -+ res->mutex->unlock(); -+ t->deleteLater(); -+} -+ -+static void set_combo(QComboBox *dest, char *str) -+{ -+ if (str) { -+ int idx = dest->findText(QString(str), Qt::MatchExactly); -+ if (idx >= 0) { -+ dest->setCurrentIndex(idx); -+ } -+ } -+} -+ -+void RunJob::fill_defaults(task *t) -+{ -+ if (t->status == true) { -+ res->mutex->lock(); -+ set_combo(ui.levelCombo, res->defaults.level); -+ set_combo(ui.filesetCombo, res->defaults.fileset); -+ set_combo(ui.clientCombo, res->defaults.client); -+ set_combo(ui.storageCombo, res->defaults.storage); -+ set_combo(ui.poolCombo, res->defaults.pool); -+ set_combo(ui.catalogCombo, res->defaults.catalog); -+ res->mutex->unlock(); -+ } -+ -+ ui.tab2->setEnabled(true); -+ t->deleteLater(); -+} -+ -+RunJob::~RunJob() -+{ -+ Dmsg0(10, "~RunJob()\n"); -+ if (tabAdvanced) { -+ delete tabAdvanced; -+ } -+} -+ -+void TSched::init(const char *cmd_dir) -+{ -+ bool started = (timer >= 0); -+ if (started) { -+ stop(); -+ } -+ -+ bfree_and_null(command_dir); -+ command_dir = bstrdup(cmd_dir); -+ -+ if (started) { -+ start(); -+ } -+} -+ -+TSched::TSched() { -+ timer = -1; -+ command_dir = NULL; -+} -+ -+TSched::~TSched() { -+ if (timer >= 0) { -+ stop(); -+ } -+ bfree_and_null(command_dir); -+} -+ -+#ifndef HAVE_READDIR_R -+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); -+#else -+#include -+#endif -+ -+bool TSched::read_command_file(const char *file, alist *lst, btime_t mtime) -+{ -+ POOLMEM *line; -+ bool ret=false; -+ char *p; -+ TSchedJob *s; -+ Dmsg1(50, "open command file %s\n", file); -+ FILE *fp = fopen(file, "r"); -+ if (!fp) { -+ return false; -+ } -+ line = get_pool_memory(PM_FNAME); -+ -+ /* Get the first line, client/component:command */ -+ while (bfgets(line, fp) != NULL) { -+ strip_trailing_junk(line); -+ Dmsg1(50, "%s\n", line); -+ if (line[0] == '#') { -+ continue; -+ } -+ -+ if ((p = strchr(line, ':')) != NULL) { -+ *p=0; -+ s = new TSchedJob(line, p+1, mtime); -+ lst->append(s); -+ ret = true; -+ } -+ } -+ -+ free_pool_memory(line); -+ fclose(fp); -+ return ret; -+} -+ -+#include "lib/plugins.h" -+#include "lib/cmd_parser.h" -+ -+void TSched::timerEvent(QTimerEvent *event) -+{ -+ POOL_MEM tmp, command; -+ TSchedJob *j; -+ alist lst(10, not_owned_by_alist); -+ arg_parser parser; -+ int i; -+ task *t; -+ RESMON *res; -+ scan_for_commands(&lst); -+ -+ foreach_alist(j, (&lst)) { -+ if (parser.parse_cmd(j->command) == bRC_OK) { -+ if ((i = parser.find_arg_with_value("job")) > 0) { -+ QMessageBox msgbox; -+ foreach_res(res, R_CLIENT) { -+ if (strcmp(res->hdr.name, j->component) == 0) { -+ break; -+ } -+ } -+ if (!res) { -+ foreach_res(res, R_DIRECTOR) { -+ if (strcmp(res->hdr.name, j->component) == 0) { -+ break; -+ } -+ } -+ } -+ if (!res) { -+ msgbox.setIcon(QMessageBox::Information); -+ msgbox.setText(QString("Unable to find the component \"%1\" to run the job \"%2\".").arg(j->component, j->command)); -+ msgbox.setStandardButtons(QMessageBox::Ignore); -+ } else { -+ -+ msgbox.setIcon(QMessageBox::Information); -+ msgbox.setText(QString("The job \"%1\" will start automatically in few seconds...").arg(parser.argv[i])); -+ msgbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Ignore); -+ msgbox.setDefaultButton(QMessageBox::Ok); -+ msgbox.button(QMessageBox::Ok)->animateClick(6000); -+ } -+ switch(msgbox.exec()) { -+ case QMessageBox::Ok: -+ Mmsg(command, "%s yes", j->command); -+ -+ if (res->type == R_CLIENT) { -+ pm_strcat(command, " fdcalled=1"); -+ } -+ -+ // Build the command and run it! -+ t = new task(); -+ connect(t, SIGNAL(done(task *)), this, SLOT(jobStarted(task *)), Qt::QueuedConnection); -+ t->arg = command.c_str(); -+ t->init(res, TASK_RUN); -+ res->wrk->queue(t); -+ -+ break; -+ case QMessageBox::Cancel: -+ case QMessageBox::Ignore: -+ break; -+ } -+ } -+ } -+ delete j; -+ } -+} -+ -+void TSched::jobStarted(task *t) -+{ -+ Dmsg1(10, "-> jobid=%d\n", t->result.i); -+ t->deleteLater(); -+} -+ -+ -+bool TSched::scan_for_commands(alist *commands) -+{ -+ int name_max, len; -+ DIR* dp = NULL; -+ POOL_MEM fname(PM_FNAME), fname2(PM_FNAME); -+ bool ret=false, found=false; -+ struct dirent *entry = NULL, *result; -+ struct stat statp; -+ -+ name_max = pathconf(".", _PC_NAME_MAX); -+ if (name_max < 1024) { -+ name_max = 1024; -+ } -+ -+ if (!(dp = opendir(command_dir))) { -+ berrno be; -+ Dmsg2(0, "Failed to open directory %s: ERR=%s\n", -+ command_dir, be.bstrerror()); -+ goto bail_out; -+ } -+ -+ entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000); -+ for ( ;; ) { -+ if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) { -+ if (!found) { -+ goto bail_out; -+ } -+ break; -+ } -+ if (strcmp(result->d_name, ".") == 0 || -+ strcmp(result->d_name, "..") == 0) { -+ continue; -+ } -+ len = strlen(result->d_name); -+ if (len <= 5) { -+ continue; -+ } -+ if (strcmp(result->d_name + len - 5, ".bcmd") != 0) { -+ continue; -+ } -+ -+ Mmsg(fname, "%s/%s", command_dir, result->d_name); -+ -+ if (lstat(fname.c_str(), &statp) != 0 || !S_ISREG(statp.st_mode)) { -+ continue; /* ignore directories & special files */ -+ } -+ -+ if (read_command_file(fname.c_str(), commands, statp.st_mtime)) { -+ Mmsg(fname2, "%s.ok", fname.c_str()); -+ unlink(fname2.c_str()); -+ rename(fname.c_str(), fname2.c_str()); // TODO: We should probably unlink the file -+ } -+ } -+bail_out: -+ if (entry) { -+ free(entry); -+ } -+ if (dp) { -+ closedir(dp); -+ } -+ return ret; -+} -diff --git a/bacula/src/qt-console/tray-monitor/runjob.h b/bacula/src/qt-console/tray-monitor/runjob.h -new file mode 100644 -index 000000000..6333865bd ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/runjob.h -@@ -0,0 +1,118 @@ -+/* -+ Bacula(R) - The Network Backup Solution -+ -+ Copyright (C) 2000-2017 Kern Sibbald -+ -+ 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. -+*/ -+ -+#ifndef RUN_H -+#define RUN_H -+ -+#include "common.h" -+#include "ui_run.h" -+#include "tray_conf.h" -+#include "task.h" -+ -+class RunJob: public QDialog -+{ -+ Q_OBJECT -+ -+public: -+ RESMON *res; -+ QWidget *tabAdvanced; -+ POOL_MEM command; -+ POOL_MEM info; -+ POOL_MEM level; -+ POOL_MEM curjob; -+ Ui::runForm ui; -+ RunJob(RESMON *r); -+ ~RunJob(); -+ -+public slots: -+ void jobChanged(int); -+ void levelChanged(int); -+ void jobStarted(task *); -+ void jobInfo(task *); -+ void fill_defaults(task *); -+ void tabChange(int idx); -+ void runjob(); -+ /* close the window properly */ -+ void close_cb(task *t); -+ void close_cb(); -+}; -+ -+/* Object that can scan a directory to find jobs */ -+class TSched: public QObject -+{ -+ Q_OBJECT -+private: -+ char *command_dir; -+ bool read_command_file(const char *file, alist *lst, btime_t mtime); -+ int timer; -+ -+public: -+ TSched(); -+ ~TSched(); -+ void init(const char *cmd_dir); -+ bool scan_for_commands(alist *lst); -+ void start() { -+ timer = startTimer(60000); // 1-minute timer -+ }; -+ void stop() { -+ if (timer >= 0) { -+ killTimer(timer); -+ timer = -1; -+ } -+ }; -+public slots: -+ void jobStarted(task *t); -+protected: -+ void timerEvent(QTimerEvent *event); -+ -+}; -+ -+ -+/* Job found in the command directory */ -+class TSchedJob: public QObject -+{ -+ Q_OBJECT -+ -+public: -+ char *component; // Name of the daemon -+ char *command; // job command -+ btime_t create_date; // When the command file was created -+ TSchedJob() : component(NULL), command(NULL) {}; -+ -+ TSchedJob(const char *comp, const char *cmd, btime_t cd) { -+ component = bstrdup(comp); -+ command = bstrdup(cmd); -+ create_date = cd; -+ }; -+ -+ ~TSchedJob() { -+ clear(); -+ }; -+ void clear() { -+ if (component) { -+ bfree_and_null(component); -+ } -+ if (command) { -+ bfree_and_null(command); -+ } -+ create_date = 0; -+ }; -+}; -+ -+#endif -diff --git a/bacula/src/qt-console/tray-monitor/sd-monitor.ui b/bacula/src/qt-console/tray-monitor/sd-monitor.ui -new file mode 100644 -index 000000000..3c00e6c9f ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/sd-monitor.ui -@@ -0,0 +1,162 @@ -+ -+ -+ sdStatus -+ -+ -+ -+ 0 -+ 0 -+ 518 -+ 435 -+ -+ -+ -+ Form -+ -+ -+ -+ -+ -+ -+ -+ Storage Daemon Status -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Name: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Started: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Version: -+ -+ -+ -+ -+ -+ -+ Plugins: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Running Jobs -+ -+ -+ -+ -+ -+ QAbstractItemView::SingleSelection -+ -+ -+ false -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Terminated Jobs -+ -+ -+ -+ -+ -+ QAbstractItemView::SingleSelection -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Qt::Horizontal -+ -+ -+ -+ 40 -+ 20 -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ :/images/view-refresh.png:/images/view-refresh.png -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/bacula/src/qt-console/tray-monitor/sdstatus.cpp b/bacula/src/qt-console/tray-monitor/sdstatus.cpp -new file mode 100644 -index 000000000..741305afb ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/sdstatus.cpp -@@ -0,0 +1,125 @@ -+/* -+ Bacula(R) - The Network Backup Solution -+ -+ Copyright (C) 2000-2017 Kern Sibbald -+ -+ 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. -+*/ -+ -+#include "sdstatus.h" -+#include "../util/fmtwidgetitem.h" -+#include "jcr.h" -+ -+void SDStatus::doUpdate() -+{ -+ if (count == 0) { -+ count++; -+ task *t = new task(); -+ status.pushButton->setEnabled(false); -+ connect(t, SIGNAL(done(task *)), this, SLOT(taskDone(task *)), Qt::QueuedConnection); -+ t->init(res, TASK_STATUS); -+ res->wrk->queue(t); -+ status.statusBar->setText(QString("Trying to connect to Storage...")); -+ Dmsg1(50, "doUpdate(%p)\n", res); -+ } -+} -+ -+void SDStatus::taskDone(task *t) -+{ -+ count--; -+ if (!t->status) { -+ status.statusBar->setText(QString(t->errmsg)); -+ -+ } else { -+ status.statusBar->clear(); -+ if (t->type == TASK_STATUS) { -+ char ed1[50]; -+ struct s_last_job *ljob; -+ struct s_running_job *rjob; -+ res->mutex->lock(); -+ status.labelName->setText(QString(res->name)); -+ status.labelVersion->setText(QString(res->version)); -+ status.labelStarted->setText(QString(res->started)); -+ status.labelPlugins->setText(QString(res->plugins)); -+ /* Clear the table first */ -+ Freeze(*status.tableRunning); -+ Freeze(*status.tableTerminated); -+ QStringList headerlistR = (QStringList() << tr("JobId") -+ << tr("Job") << tr("Level") << tr("Client") -+ << tr("Storage") -+ << tr("Files") << tr("Bytes") << tr("Errors")); -+ status.tableRunning->clear(); -+ status.tableRunning->setRowCount(0); -+ status.tableRunning->setColumnCount(headerlistR.count()); -+ status.tableRunning->setHorizontalHeaderLabels(headerlistR); -+ status.tableRunning->setEditTriggers(QAbstractItemView::NoEditTriggers); -+ status.tableRunning->verticalHeader()->hide(); -+ status.tableRunning->setSortingEnabled(true); -+ -+ if (res->running_jobs) { -+ status.tableRunning->setRowCount(res->running_jobs->size()); -+ int row=0; -+ foreach_alist(rjob, res->running_jobs) { -+ int col=0; -+ TableItemFormatter item(*status.tableRunning, row++); -+ item.setNumericFld(col++, QString(edit_uint64(rjob->JobId, ed1))); -+ item.setTextFld(col++, QString(rjob->Job)); -+ item.setJobLevelFld(col++, QString(rjob->JobLevel)); -+ item.setTextFld(col++, QString(rjob->Client)); -+ item.setTextFld(col++, QString(rjob->Storage)); -+ item.setNumericFld(col++, QString(edit_uint64(rjob->JobFiles, ed1))); -+ item.setBytesFld(col++, QString(edit_uint64(rjob->JobBytes, ed1))); -+ item.setNumericFld(col++, QString(edit_uint64(rjob->Errors, ed1))); -+ } -+ } else { -+ Dmsg0(0, "Strange, the list is NULL\n"); -+ } -+ -+ QStringList headerlistT = (QStringList() << tr("JobId") -+ << tr("Job") << tr("Level") -+ << tr("Status") << tr("Files") << tr("Bytes") -+ << tr("Errors")); -+ -+ status.tableTerminated->clear(); -+ status.tableTerminated->setRowCount(0); -+ status.tableTerminated->setColumnCount(headerlistT.count()); -+ status.tableTerminated->setHorizontalHeaderLabels(headerlistT); -+ status.tableTerminated->setEditTriggers(QAbstractItemView::NoEditTriggers); -+ status.tableTerminated->verticalHeader()->hide(); -+ status.tableTerminated->setSortingEnabled(true); -+ -+ if (res->terminated_jobs) { -+ status.tableTerminated->setRowCount(res->terminated_jobs->size()); -+ int row=0; -+ foreach_dlist(ljob, res->terminated_jobs) { -+ int col=0; -+ TableItemFormatter item(*status.tableTerminated, row++); -+ item.setNumericFld(col++, QString(edit_uint64(ljob->JobId, ed1))); -+ item.setTextFld(col++, QString(ljob->Job)); -+ item.setJobLevelFld(col++, QString(ljob->JobLevel)); -+ item.setJobStatusFld(col++, QString(ljob->JobStatus)); -+ item.setNumericFld(col++, QString(edit_uint64(ljob->JobFiles, ed1))); -+ item.setBytesFld(col++, QString(edit_uint64(ljob->JobBytes, ed1))); -+ item.setNumericFld(col++, QString(edit_uint64(ljob->Errors, ed1))); -+ } -+ } else { -+ Dmsg0(0, "Strange, the list is NULL\n"); -+ } -+ res->mutex->unlock(); -+ } -+ Dmsg1(50, " Task %p OK\n", t); -+ } -+ t->deleteLater(); -+ status.pushButton->setEnabled(true); -+} -diff --git a/bacula/src/qt-console/tray-monitor/sdstatus.h b/bacula/src/qt-console/tray-monitor/sdstatus.h -new file mode 100644 -index 000000000..17f0a3fd4 ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/sdstatus.h -@@ -0,0 +1,42 @@ -+/* -+ Bacula(R) - The Network Backup Solution -+ -+ Copyright (C) 2000-2017 Kern Sibbald -+ -+ 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. -+*/ -+ -+#include "common.h" -+#include "ui_sd-monitor.h" -+#include "task.h" -+#include "status.h" -+ -+class SDStatus: public ResStatus -+{ -+ Q_OBJECT -+ -+public: -+ Ui::sdStatus status; -+ -+ SDStatus(RESMON *d): ResStatus(d) -+ { -+ status.setupUi(this); -+ QObject::connect(status.pushButton, SIGNAL(clicked()), this, SLOT(doUpdate()), Qt::QueuedConnection); -+ }; -+ ~SDStatus() { -+ }; -+public slots: -+ void doUpdate(); -+ void taskDone(task *); -+}; -diff --git a/bacula/src/qt-console/tray-monitor/status.cpp b/bacula/src/qt-console/tray-monitor/status.cpp -new file mode 100644 -index 000000000..8320c5b22 ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/status.cpp -@@ -0,0 +1,42 @@ -+/* -+ Bacula(R) - The Network Backup Solution -+ -+ Copyright (C) 2000-2017 Kern Sibbald -+ -+ 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. -+*/ -+ -+#include "status.h" -+#include "lib/worker.h" -+ -+void ResStatus::doUpdate() -+{ -+ if (count == 0) { -+ task *t = new task(); -+ connect(t, SIGNAL(done(task *)), this, SLOT(taskDone(task *)), Qt::QueuedConnection); -+ t->init(res, TASK_STATUS); -+ res->wrk->queue(t); -+ Dmsg0(0, "doUpdate()\n"); -+ count++; -+ } -+} -+ -+void ResStatus::taskDone(task *t) -+{ -+ if (!t->status) { -+ Dmsg2(0, " Task %p failed => %s\n", t, t->errmsg); -+ } -+ delete t; -+ count--; -+} -diff --git a/bacula/src/qt-console/tray-monitor/status.h b/bacula/src/qt-console/tray-monitor/status.h -new file mode 100644 -index 000000000..0e0f4ea98 ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/status.h -@@ -0,0 +1,44 @@ -+/* -+ Bacula(R) - The Network Backup Solution -+ -+ Copyright (C) 2000-2017 Kern Sibbald -+ -+ 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. -+*/ -+ -+#ifndef STATUS_H -+#define STATUS_H -+ -+#include "common.h" -+#include -+#include "tray_conf.h" -+#include "task.h" -+ -+class ResStatus: public QWidget -+{ -+ Q_OBJECT -+ -+public: -+ int count; -+ RESMON *res; -+ ResStatus(RESMON *c): count(0), res(c) { -+ }; -+ virtual ~ResStatus() { -+ }; -+public slots: -+ virtual void doUpdate(); -+ virtual void taskDone(task *t); -+}; -+ -+#endif -diff --git a/bacula/src/qt-console/tray-monitor/task.cpp b/bacula/src/qt-console/tray-monitor/task.cpp -new file mode 100644 -index 000000000..911ba2f3d ---- /dev/null -+++ b/bacula/src/qt-console/tray-monitor/task.cpp -@@ -0,0 +1,951 @@ -+/* -+ Bacula(R) - The Network Backup Solution -+ -+ Copyright (C) 2000-2017 Kern Sibbald -+ -+ 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. -+*/ -+ -+#include "task.h" -+#include "jcr.h" -+#define dbglvl 10 -+int authenticate_daemon(JCR *jcr, MONITOR *monitor, RESMON *res); -+ -+static void *handle_task(void *data) -+{ -+ task *t; -+ worker *wrk = (worker *)data; -+ lmgr_init_thread(); -+ -+ wrk->set_running(); -+ Dmsg0(dbglvl, "Worker started\n"); -+ -+ while (!wrk->is_quit_state()) { -+ if (wrk->is_wait_state()) { -+ wrk->wait(); -+ continue; -+ } -+ t = (task *)wrk->dequeue(); -+ if (!t) { -+ continue; -+ } -+ /* Do the work */ -+ switch(t->type) { -+ case TASK_STATUS: -+ t->do_status(); -+ break; -+ case TASK_RESOURCES: -+ t->get_resources(); -+ break; -+ case TASK_DEFAULTS: -+ t->get_job_defaults(); -+ break; -+ case TASK_RUN: -+ t->run_job(); -+ break; -+ case TASK_BWLIMIT: -+ t->set_bandwidth(); -+ break; -+ case TASK_INFO: -+ t->get_job_info(t->arg2); -+ break; -+ case TASK_DISCONNECT: -+ t->disconnect_bacula(); -+ t->mark_as_done(); -+ break; -+ default: -+ Mmsg(t->errmsg, "Unknown task"); -+ t->mark_as_failed(); -+ break; -+ } -+ } -+ Dmsg0(dbglvl, "Worker stoped\n"); -+ lmgr_cleanup_thread(); -+ return NULL; -+} -+ -+bool task::set_bandwidth() -+{ -+ bool ret = false; -+ btimer_t *tid = NULL; -+ if (res->type != R_CLIENT) { -+ mark_as_failed(); -+ Mmsg(errmsg, _("Bandwidth can set only set on Client")); -+ return false; -+ } -+ if (!arg || !*arg) { -+ mark_as_failed(); -+ Mmsg(errmsg, _("Bandwidth parameter is invalid")); -+ return false; -+ } -+ -+ if (res->proxy_sent) { -+ free_bsock(res->bs); -+ } -+ -+ if (!res->bs || !res->bs->is_open() || res->bs->is_error()) { -+ if (!connect_bacula()) { -+ mark_as_failed(); -+ return false; -+ } -+ } -+ -+ tid = start_thread_timer(NULL, pthread_self(), (uint32_t)120); -+ res->bs->fsend("setbandwidth limit=%s\n", NPRTB(arg)); -+ while (get_next_line(res)) { -+ Dmsg1(dbglvl, "-> %s\n", curline); -+ } -+ -+ if (tid) { -+ stop_thread_timer(tid); -+ } -+ -+ /* Do not reuse the same socket */ -+ disconnect_bacula(); -+ -+ if (ret) { -+ mark_as_done(); -+ } else { -+ mark_as_failed(); -+ } -+ return ret; -+} -+ -+RESMON *task::get_res() -+{ -+ return res; -+} -+ -+void task::lock_res() -+{ -+ res->mutex->lock(); -+} -+ -+void task::unlock_res() -+{ -+ res->mutex->unlock(); -+} -+ -+bool task::disconnect_bacula() -+{ -+ free_bsock(res->bs); -+ return true; -+} -+ -+bool task::connect_bacula() -+{ -+ JCR jcr; -+ bool ret = false; -+ memset(&jcr, 0, sizeof(jcr)); -+ curend = curline = NULL; -+ -+ RESMON *r = get_res(); -+ MONITOR *monitor = (MONITOR*)GetNextRes(R_MONITOR, NULL); -+ -+ if (r->type == R_CLIENT) { -+ r->proxy_sent = false; -+ if (r->bs && (r->bs->is_error() || !r->bs->is_open())) { -+ free_bsock(r->bs); -+ } -+ if (!r->bs) { -+ r->bs = new_bsock(); -+ Dmsg0(dbglvl, "Trying to connect to FD\n"); -+ if (r->bs->connect(NULL, r->connect_timeout, 0, 0, _("Client daemon"), -+ r->address, NULL, r->port, 0)) -+ { -+ Dmsg0(dbglvl, "Connect done!\n"); -+ jcr.file_bsock = r->bs; -+ if (!authenticate_daemon(&jcr, monitor, r)) { -+ Dmsg0(dbglvl, "Unable to authenticate\n"); -+ Mmsg(errmsg, "Unable to authenticate with the FileDaemon"); -+ free_bsock(r->bs); -+ return false; -+ } -+ Dmsg0(dbglvl, "Authenticate OK\n"); -+ ret = true; -+ } else { -+ Mmsg(errmsg, "Unable to connect to the FileDaemon"); -+ Dmsg0(dbglvl, "Connect error!\n"); -+ } -+ } else { -+ ret = true; -+ } -+ } -+ if (r->type == R_STORAGE) { -+ if (r->bs && (r->bs->is_error() || !r->bs->is_open())) { -+ free_bsock(r->bs); -+ } -+ if (!r->bs) { -+ r->bs = new_bsock(); -+ Dmsg0(dbglvl, "Trying to connect to FD\n"); -+ if (r->bs->connect(NULL, r->connect_timeout, 0, 0, _("Storage daemon"), -+ r->address, NULL, r->port, 0)) -+ { -+ Dmsg0(dbglvl, "Connect done!\n"); -+ jcr.store_bsock = r->bs; -+ if (!authenticate_daemon(&jcr, monitor, r)) { -+ Dmsg0(dbglvl, "Unable to authenticate\n"); -+ Mmsg(errmsg, "Unable to authenticate with the Storage Daemon"); -+ free_bsock(r->bs); -+ return false; -+ } -+ Dmsg0(dbglvl, "Authenticate OK\n"); -+ ret = true; -+ } else { -+ Mmsg(errmsg, "Unable to connect to the Storage Daemon"); -+ Dmsg0(dbglvl, "Connect error!\n"); -+ } -+ } else { -+ ret = true; -+ } -+ } -+ if (r->type == R_DIRECTOR) { -+ if (r->bs && (r->bs->is_error() || !r->bs->is_open())) { -+ free_bsock(r->bs); -+ } -+ if (!r->bs) { -+ r->bs = new_bsock(); -+ Dmsg0(dbglvl, "Trying to connect to DIR\n"); -+ if (r->bs->connect(NULL, r->connect_timeout, 0, 0, _("Director daemon"), -+ r->address, NULL, r->port, 0)) -+ { -+ Dmsg0(dbglvl, "Connect done!\n"); -+ jcr.dir_bsock = r->bs; -+ if (!authenticate_daemon(&jcr, monitor, r)) { -+ Dmsg0(dbglvl, "Unable to authenticate\n"); -+ Mmsg(errmsg, "Unable to authenticate with the Director"); -+ free_bsock(r->bs); -+ return false; -+ } -+ Dmsg0(dbglvl, "Authenticate OK\n"); -+ ret = true; -+ } else { -+ Mmsg(errmsg, "Unable to connect to the Director"); -+ Dmsg0(dbglvl, "Connect error!\n"); -+ } -+ } else { -+ ret = true; -+ } -+ } -+ return ret; -+} -+ -+bool task::read_status_running(RESMON *r) -+{ -+ bool ret = false; -+ char *start, *end; -+ struct s_running_job *item = NULL; -+ alist *running_jobs = New(alist(10, owned_by_alist)); -+ -+ while (r->bs->recv() >= -1) { -+ if (r->bs->msglen < 0 && -+ r->bs->msglen != BNET_CMD_BEGIN && -+ r->bs->msglen != BNET_CMD_OK) -+ { -+ Dmsg1(dbglvl, "Got Signal %s\n", bnet_sig_to_ascii(r->bs->msglen)); -+ break; -+ } -+ Dmsg2(dbglvl, "RECV -> %s:%d\n", r->bs->msg, r->bs->msglen); -+ start = r->bs->msg; -+ -+ while ((end = strchr(start, '\n')) != NULL) { -+ *end = 0; -+ Dmsg1(dbglvl, "line=[%s]\n", start); -+ if (strncasecmp(start, "jobid=", 6) == 0) { -+ if (item) { -+ Dmsg1(dbglvl, "Append item %ld\n", item->JobId); -+ running_jobs->append(item); -+ } -+ item = (struct s_running_job *)malloc(sizeof(struct s_running_job)); -+ memset(item, 0, sizeof(struct s_running_job)); -+ item->JobId = str_to_uint64(start + 6); -+ -+ } else if (!item) { -+ Dmsg0(dbglvl, "discard line\n"); -+ -+ } else if (strncasecmp(start, "level=", 6) == 0) { -+ item->JobLevel = start[6]; -+ -+ } else if (strncasecmp(start, "type=", 5) == 0) { -+ item->JobType = start[5]; -+ -+ } else if (strncasecmp(start, "status=", 7) == 0) { -+ item->JobStatus = start[7]; -+ -+ } else if (strncasecmp(start, "jobbytes=", 9) == 0) { -+ item->JobBytes = str_to_uint64(start + 9); -+ -+ } else if (strncasecmp(start, "jobfiles=", 9) == 0) { -+ item->JobFiles = str_to_uint64(start + 9); -+ -+ } else if (strncasecmp(start, "job=", 4) == 0) { -+ bstrncpy(item->Job, start + 4, sizeof(item->Job)); -+ -+ } else if (strncasecmp(start, "starttime_epoch=", 16) == 0) { -+ item->start_time = str_to_uint64(start + 16); -+ -+ } else if (strncasecmp(start, "schedtime_epoch=", 16) == 0) { -+ item->sched_time = str_to_uint64(start + 16); -+ -+ } else if (strncasecmp(start, "bytes/sec=", 10) == 0) { -+ item->bytespersec = str_to_uint64(start + 10); -+ -+ } else if (strncasecmp(start, "avebytes_sec=", 13) == 0) { -+ item->bytespersec = str_to_uint64(start + 13); -+ -+ } else if (strncasecmp(start, "errors=", 7) == 0) { -+ item->Errors = str_to_uint64(start + 7); -+ -+ } else if (strncasecmp(start, "readbytes=", 10) == 0) { -+ item->ReadBytes = str_to_uint64(start + 10); -+ -+ } else if (strncasecmp(start, "processing file=", 16) == 0) { -+ bstrncpy(item->CurrentFile, start + 16, sizeof(item->CurrentFile)); -+ -+ } else if (strncasecmp(start, "clientname=", 11) == 0) { -+ bstrncpy(item->Client, start + 11, sizeof(item->Client)); -+ -+ } else if (strncasecmp(start, "fileset=", 8) == 0) { -+ bstrncpy(item->FileSet, start + 8, sizeof(item->FileSet)); -+ -+ } else if (strncasecmp(start, "storage=", 8) == 0) { -+ bstrncpy(item->Storage, start + 8, sizeof(item->Storage)); -+ -+ } else if (strncasecmp(start, "rstorage=", 8) == 0) { -+ bstrncpy(item->RStorage, start + 8, sizeof(item->Storage)); -+ -+ } else if (strncasecmp(start, "sdtls=", 6) == 0) { -+ item->SDtls = str_to_uint64(start + 6); -+ } -+ start = end+1; -+ } -+ r->last_update = time(NULL); -+ -+ if (r->bs->is_error()) { -+ Mmsg(errmsg, "Got error on the socket communication line"); -+ goto bail_out; -+ } -+ } -+ if (item) { -+ Dmsg1(dbglvl, "Append item %ld\n", item->JobId); -+ running_jobs->append(item); -+ } -+ ret = true; -+ -+bail_out: -+ r->mutex->lock(); -+ if (r->running_jobs) { -+ delete r->running_jobs; -+ } -+ r->running_jobs = running_jobs; -+ r->mutex->unlock(); -+ -+ return ret; -+} -+ -+bool task::read_status_terminated(RESMON *r) -+{ -+ bool ret = false; -+ char *start, *end; -+ struct s_last_job *item = NULL; -+ -+ r->mutex->lock(); -+ if (r->terminated_jobs) { -+ delete r->terminated_jobs; -+ } -+ r->terminated_jobs = New(dlist(item, &item->link)); -+ r->mutex->unlock(); -+ -+ while (r->bs->recv() >= -1) { -+ if (r->bs->msglen < 0 && -+ r->bs->msglen != BNET_CMD_BEGIN && -+ r->bs->msglen != BNET_CMD_OK) -+ { -+ Dmsg1(dbglvl, "Got Signal %s\n", bnet_sig_to_ascii(r->bs->msglen)); -+ break; -+ } -+ -+ Dmsg2(dbglvl, "RECV -> %s:%d\n", r->bs->msg, r->bs->msglen); -+ r->mutex->lock(); -+ start = r->bs->msg; -+ -+ while ((end = strchr(start, '\n')) != NULL) { -+ *end = 0; -+ Dmsg1(dbglvl, "line=[%s]\n", start); -+ if (strncasecmp(start, "jobid=", 6) == 0) { -+ if (item) { -+ Dmsg1(dbglvl, "Append item %ld\n", item->JobId); -+ r->terminated_jobs->append(item); -+ } -+ item = (struct s_last_job *)malloc(sizeof(struct s_last_job)); -+ memset(item, 0, sizeof(struct s_last_job)); -+ item->JobId = str_to_uint64(start + 6); -+ -+ } else if (!item) { -+ Dmsg0(dbglvl, "discard line\n"); -+ -+ } else if (strncasecmp(start, "level=", 6) == 0) { -+ item->JobLevel = start[6]; -+ -+ } else if (strncasecmp(start, "type=", 5) == 0) { -+ item->JobType = start[5]; -+ -+ } else if (strncasecmp(start, "status=", 7) == 0) { -+ item->JobStatus = start[7]; -+ -+ } else if (strncasecmp(start, "jobbytes=", 9) == 0) { -+ item->JobBytes = str_to_uint64(start + 9); -+ -+ } else if (strncasecmp(start, "jobfiles=", 9) == 0) { -+ item->JobFiles = str_to_uint64(start + 9); -+ -+ } else if (strncasecmp(start, "job=", 4) == 0) { -+ bstrncpy(item->Job, start + 4, sizeof(item->Job)); -+ -+ } else if (strncasecmp(start, "starttime_epoch=", 16) == 0) { -+ item->start_time = str_to_uint64(start + 16); -+ -+ } else if (strncasecmp(start, "endtime_epoch=", 14) == 0) { -+ item->end_time = str_to_uint64(start + 14); -+ -+ } else if (strncasecmp(start, "errors=", 7) == 0) { -+ item->Errors = str_to_uint64(start + 7); -+ } -+ start = end+1; -+ } -+ r->last_update = time(NULL); -+ r->mutex->unlock(); -+ -+ if (r->bs->is_error()) { -+ Mmsg(errmsg, "Got error on the socket communication line"); -+ goto bail_out; -+ } -+ } -+ if (item) { -+ r->mutex->lock(); -+ Dmsg1(dbglvl, "Append item %ld\n", item->JobId); -+ r->terminated_jobs->append(item); -+ r->mutex->unlock(); -+ } -+ ret = true; -+ -+bail_out: -+ return ret; -+} -+ -+bool task::read_status_header(RESMON *r) -+{ -+ bool ret = false; -+ char *start, *end; -+ -+ while (r->bs->recv() >= -1) { -+ if (r->bs->msglen < 0 && -+ r->bs->msglen != BNET_CMD_BEGIN && -+ r->bs->msglen != BNET_CMD_OK) -+ { -+ Dmsg1(dbglvl, "Got Signal %d\n", r->bs->msglen); -+ break; -+ } -+ -+ Dmsg2(dbglvl, "RECV -> %s:%d\n", r->bs->msg, r->bs->msglen); -+ r->mutex->lock(); -+ start = r->bs->msg; -+ -+ while ((end = strchr(start, '\n')) != NULL) { -+ *end = 0; -+ Dmsg1(dbglvl, "line=[%s]\n", start); -+ if (strncasecmp(start, "name=", 5) == 0) { -+ bstrncpy(r->name, start + 5, sizeof(r->name)); -+ -+ } else if (strncasecmp(start, "version=", 8) == 0) { -+ bstrncpy(r->version, start + 8, sizeof(r->version)); -+ -+ } else if (strncasecmp(start, "plugins=", 8) == 0) { -+ bstrncpy(r->plugins, start + 8, sizeof(r->plugins)); -+ -+ } else if (strncasecmp(start, "bwlimit=", 8) == 0) { -+ r->bwlimit = str_to_uint64(start + 8); -+ -+ } else if (strncasecmp(start, "started=", 8) == 0) { -+ bstrncpy(r->started, start + 8, sizeof(r->started)); -+ -+ } else if (strncasecmp(start, "reloaded=", 9) == 0) { -+ bstrncpy(r->reloaded, start + 9, sizeof(r->reloaded)); -+ } -+ start = end+1; -+ } -+ -+ if (r->bs->is_error()) { -+ r->mutex->unlock(); -+ Mmsg(errmsg, "Got error on the socket communication line"); -+ goto bail_out; -+ -+ } -+ r->last_update = time(NULL); -+ r->mutex->unlock(); -+ } -+ ret = true; -+bail_out: -+ return ret; -+} -+ -+ -+bool task::do_status() -+{ -+ bool ret = false; -+ btimer_t *tid = NULL; -+ -+ /* We don't want to use a proxy session */ -+ if (res->type == R_CLIENT && res->proxy_sent) { -+ free_bsock(res->bs); -+ } -+ if (!res->bs || !res->bs->is_open() || res->bs->is_error()) { -+ if (!connect_bacula()) { -+ goto bail_out; -+ } -+ } -+ /* TODO: */ -+ tid = start_thread_timer(NULL, pthread_self(), (uint32_t)120); -+ if (res->type == R_CLIENT || res->type == R_STORAGE) { -+ Dmsg0(dbglvl, "Send status command header\n"); -+ res->bs->fsend(".status header api=2\n"); -+ // TODO: Update a local set of variables and commit everything when it's done -+ ret = read_status_header(res); -+ -+ if (ret) { -+ res->bs->fsend(".status terminated api=2\n"); -+ ret = read_status_terminated(res); -+ } -+ if (ret) { -+ res->bs->fsend(".status running api=2\n"); -+ ret = read_status_running(res); -+ } -+ } -+ if (res->type == R_DIRECTOR) { -+ Dmsg0(dbglvl, "-> .api 2\n"); -+ res->bs->fsend(".api 2\n"); -+ while (get_next_line(res)) { -+ Dmsg2(dbglvl, "<- %d %s\n", res->bs->msglen, curline); -+ } -+ Dmsg0(dbglvl, "Send status command header\n"); -+ res->bs->fsend(".status dir header\n"); -+ // TODO: Update a local set of variables and commit everything when it's done -+ ret = read_status_header(res); -+ -+ if (ret) { -+ Dmsg0(dbglvl, "Send status command terminated\n"); -+ res->bs->fsend(".status dir terminated\n"); -+ ret = read_status_terminated(res); -+ } -+ if (ret) { -+ Dmsg0(dbglvl, "Send status command running\n"); -+ res->bs->fsend(".status dir running\n"); -+ ret = read_status_running(res); -+ } -+ } -+bail_out: -+ if (tid) { -+ stop_thread_timer(tid); -+ } -+ /* Use a new socket the next time */ -+ disconnect_bacula(); -+ if (ret) { -+ mark_as_done(); -+ } else { -+ mark_as_failed(); -+ } -+ return ret; -+} -+ -+bool task::get_next_line(RESMON *r) -+{ -+ /* We are currently reading a line */ -+ if (curline && curend && r->bs->msglen > 0 && curend < (r->bs->msg + r->bs->msglen - 1)) { -+ curline = curend + 1; /* skip \0 */ -+ if ((curend = strchr(curline, '\n')) != NULL) { -+ *curend = '\0'; -+ } -+ return true; -+ } -+ curline = curend = NULL; -+ do { -+ r->bs->recv(); -+ -+ if (r->bs->msglen < 0) { -+ Dmsg1(dbglvl, "<- %s\n", bnet_sig_to_ascii(r->bs->msglen)); -+ switch(r->bs->msglen) { -+ case BNET_ERROR_MSG: -+ r->bs->recv(); -+ strip_trailing_junk(r->bs->msg); -+ Dmsg1(0, "ERROR: %s\n", r->bs->msg); -+ break; -+ case BNET_MAIN_PROMPT: // stop -+ return false; -+ case BNET_CMD_OK: -+ case BNET_CMD_BEGIN: -+ case BNET_MSGS_PENDING: -+ break; -+ case BNET_TERMINATE: -+ return false; -+ default: // error or question? -+ return false; -+ } -+ -+ } else if (r->bs->msglen == 0) { // strange -+ return false; -+ -+ } else { -+ Dmsg1(10, "<- %s\n", r->bs->msg); -+ curline = r->bs->msg; -+ curend = strchr(curline, '\n'); -+ if (curend) { -+ *curend = 0; -+ } -+ return true; // something to read -+ } -+ } while (!r->bs->is_error()); -+ return false; -+} -+ -+bool task::get_job_defaults() -+{ -+ bool ret = false; -+ btimer_t *tid = NULL; -+ char *p; -+ -+ if (!res->bs || !res->bs->is_open() || res->bs->is_error()) { -+ if (!connect_bacula()) { -+ goto bail_out; -+ } -+ } -+ -+ res->mutex->lock(); -+ bfree_and_null(res->defaults.client); -+ bfree_and_null(res->defaults.pool); -+ bfree_and_null(res->defaults.storage); -+ bfree_and_null(res->defaults.level); -+ bfree_and_null(res->defaults.type); -+ bfree_and_null(res->defaults.fileset); -+ bfree_and_null(res->defaults.catalog); -+ -+ tid = start_thread_timer(NULL, pthread_self(), (uint32_t)120); -+ if (res->type == R_CLIENT && !res->proxy_sent) { -+ res->proxy_sent = true; -+ res->bs->fsend("proxy\n"); -+ while (get_next_line(res)) { -+ if (strncmp(curline, "2000", 4) != 0) { -+ pm_strcpy(errmsg, curline); -+ goto bail_out; -+ } -+ Dmsg2(dbglvl, "<- %d %s\n", res->bs->msglen, curline); -+ } -+ } -+ -+ res->bs->fsend(".api 2\n"); -+ while (get_next_line(res)) { -+ Dmsg2(dbglvl, "<- %d %s\n", res->bs->msglen, curline); -+ } -+ res->bs->fsend(".defaults job=\"%s\"\n", res->defaults.job); -+ while (get_next_line(res)) { -+ Dmsg1(dbglvl, "line = [%s]\n", curline); -+ if ((p = strchr(curline, '=')) == NULL) { -+ continue; -+ } -+ *p++ = 0; -+ if (strcasecmp(curline, "client") == 0) { -+ res->defaults.client = bstrdup(p); -+ -+ } else if (strcasecmp(curline, "pool") == 0) { -+ res->defaults.pool = bstrdup(p); -+ -+ } else if (strcasecmp(curline, "storage") == 0) { -+ res->defaults.storage = bstrdup(p); -+ -+ } else if (strcasecmp(curline, "level") == 0) { -+ res->defaults.level = bstrdup(p); -+ -+ } else if (strcasecmp(curline, "type") == 0) { -+ res->defaults.type = bstrdup(p); -+ -+ } else if (strcasecmp(curline, "fileset") == 0) { -+ res->defaults.fileset = bstrdup(p); -+ -+ } else if (strcasecmp(curline, "catalog") == 0) { -+ res->defaults.catalog = bstrdup(p); -+ -+ } else if (strcasecmp(curline, "priority") == 0) { -+ res->defaults.priority = str_to_uint64(p); -+ } -+ } -+ ret = true; -+bail_out: -+ if (tid) { -+ stop_thread_timer(tid); -+ } -+ if (ret) { -+ mark_as_done(); -+ } else { -+ mark_as_failed(); -+ } -+ res->mutex->unlock(); -+ return ret; -+} -+ -+bool task::get_job_info(const char *level) -+{ -+ bool ret = false; -+ btimer_t *tid = NULL; -+ char *p; -+ -+ if (!res->bs || !res->bs->is_open() || res->bs->is_error()) { -+ if (!connect_bacula()) { -+ goto bail_out; -+ } -+ } -+ res->mutex->lock(); -+ memset(&res->infos, 0, sizeof(res->infos)); -+ -+ tid = start_thread_timer(NULL, pthread_self(), (uint32_t)120); -+ if (res->type == R_CLIENT && !res->proxy_sent) { -+ res->proxy_sent = true; -+ res->bs->fsend("proxy\n"); -+ while (get_next_line(res)) { -+ if (strncmp(curline, "2000", 4) != 0) { -+ pm_strcpy(errmsg, curline); -+ goto bail_out; -+ } -+ Dmsg2(dbglvl, "<- %d %s\n", res->bs->msglen, curline); -+ } -+ } -+ -+ res->bs->fsend(".api 2\n"); -+ while (get_next_line(res)) { -+ Dmsg2(dbglvl, "<- %d %s\n", res->bs->msglen, curline); -+ } -+ if (level) { -+ res->bs->fsend(".estimate job=\"%s\" level=%s\n", arg, level); -+ } else { -+ res->bs->fsend(".estimate job=\"%s\"\n", arg); -+ } -+ while (get_next_line(res)) { -+ Dmsg1(dbglvl, "line = [%s]\n", curline); -+ if ((p = strchr(curline, '=')) == NULL) { -+ continue; -+ } -+ *p++ = 0; -+ if (strcasecmp(curline, "level") == 0) { -+ res->infos.JobLevel = p[0]; -+ -+ } else if (strcasecmp(curline, "jobbytes") == 0) { -+ res->infos.JobBytes = str_to_uint64(p); -+ -+ } else if (strcasecmp(curline, "jobfiles") == 0) { -+ res->infos.JobFiles = str_to_uint64(p); -+ -+ } else if (strcasecmp(curline, "corrbytes") == 0) { -+ res->infos.CorrJobBytes = str_to_uint64(p); -+ -+ } else if (strcasecmp(curline, "corrfiles") == 0) { -+ res->infos.CorrJobFiles = str_to_uint64(p); -+ -+ } else if (strcasecmp(curline, "nbjob") == 0) { -+ res->infos.CorrNbJob = str_to_uint64(p); -+ } -+ } -+ ret = true; -+bail_out: -+ res->mutex->unlock(); -+ if (tid) { -+ stop_thread_timer(tid); -+ } -+ if (ret) { -+ mark_as_done(); -+ } else { -+ mark_as_failed(); -+ } -+ return ret; -+} -+ -+bool task::run_job() -+{ -+ bool ret = false; -+ char *p; -+ btimer_t *tid = NULL; -+ -+ if (!res->bs || !res->bs->is_open() || res->bs->is_error()) { -+ if (!connect_bacula()) { -+ goto bail_out; -+ } -+ } -+ -+ tid = start_thread_timer(NULL, pthread_self(), (uint32_t)120); -+ if (res->type == R_CLIENT && !res->proxy_sent) { -+ res->proxy_sent = true; -+ res->bs->fsend("proxy\n"); -+ while (get_next_line(res)) { -+ if (strncmp(curline, "2000", 4) != 0) { -+ pm_strcpy(errmsg, curline); -+ goto bail_out; -+ } -+ Dmsg2(dbglvl, "<- %d %s\n", res->bs->msglen, curline); -+ } -+ } -+ -+ res->bs->fsend(".api 2\n"); -+ while (get_next_line(res)) { -+ Dmsg2(dbglvl, "<- %d %s\n", res->bs->msglen, curline); -+ } -+ if (res->type == R_DIRECTOR && res->use_setip) { -+ res->bs->fsend("setip\n"); -+ while (get_next_line(res)) { -+ Dmsg2(dbglvl, "<- %d %s\n", res->bs->msglen, curline); -+ } -+ } -+ res->bs->fsend("%s\n", arg); -+ while (get_next_line(res)) { -+ if ((p = strstr(curline, "JobId=")) != NULL && sscanf(p, "JobId=%d\n", &result.i) == 1) { -+ ret = true; -+ } -+ } -+ // Close the socket, it's over or we don't want to reuse it -+ disconnect_bacula(); -+ -+bail_out: -+ -+ if (tid) { -+ stop_thread_timer(tid); -+ } -+ if (ret) { -+ mark_as_done(); -+ } else { -+ mark_as_failed(); -+ } -+ return ret; -+} -+ -+/* Get resources to run a job */ -+bool task::get_resources() -+{ -+ bool ret = false; -+ btimer_t *tid = NULL; -+ -+ if (!res->bs || !res->bs->is_open() || res->bs->is_error()) { -+ if (!connect_bacula()) { -+ goto bail_out; -+ } -+ } -+ -+ res->mutex->lock(); -+ if (res->jobs) { -+ delete res->jobs; -+ } -+ res->jobs = New(alist(10, owned_by_alist)); -+ if (res->clients) { -+ delete res->clients; -+ } -+ res->clients = New(alist(10, owned_by_alist)); -+ if (res->filesets) { -+ delete res->filesets; -+ } -+ res->filesets = New(alist(10, owned_by_alist)); -+ if (res->pools) { -+ delete res->pools; -+ } -+ res->pools = New(alist(10, owned_by_alist)); -+ if (res->storages) { -+ delete res->storages; -+ } -+ res->storages = New(alist(10, owned_by_alist)); -+ if (res->catalogs) { -+ delete res->catalogs; -+ } -+ res->catalogs = New(alist(10, owned_by_alist)); -+ -+ tid = start_thread_timer(NULL, pthread_self(), (uint32_t)120); -+ if (res->type == R_CLIENT && !res->proxy_sent) { -+ res->proxy_sent = true; -+ res->bs->fsend("proxy\n"); -+ while (get_next_line(res)) { -+ if (strncmp(curline, "2000", 4) != 0) { -+ pm_strcpy(errmsg, curline); -+ goto bail_out; -+ } -+ Dmsg2(dbglvl, "<- %d %s\n", res->bs->msglen, curline); -+ } -+ Dmsg2(dbglvl, "<- %d %s\n", res->bs->msglen, curline); -+ } -+ -+ res->bs->fsend(".api 2\n"); -+ while (get_next_line(res)) { -+ Dmsg2(dbglvl, "<- %d %s\n", res->bs->msglen, curline); -+ } -+ -+ res->bs->fsend(".jobs type=B\n"); -+ while (get_next_line(res)) { -+ res->jobs->append(bstrdup(curline)); -+ } -+ -+ res->bs->fsend(".pools\n"); -+ while (get_next_line(res)) { -+ res->pools->append(bstrdup(curline)); -+ } -+ -+ res->bs->fsend(".clients\n"); -+ while (get_next_line(res)) { -+ res->clients->append(bstrdup(curline)); -+ } -+ -+ res->bs->fsend(".filesets\n"); -+ while (get_next_line(res)) { -+ res->filesets->append(bstrdup(curline)); -+ } -+ -+ res->bs->fsend(".storage\n"); -+ while (get_next_line(res)) { -+ res->storages->append(bstrdup(curline)); -+ } -+ -+ res->bs->fsend(".catalog\n"); -+ while (get_next_line(res)) { -+ res->catalogs->append(bstrdup(curline)); -+ } -+ -+bail_out: -+ res->mutex->unlock(); -+ -+ if (tid) { -+ stop_thread_timer(tid); -+ } -+ if (ret) { -+ mark_as_done(); -+ } else { -+ mark_as_failed(); -+ } -+ return ret; -+} -+ -+worker *worker_start() -+{ -+ worker *w = New(worker()); -+ w->start(handle_task, w); -+ return w; -+} -+ -+void worker_stop(worker *w) -+{ -+ if (w) { -+ w->stop(); -+ delete w; -+ } -+} -diff --git a/bacula/src/qt-console/tray-monitor/tray-monitor.conf.in b/bacula/src/qt-console/tray-monitor/tray-monitor.conf.in -index 30aea7db3..3f72921b2 100644 ---- a/bacula/src/qt-console/tray-monitor/tray-monitor.conf.in -+++ b/bacula/src/qt-console/tray-monitor/tray-monitor.conf.in -@@ -1,6 +1,9 @@ - # - # Bacula Tray Monitor Configuration File - # -+# Copyright (C) 2000-2017 Kern Sibbald -+# License: BSD 2-Clause; see file LICENSE-FOSS -+# - - Monitor { - Name = @basename@-mon -diff --git a/bacula/src/qt-console/tray-monitor/tray-monitor.pro.in b/bacula/src/qt-console/tray-monitor/tray-monitor.pro.in -index 92247c0ca..8c414a05a 100644 ---- a/bacula/src/qt-console/tray-monitor/tray-monitor.pro.in -+++ b/bacula/src/qt-console/tray-monitor/tray-monitor.pro.in -@@ -6,6 +6,9 @@ - # - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # -+# Copyright (C) 2000-2017 Kern Sibbald -+# License: BSD 2-Clause; see file LICENSE-FOSS -+# - # CONFIG options for Windows are pulled from win32/qmake.conf - CONFIG += qt - #CONFIG += qt debug -diff --git a/bacula/src/qt-console/tray-monitor/tray-monitor.pro.mingw32.in b/bacula/src/qt-console/tray-monitor/tray-monitor.pro.mingw32.in -index 763c03244..362fff1b3 100644 ---- a/bacula/src/qt-console/tray-monitor/tray-monitor.pro.mingw32.in -+++ b/bacula/src/qt-console/tray-monitor/tray-monitor.pro.mingw32.in -@@ -7,11 +7,16 @@ - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # - # CONFIG options for Windows are pulled from win32/qmake.conf --CONFIG += qt -+# -+# Copyright (C) 2000-2017 Kern Sibbald -+# License: BSD 2-Clause; see file LICENSE-FOSS -+# -+ -+CONFIG += qt cross-win32 - #CONFIG += qt debug - - cross-win32 { -- LIBS += -mwindows -L../../win32/release32 -lbacula -+ LIBS += -mwindows -L../../win32/release32 -lbacula -lpthread - INCLUDEPATH += ../../win32/compat - } - !cross-win32 { -diff --git a/bacula/src/qt-console/tray-monitor/tray-monitor.pro.mingw64.in b/bacula/src/qt-console/tray-monitor/tray-monitor.pro.mingw64.in -index 39957e67f..20719ba89 100644 ---- a/bacula/src/qt-console/tray-monitor/tray-monitor.pro.mingw64.in -+++ b/bacula/src/qt-console/tray-monitor/tray-monitor.pro.mingw64.in -@@ -7,11 +7,16 @@ - # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - # - # CONFIG options for Windows are pulled from win32/qmake.conf --CONFIG += qt -+# -+# Copyright (C) 2000-2017 Kern Sibbald -+# License: BSD 2-Clause; see file LICENSE-FOSS -+# -+ -+CONFIG += qt cross-win32 - #CONFIG += qt debug - - cross-win32 { -- LIBS += -mwindows -L../../win32/release64 -lbacula -+ LIBS += -mwindows -L../../win32/release64 -lbacula -lpthread - INCLUDEPATH += ../../win32/compat - } - !cross-win32 { --- -2.13.0 - diff --git a/0002-Fix-bug-2293-bad-big-endian-detection-in-lz4.c.patch b/0002-Fix-bug-2293-bad-big-endian-detection-in-lz4.c.patch deleted file mode 100644 index 6eb4a16..0000000 --- a/0002-Fix-bug-2293-bad-big-endian-detection-in-lz4.c.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 2e3e5dd3d1e7408b7e58f67a618e6579e5b7d302 Mon Sep 17 00:00:00 2001 -From: Kern Sibbald -Date: Mon, 10 Jul 2017 19:10:34 +0200 -Subject: [PATCH 2/4] Fix bug #2293 bad big endian detection in lz4.c - ---- - bacula/src/lib/lz4.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/bacula/src/lib/lz4.c b/bacula/src/lib/lz4.c -index e04c1345c..2ffb24452 100644 ---- a/bacula/src/lib/lz4.c -+++ b/bacula/src/lib/lz4.c -@@ -67,7 +67,8 @@ Note : this source file requires "lz4_encoder.h" - || defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) \ - || defined(__hpux) || defined(__hppa) \ - || defined(_MIPSEB) || defined(__s390__) --#error "BIG Endian detected but not set" -+// KES -- the following is not a correct assumption -+//#error "BIG Endian detected but not set" - #endif - #endif - --- -2.13.0 - diff --git a/0004-Remove-two-incorrect-trailing-commas-in-bsock.h.patch b/0004-Remove-two-incorrect-trailing-commas-in-bsock.h.patch deleted file mode 100644 index 96fe48f..0000000 --- a/0004-Remove-two-incorrect-trailing-commas-in-bsock.h.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 54f7bf4f627bb73bf8fdd672d6e723dfdf60d7b4 Mon Sep 17 00:00:00 2001 -From: Kern Sibbald -Date: Mon, 10 Jul 2017 20:24:10 +0200 -Subject: [PATCH 4/4] Remove two incorrect trailing commas in bsock.h - ---- - bacula/src/lib/bsock.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/bacula/src/lib/bsock.h b/bacula/src/lib/bsock.h -index e2de186b5..b18b9bcee 100644 ---- a/bacula/src/lib/bsock.h -+++ b/bacula/src/lib/bsock.h -@@ -289,7 +289,7 @@ enum { - BNET_SIGNAL = -1, - BNET_HARDEOF = -2, - BNET_ERROR = -3, -- BNET_COMMAND = -4, -+ BNET_COMMAND = -4 - }; - - /* -@@ -307,7 +307,7 @@ enum { - BNET_CMD_STO_BLOCK = 4, /* backup FD->SD FD send requested block */ - BNET_CMD_REC_ACK = 5, /* restore FD->SD FD has consumed records from the buffer */ - BNET_CMD_STP_THREAD = 6, /* restore FD->SD SD must stop thread */ -- BNET_CMD_STP_FLOWCTRL = 7, /* backup FD->SD SD must stop sending flowcontrol information */ -+ BNET_CMD_STP_FLOWCTRL = 7 /* backup FD->SD SD must stop sending flowcontrol information */ - }; - - const char *bnet_cmd_to_name(int val); --- -2.13.0 - diff --git a/bacula.spec b/bacula.spec index 7601c79..a1842f2 100644 --- a/bacula.spec +++ b/bacula.spec @@ -2,8 +2,8 @@ %global username bacula Name: bacula -Version: 9.0.0 -Release: 2%{?dist} +Version: 9.0.1 +Release: 1%{?dist} Summary: Cross platform network backup for Linux, Unix, Mac and Windows # See LICENSE for details License: AGPLv3 with exceptions @@ -44,11 +44,6 @@ Patch8: %{name}-9.0.0-tray-monitor-desktop.patch # http://bugs.bacula.org/view.php?id=2084 Patch10: %{name}-7.0.4-autoconf.patch -# Temporary patches from upstream git -Patch11: 0001-Add-new-tray-monitor-files-that-were-omitted-in-the-.patch -Patch12: 0002-Fix-bug-2293-bad-big-endian-detection-in-lz4.c.patch -Patch13: 0004-Remove-two-incorrect-trailing-commas-in-bsock.h.patch - BuildRequires: desktop-file-utils BuildRequires: perl-interpreter BuildRequires: perl-generators @@ -320,9 +315,6 @@ Provides check_bacula support for Nagios. %patch10 -p1 -%patch11 -p2 -%patch12 -p2 -%patch13 -p2 cp %{SOURCE2} %{SOURCE3} %{SOURCE4} %{SOURCE5} . # Remove execution permissions from files we're packaging as docs later on @@ -735,6 +727,9 @@ fi %{_libdir}/nagios/plugins/check_bacula %changelog +* Tue Jul 18 2017 Simone Caronni - 9.0.1-1 +- Update to 9.0.1. + * Tue Jul 11 2017 Simone Caronni - 9.0.0-2 - Fix ppc64le build. - Fix tray-monitor build. Use source file for tray monitor desktop entry. diff --git a/sources b/sources index cc750ed..c021cdf 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (bacula-9.0.0.tar.gz) = 2ca4bd763dcb9cf7b6411302b55757c52820b8598683ef664f4eee2d1acfd55718906b17be8f8f093f33f173469a6221635b244248c8eedd5bd0dc477b21d5af +SHA512 (bacula-9.0.1.tar.gz) = c189a2f7d6318c1e9b1fee6e15d7fb1dfa09782a8f56201660c3baec74f1ba29d8048752fc81bde5039e0139440e611503ceaead6359eb4b36ed06336db0939a