From 38a8c834529d9d02032fbf7db2afd79ed6089121 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 20 Sep 2010 16:49:01 +0200 Subject: [PATCH] First cut of bat rerun a Job from Jobs Run --- bacula/src/dird/ua_run.c | 198 +++++++++++++++++++--- bacula/src/qt-console/joblist/joblist.cpp | 41 ++++- bacula/src/qt-console/joblist/joblist.h | 8 + bacula/src/qt-console/joblist/joblist.ui | 23 ++- bacula/src/qt-console/pages.cpp | 13 +- bacula/src/qt-console/run/run.cpp | 5 +- bacula/src/qt-console/run/runcmd.cpp | 13 +- 7 files changed, 257 insertions(+), 44 deletions(-) diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index 7dde36effb..d08bfc557f 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2001-2008 Free Software Foundation Europe e.V. + Copyright (C) 2001-2010 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -31,7 +31,6 @@ * * Kern Sibbald, December MMI * - * Version $Id$ */ #include "bacula.h" @@ -750,8 +749,24 @@ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char char ec1[30]; char dt[MAX_TIME_LENGTH]; case JT_ADMIN: - if (ua->api) ua->signal(BNET_RUN_CMD); - ua->send_msg(_("Run %s job\n" + if (ua->api) { + ua->signal(BNET_RUN_CMD); + ua->send_msg("Type: Admin\n" + "Title: Run Admin Job\n" + "JobName: %s\n" + "FileSet: %s\n" + "Client: %s\n" + "Storage: %s\n" + "When: %s\n" + "Priority: %d\n", + job->name(), + jcr->fileset->name(), + NPRT(jcr->client->name()), + jcr->wstore?jcr->wstore->name():"*None*", + bstrutime(dt, sizeof(dt), jcr->sched_time), + jcr->JobPriority); + } else { + ua->send_msg(_("Run %s job\n" "JobName: %s\n" "FileSet: %s\n" "Client: %s\n" @@ -765,13 +780,38 @@ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char jcr->wstore?jcr->wstore->name():"*None*", bstrutime(dt, sizeof(dt), jcr->sched_time), jcr->JobPriority); + } jcr->set_JobLevel(L_FULL); break; case JT_BACKUP: case JT_VERIFY: if (jcr->getJobType() == JT_BACKUP) { - if (ua->api) ua->signal(BNET_RUN_CMD); - ua->send_msg(_("Run %s job\n" + if (ua->api) { + ua->signal(BNET_RUN_CMD); + ua->send_msg("Type: Backup\n" + "Title: Run Backup Job\n" + "JobName: %s\n" + "Level: %s\n" + "Client: %s\n" + "FileSet: %s\n" + "Pool: %s\n" + "Storage: %s\n" + "When: %s\n" + "Priority: %d\n" + "%s%s%s", + job->name(), + level_to_str(jcr->getJobLevel()), + jcr->client->name(), + jcr->fileset->name(), + NPRT(jcr->pool->name()), + jcr->wstore?jcr->wstore->name():"*None*", + bstrutime(dt, sizeof(dt), jcr->sched_time), + jcr->JobPriority, + jcr->plugin_options?"Plugin Options: ":"", + jcr->plugin_options?jcr->plugin_options:"", + jcr->plugin_options?"\n":""); + } else { + ua->send_msg(_("Run %s job\n" "JobName: %s\n" "Level: %s\n" "Client: %s\n" @@ -781,7 +821,6 @@ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char "When: %s\n" "Priority: %d\n" "%s%s%s"), - _("Backup"), job->name(), level_to_str(jcr->getJobLevel()), jcr->client->name(), @@ -793,6 +832,7 @@ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char jcr->plugin_options?"Plugin Options: ":"", jcr->plugin_options?jcr->plugin_options:"", jcr->plugin_options?"\n":""); + } } else { /* JT_VERIFY */ const char *Name; if (jcr->verify_job) { @@ -806,8 +846,32 @@ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char if (!verify_list) { verify_list = ""; } - if (ua->api) ua->signal(BNET_RUN_CMD); - ua->send_msg(_("Run %s job\n" + if (ua->api) { + ua->signal(BNET_RUN_CMD); + ua->send_msg("Type: Verify\n" + "Title: Run Verify Job\n" + "JobName: %s\n" + "Level: %s\n" + "Client: %s\n" + "FileSet: %s\n" + "Pool: %s (From %s)\n" + "Storage: %s (From %s)\n" + "Verify Job: %s\n" + "Verify List: %s\n" + "When: %s\n" + "Priority: %d\n", + job->name(), + level_to_str(jcr->getJobLevel()), + jcr->client->name(), + jcr->fileset->name(), + NPRT(jcr->pool->name()), jcr->pool_source, + jcr->rstore->name(), jcr->rstore_source, + Name, + verify_list, + bstrutime(dt, sizeof(dt), jcr->sched_time), + jcr->JobPriority); + } else { + ua->send_msg(_("Run %s job\n" "JobName: %s\n" "Level: %s\n" "Client: %s\n" @@ -829,6 +893,7 @@ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char verify_list, bstrutime(dt, sizeof(dt), jcr->sched_time), jcr->JobPriority); + } } break; case JT_RESTORE: @@ -845,10 +910,38 @@ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char jcr->set_JobLevel(L_FULL); /* default level */ Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId); if (jcr->RestoreJobId == 0) { - if (ua->api) ua->signal(BNET_RUN_CMD); /* RegexWhere is take before RestoreWhere */ if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) { - ua->send_msg(_("Run Restore job\n" + if (ua->api) { + ua->signal(BNET_RUN_CMD); + ua->send_msg("Type: Restore\n" + "Title: Run Restore Job\n" + "JobName: %s\n" + "Bootstrap: %s\n" + "RegexWhere: %s\n" + "Replace: %s\n" + "FileSet: %s\n" + "Backup Client: %s\n" + "Restore Client: %s\n" + "Storage: %s\n" + "When: %s\n" + "Catalog: %s\n" + "Priority: %d\n" + "Plugin Options: %s\n", + job->name(), + NPRT(jcr->RestoreBootstrap), + jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere, + replace, + jcr->fileset->name(), + client_name, + jcr->client->name(), + jcr->rstore->name(), + bstrutime(dt, sizeof(dt), jcr->sched_time), + jcr->catalog->name(), + jcr->JobPriority, + NPRT(jcr->plugin_options)); + } else { + ua->send_msg(_("Run Restore job\n" "JobName: %s\n" "Bootstrap: %s\n" "RegexWhere: %s\n" @@ -873,9 +966,38 @@ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char jcr->catalog->name(), jcr->JobPriority, NPRT(jcr->plugin_options)); - + } } else { - ua->send_msg(_("Run Restore job\n" + if (ua->api) { + ua->signal(BNET_RUN_CMD); + ua->send_msg("Type: Restore\n" + "Title: Run Restore job\n" + "JobName: %s\n" + "Bootstrap: %s\n" + "Where: %s\n" + "Replace: %s\n" + "FileSet: %s\n" + "Backup Client: %s\n" + "Restore Client: %s\n" + "Storage: %s\n" + "When: %s\n" + "Catalog: %s\n" + "Priority: %d\n" + "Plugin Options: %s\n", + job->name(), + NPRT(jcr->RestoreBootstrap), + jcr->where?jcr->where:NPRT(job->RestoreWhere), + replace, + jcr->fileset->name(), + client_name, + jcr->client->name(), + jcr->rstore->name(), + bstrutime(dt, sizeof(dt), jcr->sched_time), + jcr->catalog->name(), + jcr->JobPriority, + NPRT(jcr->plugin_options)); + } else { + ua->send_msg(_("Run Restore job\n" "JobName: %s\n" "Bootstrap: %s\n" "Where: %s\n" @@ -900,9 +1022,11 @@ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char jcr->catalog->name(), jcr->JobPriority, NPRT(jcr->plugin_options)); + } } } else { + /* ***FIXME*** This needs to be fixed for bat */ if (ua->api) ua->signal(BNET_RUN_CMD); ua->send_msg(_("Run Restore job\n" "JobName: %s\n" @@ -939,15 +1063,46 @@ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char break; case JT_COPY: case JT_MIGRATE: - const char *prt_type; - if (jcr->getJobType() == JT_COPY) { - prt_type = _("Run Copy job\n"); - } else { - prt_type = _("Run Migration job\n"); - } + char *prt_type; jcr->set_JobLevel(L_FULL); /* default level */ - if (ua->api) ua->signal(BNET_RUN_CMD); - ua->send_msg("%s" + if (ua->api) { + ua->signal(BNET_RUN_CMD); + if (jcr->getJobType() == JT_COPY) { + prt_type = (char *)"Type: Copy\nTitle: Run Copy Job\n"; + } else { + prt_type = (char *)"Type: Migration\nTitle: Run Migration Job\n"; + } + ua->send_msg("%s" + "JobName: %s\n" + "Bootstrap: %s\n" + "Client: %s\n" + "FileSet: %s\n" + "Pool: %s\n" + "Read Storage: %s\n" + "Write Storage: %s\n" + "JobId: %s\n" + "When: %s\n" + "Catalog: %s\n" + "Priority: %d\n", + prt_type, + job->name(), + NPRT(jcr->RestoreBootstrap), + jcr->client->name(), + jcr->fileset->name(), + NPRT(jcr->pool->name()), + jcr->rstore->name(), + jcr->wstore?jcr->wstore->name():"*None*", + jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1), + bstrutime(dt, sizeof(dt), jcr->sched_time), + jcr->catalog->name(), + jcr->JobPriority); + } else { + if (jcr->getJobType() == JT_COPY) { + prt_type = _("Run Copy job\n"); + } else { + prt_type = _("Run Migration job\n"); + } + ua->send_msg("%s" "JobName: %s\n" "Bootstrap: %s\n" "Client: %s\n" @@ -971,6 +1126,7 @@ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char bstrutime(dt, sizeof(dt), jcr->sched_time), jcr->catalog->name(), jcr->JobPriority); + } break; default: ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType()); diff --git a/bacula/src/qt-console/joblist/joblist.cpp b/bacula/src/qt-console/joblist/joblist.cpp index c81663158a..2cffc47ef1 100644 --- a/bacula/src/qt-console/joblist/joblist.cpp +++ b/bacula/src/qt-console/joblist/joblist.cpp @@ -56,7 +56,6 @@ JobList::JobList(const QString &mediaName, const QString &clientName, m_clientName = clientName; m_jobName = jobName; m_filesetName = filesetName; - m_filesetName = filesetName; pgInitialize("", parentTreeWidgetItem); QTreeWidgetItem* thisitem = mainWin->getFromHash(this); thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/emblem-system.png"))); @@ -134,6 +133,10 @@ void JobList::populateTable() m_startIndex = headerlist.indexOf(tr("Job Starttime")); m_filesIndex = headerlist.indexOf(tr("Job Files")); m_bytesIndex = headerlist.indexOf(tr("Job Bytes")); + m_levelIndex = headerlist.indexOf(tr("Job Level")); + m_nameIndex = headerlist.indexOf(tr("Job Name")); + m_filesetIndex = headerlist.indexOf(tr("File Set")); + m_clientIndex = headerlist.indexOf(tr("Client")); /* Initialize the QTableWidget */ m_checkCurrentWidget = false; @@ -415,6 +418,7 @@ void JobList::createConnections() connect(actionListFilesOnJob, SIGNAL(triggered()), this, SLOT(consoleListFilesOnJob())); connect(actionListJobMedia, SIGNAL(triggered()), this, SLOT(consoleListJobMedia())); connect(actionDeleteJob, SIGNAL(triggered()), this, SLOT(consoleDeleteJob())); + connect(actionRestartJob, SIGNAL(triggered()), this, SLOT(consoleRestartJob())); connect(actionPurgeFiles, SIGNAL(triggered()), this, SLOT(consolePurgeFiles())); connect(actionRestoreFromJob, SIGNAL(triggered()), this, SLOT(preRestoreFromJob())); connect(actionRestoreFromTime, SIGNAL(triggered()), this, SLOT(preRestoreFromTime())); @@ -453,6 +457,7 @@ void JobList::consoleListJobTotals() if (mainWin->m_longList) { cmd.prepend("l"); } consoleCommand(cmd); } + void JobList::consoleDeleteJob() { if (QMessageBox::warning(this, "Bat", @@ -472,6 +477,23 @@ void JobList::consoleDeleteJob() consoleCommand(cmd, false); populateTable(); } + +void JobList::consoleRestartJob() +{ + QString cmd; + + cmd = tr("run job=\"%1\" client=\"%2\" level=%3").arg(m_jobName).arg(m_clientName).arg(m_levelName); + if (m_filesetName != "" && m_filesetName != "*None*") { + cmd += tr(" fileset=\"%1\"").arg(m_filesetName); + } + + if (mainWin->m_commandDebug) Pmsg1(000, "Run cmd : %s\n",cmd.toUtf8().data()); + consoleCommand(cmd, false); + populateTable(); +} + + + void JobList::consolePurgeFiles() { if (QMessageBox::warning(this, "Bat", @@ -639,6 +661,7 @@ void JobList::selectionChanged() if (m_selectedJobsCount == 1) { mp_tableWidget->addAction(actionListFilesOnJob); mp_tableWidget->addAction(actionListJobMedia); + mp_tableWidget->addAction(actionRestartJob); mp_tableWidget->addAction(actionRestoreFromJob); mp_tableWidget->addAction(actionRestoreFromTime); mp_tableWidget->addAction(actionShowLogForJob); @@ -653,7 +676,19 @@ void JobList::selectionChanged() if (m_checkCurrentWidget) { int row = mp_tableWidget->currentRow(); QTableWidgetItem* jobitem = mp_tableWidget->item(row, 0); - m_currentJob = jobitem->text(); + m_currentJob = jobitem->text(); /* get JobId */ + jobitem = mp_tableWidget->item(row, m_clientIndex); + m_clientName = jobitem->text(); /* get Client Name */ + jobitem = mp_tableWidget->item(row, m_nameIndex); + m_jobName = jobitem->text(); /* get Job Name */ + jobitem = mp_tableWidget->item(row, m_levelIndex); + m_levelName = jobitem->text(); /* get level */ + jobitem = mp_tableWidget->item(row, m_filesetIndex); + if (jobitem) { + m_filesetName = jobitem->text(); /* get FileSet Name */ + } else { + m_filesetName = ""; + } /* include purged action or not */ jobitem = mp_tableWidget->item(row, m_purgedIndex); @@ -662,6 +697,7 @@ void JobList::selectionChanged() if (purged == tr("No") ) { mp_tableWidget->addAction(actionPurgeFiles); }*/ + /* include restore from time and job action or not */ jobitem = mp_tableWidget->item(row, m_typeIndex); QString type = jobitem->text(); @@ -673,6 +709,7 @@ void JobList::selectionChanged() mp_tableWidget->addAction(actionRestoreFromTime); } } + /* include cancel action or not */ jobitem = mp_tableWidget->item(row, m_statusIndex); QString status = jobitem->text(); diff --git a/bacula/src/qt-console/joblist/joblist.h b/bacula/src/qt-console/joblist/joblist.h index 6e9a022729..dceaf205fe 100644 --- a/bacula/src/qt-console/joblist/joblist.h +++ b/bacula/src/qt-console/joblist/joblist.h @@ -60,6 +60,7 @@ private slots: void consoleListJobMedia(); void consoleListJobTotals(); void consoleDeleteJob(); + void consoleRestartJob(); void consolePurgeFiles(); void preRestoreFromJob(); void preRestoreFromTime(); @@ -76,6 +77,7 @@ private: void prepareFilterWidgets(); void fillQueryString(QString &query); QSplitter *m_splitter; + QString m_groupText; QString m_splitText; QString m_mediaName; @@ -83,11 +85,17 @@ private: QString m_jobName; QString m_filesetName; QString m_currentJob; + QString m_levelName; + bool m_populated; bool m_checkCurrentWidget; int m_jobIdIndex; int m_purgedIndex; int m_typeIndex; + int m_levelIndex; + int m_clientIndex; + int m_nameIndex; + int m_filesetIndex; int m_statusIndex; int m_startIndex; int m_bytesIndex; diff --git a/bacula/src/qt-console/joblist/joblist.ui b/bacula/src/qt-console/joblist/joblist.ui index dd40d2c52f..5d5947558a 100644 --- a/bacula/src/qt-console/joblist/joblist.ui +++ b/bacula/src/qt-console/joblist/joblist.ui @@ -385,7 +385,7 @@ :/images/utilities-terminal.png:/images/utilities-terminal.png - ListJobMedia + List Job Volumes @@ -394,7 +394,7 @@ :/images/utilities-terminal.png:/images/utilities-terminal.png - ListVolumes + List Volumes @@ -403,7 +403,7 @@ :/images/weather-severe-alert.png:/images/weather-severe-alert.png - DeleteJob + Delete Job @@ -412,7 +412,16 @@ :/images/weather-severe-alert.png:/images/weather-severe-alert.png - PurgeFiles + Purge Files + + + + + + :/images/weather-severe-alert.png:/images/weather-severe-alert.png + + + Restart Job @@ -439,7 +448,7 @@ :/images/joblog.png:/images/joblog.png - Show Log for Job + Show Job Log @@ -448,7 +457,7 @@ :/images/joblog.png:/images/joblog.png - Show Info for Job + Show Job Info @@ -466,7 +475,7 @@ :/images/utilities-terminal.png:/images/utilities-terminal.png - List Job Totals in Console + List Job Totals on Console diff --git a/bacula/src/qt-console/pages.cpp b/bacula/src/qt-console/pages.cpp index 8537604b02..e1160a7a2a 100644 --- a/bacula/src/qt-console/pages.cpp +++ b/bacula/src/qt-console/pages.cpp @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2007-2009 Free Software Foundation Europe e.V. + Copyright (C) 2007-2010 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -225,9 +225,11 @@ void Pages::closeStackPage() /* First get the tree widget item and destroy it */ QTreeWidgetItem *item=mainWin->getFromHash(this); /* remove the QTreeWidgetItem <-> page from the hash */ - mainWin->hashRemove(item, this); - /* remove the item from the page selector by destroying it */ - delete item; + if (item) { + mainWin->hashRemove(item, this); + /* remove the item from the page selector by destroying it */ + delete item; + } /* remove this */ delete this; } @@ -285,6 +287,7 @@ void Pages::consoleCommand(QString &command) { consoleCommand(command, true); } + void Pages::consoleCommand(QString &command, bool setCurrent) { int conn; @@ -298,10 +301,12 @@ void Pages::consoleCommand(QString &command, bool setCurrent) if (donotify) { m_console->notify(conn, true); } } } + void Pages::consoleCommand(QString &command, int conn) { consoleCommand(command, conn, true); } + void Pages::consoleCommand(QString &command, int conn, bool setCurrent) { /* Bring this director's console to the front of the stack */ diff --git a/bacula/src/qt-console/run/run.cpp b/bacula/src/qt-console/run/run.cpp index 60c59b3972..3c98acb674 100644 --- a/bacula/src/qt-console/run/run.cpp +++ b/bacula/src/qt-console/run/run.cpp @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2007-2009 Free Software Foundation Europe e.V. + Copyright (C) 2007-2010 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -31,7 +31,6 @@ * * Kern Sibbald, February MMVII * - * $Id$ */ #include "bat.h" @@ -111,7 +110,7 @@ void runPage::init() connect(cancelButton, SIGNAL(pressed()), this, SLOT(cancelButtonPushed())); // find a way to place the new window at the cursor position - // or in the midle of the page + // or in the middle of the page // dockPage(); setCurrent(); } diff --git a/bacula/src/qt-console/run/runcmd.cpp b/bacula/src/qt-console/run/runcmd.cpp index 1926c35e47..6b21a4b46d 100644 --- a/bacula/src/qt-console/run/runcmd.cpp +++ b/bacula/src/qt-console/run/runcmd.cpp @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2007-2009 Free Software Foundation Europe e.V. + Copyright (C) 2007-2010 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -37,7 +37,6 @@ * * Kern Sibbald, March MMVII * - * $Id$ */ #include "bat.h" @@ -84,15 +83,15 @@ void runCmdPage::fill() m_console->read(m_conn); item = m_console->msg(m_conn); items = item.split("\n"); - label->setText(items[0]); - Dmsg1(200, "Title=%s\n", items[0].toUtf8().data()); - items.removeFirst(); /* remove title */ foreach(item, items) { rx.indexIn(item); val = rx.cap(1); - Dmsg1(200, "Item=%s\n", item.toUtf8().data()); - Dmsg1(200, "Value=%s\n", val.toUtf8().data()); + Dmsg1(000, "Item=%s\n", item.toUtf8().data()); + Dmsg1(000, "Value=%s\n", val.toUtf8().data()); + if (item.startsWith("Title:")) { + run->setText(val); + } if (item.startsWith("JobName:")) { jobCombo->addItem(val); continue; -- 2.39.2