From: Marcin Haba Date: Fri, 25 Dec 2015 19:51:24 +0000 (+0100) Subject: baculum: Add dashboard panel X-Git-Tag: Release-7.4.0~88 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=37ac8d8da316d06d960eed934085f8fefed516f2;p=bacula%2Fbacula baculum: Add dashboard panel --- diff --git a/gui/baculum/protected/Class/Bconsole.php b/gui/baculum/protected/Class/Bconsole.php index a3f27202bc..9dc27690df 100644 --- a/gui/baculum/protected/Class/Bconsole.php +++ b/gui/baculum/protected/Class/Bconsole.php @@ -91,6 +91,7 @@ class Bconsole extends TModule { } private function execCommand($director, array $command, $user) { + $cmd = ''; if(!is_null($director) && $this->isValidDirector($director) === false) { $output = array(BconsoleError::MSG_ERROR_INVALID_DIRECTOR, ''); $exitcode = BconsoleError::ERROR_INVALID_DIRECTOR; diff --git a/gui/baculum/protected/Class/Database.php b/gui/baculum/protected/Class/Database.php index 0d6a9b356a..a2fdfd71a9 100644 --- a/gui/baculum/protected/Class/Database.php +++ b/gui/baculum/protected/Class/Database.php @@ -119,5 +119,38 @@ class Database extends TModule { $ret = (array_key_exists('versionid', $result) === true) ? $result['versionid'] : false; return $ret; } + + public function getDatabaseSize() { + $configuration = $this->Application->getModule('configuration'); + $db_params = $this->getDBParams(); + $dbtype = $db_params['type']; + $dbname = $db_params['name']; + + $db = new ActiveRecord(); + $connection = $db->getDbConnection(); + $connection->setActive(true); + $pdo = $connection->getPdoInstance(); + + $dbsize = 0; + if ($configuration->isPostgreSQLType($dbtype)) { + $sql = "SELECT pg_database_size('$dbname') AS dbsize"; + $result = $pdo->query($sql); + $dbsize = $result->fetch(); + } else if ($configuration->isMySQLType($dbtype)) { + $sql = "SELECT Sum(data_length + index_length) AS dbsize FROM information_schema.tables"; + $result = $pdo->query($sql); + $dbsize = $result->fetch(); + } else if ($configuration->isSQLiteType($dbtype)) { + $sql = "PRAGMA page_count"; + $result = $pdo->query($sql); + $page_count = $result->fetch(); + $sql = "PRAGMA page_size"; + $result = $pdo->query($sql); + $page_size = $result->fetch(); + $dbsize = array('dbsize' => ($page_count['page_count'] * $page_size['page_size'])); + } + $pdo = null; + return $dbsize['dbsize']; + } } -?> \ No newline at end of file +?> diff --git a/gui/baculum/protected/Class/JobManager.php b/gui/baculum/protected/Class/JobManager.php index d4d5fc4ae4..cf53733d6b 100644 --- a/gui/baculum/protected/Class/JobManager.php +++ b/gui/baculum/protected/Class/JobManager.php @@ -71,5 +71,19 @@ class JobManager extends TModule { } return $jobids; } + + public function getJobTotals() { + $jobtotals = array('bytes' => 0, 'files' => 0); + $connection = JobRecord::finder()->getDbConnection(); + $connection->setActive(true); + $sql = "SELECT sum(JobFiles) AS files, sum(JobBytes) AS bytes FROM Job"; + $pdo = $connection->getPdoInstance(); + $result = $pdo->query($sql); + $ret = $result->fetch(); + $jobtotals['bytes'] = $ret['bytes']; + $jobtotals['files'] = $ret['files']; + $pdo = null; + return $jobtotals; + } } ?> diff --git a/gui/baculum/protected/Class/Miscellaneous.php b/gui/baculum/protected/Class/Miscellaneous.php index f1e33a03be..1767f1ebb3 100644 --- a/gui/baculum/protected/Class/Miscellaneous.php +++ b/gui/baculum/protected/Class/Miscellaneous.php @@ -75,6 +75,12 @@ class Miscellaneous extends TModule { 'L' => array('value' => 'Commiting data', 'description' =>'Committing data (last despool)') ); + private $jobStatesOK = array('T', 'D'); + private $jobStatesWarning = array('W'); + private $jobStatesError = array('E', 'e', 'f', 'I'); + private $jobStatesCancel = array('A'); + private $jobStatesRunning = array('C', 'R', 'B', 'F', 'S', 'm', 'M', 's', 'j', 'c', 'd','t', 'p', 'i', 'a', 'l', 'L'); + private $runningJobStates = array('C', 'R'); /** @@ -117,6 +123,34 @@ class Miscellaneous extends TModule { } + public function getJobStatesByType($type) { + $statesByType = array(); + $states = array(); + switch($type) { + case 'ok': + $states = $this->jobStatesOK; + break; + case 'warning': + $states = $this->jobStatesWarning; + break; + case 'error': + $states = $this->jobStatesError; + break; + case 'cancel': + $states = $this->jobStatesCancel; + break; + case 'running': + $states = $this->jobStatesRunning; + break; + } + + for ($i = 0; $i < count($states); $i++) { + $statesByType[$states[$i]] = $this->getJobState($states[$i]); + } + + return $statesByType; + } + public function isValidJobLevel($jobLevel) { return array_key_exists($jobLevel, $this->getJobLevels()); } diff --git a/gui/baculum/protected/JavaScript/graph.js b/gui/baculum/protected/JavaScript/graph.js index c8c92c765c..ed3f90949f 100644 --- a/gui/baculum/protected/JavaScript/graph.js +++ b/gui/baculum/protected/JavaScript/graph.js @@ -411,6 +411,67 @@ var GraphClass = Class.create({ } }); +var GraphPieClass = Class.create({ + jobs: [], + container: null, + series: null, + pie: null, + graph_options: { + colors: ['#63c422', '#d70808', '#FFFF66', 'orange', 'blue'], + HtmlText: false, + fontColor: '#ffffff', + grid: { + verticalLines : false, + horizontalLines : false, + outlineWidth: 0, + }, + xaxis: { showLabels : false,}, + yaxis: { showLabels : false }, + pie: { + show : true, + explode : 5, + labelFormatter: PieGraph.pie_label_formatter, + shadowSize: 4, + fillOpacity: 1, + sizeRatio: 0.6 + }, + mouse: { + track : true, + trackFormatter: PieGraph.pie_track_formatter, + relative: true + }, + legend: { + position : 'se', + backgroundColor : '#D2E8FF', + margin: 0 + } + }, + initialize: function(jobs, container_id) { + this.jobs = jobs; + this.container = document.getElementById(container_id); + this.series = this.prepare_series(); + this.draw_grah(); + }, + prepare_series: function() { + var series = []; + var label, serie; + var job_types = Object.keys(this.jobs); + var jobs_count; + for (var i = 0; i < job_types.length; i++) { + label = job_types[i]; + jobs_count = this.jobs[label].length; + serie = { + data: [[0, jobs_count]], + label: label + ' (' + jobs_count.toString() + ')' + } + series.push(serie); + } + return series; + }, + draw_grah: function() { + this.pie = Flotr.draw(this.container, this.series, this.graph_options); + } +}); var iso_date_to_timestamp = function(iso_date) { var date_split = iso_date.split(' '); diff --git a/gui/baculum/protected/JavaScript/misc.js b/gui/baculum/protected/JavaScript/misc.js index 34f93eba0e..9500c03026 100644 --- a/gui/baculum/protected/JavaScript/misc.js +++ b/gui/baculum/protected/JavaScript/misc.js @@ -1,5 +1,9 @@ var Units = { get_decimal_size: function(size) { + if (size === null) { + size = 0; + } + size = parseInt(size, 10); var size_unit = 'B'; var units = ['K', 'M', 'G', 'T', 'P']; @@ -17,6 +21,35 @@ var Units = { } } +var Strings = { + limits: { + label: 15 + }, + get_short_label: function(txt) { + var short_txt = txt; + var cut = ((this.limits.label - 2) / 2); + if (txt.length > this.limits.label) { + short_txt = txt.substr(0, cut) + '..' + txt.substr(-cut); + } + return short_txt; + } +} + +var PieGraph = { + pie_label_formatter: function (total, value) { + var percents = (100 * value / total).toFixed(1); + if (percents >= 1) { + percents = percents.toString() + '%'; + } else { + percents = ''; + } + return percents; + }, + pie_track_formatter: function(e) { + return e.series.label; + } +} + var Formatters = { formatter: [ {css_class: 'size', format_func: Units.get_decimal_size} @@ -62,3 +95,133 @@ var Cookies = { return cookie_val; } } + +var Dashboard = { + stats: null, + txt: null, + pie: null, + noval: '-', + ids: { + clients: { + no: 'clients_no', + most: 'clients_most', + jobs: 'clients_jobs' + }, + jobs: { + to_view: 'jobs_to_view', + most: 'jobs_most', + most_count: 'jobs_most_count' + }, + jobtotals: { + total_bytes: 'jobs_total_bytes', + total_files: 'jobs_total_files' + }, + database: { + size: 'database_size' + }, + pools: { + no: 'pools_no', + most: 'pools_most', + jobs: 'pools_jobs' + }, + pie_summary: 'jobs_summary_graph' + }, + update_all: function(statistics, txt) { + this.stats = statistics; + this.txt = txt; + this.update_pie_jobstatus(); + this.update_clients(); + this.update_job_access(); + this.update_jobs(); + this.update_jobtotals(); + this.update_database(); + this.update_pools(); + }, + update_clients: function() { + var clients = this.stats.clients_occupancy; + var most_occuped_client = this.noval; + var occupancy = -1; + for (client in clients) { + if (occupancy < clients[client]) { + most_occuped_client = client; + occupancy = clients[client]; + } + } + + if (occupancy === -1) { + occupancy = 0; + } + + document.getElementById(this.ids.clients.no).textContent = Object.keys(this.stats.clients).length; + document.getElementById(this.ids.clients.most).setAttribute('title', most_occuped_client); + document.getElementById(this.ids.clients.most).textContent = Strings.get_short_label(most_occuped_client); + document.getElementById(this.ids.clients.jobs).textContent = occupancy; + }, + update_job_access: function() { + var jobs_combobox= document.getElementById(this.ids.jobs.to_view); + jobs_combobox.innerHTML = ''; + var last_jobs = this.stats.jobs.slice(0, 100); + for (var i = 0; i < last_jobs.length; i++) { + var opt = document.createElement('OPTION'); + var txt = '[' + last_jobs[i].jobid + '] ' + last_jobs[i].name + ' (' + this.txt.level + ': ' + last_jobs[i].level + ' ' + this.txt.status + ': ' + last_jobs[i].jobstatus + ' ' + this.txt.starttime + ': ' + last_jobs[i].starttime + ')'; + var label = document.createTextNode(txt); + opt.value = last_jobs[i].jobid; + opt.appendChild(label); + jobs_combobox.appendChild(opt); + } + }, + update_jobs: function() { + var jobs = this.stats.jobs_occupancy; + var most_occuped_job = this.noval; + var occupancy = -1; + for (job in jobs) { + if (occupancy < jobs[job]) { + most_occuped_job = job; + occupancy = jobs[job]; + } + } + + if (occupancy === -1) { + occupancy = 0; + } + + document.getElementById(this.ids.jobs.most).setAttribute('title',most_occuped_job); + document.getElementById(this.ids.jobs.most).textContent = Strings.get_short_label(most_occuped_job); + document.getElementById(this.ids.jobs.most_count).textContent = occupancy; + }, + update_jobtotals: function() { + document.getElementById(this.ids.jobtotals.total_bytes).textContent = Units.get_decimal_size(this.stats.jobtotals.bytes); + document.getElementById(this.ids.jobtotals.total_files).textContent = this.stats.jobtotals.files || 0; + }, + update_database: function() { + document.getElementById(this.ids.database.size).textContent = Units.get_decimal_size(this.stats.dbsize); + }, + update_pools: function() { + var pools = this.stats.pools_occupancy; + var most_occuped_pool = this.noval; + var occupancy = -1; + for (pool in pools) { + if (occupancy < pools[pool]) { + most_occuped_pool = pool; + occupancy = pools[pool]; + } + } + + if (occupancy === -1) { + occupancy = 0; + } + + document.getElementById(this.ids.pools.no).textContent = Object.keys(this.stats.pools).length; + document.getElementById(this.ids.pools.most).setAttribute('title', most_occuped_pool); + document.getElementById(this.ids.pools.most).textContent = Strings.get_short_label(most_occuped_pool); + document.getElementById(this.ids.pools.jobs).textContent = occupancy; + }, + update_pie_jobstatus: function() { + if (PanelWindow.currentWindowId === 'dashboard') { + if (this.pie != null) { + this.pie.pie.destroy(); + } + this.pie = new GraphPieClass(this.stats.jobs_summary, this.ids.pie_summary); + } + } +} diff --git a/gui/baculum/protected/JavaScript/panel-window.js b/gui/baculum/protected/JavaScript/panel-window.js index 77bd1a11eb..82881cb1dc 100644 --- a/gui/baculum/protected/JavaScript/panel-window.js +++ b/gui/baculum/protected/JavaScript/panel-window.js @@ -1,18 +1,28 @@ var PanelWindowClass = Class.create({ - currentWindow: null, - windowElements: ['container', 'graphs'], + currentWindowId: null, + windowIds: ['dashboard', 'container', 'graphs'], onShow: null, + initialize: function() { + this.currentWindowId = this.windowIds[0]; + }, + hideOthers: function() { - this.windowElements.each(function(element) { - if(element != this.currentWindow) { - Effect.toggle(element, 'slide', {duration: 0.3, afterFinish : function() { - $(element).hide(); - }.bind(element) + var hide_panel_by_id = function(id) { + var el = $(id); + if(el.visible() === true && id != this.currentWindowId) { + Effect.toggle(el, 'slide', { + duration: 0.3, + afterFinish: function() { + el.hide(); + }.bind(el) }); } - }.bind(this)); + } + for (var i = 0, j = 1; i < this.windowIds.length; i++, j++) { + hide_panel_by_id(this.windowIds[i]); + } }, show: function(id) { @@ -20,7 +30,7 @@ var PanelWindowClass = Class.create({ return; } - this.currentWindow = id; + this.currentWindowId = id; Effect.toggle(id, 'slide', { duration: 0.3, beforeStart: function() { @@ -30,6 +40,7 @@ var PanelWindowClass = Class.create({ if (this.onShow) { this.onShow(); } + setContentWidth(); }.bind(this) }); } diff --git a/gui/baculum/protected/JavaScript/slide-window.js b/gui/baculum/protected/JavaScript/slide-window.js index 202ee88845..557b6e826d 100644 --- a/gui/baculum/protected/JavaScript/slide-window.js +++ b/gui/baculum/protected/JavaScript/slide-window.js @@ -596,6 +596,15 @@ var SlideWindowClass = Class.create({ }, setInitElementId: function(id) { this.initElementId = id; + }, + quickJumpToElement: function(id, btn_id, panel_obj) { + this.setInitElementId(id); + panel_obj.show('container'); + if (this.isWindowOpen() === true) { + this.openConfigurationById(id); + } else { + $(btn_id).click(); + } } }); diff --git a/gui/baculum/protected/JavaScript/statistics.js b/gui/baculum/protected/JavaScript/statistics.js new file mode 100644 index 0000000000..b211691fa3 --- /dev/null +++ b/gui/baculum/protected/JavaScript/statistics.js @@ -0,0 +1,75 @@ +var Statistics = { + jobs: null, + clients: null, + pools: null, + jobtotals: null, + dbsize: null, + clients_occupancy: {}, + pools_occupancy: {}, + jobs_summary: [], + grab_statistics: function(data, jobstates) { + this.jobs = data.jobs; + this.clients = data.clients; + this.pools = data.pools; + this.jobtotals = data.jobtotals; + this.dbsize = data.dbsize; + var jobs_count = this.jobs.length; + var clients_occupancy = {}; + var pools_occupancy = {}; + var jobs_occupancy = {}; + var jobs_summary = { + ok: [], + error: [], + warning: [], + cancel: [], + running: [] + }; + var status_type; + for (var i = 0; i < jobs_count; i++) { + if (typeof(clients_occupancy[this.jobs[i].clientid]) === 'undefined') { + clients_occupancy[this.jobs[i].clientid] = 1; + } else { + clients_occupancy[this.jobs[i].clientid] += 1; + } + + if (typeof(pools_occupancy[this.jobs[i].poolid]) === 'undefined') { + pools_occupancy[this.jobs[i].poolid] = 1; + } else { + pools_occupancy[this.jobs[i].poolid] += 1; + } + + if (typeof(jobs_occupancy[this.jobs[i].name]) === 'undefined') { + jobs_occupancy[this.jobs[i].name] = 1; + } else { + jobs_occupancy[this.jobs[i].name] += 1; + } + if (jobstates.hasOwnProperty(this.jobs[i].jobstatus)) { + status_type = jobstates[this.jobs[i].jobstatus].type; + if (status_type == 'ok' && this.jobs[i].joberrors > 0) { + status_type = 'warning'; + } + jobs_summary[status_type].push(this.jobs[i]); + } + } + var clients_ids = Object.keys(clients_occupancy); + for (var i = 0; i < clients_ids.length; i++) { + for (var j = 0; j < this.clients.length; j++) { + if (clients_ids[i] == this.clients[j].clientid) { + this.clients_occupancy[this.clients[j].name] = clients_occupancy[clients_ids[i]]; + } + } + } + + var pools_ids = Object.keys(pools_occupancy); + for (var i = 0; i < pools_ids.length; i++) { + for (var j = 0; j < this.pools.length; j++) { + if (pools_ids[i] == this.pools[j].poolid) { + this.pools_occupancy[this.pools[j].name] = pools_occupancy[pools_ids[i]]; + } + } + } + + this.jobs_occupancy = jobs_occupancy; + this.jobs_summary = jobs_summary; + } +} diff --git a/gui/baculum/protected/Lang/en/messages.mo b/gui/baculum/protected/Lang/en/messages.mo index 14202632c6..bf230e4dea 100644 Binary files a/gui/baculum/protected/Lang/en/messages.mo and b/gui/baculum/protected/Lang/en/messages.mo differ diff --git a/gui/baculum/protected/Lang/en/messages.po b/gui/baculum/protected/Lang/en/messages.po index 790af8a41f..b4dcf0f6f4 100644 --- a/gui/baculum/protected/Lang/en/messages.po +++ b/gui/baculum/protected/Lang/en/messages.po @@ -1022,6 +1022,78 @@ msgstr "Job:" msgid "Media Type" msgstr "Media Type" +msgid "Dashboard" +msgstr "Dashboard" + msgid "Go to started job after start:" msgstr "Go to started job after start:" +msgid "Jobs status summary" +msgstr "Jobs status summary" + +msgid "Quick job access" +msgstr "Quick job access" + +msgid "Finished jobs" +msgstr "Finished jobs" + +msgid "Most often used:" +msgstr "Most often used:" + +msgid "Number of clients:" +msgstr "Number of clients:" + +msgid "jobs" +msgstr "jobs" + +msgid "Jobs count on most used:" +msgstr "Jobs count on most used:" + +msgid "level" +msgstr "level" + +msgid "status" +msgstr "status" + +msgid "Jump to job (last 100):" +msgstr "Jump to job (last 100):" + +msgid "View" +msgstr "View" + +msgid "Total bytes:" +msgstr "Total bytes:" + +msgid "Total files:" +msgstr "Total files:" + +msgid "Database size:" +msgstr "Database size:" + +msgid "Number of pools:" +msgstr "Number of pools:" + +msgid "times" +msgstr "times" + +msgid "Execution count most used:" +msgstr "Execution count most used:" + +msgid "Job Totals" +msgstr "Job Totals" + +msgid "Restore Wizard" +msgstr "Restore Wizard" + +msgid "Perform Restore" +msgstr "Perform Restore" + +msgid "Configuration Wizard" +msgstr "Configuration Wizard" + +msgid "Baculum Settings" +msgstr "Baculum Settings" + +msgid "start time" +msgstr "start time" + diff --git a/gui/baculum/protected/Lang/pl/messages.mo b/gui/baculum/protected/Lang/pl/messages.mo index 953bc6e95a..ba936762c4 100644 Binary files a/gui/baculum/protected/Lang/pl/messages.mo and b/gui/baculum/protected/Lang/pl/messages.mo differ diff --git a/gui/baculum/protected/Lang/pl/messages.po b/gui/baculum/protected/Lang/pl/messages.po index 8292ffd2b8..eb0f93f57c 100644 --- a/gui/baculum/protected/Lang/pl/messages.po +++ b/gui/baculum/protected/Lang/pl/messages.po @@ -1023,6 +1023,78 @@ msgstr "Zadanie:" msgid "Media Type" msgstr "Media Type" +msgid "Dashboard" +msgstr "Start" + msgid "Go to started job after start:" msgstr "Przejdź do uruchomionego zadania po starcie:" +msgid "Jobs status summary" +msgstr "Podsumowanie statusu zadań" + +msgid "Quick job access" +msgstr "Quick job access" + +msgid "Finished jobs" +msgstr "Zakończone zadania" + +msgid "Most often used:" +msgstr "Najczęściej używany:" + +msgid "Number of clients:" +msgstr "Ilość klientów:" + +msgid "jobs" +msgstr "zadań" + +msgid "Jobs count on most used:" +msgstr "Ilość zadań na najczęściej używanym:" + +msgid "level" +msgstr "poziom" + +msgid "status" +msgstr "status" + +msgid "Jump to job (last 100):" +msgstr "Skocz do zadania (ostatnie 100):" + +msgid "View" +msgstr "Zobacz" + +msgid "Total bytes:" +msgstr "Całkowita ilość danych:" + +msgid "Total files:" +msgstr "Całkowita ilość plików:" + +msgid "Database size:" +msgstr "Rozmiar bazy danych:" + +msgid "Number of pools:" +msgstr "Ilość puli wolumenów:" + +msgid "times" +msgstr "razy" + +msgid "Execution count most used:" +msgstr "Ilość wykonań najczęściej używanego:" + +msgid "Job Totals" +msgstr "Podsumowanie zadań" + +msgid "Restore Wizard" +msgstr "Kreator przywracania danych" + +msgid "Perform Restore" +msgstr "Wykonaj przywracanie danych" + +msgid "Configuration Wizard" +msgstr "Kreator Konfiguracji" + +msgid "Baculum Settings" +msgstr "Ustawienia Baculum" + +msgid "start time" +msgstr "czas rozpoczęcia" + diff --git a/gui/baculum/protected/Layouts/Main.tpl b/gui/baculum/protected/Layouts/Main.tpl index 74fbdaca87..ed3bc171ce 100644 --- a/gui/baculum/protected/Layouts/Main.tpl +++ b/gui/baculum/protected/Layouts/Main.tpl @@ -7,12 +7,13 @@ /> /> /> + /> /> /> /> /> /> - /> + /> diff --git a/gui/baculum/protected/Pages/API/DbSize.php b/gui/baculum/protected/Pages/API/DbSize.php new file mode 100644 index 0000000000..6d0c2e4757 --- /dev/null +++ b/gui/baculum/protected/Pages/API/DbSize.php @@ -0,0 +1,30 @@ +getModule('db')->getDatabaseSize(); + $this->output = $dbsize; + $this->error = JobError::ERROR_NO_ERRORS; + } +} +?> diff --git a/gui/baculum/protected/Pages/API/JobTotals.php b/gui/baculum/protected/Pages/API/JobTotals.php new file mode 100644 index 0000000000..18e04cac9e --- /dev/null +++ b/gui/baculum/protected/Pages/API/JobTotals.php @@ -0,0 +1,30 @@ +getModule('job')->getJobTotals(); + $this->output = $jobtotals; + $this->error = JobError::ERROR_NO_ERRORS; + } +} +?> diff --git a/gui/baculum/protected/Pages/Home.page b/gui/baculum/protected/Pages/Home.page index cadfe132f7..068f060e00 100644 --- a/gui/baculum/protected/Pages/Home.page +++ b/gui/baculum/protected/Pages/Home.page @@ -1,17 +1,82 @@ <%@ MasterClass="Application.Layouts.Main" Theme="Baculum-v1"%>
- Baculum +
- - + + + + + +
-
+
+
+
+
+ +
+ <%[ Jobs status summary ]%> +
+
+
+ <%[ Clients ]%> + +

<%[ Number of clients: ]%>

+

<%[ Most often used: ]%>

+

<%[ Jobs count on most used: ]%> <%[ jobs ]%>

+
+
+ <%[ Quick job access ]%> + +

<%[ Jump to job (last 100): ]%>

+

<%[ View ]%>

+
+
+ <%[ Finished jobs ]%> + +

<%[ Most often used: ]%>

+

<%[ Execution count most used: ]%> <%[ times ]%>

+
+
+ <%[ Database ]%> + +

<%[ Database type: ]%><%=$this->dbtype%>

+

<%[ Database size: ]%>

+
+
+ <%[ Pools ]%> + +

<%[ Number of pools: ]%>

+

<%[ Most often used: ]%>

+

<%[ Jobs count on most used: ]%> <%[ jobs ]%>

+
+
+ <%[ Job Totals ]%> + +

<%[ Total bytes: ]%>

+

<%[ Total files: ]%>

+
+
+ <%[ Restore Wizard ]%> + <%[ Perform Restore ]%> +
+
+ <%[ Configuration Wizard ]%> + <%[ Baculum Settings ]%> +
+
+
+
+
+