3618 lines
105 KiB
Diff
3618 lines
105 KiB
Diff
From a34f61be3e65120b8b22d306c0718d7a5aec7bc1 Mon Sep 17 00:00:00 2001
|
|
From: Kern Sibbald <kern@sibbald.com>
|
|
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 @@
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
+<ui version="4.0">
|
|
+ <class>Conf</class>
|
|
+ <widget class="QDialog" name="Conf">
|
|
+ <property name="geometry">
|
|
+ <rect>
|
|
+ <x>0</x>
|
|
+ <y>0</y>
|
|
+ <width>556</width>
|
|
+ <height>337</height>
|
|
+ </rect>
|
|
+ </property>
|
|
+ <property name="windowTitle">
|
|
+ <string>Configuration</string>
|
|
+ </property>
|
|
+ <layout class="QHBoxLayout" name="horizontalLayout">
|
|
+ <item>
|
|
+ <widget class="QTabWidget" name="tabWidget">
|
|
+ <property name="currentIndex">
|
|
+ <number>0</number>
|
|
+ </property>
|
|
+ <widget class="QWidget" name="tabMonitor">
|
|
+ <attribute name="title">
|
|
+ <string>Monitor Configuration</string>
|
|
+ </attribute>
|
|
+ <layout class="QVBoxLayout" name="verticalLayout">
|
|
+ <item>
|
|
+ <layout class="QFormLayout" name="formLayout">
|
|
+ <property name="fieldGrowthPolicy">
|
|
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
|
+ </property>
|
|
+ <item row="0" column="0">
|
|
+ <widget class="QLabel" name="label">
|
|
+ <property name="toolTip">
|
|
+ <string>The Monitor name will be used during the authentication phase.</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string>Name:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="0" column="1">
|
|
+ <widget class="QLineEdit" name="editName">
|
|
+ <property name="toolTip">
|
|
+ <string>The Monitor name will be used during the authentication phase.</string>
|
|
+ </property>
|
|
+ <property name="maxLength">
|
|
+ <number>127</number>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="0">
|
|
+ <widget class="QLabel" name="label_2">
|
|
+ <property name="text">
|
|
+ <string>Refresh Interval:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="1">
|
|
+ <widget class="QSpinBox" name="spinRefresh">
|
|
+ <property name="minimum">
|
|
+ <number>5</number>
|
|
+ </property>
|
|
+ <property name="maximum">
|
|
+ <number>9999</number>
|
|
+ </property>
|
|
+ <property name="value">
|
|
+ <number>120</number>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="2" column="0">
|
|
+ <widget class="QLabel" name="label_3">
|
|
+ <property name="toolTip">
|
|
+ <string>Specify the "Command Directory" where the tray-monitor program will check regularly for jobs to run</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string>Command Directory:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="2" column="1">
|
|
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
+ <item>
|
|
+ <widget class="QLineEdit" name="editCommandDir">
|
|
+ <property name="toolTip">
|
|
+ <string>Specify the "Command Directory" where the tray-monitor program will check regularly for jobs to run</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QToolButton" name="bpCommandDir">
|
|
+ <property name="text">
|
|
+ <string>...</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </item>
|
|
+ <item row="3" column="0">
|
|
+ <widget class="QLabel" name="label_4">
|
|
+ <property name="toolTip">
|
|
+ <string>Display or Hide advanced options in the "Run Job" window</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string>Display Advanced Options:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="3" column="1">
|
|
+ <widget class="QCheckBox" name="cbDspAdvanced">
|
|
+ <property name="toolTip">
|
|
+ <string>Display or Hide advanced options in the "Run Job" window</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <layout class="QVBoxLayout" name="verticalLayout_2">
|
|
+ <item>
|
|
+ <widget class="QPushButton" name="bpSave">
|
|
+ <property name="toolTip">
|
|
+ <string>Save and Apply the changes</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string>Save</string>
|
|
+ </property>
|
|
+ <property name="icon">
|
|
+ <iconset resource="../main.qrc">
|
|
+ <normaloff>:/images/label.png</normaloff>:/images/label.png</iconset>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QPushButton" name="bpCancel">
|
|
+ <property name="text">
|
|
+ <string>Cancel</string>
|
|
+ </property>
|
|
+ <property name="icon">
|
|
+ <iconset resource="../main.qrc">
|
|
+ <normaloff>:/images/A.png</normaloff>:/images/A.png</iconset>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <spacer name="verticalSpacer">
|
|
+ <property name="orientation">
|
|
+ <enum>Qt::Vertical</enum>
|
|
+ </property>
|
|
+ <property name="sizeHint" stdset="0">
|
|
+ <size>
|
|
+ <width>20</width>
|
|
+ <height>40</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ </spacer>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QPushButton" name="bpStrip">
|
|
+ <property name="toolTip">
|
|
+ <string>Show/Hide Passwords</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string>Password</string>
|
|
+ </property>
|
|
+ <property name="icon">
|
|
+ <iconset resource="../main.qrc">
|
|
+ <normaloff>:/images/zoom.png</normaloff>:/images/zoom.png</iconset>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QPushButton" name="bpAddClient">
|
|
+ <property name="toolTip">
|
|
+ <string>Add Client resource to monitor</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string>Client </string>
|
|
+ </property>
|
|
+ <property name="icon">
|
|
+ <iconset resource="../main.qrc">
|
|
+ <normaloff>:/images/mark.png</normaloff>:/images/mark.png</iconset>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QPushButton" name="bpAddStorage">
|
|
+ <property name="toolTip">
|
|
+ <string>Add Storage resource to monitor</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string>Storage</string>
|
|
+ </property>
|
|
+ <property name="icon">
|
|
+ <iconset resource="../main.qrc">
|
|
+ <normaloff>:/images/mark.png</normaloff>:/images/mark.png</iconset>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QPushButton" name="bpAddDir">
|
|
+ <property name="toolTip">
|
|
+ <string>Add Director resource to monitor</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string> Director</string>
|
|
+ </property>
|
|
+ <property name="icon">
|
|
+ <iconset resource="../main.qrc">
|
|
+ <normaloff>:/images/mark.png</normaloff>:/images/mark.png</iconset>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ <resources>
|
|
+ <include location="../main.qrc"/>
|
|
+ </resources>
|
|
+ <connections>
|
|
+ <connection>
|
|
+ <sender>bpSave</sender>
|
|
+ <signal>clicked()</signal>
|
|
+ <receiver>Conf</receiver>
|
|
+ <slot>accept()</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>511</x>
|
|
+ <y>30</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>521</x>
|
|
+ <y>46</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>bpCancel</sender>
|
|
+ <signal>clicked()</signal>
|
|
+ <receiver>Conf</receiver>
|
|
+ <slot>close()</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>511</x>
|
|
+ <y>76</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>521</x>
|
|
+ <y>159</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>bpStrip</sender>
|
|
+ <signal>clicked()</signal>
|
|
+ <receiver>Conf</receiver>
|
|
+ <slot>togglePassword()</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>511</x>
|
|
+ <y>178</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>496</x>
|
|
+ <y>142</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>bpAddClient</sender>
|
|
+ <signal>clicked()</signal>
|
|
+ <receiver>Conf</receiver>
|
|
+ <slot>addClient()</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>511</x>
|
|
+ <y>239</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>521</x>
|
|
+ <y>245</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>bpAddStorage</sender>
|
|
+ <signal>clicked()</signal>
|
|
+ <receiver>Conf</receiver>
|
|
+ <slot>addStore()</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>511</x>
|
|
+ <y>272</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>521</x>
|
|
+ <y>289</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>bpAddDir</sender>
|
|
+ <signal>clicked()</signal>
|
|
+ <receiver>Conf</receiver>
|
|
+ <slot>addDir()</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>511</x>
|
|
+ <y>313</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>521</x>
|
|
+ <y>331</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>bpCommandDir</sender>
|
|
+ <signal>clicked()</signal>
|
|
+ <receiver>Conf</receiver>
|
|
+ <slot>selectCommandDir()</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>405</x>
|
|
+ <y>135</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>466</x>
|
|
+ <y>112</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ </connections>
|
|
+ <slots>
|
|
+ <slot>togglePassword()</slot>
|
|
+ <slot>addClient()</slot>
|
|
+ <slot>addStore()</slot>
|
|
+ <slot>addDir()</slot>
|
|
+ <slot>selectCommandDir()</slot>
|
|
+ </slots>
|
|
+</ui>
|
|
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 @@
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
+<ui version="4.0">
|
|
+ <class>ResConf</class>
|
|
+ <widget class="QWidget" name="ResConf">
|
|
+ <property name="geometry">
|
|
+ <rect>
|
|
+ <x>0</x>
|
|
+ <y>0</y>
|
|
+ <width>417</width>
|
|
+ <height>541</height>
|
|
+ </rect>
|
|
+ </property>
|
|
+ <property name="windowTitle">
|
|
+ <string>Form</string>
|
|
+ </property>
|
|
+ <layout class="QGridLayout" name="gridLayout">
|
|
+ <item row="0" column="0">
|
|
+ <widget class="QGroupBox" name="groupBox_2">
|
|
+ <property name="title">
|
|
+ <string>General</string>
|
|
+ </property>
|
|
+ <layout class="QFormLayout" name="formLayout">
|
|
+ <property name="fieldGrowthPolicy">
|
|
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
|
+ </property>
|
|
+ <item row="0" column="0">
|
|
+ <widget class="QLabel" name="label">
|
|
+ <property name="toolTip">
|
|
+ <string>The Name will be used only in the Tray Monitor interface</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string>Name:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="0" column="1">
|
|
+ <widget class="QLineEdit" name="editName">
|
|
+ <property name="toolTip">
|
|
+ <string>The Name will be used only in the Tray Monitor interface</string>
|
|
+ </property>
|
|
+ <property name="maxLength">
|
|
+ <number>127</number>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="0">
|
|
+ <widget class="QLabel" name="label_9">
|
|
+ <property name="text">
|
|
+ <string>Description:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="1">
|
|
+ <widget class="QLineEdit" name="editDescription">
|
|
+ <property name="maxLength">
|
|
+ <number>512</number>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="2" column="0">
|
|
+ <widget class="QLabel" name="labelPassword">
|
|
+ <property name="text">
|
|
+ <string>Password:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="2" column="1">
|
|
+ <widget class="QLineEdit" name="editPassword">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ <property name="maxLength">
|
|
+ <number>127</number>
|
|
+ </property>
|
|
+ <property name="echoMode">
|
|
+ <enum>QLineEdit::PasswordEchoOnEdit</enum>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="3" column="0">
|
|
+ <widget class="QLabel" name="label_3">
|
|
+ <property name="text">
|
|
+ <string>Address:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="3" column="1">
|
|
+ <widget class="QLineEdit" name="editAddress">
|
|
+ <property name="maxLength">
|
|
+ <number>1024</number>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="5" column="0">
|
|
+ <widget class="QLabel" name="label_4">
|
|
+ <property name="text">
|
|
+ <string>Port:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="5" column="1">
|
|
+ <widget class="QLineEdit" name="editPort">
|
|
+ <property name="sizePolicy">
|
|
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
+ <horstretch>0</horstretch>
|
|
+ <verstretch>0</verstretch>
|
|
+ </sizepolicy>
|
|
+ </property>
|
|
+ <property name="maximumSize">
|
|
+ <size>
|
|
+ <width>100</width>
|
|
+ <height>16777215</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ <property name="maxLength">
|
|
+ <number>5</number>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="6" column="0">
|
|
+ <widget class="QLabel" name="label_2">
|
|
+ <property name="text">
|
|
+ <string>Timeout:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="6" column="1">
|
|
+ <widget class="QLineEdit" name="editTimeout">
|
|
+ <property name="sizePolicy">
|
|
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
+ <horstretch>0</horstretch>
|
|
+ <verstretch>0</verstretch>
|
|
+ </sizepolicy>
|
|
+ </property>
|
|
+ <property name="maximumSize">
|
|
+ <size>
|
|
+ <width>100</width>
|
|
+ <height>16777215</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ <property name="maxLength">
|
|
+ <number>5</number>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="8" column="0">
|
|
+ <widget class="QLabel" name="labelRemote">
|
|
+ <property name="toolTip">
|
|
+ <string>Use Client Initiated backup/restore feature</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string>Remote</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="8" column="1">
|
|
+ <widget class="QCheckBox" name="cbRemote">
|
|
+ <property name="toolTip">
|
|
+ <string>Use Client Initiated backup/restore feature</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="7" column="0">
|
|
+ <widget class="QLabel" name="label_10">
|
|
+ <property name="toolTip">
|
|
+ <string>Update the tray monitor icon with the status of this component</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string>Monitor:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="7" column="1">
|
|
+ <widget class="QCheckBox" name="cbMonitor">
|
|
+ <property name="toolTip">
|
|
+ <string>Update the tray monitor icon with the status of this component</string>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="9" column="1">
|
|
+ <widget class="QCheckBox" name="cbUseSetIp">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="9" column="0">
|
|
+ <widget class="QLabel" name="labelSetIp">
|
|
+ <property name="text">
|
|
+ <string>Use SetIp:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="2" column="0">
|
|
+ <widget class="QGroupBox" name="groupBox">
|
|
+ <property name="title">
|
|
+ <string>TLS</string>
|
|
+ </property>
|
|
+ <layout class="QGridLayout" name="gridLayout_2">
|
|
+ <item row="3" column="2">
|
|
+ <widget class="QToolButton" name="bpCertificate">
|
|
+ <property name="text">
|
|
+ <string>...</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="0">
|
|
+ <widget class="QLabel" name="label_5">
|
|
+ <property name="text">
|
|
+ <string>CA Certificate File:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="0" column="0">
|
|
+ <widget class="QCheckBox" name="cbTLSEnabled">
|
|
+ <property name="text">
|
|
+ <string>Enabled</string>
|
|
+ </property>
|
|
+ <property name="checked">
|
|
+ <bool>true</bool>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="2">
|
|
+ <widget class="QToolButton" name="bpCaCertificateFile">
|
|
+ <property name="text">
|
|
+ <string>...</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="4" column="0">
|
|
+ <widget class="QLabel" name="label_8">
|
|
+ <property name="text">
|
|
+ <string>Key File:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="2" column="1">
|
|
+ <widget class="QLineEdit" name="editCaCertificateDir"/>
|
|
+ </item>
|
|
+ <item row="2" column="2">
|
|
+ <widget class="QToolButton" name="bpCaCertificateDir">
|
|
+ <property name="text">
|
|
+ <string>...</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="3" column="0">
|
|
+ <widget class="QLabel" name="label_7">
|
|
+ <property name="text">
|
|
+ <string>Certificate File:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="4" column="1">
|
|
+ <widget class="QLineEdit" name="editKey"/>
|
|
+ </item>
|
|
+ <item row="3" column="1">
|
|
+ <widget class="QLineEdit" name="editCertificate"/>
|
|
+ </item>
|
|
+ <item row="1" column="1">
|
|
+ <widget class="QLineEdit" name="editCaCertificateFile"/>
|
|
+ </item>
|
|
+ <item row="2" column="0">
|
|
+ <widget class="QLabel" name="label_6">
|
|
+ <property name="text">
|
|
+ <string>CA Certificate Directory:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="4" column="2">
|
|
+ <widget class="QToolButton" name="bpKey">
|
|
+ <property name="text">
|
|
+ <string>...</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ <zorder>cbTLSEnabled</zorder>
|
|
+ <zorder>editCaCertificateFile</zorder>
|
|
+ <zorder>label_5</zorder>
|
|
+ <zorder>label_6</zorder>
|
|
+ <zorder>editCaCertificateDir</zorder>
|
|
+ <zorder>label_7</zorder>
|
|
+ <zorder>editCertificate</zorder>
|
|
+ <zorder>label_8</zorder>
|
|
+ <zorder>editKey</zorder>
|
|
+ <zorder>bpCaCertificateFile</zorder>
|
|
+ <zorder>bpCaCertificateDir</zorder>
|
|
+ <zorder>bpCertificate</zorder>
|
|
+ <zorder>bpKey</zorder>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="3" column="2">
|
|
+ <widget class="QPushButton" name="bpDelete">
|
|
+ <property name="maximumSize">
|
|
+ <size>
|
|
+ <width>64</width>
|
|
+ <height>16777215</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ <property name="baseSize">
|
|
+ <size>
|
|
+ <width>64</width>
|
|
+ <height>0</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ <property name="icon">
|
|
+ <iconset resource="../main.qrc">
|
|
+ <normaloff>:/images/purge.png</normaloff>:/images/purge.png</iconset>
|
|
+ </property>
|
|
+ <property name="flat">
|
|
+ <bool>false</bool>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="3" column="0">
|
|
+ <spacer name="horizontalSpacer">
|
|
+ <property name="orientation">
|
|
+ <enum>Qt::Horizontal</enum>
|
|
+ </property>
|
|
+ <property name="sizeHint" stdset="0">
|
|
+ <size>
|
|
+ <width>40</width>
|
|
+ <height>20</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ </spacer>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ <tabstops>
|
|
+ <tabstop>editName</tabstop>
|
|
+ <tabstop>editDescription</tabstop>
|
|
+ <tabstop>editPassword</tabstop>
|
|
+ <tabstop>editAddress</tabstop>
|
|
+ <tabstop>editPort</tabstop>
|
|
+ <tabstop>editTimeout</tabstop>
|
|
+ <tabstop>cbRemote</tabstop>
|
|
+ <tabstop>cbTLSEnabled</tabstop>
|
|
+ <tabstop>editCaCertificateFile</tabstop>
|
|
+ <tabstop>bpCaCertificateFile</tabstop>
|
|
+ <tabstop>editCaCertificateDir</tabstop>
|
|
+ <tabstop>bpCaCertificateDir</tabstop>
|
|
+ <tabstop>editCertificate</tabstop>
|
|
+ <tabstop>bpCertificate</tabstop>
|
|
+ <tabstop>editKey</tabstop>
|
|
+ <tabstop>bpKey</tabstop>
|
|
+ </tabstops>
|
|
+ <resources>
|
|
+ <include location="../main.qrc"/>
|
|
+ </resources>
|
|
+ <connections>
|
|
+ <connection>
|
|
+ <sender>bpCaCertificateFile</sender>
|
|
+ <signal>clicked()</signal>
|
|
+ <receiver>ResConf</receiver>
|
|
+ <slot>selectCaCertificateFile()</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>461</x>
|
|
+ <y>294</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>521</x>
|
|
+ <y>247</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>bpCaCertificateDir</sender>
|
|
+ <signal>clicked()</signal>
|
|
+ <receiver>ResConf</receiver>
|
|
+ <slot>selectCaCertificateDir()</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>452</x>
|
|
+ <y>334</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>501</x>
|
|
+ <y>355</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>bpCertificate</sender>
|
|
+ <signal>clicked()</signal>
|
|
+ <receiver>ResConf</receiver>
|
|
+ <slot>selectCertificate()</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>459</x>
|
|
+ <y>364</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>495</x>
|
|
+ <y>384</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>bpKey</sender>
|
|
+ <signal>clicked()</signal>
|
|
+ <receiver>ResConf</receiver>
|
|
+ <slot>selectKey()</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>461</x>
|
|
+ <y>395</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>481</x>
|
|
+ <y>410</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>cbTLSEnabled</sender>
|
|
+ <signal>toggled(bool)</signal>
|
|
+ <receiver>editCaCertificateFile</receiver>
|
|
+ <slot>setEnabled(bool)</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>132</x>
|
|
+ <y>271</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>249</x>
|
|
+ <y>291</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>cbTLSEnabled</sender>
|
|
+ <signal>toggled(bool)</signal>
|
|
+ <receiver>editCaCertificateDir</receiver>
|
|
+ <slot>setEnabled(bool)</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>120</x>
|
|
+ <y>274</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>203</x>
|
|
+ <y>325</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>cbTLSEnabled</sender>
|
|
+ <signal>toggled(bool)</signal>
|
|
+ <receiver>editCertificate</receiver>
|
|
+ <slot>setEnabled(bool)</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>68</x>
|
|
+ <y>271</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>220</x>
|
|
+ <y>360</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>cbTLSEnabled</sender>
|
|
+ <signal>toggled(bool)</signal>
|
|
+ <receiver>editKey</receiver>
|
|
+ <slot>setEnabled(bool)</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>51</x>
|
|
+ <y>275</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>288</x>
|
|
+ <y>392</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>cbTLSEnabled</sender>
|
|
+ <signal>toggled(bool)</signal>
|
|
+ <receiver>bpCaCertificateFile</receiver>
|
|
+ <slot>setEnabled(bool)</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>161</x>
|
|
+ <y>267</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>449</x>
|
|
+ <y>291</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>cbTLSEnabled</sender>
|
|
+ <signal>toggled(bool)</signal>
|
|
+ <receiver>bpCaCertificateDir</receiver>
|
|
+ <slot>setEnabled(bool)</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>145</x>
|
|
+ <y>271</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>455</x>
|
|
+ <y>329</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>cbTLSEnabled</sender>
|
|
+ <signal>toggled(bool)</signal>
|
|
+ <receiver>bpCertificate</receiver>
|
|
+ <slot>setEnabled(bool)</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>140</x>
|
|
+ <y>266</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>459</x>
|
|
+ <y>358</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ <connection>
|
|
+ <sender>cbTLSEnabled</sender>
|
|
+ <signal>toggled(bool)</signal>
|
|
+ <receiver>bpKey</receiver>
|
|
+ <slot>setEnabled(bool)</slot>
|
|
+ <hints>
|
|
+ <hint type="sourcelabel">
|
|
+ <x>118</x>
|
|
+ <y>272</y>
|
|
+ </hint>
|
|
+ <hint type="destinationlabel">
|
|
+ <x>458</x>
|
|
+ <y>389</y>
|
|
+ </hint>
|
|
+ </hints>
|
|
+ </connection>
|
|
+ </connections>
|
|
+ <slots>
|
|
+ <slot>selectCaCertificateFile()</slot>
|
|
+ <slot>selectCaCertificateDir()</slot>
|
|
+ <slot>selectCertificate()</slot>
|
|
+ <slot>selectKey()</slot>
|
|
+ </slots>
|
|
+</ui>
|
|
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 @@
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
+<ui version="4.0">
|
|
+ <class>runForm</class>
|
|
+ <widget class="QWidget" name="runForm">
|
|
+ <property name="geometry">
|
|
+ <rect>
|
|
+ <x>0</x>
|
|
+ <y>0</y>
|
|
+ <width>568</width>
|
|
+ <height>407</height>
|
|
+ </rect>
|
|
+ </property>
|
|
+ <property name="sizePolicy">
|
|
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
+ <horstretch>0</horstretch>
|
|
+ <verstretch>0</verstretch>
|
|
+ </sizepolicy>
|
|
+ </property>
|
|
+ <property name="windowTitle">
|
|
+ <string>Run job</string>
|
|
+ </property>
|
|
+ <layout class="QVBoxLayout" name="verticalLayout_3">
|
|
+ <item>
|
|
+ <widget class="QLabel" name="run">
|
|
+ <property name="maximumSize">
|
|
+ <size>
|
|
+ <width>16777215</width>
|
|
+ <height>30</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ <property name="font">
|
|
+ <font>
|
|
+ <pointsize>11</pointsize>
|
|
+ </font>
|
|
+ </property>
|
|
+ <property name="text">
|
|
+ <string><h3>Run a Job</h3></string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="Line" name="line">
|
|
+ <property name="sizePolicy">
|
|
+ <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
|
+ <horstretch>0</horstretch>
|
|
+ <verstretch>0</verstretch>
|
|
+ </sizepolicy>
|
|
+ </property>
|
|
+ <property name="minimumSize">
|
|
+ <size>
|
|
+ <width>0</width>
|
|
+ <height>5</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ <property name="orientation">
|
|
+ <enum>Qt::Horizontal</enum>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <layout class="QHBoxLayout" name="horizontalLayout">
|
|
+ <item>
|
|
+ <widget class="QLabel" name="label_12">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ <property name="pixmap">
|
|
+ <pixmap resource="../main.qrc">:/images/runit.png</pixmap>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QTabWidget" name="tabWidget">
|
|
+ <property name="currentIndex">
|
|
+ <number>0</number>
|
|
+ </property>
|
|
+ <widget class="QWidget" name="tab1">
|
|
+ <attribute name="title">
|
|
+ <string>Properties</string>
|
|
+ </attribute>
|
|
+ <layout class="QGridLayout" name="gridLayout">
|
|
+ <item row="0" column="0">
|
|
+ <widget class="QGroupBox" name="groupBox">
|
|
+ <property name="title">
|
|
+ <string/>
|
|
+ </property>
|
|
+ <layout class="QFormLayout" name="formLayout">
|
|
+ <property name="fieldGrowthPolicy">
|
|
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
|
+ </property>
|
|
+ <item row="0" column="0">
|
|
+ <widget class="QLabel" name="label_6">
|
|
+ <property name="text">
|
|
+ <string>Job:</string>
|
|
+ </property>
|
|
+ <property name="buddy">
|
|
+ <cstring>jobCombo</cstring>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="0" column="1">
|
|
+ <widget class="QComboBox" name="jobCombo">
|
|
+ <property name="sizePolicy">
|
|
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
+ <horstretch>0</horstretch>
|
|
+ <verstretch>0</verstretch>
|
|
+ </sizepolicy>
|
|
+ </property>
|
|
+ <property name="sizeAdjustPolicy">
|
|
+ <enum>QComboBox::AdjustToContents</enum>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="0">
|
|
+ <widget class="QLabel" name="label">
|
|
+ <property name="text">
|
|
+ <string>When:</string>
|
|
+ </property>
|
|
+ <property name="buddy">
|
|
+ <cstring>dateTimeEdit</cstring>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="1">
|
|
+ <widget class="QDateTimeEdit" name="dateTimeEdit">
|
|
+ <property name="currentSection">
|
|
+ <enum>QDateTimeEdit::YearSection</enum>
|
|
+ </property>
|
|
+ <property name="displayFormat">
|
|
+ <string>yyyy-MM-dd hh:mm:ss</string>
|
|
+ </property>
|
|
+ <property name="calendarPopup">
|
|
+ <bool>true</bool>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="0">
|
|
+ <widget class="QGroupBox" name="boxEstimate">
|
|
+ <property name="toolTip">
|
|
+ <string><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></string>
|
|
+ </property>
|
|
+ <property name="title">
|
|
+ <string>Estimate:</string>
|
|
+ </property>
|
|
+ <layout class="QFormLayout" name="formLayout_3">
|
|
+ <item row="0" column="0">
|
|
+ <widget class="QLabel" name="labelJobBytes_2">
|
|
+ <property name="text">
|
|
+ <string>Job Bytes:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="0" column="1">
|
|
+ <widget class="QLabel" name="labelJobBytes">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="0">
|
|
+ <widget class="QLabel" name="labelJobFiles_2">
|
|
+ <property name="text">
|
|
+ <string>Job Files:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="1">
|
|
+ <widget class="QLabel" name="labelJobFiles">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="2" column="0">
|
|
+ <widget class="QLabel" name="label_13">
|
|
+ <property name="text">
|
|
+ <string>Level:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="2" column="1">
|
|
+ <widget class="QLabel" name="labelJobLevel">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ <widget class="QWidget" name="tab2">
|
|
+ <attribute name="title">
|
|
+ <string>Advanced</string>
|
|
+ </attribute>
|
|
+ <layout class="QFormLayout" name="formLayout_2">
|
|
+ <item row="0" column="0">
|
|
+ <widget class="QLabel" name="label_11">
|
|
+ <property name="text">
|
|
+ <string>Level:</string>
|
|
+ </property>
|
|
+ <property name="buddy">
|
|
+ <cstring>levelCombo</cstring>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="0" column="1">
|
|
+ <widget class="QComboBox" name="levelCombo"/>
|
|
+ </item>
|
|
+ <item row="1" column="0">
|
|
+ <widget class="QLabel" name="label_8">
|
|
+ <property name="text">
|
|
+ <string>Client:</string>
|
|
+ </property>
|
|
+ <property name="buddy">
|
|
+ <cstring>clientCombo</cstring>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="1">
|
|
+ <widget class="QComboBox" name="clientCombo"/>
|
|
+ </item>
|
|
+ <item row="2" column="0">
|
|
+ <widget class="QLabel" name="label_9">
|
|
+ <property name="text">
|
|
+ <string>FileSet:</string>
|
|
+ </property>
|
|
+ <property name="buddy">
|
|
+ <cstring>filesetCombo</cstring>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="2" column="1">
|
|
+ <widget class="QComboBox" name="filesetCombo"/>
|
|
+ </item>
|
|
+ <item row="3" column="0">
|
|
+ <widget class="QLabel" name="label_3">
|
|
+ <property name="text">
|
|
+ <string>Pool:</string>
|
|
+ </property>
|
|
+ <property name="buddy">
|
|
+ <cstring>poolCombo</cstring>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="3" column="1">
|
|
+ <widget class="QComboBox" name="poolCombo"/>
|
|
+ </item>
|
|
+ <item row="4" column="0">
|
|
+ <widget class="QLabel" name="label_2">
|
|
+ <property name="text">
|
|
+ <string>Storage:</string>
|
|
+ </property>
|
|
+ <property name="buddy">
|
|
+ <cstring>storageCombo</cstring>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="4" column="1">
|
|
+ <widget class="QComboBox" name="storageCombo"/>
|
|
+ </item>
|
|
+ <item row="5" column="0">
|
|
+ <widget class="QLabel" name="label_7">
|
|
+ <property name="text">
|
|
+ <string>Catalog:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="5" column="1">
|
|
+ <widget class="QComboBox" name="catalogCombo"/>
|
|
+ </item>
|
|
+ <item row="6" column="0">
|
|
+ <widget class="QLabel" name="label_4">
|
|
+ <property name="text">
|
|
+ <string>Priority:</string>
|
|
+ </property>
|
|
+ <property name="buddy">
|
|
+ <cstring>prioritySpin</cstring>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="6" column="1">
|
|
+ <widget class="QSpinBox" name="prioritySpin">
|
|
+ <property name="minimumSize">
|
|
+ <size>
|
|
+ <width>60</width>
|
|
+ <height>0</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ <property name="maximumSize">
|
|
+ <size>
|
|
+ <width>60</width>
|
|
+ <height>16777215</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ <property name="baseSize">
|
|
+ <size>
|
|
+ <width>60</width>
|
|
+ <height>0</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ <property name="minimum">
|
|
+ <number>1</number>
|
|
+ </property>
|
|
+ <property name="maximum">
|
|
+ <number>10000</number>
|
|
+ </property>
|
|
+ <property name="value">
|
|
+ <number>10</number>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="Line" name="line_2">
|
|
+ <property name="sizePolicy">
|
|
+ <sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
|
+ <horstretch>0</horstretch>
|
|
+ <verstretch>0</verstretch>
|
|
+ </sizepolicy>
|
|
+ </property>
|
|
+ <property name="minimumSize">
|
|
+ <size>
|
|
+ <width>0</width>
|
|
+ <height>5</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ <property name="orientation">
|
|
+ <enum>Qt::Horizontal</enum>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <layout class="QHBoxLayout">
|
|
+ <item>
|
|
+ <spacer>
|
|
+ <property name="orientation">
|
|
+ <enum>Qt::Horizontal</enum>
|
|
+ </property>
|
|
+ <property name="sizeHint" stdset="0">
|
|
+ <size>
|
|
+ <width>40</width>
|
|
+ <height>20</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ </spacer>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QPushButton" name="okButton">
|
|
+ <property name="text">
|
|
+ <string>OK</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QPushButton" name="cancelButton">
|
|
+ <property name="text">
|
|
+ <string>Cancel</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ <resources>
|
|
+ <include location="../main.qrc"/>
|
|
+ </resources>
|
|
+ <connections/>
|
|
+</ui>
|
|
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 <QMessageBox>
|
|
+
|
|
+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 <dirent.h>
|
|
+#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 @@
|
|
+<?xml version="1.0" encoding="UTF-8"?>
|
|
+<ui version="4.0">
|
|
+ <class>sdStatus</class>
|
|
+ <widget class="QWidget" name="sdStatus">
|
|
+ <property name="geometry">
|
|
+ <rect>
|
|
+ <x>0</x>
|
|
+ <y>0</y>
|
|
+ <width>518</width>
|
|
+ <height>435</height>
|
|
+ </rect>
|
|
+ </property>
|
|
+ <property name="windowTitle">
|
|
+ <string>Form</string>
|
|
+ </property>
|
|
+ <layout class="QVBoxLayout" name="verticalLayout_2">
|
|
+ <item>
|
|
+ <layout class="QVBoxLayout" name="verticalLayout">
|
|
+ <item>
|
|
+ <widget class="QGroupBox" name="groupBox">
|
|
+ <property name="title">
|
|
+ <string>Storage Daemon Status</string>
|
|
+ </property>
|
|
+ <layout class="QGridLayout" name="gridLayout">
|
|
+ <item row="1" column="1">
|
|
+ <widget class="QLabel" name="labelName">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="0">
|
|
+ <widget class="QLabel" name="label">
|
|
+ <property name="text">
|
|
+ <string>Name:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="3" column="3">
|
|
+ <widget class="QLabel" name="labelPlugins">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="2">
|
|
+ <widget class="QLabel" name="label_3">
|
|
+ <property name="text">
|
|
+ <string>Started:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="1" column="3">
|
|
+ <widget class="QLabel" name="labelStarted">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="3" column="1">
|
|
+ <widget class="QLabel" name="labelVersion">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="3" column="0">
|
|
+ <widget class="QLabel" name="label_2">
|
|
+ <property name="text">
|
|
+ <string>Version:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item row="3" column="2">
|
|
+ <widget class="QLabel" name="label_4">
|
|
+ <property name="text">
|
|
+ <string>Plugins:</string>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QGroupBox" name="groupBox_2">
|
|
+ <property name="title">
|
|
+ <string>Running Jobs</string>
|
|
+ </property>
|
|
+ <layout class="QHBoxLayout" name="horizontalLayout">
|
|
+ <item>
|
|
+ <widget class="QTableWidget" name="tableRunning">
|
|
+ <property name="selectionMode">
|
|
+ <enum>QAbstractItemView::SingleSelection</enum>
|
|
+ </property>
|
|
+ <attribute name="verticalHeaderVisible">
|
|
+ <bool>false</bool>
|
|
+ </attribute>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QGroupBox" name="groupBox_3">
|
|
+ <property name="title">
|
|
+ <string>Terminated Jobs</string>
|
|
+ </property>
|
|
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
+ <item>
|
|
+ <widget class="QTableWidget" name="tableTerminated">
|
|
+ <property name="selectionMode">
|
|
+ <enum>QAbstractItemView::SingleSelection</enum>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </item>
|
|
+ <item>
|
|
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
+ <item>
|
|
+ <widget class="QLabel" name="statusBar">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ <item>
|
|
+ <spacer name="horizontalSpacer">
|
|
+ <property name="orientation">
|
|
+ <enum>Qt::Horizontal</enum>
|
|
+ </property>
|
|
+ <property name="sizeHint" stdset="0">
|
|
+ <size>
|
|
+ <width>40</width>
|
|
+ <height>20</height>
|
|
+ </size>
|
|
+ </property>
|
|
+ </spacer>
|
|
+ </item>
|
|
+ <item>
|
|
+ <widget class="QPushButton" name="pushButton">
|
|
+ <property name="text">
|
|
+ <string/>
|
|
+ </property>
|
|
+ <property name="icon">
|
|
+ <iconset resource="../main.qrc">
|
|
+ <normaloff>:/images/view-refresh.png</normaloff>:/images/view-refresh.png</iconset>
|
|
+ </property>
|
|
+ </widget>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </item>
|
|
+ </layout>
|
|
+ </widget>
|
|
+ <resources>
|
|
+ <include location="../main.qrc"/>
|
|
+ </resources>
|
|
+ <connections/>
|
|
+</ui>
|
|
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 <QWidget>
|
|
+#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
|
|
|