2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
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 two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
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.
18 You should have received a copy of the GNU 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
23 Bacula® is a registered trademark of John Walker.
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.
33 * Kern Sibbald, January MMVII
37 #include <QAbstractEventDispatcher>
41 Console::Console(QStackedWidget *parent)
52 m_textEdit = textEdit; /* our console screen */
53 m_cursor = new QTextCursor(m_textEdit->document());
54 mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
56 /* Check for messages every 5 seconds */
57 // m_timer = new QTimer(this);
58 // QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
59 // m_timer->start(5000);
66 void Console::poll_messages()
68 m_messages_pending = true;
71 /* Terminate any open socket */
72 void Console::terminate()
82 * Connect to Director. If there are more than one, put up
83 * a modal dialog so that the user chooses one.
85 void Console::connect()
90 m_textEdit = textEdit; /* our console screen */
93 mainWin->set_status("No Director found.");
97 mainWin->set_status("Already connected.");
101 memset(&jcr, 0, sizeof(jcr));
103 mainWin->set_statusf(_("Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
104 display_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
106 /* Give GUI a chance */
107 app->processEvents();
110 /* If cons==NULL, default console will be used */
111 CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
114 if (m_dir->heartbeat_interval) {
115 heart_beat = m_dir->heartbeat_interval;
117 heart_beat = cons->heartbeat_interval;
122 m_sock = bnet_connect(NULL, 5, 15, heart_beat,
123 _("Director daemon"), m_dir->address,
124 NULL, m_dir->DIRport, 0);
125 if (m_sock == NULL) {
126 mainWin->set_status("Connection failed");
129 /* Update page selector to green to indicate that Console is connected */
130 mainWin->actionConnect->setIcon(QIcon(":images/connected.png"));
131 QBrush greenBrush(Qt::green);
132 QTreeWidgetItem *item = mainWin->getFromHash(this);
133 item->setForeground(0, greenBrush);
136 jcr.dir_bsock = m_sock;
138 if (!authenticate_director(&jcr, m_dir, cons)) {
139 display_text(m_sock->msg);
143 /* Give GUI a chance */
144 app->processEvents();
146 mainWin->set_status(_("Initializing ..."));
148 /* Set up input notifier */
149 m_notifier = new QSocketNotifier(m_sock->fd, QSocketNotifier::Read, 0);
150 QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
156 dir_cmd(".jobs", job_list);
157 dir_cmd(".clients", client_list);
158 dir_cmd(".filesets", fileset_list);
159 dir_cmd(".messages", messages_list);
160 dir_cmd(".pools", pool_list);
161 dir_cmd(".storage", storage_list);
162 dir_cmd(".types", type_list);
163 dir_cmd(".levels", level_list);
165 mainWin->set_status(_("Connected"));
169 bool Console::dir_cmd(QString &cmd, QStringList &results)
171 return dir_cmd(cmd.toUtf8().data(), results);
175 * Send a command to the Director, and return the
176 * results in a QStringList.
178 bool Console::dir_cmd(const char *cmd, QStringList &results)
184 while ((stat = read()) > 0) {
185 strip_trailing_junk(msg());
190 return true; /* ***FIXME*** return any command error */
193 bool Console::sql_cmd(QString &query, QStringList &results)
195 return sql_cmd(query.toUtf8().data(), results);
199 * Send an sql query to the Director, and return the
200 * results in a QStringList.
202 bool Console::sql_cmd(const char *query, QStringList &results)
204 if (!is_connectedGui())
207 POOL_MEM cmd(PM_MESSAGE);
211 pm_strcpy(cmd, ".sql query=\"");
212 pm_strcat(cmd, query);
213 pm_strcat(cmd, "\"");
215 while ((stat = read()) > 0) {
216 strip_trailing_junk(msg());
221 return true; /* ***FIXME*** return any command error */
226 * Send a job name to the director, and read all the resulting
229 bool Console::get_job_defaults(struct job_defaults &job_defs)
237 scmd = QString(".defaults job=\"%1\"").arg(job_defs.job_name);
239 while ((stat = read()) > 0) {
240 def = strchr(msg(), '=');
244 /* Pointer to default value */
246 strip_trailing_junk(def);
248 if (strcmp(msg(), "job") == 0) {
249 if (strcmp(def, job_defs.job_name.toUtf8().data()) != 0) {
254 if (strcmp(msg(), "pool") == 0) {
255 job_defs.pool_name = def;
258 if (strcmp(msg(), "messages") == 0) {
259 job_defs.messages_name = def;
262 if (strcmp(msg(), "client") == 0) {
263 job_defs.client_name = def;
266 if (strcmp(msg(), "storage") == 0) {
267 job_defs.store_name = def;
270 if (strcmp(msg(), "where") == 0) {
271 job_defs.where = def;
274 if (strcmp(msg(), "level") == 0) {
275 job_defs.level = def;
278 if (strcmp(msg(), "type") == 0) {
282 if (strcmp(msg(), "fileset") == 0) {
283 job_defs.fileset_name = def;
286 if (strcmp(msg(), "catalog") == 0) {
287 job_defs.catalog_name = def;
290 if (strcmp(msg(), "enabled") == 0) {
291 job_defs.enabled = *def == '1' ? true : false;
297 bsnprintf(cmd, sizeof(cmd), "job=%s pool=%s client=%s storage=%s where=%s\n"
298 "level=%s type=%s fileset=%s catalog=%s enabled=%d\n",
299 job_defs.job_name.toUtf8().data(), job_defs.pool_name.toUtf8().data(),
300 job_defs.client_name.toUtf8().data(),
301 job_defs.pool_name.toUtf8().data(), job_defs.messages_name.toUtf8().data(),
302 job_defs.store_name.toUtf8().data(),
303 job_defs.where.toUtf8().data(), job_defs.level.toUtf8().data(),
304 job_defs.type.toUtf8().data(), job_defs.fileset_name.toUtf8().data(),
305 job_defs.catalog_name.toUtf8().data(), job_defs.enabled);
318 * Save user settings associated with this console
320 void Console::writeSettings()
322 QFont font = get_font();
324 QSettings settings(m_dir->name(), "bat");
325 settings.beginGroup("Console");
326 settings.setValue("consoleFont", font.family());
327 settings.setValue("consolePointSize", font.pointSize());
328 settings.setValue("consoleFixedPitch", font.fixedPitch());
333 * Read and restore user settings associated with this console
335 void Console::readSettings()
337 QFont font = get_font();
339 QSettings settings(m_dir->name(), "bat");
340 settings.beginGroup("Console");
341 font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
342 font.setPointSize(settings.value("consolePointSize", 10).toInt());
343 font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
345 m_textEdit->setFont(font);
349 * Set the console textEdit font
351 void Console::set_font()
354 QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
356 m_textEdit->setFont(font);
361 * Get the console text edit font
363 const QFont Console::get_font()
365 return m_textEdit->font();
369 * Slot for responding to status dir button on button bar
371 void Console::status_dir()
373 QString cmd("status dir");
378 * Slot for responding to messages button on button bar
380 void Console::messages()
382 QString cmd(".messages");
387 * Put text into the console window
389 void Console::display_textf(const char *fmt, ...)
394 va_start(arg_ptr, fmt);
395 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
400 void Console::display_text(const QString buf)
402 m_cursor->movePosition(QTextCursor::End);
403 m_cursor->insertText(buf);
407 void Console::display_text(const char *buf)
409 m_cursor->movePosition(QTextCursor::End);
410 m_cursor->insertText(buf);
413 /* Position cursor to end of screen */
414 void Console::update_cursor()
416 QApplication::restoreOverrideCursor();
417 m_textEdit->moveCursor(QTextCursor::End);
418 m_textEdit->ensureCursorVisible();
422 * This should be moved into a bSocket class
432 /* Send a command to the Director */
433 void Console::write_dir(const char *msg)
436 mainWin->set_status(_("Processing command ..."));
437 QApplication::setOverrideCursor(Qt::WaitCursor);
440 mainWin->set_status(" Director not connected. Click on connect button.");
441 mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
442 QBrush redBrush(Qt::red);
443 QTreeWidgetItem *item = mainWin->getFromHash(this);
444 item->setForeground(0, redBrush);
449 int Console::write(const QString msg)
451 return write(msg.toUtf8().data());
454 int Console::write(const char *msg)
456 m_sock->msglen = pm_strcpy(m_sock->msg, msg);
458 if (commDebug) Pmsg1(000, "send: %s\n", msg);
459 return m_sock->send();
463 * Get to main command prompt
465 void Console::beginNewCommand()
479 void Console::displayToPrompt()
482 if (commDebug) Pmsg0(000, "DisplaytoPrompt\n");
483 while (!m_at_prompt) {
484 if ((stat=read()) > 0) {
488 if (commDebug) Pmsg1(000, "endDisplaytoPrompt=%d\n", stat);
491 void Console::discardToPrompt()
494 if (commDebug) Pmsg0(000, "discardToPrompt\n");
495 while (!m_at_prompt) {
498 if (commDebug) Pmsg1(000, "endDisplayToPrompt=%d\n", stat);
503 * Blocking read from director
510 stat = bnet_wait_data_intr(m_sock, 1);
514 app->processEvents();
515 if (m_api_set && m_messages_pending) {
516 write_dir(".messages");
517 m_messages_pending = false;
520 stat = m_sock->recv();
526 if (commDebug) Pmsg1(000, "got: %s", m_sock->msg);
528 switch (m_sock->msglen) {
529 case BNET_SERVER_READY:
530 if (m_api_set && m_messages_pending) {
531 write_dir(".messages");
532 m_messages_pending = false;
536 case BNET_MSGS_PENDING:
537 if (commDebug) Pmsg0(000, "MSGS PENDING\n");
538 m_messages_pending = true;
541 if (commDebug) Pmsg0(000, "CMD OK\n");
545 if (commDebug) Pmsg0(000, "CMD BEGIN\n");
549 if (commDebug) Pmsg0(000, "PROMPT\n");
551 mainWin->set_status(_("At prompt waiting for input ..."));
553 QApplication::restoreOverrideCursor();
555 case BNET_CMD_FAILED:
556 if (commDebug) Pmsg0(000, "CMD FAIL\n");
557 mainWin->set_status(_("Command failed. At prompt waiting for input ..."));
559 QApplication::restoreOverrideCursor();
561 /* We should not get this one */
563 if (commDebug) Pmsg0(000, "EOD\n");
564 mainWin->set_status_ready();
566 QApplication::restoreOverrideCursor();
571 case BNET_START_SELECT:
572 new selectDialog(this);
575 new runCmdDialog(this);
578 m_sock->recv(); /* get the message */
580 QMessageBox::critical(this, "Error", msg(), QMessageBox::Ok);
582 case BNET_WARNING_MSG:
583 m_sock->recv(); /* get the message */
585 QMessageBox::critical(this, "Warning", msg(), QMessageBox::Ok);
588 m_sock->recv(); /* get the message */
590 mainWin->set_status(msg());
593 if (is_bnet_stop(m_sock)) { /* error or term request */
596 mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
597 QBrush redBrush(Qt::red);
598 QTreeWidgetItem *item = mainWin->getFromHash(this);
599 item->setForeground(0, redBrush);
600 m_notifier->setEnabled(false);
603 mainWin->set_status(_("Director disconnected."));
604 QApplication::restoreOverrideCursor();
612 /* Called by signal when the Director has output for us */
613 void Console::read_dir(int fd)
618 if (commDebug) Pmsg0(000, "read_dir\n");
619 while ((stat = read()) >= 0) {
625 * When the notifier is enabled, read_dir() will automatically be
626 * called by the Qt event loop when ever there is any output
627 * from the Directory, and read_dir() will then display it on
630 * When we are in a bat dialog, we want to control *all* output
631 * from the Directory, so we set notify to off.
632 * m_console->notifiy(false);
634 void Console::notify(bool enable)
636 m_notifier->setEnabled(enable);
639 void Console::setDirectorTreeItem(QTreeWidgetItem *item)
641 m_directorTreeItem = item;
644 void Console::setDirRes(DIRRES *dir)
650 * To have the ability to get the name of the director resource.
652 void Console::getDirResName(QString &name_returned)
654 name_returned = m_dir->name();
657 bool Console::is_connectedGui()
659 if (is_connected()) {
662 QString message("Director ");
663 message += m_dir->name();
664 message += " is curerntly disconnected\n Please reconnect!!";
665 QMessageBox::warning(this, tr("Bat"),
666 tr(message.toUtf8().data()), QMessageBox::Ok );