]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/status/storstat.cpp
Make bad Storage check in is_on_same_storage non-fatal
[bacula/bacula] / bacula / src / qt-console / status / storstat.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2010 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *
30  *   Dirk Bartley, March 2007
31  */
32  
33 #include "bat.h"
34 #include <QAbstractEventDispatcher>
35 #include <QTableWidgetItem>
36 #include "storstat.h"
37 #include "mount/mount.h"
38 #include "label/label.h"
39
40 static bool working = false;     /* prevent timer recursion */
41
42 /*
43 .status storage=<storage-name> <keyword>
44 where <storage-name> is the storage name in the Director, and 
45 <keyword> is one of the following:
46 header
47 running
48 terminated
49
50 waitreservation
51 devices
52 volumes
53 spooling
54 */
55
56 /*
57  * Constructor for the class
58  */
59 StorStat::StorStat(QString &storage, QTreeWidgetItem *parentTreeWidgetItem)
60    : Pages()
61 {
62    m_storage = storage;
63    setupUi(this);
64    pgInitialize(tr("Storage Status %1").arg(m_storage), parentTreeWidgetItem);
65    QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
66    thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/status.png")));
67    m_cursor = new QTextCursor(textEditHeader->document());
68
69    m_timer = new QTimer(this);
70    readSettings();
71
72    createConnections();
73    m_timer->start(1000);
74    setCurrent();
75
76    dockPage();
77 }
78
79 void StorStat::getFont()
80 {
81    QFont font = textEditHeader->font();
82
83    QString dirname;
84    m_console->getDirResName(dirname);
85    QSettings settings(dirname, "bat");
86    settings.beginGroup("Console");
87    font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
88    font.setPointSize(settings.value("consolePointSize", 10).toInt());
89    font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
90    settings.endGroup();
91    textEditHeader->setFont(font);
92 }
93
94 /*
95  * Write the m_splitter settings in the destructor
96  */
97 StorStat::~StorStat()
98 {
99    writeSettings();
100 }
101
102 /*
103  * Populate all tables and header widgets
104  */
105 void StorStat::populateAll()
106 {
107    populateTerminated();
108    populateCurrentTab(tabWidget->currentIndex());
109 }
110
111 /*
112  *  Timer is triggered, see if is current and repopulate.
113  */
114 void StorStat::timerTriggered()
115 {
116    double value = timerDisplay->value();
117    value -= 1;
118    if (value <= 0 && !working) {
119       working = true;
120       value = spinBox->value();
121       bool iscurrent = mainWin->tabWidget->currentIndex() == mainWin->tabWidget->indexOf(this);
122       if (((isDocked() && iscurrent) || (!isDocked())) && (checkBox->checkState() == Qt::Checked)) {
123          populateAll();
124       }
125       working = false;
126    }
127    timerDisplay->display(value);
128 }
129
130 /*
131  * Populate header text widget
132  */
133 void StorStat::populateHeader()
134 {
135    QString command = QString(".status storage=\"" + m_storage + "\" header");
136    if (mainWin->m_commandDebug)
137       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
138    QStringList results;
139    textEditHeader->clear();
140
141    if (m_console->dir_cmd(command, results)) {
142       foreach (QString line, results) {
143          line += "\n";
144          textEditHeader->insertPlainText(line);
145       }
146    }
147 }
148
149 void StorStat::populateWaitReservation()
150 {
151    QString command = QString(".status storage=\"" + m_storage + "\" waitreservation");
152    if (mainWin->m_commandDebug)
153       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
154    QStringList results;
155    textEditWaitReservation->clear();
156
157    if (m_console->dir_cmd(command, results)) {
158       foreach (QString line, results) {
159          line += "\n";
160          textEditWaitReservation->insertPlainText(line);
161       }
162    }
163 }
164
165 void StorStat::populateDevices()
166 {
167    QString command = QString(".status storage=\"" + m_storage + "\" devices");
168    if (mainWin->m_commandDebug)
169       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
170    QStringList results;
171    textEditDevices->clear();
172
173    if (m_console->dir_cmd(command, results)) {
174       foreach (QString line, results) {
175          line += "\n";
176          textEditDevices->insertPlainText(line);
177       }
178    }
179 }
180
181 void StorStat::populateVolumes()
182 {
183    QString command = QString(".status storage=\"" + m_storage + "\" volumes");
184    if (mainWin->m_commandDebug)
185       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
186    QStringList results;
187    textEditVolumes->clear();
188
189    if (m_console->dir_cmd(command, results)) {
190       foreach (QString line, results) {
191          line += "\n";
192          textEditVolumes->insertPlainText(line);
193       }
194    }
195 }
196
197 void StorStat::populateSpooling()
198 {
199    QString command = QString(".status storage=\"" + m_storage + "\" spooling");
200    if (mainWin->m_commandDebug)
201       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
202    QStringList results;
203    textEditSpooling->clear();
204
205    if (m_console->dir_cmd(command, results)) {
206       foreach (QString line, results) {
207          line += "\n";
208          textEditSpooling->insertPlainText(line);
209       }
210    }
211 }
212
213 void StorStat::populateRunning()
214 {
215    QString command = QString(".status storage=\"" + m_storage + "\" running");
216    if (mainWin->m_commandDebug)
217       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
218    QStringList results;
219    textEditRunning->clear();
220
221    if (m_console->dir_cmd(command, results)) {
222       foreach (QString line, results) {
223          line += "\n";
224          textEditRunning->insertPlainText(line);
225       }
226    }
227 }
228
229 /*
230  * Populate teminated table
231  */
232 void StorStat::populateTerminated()
233 {
234    QString command = QString(".status storage=\"" + m_storage + "\" terminated");
235    if (mainWin->m_commandDebug)
236       Pmsg1(000, "sending command : %s\n",command.toUtf8().data());
237    QStringList results;
238    QBrush blackBrush(Qt::black);
239
240    terminatedTable->clear();
241    QStringList headerlist = (QStringList()
242       << tr("Job Id") << tr("Job Level") << tr("Job Files")
243       << tr("Job Bytes") << tr("Job Status") << tr("Job Time") 
244       << tr("Job Name"));
245    QStringList flaglist = (QStringList()
246       << "R" << "L" << "R" << "R" << "LC" 
247       << "L" << "L");
248
249    terminatedTable->setColumnCount(headerlist.size());
250    terminatedTable->setHorizontalHeaderLabels(headerlist);
251
252    if (m_console->dir_cmd(command, results)) {
253       int row = 0;
254       QTableWidgetItem* p_tableitem;
255       terminatedTable->setRowCount(results.size());
256       foreach (QString line, results) {
257          /* Iterate through the record returned from the query */
258          QStringList fieldlist = line.split("\t");
259          int column = 0;
260          QString statusCode("");
261          /* Iterate through fields in the record */
262          foreach (QString field, fieldlist) {
263             field = field.trimmed();  /* strip leading & trailing spaces */
264             p_tableitem = new QTableWidgetItem(field, 1);
265             p_tableitem->setForeground(blackBrush);
266             p_tableitem->setFlags(0);
267             if (flaglist[column].contains("R"))
268                p_tableitem->setTextAlignment(Qt::AlignRight);
269             if (flaglist[column].contains("C")) {
270                if (field == "OK")
271                   p_tableitem->setBackground(Qt::green);
272                else
273                   p_tableitem->setBackground(Qt::red);
274             }
275             terminatedTable->setItem(row, column, p_tableitem);
276             column += 1;
277          }
278          row += 1;
279       }
280    }
281    terminatedTable->resizeColumnsToContents();
282    terminatedTable->resizeRowsToContents();
283    terminatedTable->verticalHeader()->hide();
284 }
285
286 /*
287  * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
288  * The tree has been populated.
289  */
290 void StorStat::PgSeltreeWidgetClicked()
291 {
292    if (!m_populated) {
293       populateAll();
294       m_populated=true;
295    }
296 }
297
298 /*
299  *  Virtual function override of pages function which is called when this page
300  *  is visible on the stack
301  */
302 void StorStat::currentStackItem()
303 {
304    populateAll();
305    timerDisplay->display(spinBox->value());
306    if (!m_populated) {
307       m_populated=true;
308    }
309 }
310
311 /*
312  * Function to create connections for context sensitive menu for this and
313  * the page selector
314  */
315 void StorStat::createConnections()
316 {
317    connect(actionRefresh, SIGNAL(triggered()), this, SLOT(populateAll()));
318    connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(populateCurrentTab(int)));
319    connect(mountButton, SIGNAL(pressed()), this, SLOT(mountButtonPushed()));
320    connect(umountButton, SIGNAL(pressed()), this, SLOT(umountButtonPushed()));
321    connect(labelButton, SIGNAL(pressed()), this, SLOT(labelButtonPushed()));
322    connect(releaseButton, SIGNAL(pressed()), this, SLOT(releaseButtonPushed()));
323    terminatedTable->setContextMenuPolicy(Qt::ActionsContextMenu);
324    terminatedTable->addAction(actionRefresh);
325    connect(m_timer, SIGNAL(timeout()), this, SLOT(timerTriggered()));
326 }
327
328 /*
329  * Save user settings associated with this page
330  */
331 void StorStat::writeSettings()
332 {
333    QSettings settings(m_console->m_dir->name(), "bat");
334    settings.beginGroup(m_groupText);
335    settings.setValue(m_splitText, splitter->saveState());
336    settings.setValue("refreshInterval", spinBox->value());
337    settings.setValue("refreshCheck", checkBox->checkState());
338    settings.endGroup();
339
340    settings.beginGroup("OpenOnExit");
341    QString toWrite = "StorageStatus_" + m_storage;
342    settings.setValue(toWrite, 1);
343    settings.endGroup();
344 }
345
346 /*
347  * Read and restore user settings associated with this page
348  */
349 void StorStat::readSettings()
350 {
351    m_groupText = "StorStatPage";
352    m_splitText = "splitterSizes_0";
353    QSettings settings(m_console->m_dir->name(), "bat");
354    settings.beginGroup(m_groupText);
355    if (settings.contains(m_splitText)) { splitter->restoreState(settings.value(m_splitText).toByteArray()); }
356    spinBox->setValue(settings.value("refreshInterval", 28).toInt());
357    checkBox->setCheckState((Qt::CheckState)settings.value("refreshCheck", Qt::Checked).toInt());
358    settings.endGroup();
359
360    timerDisplay->display(spinBox->value());
361 }
362
363 /*
364  * Populate the text edit window in the current tab
365  */
366 void StorStat::populateCurrentTab(int index)
367 {
368    if (index == 0)
369       populateHeader();
370    if (index == 1)
371       populateWaitReservation();
372    if (index == 2)
373       populateDevices();
374    if (index == 3)
375       populateVolumes();
376    if (index == 4)
377       populateSpooling();
378    if (index == 5)
379       populateRunning();
380 }
381
382 /*
383  * execute mount in console
384  */
385 void StorStat::mountButtonPushed()
386 {
387    int haschanger = 3;
388
389    /* Set up query QString and header QStringList */
390    QString query("SELECT AutoChanger AS Changer"
391             " FROM Storage WHERE Name='" + m_storage + "'"
392             " ORDER BY Name" );
393
394    QStringList results;
395    /* This could be a log item */
396    if (mainWin->m_sqlDebug) {
397       Pmsg1(000, "Storage query cmd : %s\n",query.toUtf8().data());
398    }
399    if (m_console->sql_cmd(query, results)) {
400       int resultCount = results.count();
401       if (resultCount == 1){
402          QString resultline;
403          QString field;
404          QStringList fieldlist;
405          /* there will only be one of these */
406          foreach (resultline, results) {
407             fieldlist = resultline.split("\t");
408             int index = 0;
409             /* Iterate through fields in the record */
410             foreach (field, fieldlist) {
411                field = field.trimmed();  /* strip leading & trailing spaces */
412                haschanger = field.toInt();
413                index++;
414             }
415          }
416       }
417    }
418
419    Pmsg1(000, "haschanger is : %i\n", haschanger);
420    if (haschanger == 0){
421       /* no autochanger, just execute the command in the console */
422       QString cmd("mount storage=" + m_storage);
423       consoleCommand(cmd);
424    } else if (haschanger != 3) {
425       setConsoleCurrent();
426       /* if this storage is an autochanger, lets ask for the slot */
427       new mountDialog(m_console, m_storage);
428    }
429 }
430
431 /*
432  * execute umount in console
433  */
434 void StorStat::umountButtonPushed()
435 {
436    QString cmd("umount storage=" + m_storage);
437    consoleCommand(cmd);
438 }
439
440 /* Release a tape in the drive */
441 void StorStat::releaseButtonPushed()
442 {
443    QString cmd("release storage=");
444    cmd += m_storage;
445    consoleCommand(cmd);
446 }
447
448 /* Label Media populating current storage by default */
449 void StorStat::labelButtonPushed()
450 {
451    new labelPage(m_storage);
452 }