OnClick="status"
CssClass="w3-button w3-green w3-margin-bottom"
CausesValidation="false"
- ClientSide.OnLoading="$('#status_storage_loading').show();"
- ClientSide.OnSuccess="$('#status_storage_loading').hide();"
+ ClientSide.OnLoading="$('#status_storage_loading').show();$('#status_storage_error').hide();"
+ ClientSide.OnSuccess="$('#status_storage_loading').hide(); $('#show_storage_container').hide();$('#status_storage_container').show();oGraphicalStorageStatus.set_refresh_timeout(document.getElementById('status_storage_refresh_interval').value);"
+ ClientSide.OnFailure="$('#status_storage_loading').hide();status_storage_show_error(parameter);"
+ Attributes.onclick="hide_action_text_output(event);"
>
<prop:Text><%=Prado::localize('Status storage')%> <i class="fa fa-file-medical-alt"></i></prop:Text>
</com:TActiveLinkButton>
ValidationGroup="AutoChangerGroup"
CausesValidation="true"
ClientSide.OnLoading="$('#status_storage_loading').show();"
- ClientSide.OnSuccess="$('#status_storage_loading').hide();"
+ ClientSide.OnSuccess="$('#status_storage_loading').hide();$('#storage_action_text_output').slideDown();"
>
<prop:Text><%=Prado::localize('Mount')%> <i class="fa fa-caret-down"></i></prop:Text>
</com:TActiveLinkButton>
ValidationGroup="AutoChangerGroup"
CausesValidation="true"
ClientSide.OnLoading="$('#status_storage_loading').show();"
- ClientSide.OnSuccess="$('#status_storage_loading').hide();"
+ ClientSide.OnSuccess="$('#status_storage_loading').hide();$('#storage_action_text_output').slideDown();"
>
<prop:Text><%=Prado::localize('Release')%> <i class="fa fa-caret-right"></i></prop:Text>
</com:TActiveLinkButton>
ValidationGroup="AutoChangerGroup"
CausesValidation="true"
ClientSide.OnLoading="$('#status_storage_loading').show();"
- ClientSide.OnSuccess="$('#status_storage_loading').hide();"
+ ClientSide.OnSuccess="$('#status_storage_loading').hide();$('#storage_action_text_output').slideDown();"
>
<prop:Text><%=Prado::localize('Umount')%> <i class="fa fa-caret-up"></i></prop:Text>
</com:TActiveLinkButton>
- <i id="status_storage_loading" class="fa fa-sync w3-spin" style="display: none; vertical-align: super;"></i>
- <com:TActivePanel ID="Autochanger" Display="None">
- <div class="w3-row">
- <div class="w3-quarter w3-container">
+ <i id="status_storage_loading" class="fa fa-sync w3-spin" style="display: none; vertical-align: super;"></i> <span id="status_storage_error" class="w3-text-red" style="display: none"></span>
+ <com:TActivePanel ID="Autochanger" Display="None" Height="61px">
+ <div class="w3-left w3-margin-right">
<label><%[ Drive number: ]%></label>
<com:TActiveTextBox ID="Drive" AutoPostBack="false" Text="0" MaxLength="3" CssClass="w3-input smallbox" />
<com:TDataTypeValidator ID="DriveValidator" ValidationGroup="AutoChangerGroup" ControlToValidate="Drive" ErrorMessage="<%[ Drive number must be integer. ]%>" Display="None" DataType="Integer" />
</div>
- </div>
- <div class="w3-row">
- <div class="w3-quarter w3-container">
+ <div class="w3-left">
<%[ Slot number: ]%>
<com:TActiveTextBox ID="Slot" AutoPostBack="false" Text="0" MaxLength="3" CssClass="w3-input smallbox" />
<com:TDataTypeValidator ID="SlotValidator" ValidationGroup="AutoChangerGroup" ControlToValidate="Slot" ErrorMessage="<%[ Slot number must be integer. ]%>" Display="None" DataType="Integer" />
</div>
- </div>
</com:TActivePanel>
- <div class="w3-panel w3-card w3-light-grey">
- <div class="w3-code notranslate">
- <pre><com:TActiveLabel ID="StorageLog" /></pre>
+ <div id="storage_action_text_output" class="w3-code" style="display: none; clear: both;">
+ <pre><com:TActiveLabel ID="StorageActionLog" /></pre>
+ </div>
+ <div id="status_storage_container" class="w3-clear w3-margin-top" style="display: none">
+ <div class="w3-right w3-margin-top w3-margin-right" title="<%[ To disable refreshing please type 0. ]%>">
+ <span style="line-height: 41px"><%[ Refresh interval (sec.): ]%></span> <input type="text" id="status_storage_refresh_interval" class="w3-input w3-border w3-right w3-margin-left" value="10" style="width: 50px"/>
+ </div>
+ <div class="w3-panel w3-card w3-light-grey" style="padding-bottom: 16px;">
+ <div class="w3-row">
+ <a href="javascript:void(0)" onclick="W3SubTabs.open('status_storage_subtab_graphical', 'status_storage_graphical_output');">
+ <div id="status_storage_subtab_graphical" class="subtab_btn w3-half w3-bottombar w3-hover-light-grey w3-border-red w3-padding"><%[ Graphical status ]%></div>
+ </a>
+ <a href="javascript:void(0)" onclick="W3SubTabs.open('status_storage_subtab_text', 'status_storage_text_output');">
+ <div id="status_storage_subtab_text" class="subtab_btn w3-half w3-bottombar w3-hover-light-grey w3-padding"><%[ Raw status ]%></div>
+ </a>
+ </div>
+ <div id="status_storage_graphical_output" class="subtab_item">
+ <h4 id="status_storage_status_not_supported" style="display: none"><%[ Graphical storage status is supported for Bacula storages version 9.0 and greater. ]%></h4>
+ <div id="status_storage_graphical_container">
+ <h4><%[ Storage Daemon: ]%> <span id="status_storage_name"></span></h4>
+ <table class="w3-table w3-stripped w3-border status_table">
+ <tr>
+ <td><%[ Version: ]%></td>
+ <td id="status_storage_version"></td>
+ </tr>
+ <tr>
+ <td><%[ Uname: ]%></td>
+ <td id="status_storage_uname"></td>
+ </tr>
+ <tr>
+ <td><%[ Started time: ]%></td>
+ <td id="status_storage_started_time"></td>
+ </tr>
+ <tr>
+ <td><%[ Running jobs: ]%></td>
+ <td><span id="status_storage_jobs_running"></span></td>
+ </tr>
+ <tr>
+ <td><%[ Plugins: ]%></td>
+ <td id="status_storage_plugins"></td>
+ </tr>
+ <tr>
+ <td><%[ # Autochangers: ]%></td>
+ <td id="status_storage_no_autochangers"></td>
+ </tr>
+ <tr>
+ <td><%[ # Devices: ]%></td>
+ <td id="status_storage_no_devices"></td>
+ </tr>
+ </table>
+ <div id="status_storage_filters"></div>
+ <div id="status_storage_devices"></div>
+ <h4><%[ Terminated jobs ]%></h4>
+ <div id="status_storage_terminated"></div>
+ </div>
+<com:TJuiProgressbar Display="None" />
+<script>
+var oGraphicalStorageStatus = {
+ data: {},
+ refresh_timeout: null,
+ running_jobs: [],
+ ids: {
+ refresh_interval: 'status_storage_refresh_interval',
+ status_not_supported: 'status_storage_status_not_supported',
+ graphical_container: 'status_storage_graphical_container',
+ devices: 'status_storage_devices',
+ terminated: 'status_storage_terminated',
+ filters: 'status_storage_filters',
+ header: {
+ name: 'status_storage_name',
+ version: 'status_storage_version',
+ uname: 'status_storage_uname',
+ started_epoch: 'status_storage_started_time',
+ jobs_running: 'status_storage_jobs_running',
+ plugins: 'status_storage_plugins',
+ nautochgr: 'status_storage_no_autochangers',
+ ndevices: 'status_storage_no_devices'
+ }
+ },
+ css: {
+ gauge: 'gauge',
+ gauge_label: 'gauge_label',
+ gauge_container: 'gauge_container',
+ status_header: 'status_header',
+ device_columns: 'device_columns',
+ device_colinfo: 'device_colinfo',
+ device_header: 'device_header',
+ device_table: 'device_table',
+ running_job_header: 'running_job_header',
+ running_job_table: 'running_job_table',
+ terminated_job_header: 'terminated_job_header',
+ terminated_job_table: 'terminated_job_table'
+ },
+ gauges: {
+ space: {
+ angle: -0.2, // The span of the gauge arc
+ lineWidth: 0.2, // The line thickness
+ radiusScale: 1, // Relative radius
+ pointer: {
+ length: 0.6, // // Relative to gauge radius
+ strokeWidth: 0.035, // The thickness
+ color: '#000000' // Fill color
+ },
+ limitMax: false, // If false, max value increases automatically if value > maxValue
+ limitMin: false, // If true, the min value of the gauge will be fixed
+ colorStart: '#6FADCF', // Colors
+ colorStop: '#8FC0DA', // just experiment with them
+ strokeColor: '#E0E0E0', // to see which ones work best for you
+ generateGradient: true,
+ highDpiSupport: true, // High resolution support
+ // renderTicks is Optional
+ renderTicks: {
+ divisions: 5,
+ divWidth: 1.1,
+ divLength: 0.7,
+ divColor: '#333333',
+ subDivisions: 3,
+ subLength: 0.5,
+ subWidth: 0.6,
+ subColor: '#666666'
+ },
+ staticLabels: {
+ font: "10px sans-serif", // Specifies font
+ color: "#000000", // Optional: Label text color
+ fractionDigits: 0 // Optional: Numerical precision. 0=round off.
+ }
+ },
+ speed: {
+ angle: -0.2, // The span of the gauge arc
+ lineWidth: 0.2, // The line thickness
+ radiusScale: 1, // Relative radius
+ pointer: {
+ length: 0.6, // // Relative to gauge radius
+ strokeWidth: 0.035, // The thickness
+ color: '#000000' // Fill color
+ },
+ limitMax: false, // If false, max value increases automatically if value > maxValue
+ limitMin: false, // If true, the min value of the gauge will be fixed
+ colorStart: '#6FADCF', // Colors
+ colorStop: '#8FC0DA', // just experiment with them
+ strokeColor: '#E0E0E0', // to see which ones work best for you
+ generateGradient: true,
+ highDpiSupport: true, // High resolution support
+ // renderTicks is Optional
+ renderTicks: {
+ divisions: 5,
+ divWidth: 1.1,
+ divLength: 0.7,
+ divColor: '#333333',
+ subDivisions: 3,
+ subLength: 0.5,
+ subWidth: 0.6,
+ subColor: '#666666'
+ },
+ staticLabels: {
+ font: "10px sans-serif", // Specifies font
+ color: "#000000", // Optional: Label text color
+ fractionDigits: 0 // Optional: Numerical precision. 0=round off.
+ }
+ }
+ },
+ filters: {
+ name: {
+ label: '<%[ Device: ]%>',
+ init_item: '<%[ All devices ]%>',
+ val: null
+ },
+ type: {
+ label: '<%[ Device type: ]%>',
+ init_item: '<%[ All device types ]%>',
+ val: null
+ },
+ media_type: {
+ label: '<%[ Media type: ]%>',
+ init_item: '<%[ All media types ]%>',
+ val: null
+ },
+ status: {
+ label: '<%[ Status: ]%>',
+ init_item: '<%[ All statuses ]%>',
+ val: null,
+ items: {
+ running: '<%[ running ]%>',
+ idle: '<%[ idle ]%>'
+ },
+ change: function(value) {
+ // clear all devices
+ this.remove_elements('#' + this.ids.devices, true);
+ var devices_running = [];
+ var devices_idle = [];
+ for (var i = 0; i < this.running_jobs.length; i++) {
+ if (this.running_jobs[i].read_device && devices_running.indexOf(this.running_jobs[i].read_device) == -1) {
+ devices_running.push(this.running_jobs[i].read_device);
+ }
+ if (this.running_jobs[i].write_device && devices_running.indexOf(this.running_jobs[i].write_device) == -1) {
+ devices_running.push(this.running_jobs[i].write_device);
+ }
+ }
+ if (value === 'running') {
+ this.filters['name'].val = devices_running;
+ } else if (value === 'idle') {
+ for (var i = 0; i < this.data.devices.length; i++) {
+ if (devices_running.indexOf(this.data.devices[i].name) === -1) {
+ devices_idle.push(this.data.devices[i].name);
+ }
+ }
+ this.filters['name'].val = devices_idle;
+ } else {
+ this.filters['name'].val = null;
+ }
+ this.update_status();
+ }
+ }
+ },
+ initialized: false,
+ init: function() {
+ this.set_events();
+ },
+ set_data: function(data) {
+ this.data = data;
+ },
+ set_events: function() {
+ var refresh_interval_el = document.getElementById(this.ids.refresh_interval);
+ refresh_interval_el.addEventListener('keyup', function(e) {
+ var interval = refresh_interval_el.value;
+ this.set_refresh_timeout(interval);
+ }.bind(this));
+ },
+ formatters: {
+ uname: function(value) {
+ var img = document.createElement('I');
+ img.className = 'fab fa-2x';
+ if (/win\d{2}/i.test(value)) {
+ img.className += ' fa-windows';
+ } else if (/ubuntu/i.test(value)) {
+ img.className += ' fa-ubuntu';
+ } else if (/fedora/i.test(value)) {
+ img.className += ' fa-fedora';
+ } else if (/centos/i.test(value)) {
+ img.className += ' fa-centos';
+ } else if (/redhat/i.test(value)) {
+ img.className += ' fa-redhat';
+ } else if (/suse/i.test(value)) {
+ img.className += ' fa-suse';
+ } else if (/linux/i.test(value)) {
+ img.className += ' fa-linux';
+ } else if (/freebsd/i.test(value)) {
+ img.className += ' fa-freebsd';
+ } else if (/(darwin|mac\s?os)/i.test(value)) {
+ img.className += ' fa-apple';
+ } else {
+ img.className = 'fa fa-2x fa-question';
+ }
+ img.style.marginRight = '10px';
+ var el = document.createElement('SPAN');
+ var text = document.createTextNode(value);
+ el.appendChild(img);
+ el.appendChild(text);
+ return el;
+ },
+ started_epoch: function(value) {
+ return Units.format_date(value);
+ },
+ plugins: function(value) {
+ var val;
+ if (value) {
+ val = value.replace(/-fd\.so/g, '').replace(/-fd\.dll/g, '').replace(/,/g, ', ');
+ } else {
+ val = document.createElement('I');
+ val.className = 'fa';
+ val.className += ' fa-minus';
+ }
+ return val;
+ },
+ check: function(value) {
+ var img = document.createElement('I');
+ img.className = 'fa';
+ if (value == 1) {
+ img.className += ' fa-check';
+ img.title = '<%[ Yes ]%>';
+ } else {
+ img.className += ' fa-minus';
+ img.title = '<%[ No ]%>';
+ }
+ return img;
+ },
+ value: function(value) {
+ var val;
+ if (value) {
+ val = value;
+ } else {
+ val = document.createElement('I');
+ val.className = 'fa';
+ val.className += ' fa-minus';
+ }
+ return val;
+ }
+ },
+ update: function(data) {
+ this.set_data(data);
+ if (this.is_status_supported() === false) {
+ return;
+ }
+ this.set_headers();
+ var full_refresh = this.check_full_refresh();
+ if (full_refresh) {
+ // remembered job list empty so job list changed - full refresh list
+ this.remove_elements('.' + this.css.running_job_header);
+ this.remove_elements('.' + this.css.running_job_table);
+ this.remove_elements('.' + this.css.terminated_job_header);
+ this.remove_elements('.' + this.css.terminated_job_table);
+ }
+ if (this.data.hasOwnProperty('devices')) {
+ var dev_running_jobs;
+ OUTER: for (var i = 0; i < this.data.devices.length; i++) {
+ INNER: for (var key in this.filters) {
+ if (typeof(this.filters[key].val) == 'string' && this.filters[key].val !== this.data.devices[i][key]) {
+ continue OUTER;
+ } else if (Array.isArray(this.filters[key].val) && this.filters[key].val.indexOf(this.data.devices[i][key]) == -1) {
+ continue OUTER;
+ }
+ }
+ this.add_autochanger(this.data.devices[i]);
+ this.add_device(this.data.devices[i]);
+ if (!this.initialized) {
+ for (var type in this.filters) {
+ this.set_filter(type, this.data.devices[i][type], this.filters[type].label, this.filters[type].init_item);
+ }
+ }
+ }
+ }
+ if (this.data.hasOwnProperty('terminated')) {
+ for (var i = 0; i < this.data.terminated.length; i++) {
+ this.add_terminated_job(i, this.data.terminated[i]);
+ }
+ }
+ this.initialized = true;
+ },
+ set_headers: function() {
+ var el, val;
+ ['header'].forEach(function(section) {
+ if (!this.data.hasOwnProperty(section)) {
+ return;
+ }
+ for (var key in this.ids[section]) {
+ if (!this.data[section].hasOwnProperty(key)) {
+ continue;
+ }
+ el = document.getElementById(this.ids[section][key]);
+ val = this.formatters.hasOwnProperty(key) ? this.formatters[key].call(this, this.data[section][key]) : this.data[section][key];
+ if (val instanceof HTMLElement) {
+ el.innerHTML = val.outerHTML;
+ } else {
+ el.textContent = val;
+ }
+ }
+ }.bind(this));
+ },
+ check_full_refresh: function() {
+ var full_refresh = false;
+ var running_jobs = [];
+ var found;
+ var to_add = [];
+ var to_rm = [];
+ // check if with data came new jobs or disapeared some finished jobs
+ for (var i = 0; i < this.data.running.length; i++) {
+ running_jobs.push(this.data.running[i]);
+ found = false;
+ for (var j = 0; j < this.running_jobs.length; j++) {
+ if (this.running_jobs[j].jobid === this.data.running[i].jobid) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ to_add.push(this.data.running[i]);
+ full_refresh = true;
+ }
+ }
+ if (!full_refresh) {
+ for (var i = 0; i < this.running_jobs.length; i++) {
+ found = false;
+ for (var j = 0; j < running_jobs.length; j++) {
+ if (running_jobs[j].jobid === this.running_jobs[i].jobid) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ to_rm.push(this.running_jobs[i]);
+ full_refresh = true;
+ }
+ }
+ }
+
+ // add new jobs
+ for (var i = 0; i < to_add.length; i++) {
+ this.running_jobs.push(to_add[i]);
+ }
+ // rm terminated jobs
+ for (var i = 0; i < to_rm.length; i++) {
+ for (var j = 0; j < this.running_jobs.length; j++) {
+ if (this.running_jobs[j].jobid === to_rm[i].jobid) {
+ this.running_jobs.splice(j, 1);
+ break;
+ }
+ }
+ }
+ return full_refresh;
+ },
+ set_filter: function(type, value, label, init_item) {
+ var filters = document.getElementById(this.ids.filters);
+ var select = filters.querySelector('select[rel="' + type + '"]');
+ var option, label;
+ if (!select) {
+ var title = document.createTextNode(label);
+ select = document.createElement('SELECT');
+ select.className = 'w3-select w3-border w3-margin-right';
+ select.setAttribute('rel', type);
+ var onchange_func;
+ if (this.filters[type].hasOwnProperty('change')) {
+ // custom onchange function
+ onchange_func = function(e) {
+ this.filters[type].change.call(this, select.value);
+ }.bind(this);
+ } else {
+ // default onchange function
+ onchange_func = function(e) {
+ // clear all devices
+ this.remove_elements('#' + this.ids.devices, true);
+ if (select.value) {
+ this.filters[type].val = select.value;
+ } else {
+ this.filters[type].val = null;
+ }
+ this.update_status();
+ }.bind(this)
+ }
+ select.addEventListener('change', onchange_func);
+ var option = document.createElement('OPTION');
+ option.value = '';
+ var label = document.createTextNode(init_item);
+ option.appendChild(label);
+ select.appendChild(option);
+ filters.appendChild(title);
+ filters.appendChild(select);
+ if (this.filters[type].hasOwnProperty('items')) {
+ // predefined items
+ for (var val in this.filters[type].items) {
+ option = document.createElement('OPTION');
+ option.value = val;
+ label = document.createTextNode(this.filters[type].items[val]);
+ option.appendChild(label);
+ select.appendChild(option);
+ }
+ }
+ }
+
+ if (!this.filters[type].hasOwnProperty('items')) {
+ // dynamically defined items
+ var found = false;
+ for (var i = 0; i < select.options.length; i++) {
+ if (select.options[i].value === value) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ option = document.createElement('OPTION');
+ option.value = value;
+ label = document.createTextNode(value);
+ option.appendChild(label);
+ select.appendChild(option);
+ }
+ }
+ },
+ get_show_info: function(device) {
+ var info;
+ if (this.data.hasOwnProperty('show')) {
+ for (var i = 0; i < this.data.show.length; i++) {
+ if (this.data.show[i].devicename === device) {
+ info = this.data.show[i];
+ break;
+ }
+ }
+ }
+ return info;
+ },
+ remove_elements: function(selector, empty) {
+ var elements = document.querySelectorAll(selector);
+ for (var i = 0; i < elements.length; i++) {
+ while (elements[i].firstChild) {
+ elements[i].removeChild(elements[i].firstChild);
+ }
+ }
+
+ if (!empty) {
+ var els = [].slice.call(elements);
+ var els_len = els.length;
+ for (var i = 0; i < els_len; i++) {
+ els[i].parentNode.removeChild(els[i]);
+ }
+ }
+ },
+ add_row: function(table, key, value) {
+ var tr = document.createElement('TR');
+ var tdl = document.createElement('TD');
+ var tdr = document.createElement('TD');
+ tdl.textContent = key;
+ if (value instanceof HTMLElement) {
+ tdr.appendChild(value);
+ } else {
+ tdr.innerHTML = value;
+ }
+ tr.appendChild(tdl);
+ tr.appendChild(tdr);
+ table.appendChild(tr);
+ },
+ get_device_headers: function() {
+ var header = document.createElement('DIV');
+ header.className = this.css.device_columns;
+ var device = document.createElement('DIV');
+ device.className = 'w3-container w3-cell w3-mobile';
+ device.textContent = '<%[ Device ]%>';
+ var status = document.createElement('DIV');
+ status.textContent = '<%[ Status ]%>';
+ var dev_type = document.createElement('DIV');
+ dev_type.textContent = '<%[ Device type ]%>';
+ var media_type = document.createElement('DIV');
+ media_type.textContent = '<%[ Media type ]%>';
+ header.appendChild(device);
+ header.appendChild(status);
+ header.appendChild(dev_type);
+ header.appendChild(media_type);
+ return header;
+ },
+ add_autochanger: function(device) {
+ if (!device.autochanger) {
+ // no autochanger, single device
+ this.add_single_device(device);
+ return;
+ }
+ var devices_el = document.getElementById(this.ids.devices);
+ var ach_container = document.createElement('DIV');
+ ach_container.setAttribute('rel', 'ach_' + device.autochanger);
+ var ach_label = document.createElement('H4');
+ ach_label.textContent = '<%[ Autochanger: ]%> ' + device.autochanger;
+ ach_container.appendChild(ach_label);
+ var ach_info = document.createElement('DIV');
+ ach_info.setAttribute('rel', 'ach_info_' + device.autochanger);
+ var info = this.get_show_info(device.autochanger);
+ if (info) {
+ var ach_jobs = document.createElement('DIV');
+ var ach_jobs_label = document.createElement('SPAN');
+ var ach_num_jobs = document.createElement('SPAN');
+ var ach_max_jobs = document.createElement('SPAN');
+ var ach_sep = document.createTextNode(' / ');
+ var maxjobs = info.maxjobs == 0 ? '<%[ unlimited ]%>' : info.maxjobs;
+ ach_jobs_label.textContent = '<%[ Running jobs: ]%> ';
+ ach_num_jobs.textContent = ' ' + info.numjobs;
+ ach_max_jobs.textContent = maxjobs;
+ ach_info.appendChild(ach_jobs_label);
+ ach_info.appendChild(ach_num_jobs);
+ ach_info.appendChild(ach_sep);
+ ach_info.appendChild(ach_max_jobs);
+ ach_container.appendChild(ach_info);
+ }
+ var ach_el = document.querySelector('div[rel="ach_' + device.autochanger + '"]');
+ var a = document.querySelector('div[rel="ach_info_' + device.autochanger + '"]');
+ if (a) {
+ ach_el.replaceChild(ach_info, a);
+ } else if (!ach_el) {
+ var device_headers = this.get_device_headers();
+ ach_container.appendChild(device_headers);
+ devices_el.appendChild(ach_container);
+ }
+ },
+ add_single_device: function(device) {
+ var sd_el = document.querySelector('div[rel="single_devices"]');
+ if (sd_el) {
+ // single devices container already exists, return
+ return;
+ }
+ var devices_el = document.getElementById(this.ids.devices);
+ var sd_container = document.createElement('DIV');
+ sd_container.setAttribute('rel', 'single_devices');
+ var sd_label = document.createElement('H4');
+ sd_label.textContent = '<%[ Single devices ]%>';
+ sd_container.appendChild(sd_label);
+ devices_el.appendChild(sd_container);
+ var device_headers = this.get_device_headers();
+ sd_container.appendChild(device_headers);
+ },
+ add_device: function(device) {
+ var container = document.createElement('DIV');
+ container.className = [
+ this.css.device_table,
+ 'w3-border'
+ ].join(' ');
+ container.setAttribute('rel', 'device_' + device.name);
+ var table = document.createElement('TABLE');
+ container.appendChild(table);
+
+ // arrow icon
+ var dev_arrow_img = document.createElement('I');
+ dev_arrow_img.className = 'w3-margin-right';
+
+ var header = document.createElement('DIV');
+ var open = document.querySelector('div[rel="header_device_' + device.name + '"]');
+ if (open) {
+ var data_open = open.getAttribute('data-open');
+ header.setAttribute('data-open', data_open);
+ if (data_open == 1) {
+ dev_arrow_img.className += ' fas fa-chevron-up';
+ } else {
+ dev_arrow_img.className += ' fas fa-chevron-down';
+ }
+ } else {
+ header.setAttribute('data-open', 0);
+ dev_arrow_img.className += ' fas fa-chevron-down';
+ }
+ header.setAttribute('rel', 'header_device_' + device.name);
+ header.className = [
+ this.css.device_header,
+ this.css.status_header
+ ].join(' ');
+
+ // device label
+ var dev_label = document.createElement('DIV');
+ dev_label.className = 'w3-container w3-cell w3-mobile';
+ dev_label.appendChild(dev_arrow_img);
+ var dev_label_colinfo = document.createElement('SPAN');
+ dev_label_colinfo.className = this.css.device_colinfo;
+ dev_label_colinfo.innerHTML = '<%[ Device ]%>: ';
+ dev_label.appendChild(dev_label_colinfo);
+ var dev_label_txt = document.createTextNode(' ' + device.name);
+ dev_label.appendChild(dev_label_txt);
+
+ // device running
+ var dev_running_jobs = this.get_device_jobs(device.name);
+ var dev_running = document.createElement('DIV')
+ dev_running.className = 'w3-container w3-cell w3-mobile w3-center';
+ var dev_running_img = document.createElement('I');
+ var dev_running_colinfo = document.createElement('SPAN');
+ dev_running_colinfo.className = this.css.device_colinfo;
+ dev_running_colinfo.innerHTML = '<%[ Status ]%>: ';
+ var dev_running_desc = document.createElement('SPAN');
+ var dev_running_jobs_len = dev_running_jobs.length;
+ if (dev_running_jobs_len > 0) {
+ dev_running_img.className = 'fas fa-cog fa-spin';
+ dev_running_desc.innerHTML = ' <%[ running ]%> (' + dev_running_jobs_len + ')';
+ } else {
+ dev_running_img.className = 'fas fa-minus';
+ dev_running_desc.innerHTML = ' <%[ idle ]%>';
+ }
+ dev_running.appendChild(dev_running_colinfo);
+ dev_running.appendChild(dev_running_img);
+ dev_running.appendChild(dev_running_desc);
+
+ // add running jobs
+ if (dev_running_jobs.length > 0) {
+ var dev_job_container = document.createElement('DIV');
+ dev_job_container.setAttribute('rel', 'device_jobs_' + device.name);
+ for (var i = 0; i < dev_running_jobs.length; i++) {
+ this.add_running_job(dev_job_container, i, dev_running_jobs[i]);
+ }
+ container.appendChild(dev_job_container);
+ }
+
+ // device type
+ var dev_type = document.createElement('DIV');
+ dev_type.className = 'w3-container w3-cell w3-mobile w3-center';
+ var dev_type_colinfo = document.createElement('SPAN');
+ dev_type_colinfo.className = this.css.device_colinfo;
+ dev_type_colinfo.innerHTML = '<%[ Device type ]%>: ';
+ dev_type_icon = document.createElement('I');
+ switch (device.type) {
+ case 'Tape': {
+ dev_type_icon.className = 'fas fa-tape';
+ break;
+ }
+ case 'File': {
+ dev_type_icon.className = 'fas fa-hdd';
+ break;
+ }
+ case 'Fifo': {
+ dev_type_icon.className = 'fas fa-forward';
+ break;
+ }
+ default: {
+ dev_type_icon.className = 'fas fa-hdd';
+ }
+ }
+ var dev_type_desc = document.createElement('SPAN');
+ dev_type_desc.innerHTML = ' ' + device.type;
+ dev_type.appendChild(dev_type_colinfo);
+ dev_type.appendChild(dev_type_icon);
+ dev_type.appendChild(dev_type_desc);
+
+ // media type
+ var dev_media_type = document.createElement('DIV')
+ dev_media_type.className = 'w3-container w3-cell w3-mobile w3-center';
+ var dev_media_type_img = document.createElement('I');
+ var dev_media_type_colinfo = document.createElement('SPAN');
+ dev_media_type_colinfo.className = this.css.device_colinfo;
+ dev_media_type_colinfo.innerHTML = '<%[ Media type ]%>: ';
+ dev_media_type_img.className = 'fas fa-hashtag';
+ var dev_media_type_txt = document.createElement('SPAN');
+ dev_media_type_txt.innerHTML = ' ' + device.media_type;
+ dev_media_type.appendChild(dev_media_type_colinfo);
+ dev_media_type.appendChild(dev_media_type_img);
+ dev_media_type.appendChild(dev_media_type_txt);
+
+ var set_space_gauge;
+ header.appendChild(dev_label);
+ header.appendChild(dev_running);
+ header.appendChild(dev_type);
+ header.appendChild(dev_media_type);
+ header.addEventListener('click', function(e) {
+ var container = document.querySelector('div[rel="device_' + device.name + '"]');
+ var open = this.getAttribute('data-open');
+ if (open == 1) {
+ $(container).slideUp();
+ this.setAttribute('data-open', 0);
+ dev_arrow_img.className = 'fas fa-chevron-down w3-margin-right';
+ } else {
+ $(container).slideDown('normal', function() {
+ set_space_gauge(true);
+ });
+ this.setAttribute('data-open', 1);
+ dev_arrow_img.className = 'fas fa-chevron-up w3-margin-right';
+ }
+ });
+
+ table.className = 'w3-table w3-stripped status_table device_table';
+
+ // Archive device
+ this.add_row(table, '<%[ Archive device: ]%>', device.archive_device);
+
+ // Maximum concurrent jobs
+ var mcj = device.maximum_concurrent_jobs == 0 ? '<%[ unlimited ]%>' : device.maximum_concurrent_jobs;
+ var running_max_jobs = dev_running_jobs.length + ' / ' + mcj;
+ this.add_row(table, '<%[ Running jobs ]%> / <%[ Maximum concurrent jobs: ]%>', running_max_jobs);
+
+ // Maximum volume size
+ var mvs = Units.get_formatted_size(device.maximum_volume_size);
+ this.add_row(table, '<%[ Maximum volume size: ]%>', mvs);
+
+ // Is enabled
+ var enabled = this.formatters.check(device.enabled);
+ this.add_row(table, '<%[ Enabled: ]%>', enabled);
+
+ // Is autoselect
+ var autoselect = this.formatters.check(device.autoselect);
+ this.add_row(table, 'AutoSelect:', autoselect);
+
+ // Is mounted
+ var mounted = this.formatters.check(device.mounted);
+ this.add_row(table, '<%[ Mounted: ]%>', mounted);
+
+ // Is opened
+ var open = this.formatters.check(device.open);
+ this.add_row(table, '<%[ Opened: ]%>', open);
+
+ // Is waiting
+ var waiting = this.formatters.check(device.waiting);
+ this.add_row(table, '<%[ Waiting: ]%>', waiting);
+
+ // Is blocked
+ var blocked = this.formatters.check(device.blocked);
+ this.add_row(table, '<%[ Blocked: ]%>', blocked);
+
+ // Blocked description
+ if (device.blocked_desc) {
+ this.add_row(table, '<%[ Blocked description: ]%>', device.blocked_desc);
+ }
+
+ // Is read-only
+ var read_only = this.formatters.check(device.read_only);
+ this.add_row(table, '<%[ Read-only: ]%>', read_only);
+
+ // Pool
+ var pool = this.formatters.value(device.pool);
+ this.add_row(table, '<%[ Pool: ]%>', pool);
+
+ // Volume
+ var volume = this.formatters.value(device.volume);
+ this.add_row(table, '<%[ Volume: ]%>', volume);
+
+ // Free/used device space - part 1
+ var total_space = parseInt(device.total_space, 10);
+ var free_space = parseInt(device.free_space, 10);
+ var used_space = (total_space - free_space);
+ if (total_space) {
+ var space_container = document.createElement('DIV');
+ space_container.className = this.css.gauge_container;
+ var space_label = document.createElement('SPAN');
+ space_label.className = this.css.gauge_label;
+ space_label.textContent = Units.get_formatted_size(used_space);
+ var space_gauge = document.createElement('CANVAS');
+ space_gauge.setAttribute('rel', 'space');
+ space_gauge.className = this.css.gauge;
+ space_container.appendChild(space_gauge);
+ space_container.appendChild(space_label);
+ this.add_row(table, '<%[ Used space: ]%>', space_container);
+ } else {
+ this.add_row(table, '<%[ Used space: ]%>', this.formatters.value(false));
+ }
+
+ // set default container visibility
+ if (header.getAttribute('data-open') == 0) {
+ container.style.display = 'none';
+ }
+
+ set_space_gauge = function(open) {
+ if (!total_space) {
+ // simple used space text value, no gauge
+ return;
+ }
+ var space_gauge = document.querySelector('div[rel="device_' + device.name + '"] canvas[rel="space"]');
+ var total_space_gb, used_space_gb;
+ if (typeof(SIZE_VALUES_UNIT) === 'string') {
+ if (SIZE_VALUES_UNIT === 'decimal') {
+ total_space_gb = total_space/1000/1000/1000;
+ used_space_gb = used_space/1000/1000/1000;
+ } else if (SIZE_VALUES_UNIT === 'binary') {
+ total_space_gb = total_space/1024/1024/1024;
+ used_space_gb = used_space/1024/1024/1024;
+ }
+ } else {
+ // Default decimal bytes if unit not defined
+ total_space_gb = total_space/1000/1000/1000;
+ used_space_gb = used_space/1000/1000/1000;
+ }
+
+ var val1 = 0;
+ var val2 = parseInt(total_space_gb/100*20, 10);
+ var val3 = parseInt(total_space_gb/100*40, 10);
+ var val4 = parseInt(total_space_gb/100*60, 10);
+ var val5 = parseInt(total_space_gb/100*80, 10);
+ var val6 = total_space_gb;
+ var curr_opts = {
+ staticLabels: {
+ labels: [val1, val2, val3, val4, val5, val6] // Print labels at these values
+ },
+ staticZones: [
+ {strokeStyle: "#30B32D", min: 0, max: val4}, // Green
+ {strokeStyle: "#FFDD00", min: val4, max: val5}, // Yellow
+ {strokeStyle: "#F03E3E", min: val5, max: val6} // Red
+ ]
+ };
+ var opts = $.extend(true, curr_opts, this.gauges.space);
+ var gauge = new Gauge(space_gauge).setOptions(opts); // create gauge
+ gauge.maxValue = total_space_gb // set max gauge value
+ gauge.setMinValue(0); // Prefer setter over gauge.minValue = 0
+ gauge.animationSpeed = open ? 80 : 1; // set animation speed
+ gauge.set(used_space_gb); // set actual value
+ }.bind(this);
+
+ var devices_el;
+ if (device.autochanger) {
+ devices_el = document.querySelector('div[rel="ach_' + device.autochanger + '"]');
+ } else {
+ devices_el = document.getElementById(this.ids.devices);
+ }
+ var d = devices_el.querySelector('div[rel="device_' + device.name + '"]');
+ var h = devices_el.querySelector('div[rel="header_device_' + device.name + '"]');
+ if (!d && !h) {
+ devices_el.appendChild(header);
+ devices_el.appendChild(container);
+ } else {
+ devices_el.replaceChild(container, d);
+ devices_el.replaceChild(header, h);
+ }
+
+ // Free/used device space - part 2
+ set_space_gauge();
+
+ var gauge, cname;
+ for (var i = 0; i < dev_running_jobs.length; i++) {
+ // last speed
+ cname = 'last_speed';
+ gauge = document.querySelector('div[rel="job_' + dev_running_jobs[i].jobid + '"] canvas[rel="' + cname + '"]');
+ this.set_job_gauge(dev_running_jobs[i].jobid, dev_running_jobs[i].lastbytes_sec, gauge, cname);
+
+ // average speed
+ cname = 'ave_speed';
+ gauge = document.querySelector('div[rel="job_' + dev_running_jobs[i].jobid + '"] canvas[rel="' + cname + '"]');
+ this.set_job_gauge(dev_running_jobs[i].jobid, dev_running_jobs[i].avebytes_sec, gauge, cname);
+ }
+ },
+ add_running_job: function(main_container, job_nb, job) {
+ var container = document.createElement('DIV');
+ container.className = 'w3-border';
+ container.setAttribute('rel', 'job_' + job.jobid);
+ var table = document.createElement('TABLE');
+ table.className = 'w3-table w3-stripped status_table running_job_table';
+ container.appendChild(table);
+
+ // arrow icon
+ var job_arrow_img = document.createElement('I');
+ job_arrow_img.className = 'w3-margin-right';
+
+ var header = document.createElement('DIV');
+ var open = document.querySelector('div[rel="header_job_' + job.jobid + '"]');
+ if (open) {
+ var data_open = open.getAttribute('data-open');
+ header.setAttribute('data-open', data_open);
+ if (data_open == 1) {
+ job_arrow_img.className += ' fas fa-chevron-up';
+ } else {
+ job_arrow_img.className += ' fas fa-chevron-down';
+ }
+ } else {
+ header.setAttribute('data-open', 0);
+ job_arrow_img.className += ' fas fa-chevron-down';
+ }
+ header.setAttribute('rel', 'header_job_' + job.jobid);
+ header.className = [
+ this.css.status_header,
+ this.css.running_job_header
+ ].join(' ');
+ // set default container visibility
+ if (header.getAttribute('data-open') == 0) {
+ container.style.display = 'none';
+ }
+ var self = this;
+ header.addEventListener('click', function(e) {
+ var container = document.querySelector('div[rel="job_' + job.jobid + '"]');
+ var open = this.getAttribute('data-open');
+ if (open == 1) {
+ $(container).slideUp();
+ this.setAttribute('data-open', 0);
+ job_arrow_img.className = 'fas fa-chevron-down w3-margin-right';
+ } else {
+ $(container).slideDown('normal', function() {
+ // last speed
+ var cname = 'last_speed';
+ var gauge = document.querySelector('div[rel="job_' + job.jobid + '"] canvas[rel="' + cname + '"]');
+ self.set_job_gauge(job.jobid, job.lastbytes_sec, gauge, cname, true);
+
+ // average speed
+ var cname = 'ave_speed';
+ var gauge = document.querySelector('div[rel="job_' + job.jobid + '"] canvas[rel="' + cname + '"]');
+ self.set_job_gauge(job.jobid, job.avebytes_sec, gauge, cname, true);
+ });
+ this.setAttribute('data-open', 1);
+ job_arrow_img.className = 'fas fa-chevron-up w3-margin-right';
+ }
+ });
+
+ // job label
+ var job_label = document.createElement('DIV');
+ job_label.className = 'w3-container w3-cell w3-mobile';
+ job_label.style.flexBasis = '770px';
+ job_label.appendChild(job_arrow_img);
+ var job_label_txt = document.createTextNode('<%[ Job: ]%> #' + (job_nb+1) + ' ' + job.job);
+ job_label.appendChild(job_label_txt);
+ header.appendChild(job_label);
+
+ // device running
+ var job_running = document.createElement('DIV')
+ job_running.className = 'w3-container w3-cell w3-mobile';
+ var job_running_img = document.createElement('I');
+ var job_running_label = document.createElement('SPAN');
+ job_running_label.innerHTML = '<%[ Status: ]%> ';
+ var job_running_desc = document.createElement('SPAN');
+ job_running_img.className = 'fas fa-cog fa-spin';
+ job_running_desc.innerHTML = ' <%[ running ]%>';
+ job_running.appendChild(job_running_label);
+ job_running.appendChild(job_running_img);
+ job_running.appendChild(job_running_desc);
+ header.appendChild(job_running);
+
+ // JobId
+ var jobid_img = document.createElement('I');
+ jobid_img.className = 'fa fa-external-link-alt fa-xs';
+ var jobid_a = document.createElement('A');
+ jobid_a.href = '/web/job/history/' + job.jobid + '/';
+ jobid_a.appendChild(jobid_img);
+ jobid_a.title = '<%[ Go to job with jobid %jobid ]%>'.replace('%jobid', job.jobid);
+ var jobid = job.jobid + ' ' + jobid_a.outerHTML;
+ this.add_row(table, 'JobId', jobid);
+
+ // Type
+ var type = JobType.get_type(job.type);
+ this.add_row(table, '<%[ Type: ]%>', type);
+
+ // Level
+ var level = job.type === 'R' ? '-' : JobLevel.get_level(job.level);
+ this.add_row(table, '<%[ Level: ]%>', level);
+
+ // Last job speed
+ var last_speed = Units.format_speed(job.lastbytes_sec, null, true, true);
+ var last_job_speed = last_speed.value.toFixed(2) + ' ' + last_speed.format;
+ //this.add_row(table, '<%[ Last speed: ]%>', last_job_speed);
+
+ // Last speed - part 1
+ var last_speed_container = document.createElement('DIV');
+ last_speed_container.className = this.css.gauge_container;
+ var last_speed_label = document.createElement('SPAN');
+ last_speed_label.className = this.css.gauge_label;
+ last_speed_label.textContent = last_job_speed;
+ var last_speed_gauge = document.createElement('CANVAS');
+ last_speed_gauge.setAttribute('rel', 'last_speed');
+ last_speed_gauge.className = this.css.gauge;
+ last_speed_container.appendChild(last_speed_gauge);
+ last_speed_container.appendChild(last_speed_label);
+ this.add_row(table, '<%[ Last speed: ]%>', last_speed_container);
+
+ // Average job speed
+ var ave_speed = Units.format_speed(job.avebytes_sec, null, true, true);
+ var ave_job_speed = ave_speed.value.toFixed(2) + ' ' + ave_speed.format;
+ //this.add_row(table, '<%[ Average speed: ]%>', ave_job_speed);
+
+ // Average job speed - part 1
+ var ave_speed_container = document.createElement('DIV');
+ ave_speed_container.className = this.css.gauge_container;
+ var ave_speed_label = document.createElement('SPAN');
+ ave_speed_label.className = this.css.gauge_label;
+ ave_speed_label.textContent = ave_job_speed;
+ var ave_speed_gauge = document.createElement('CANVAS');
+ ave_speed_gauge.setAttribute('rel', 'ave_speed');
+ ave_speed_gauge.className = this.css.gauge;
+ ave_speed_container.appendChild(ave_speed_gauge);
+ ave_speed_container.appendChild(ave_speed_label);
+ this.add_row(table, '<%[ Average speed: ]%>', ave_speed_container);
+
+
+ // Processing file
+ if (job.hasOwnProperty('processing_file') && job.processing_file) {
+ var processing_file = document.createElement('SPAN');
+ processing_file.title = job.processing_file;
+ if (job.processing_file.length > 60) {
+ processing_file.textContent = job.processing_file.substr(0, 17) + ' (..) ' + job.processing_file.substr(-37);
+ } else {
+ processing_file.textContent = job.processing_file;
+ }
+ this.add_row(table, '<%[ Processing file: ]%>', processing_file.outerHTML);
+ }
+
+ var job_name = job.job.replace(/\.\d{4}-\d{2}-\d{2}_\d{2}.\d{2}.\d{2}_\d{2}$/, '');
+ var bytes = parseInt(job.jobbytes, 10);
+ var files = parseInt(job.jobfiles, 10);
+ files = files > 0 ? (files - 1) : 0;
+ var est = estimate_job(oData.jobs, job_name, job.level);
+
+ // Progress bar bytes
+ var bytes_progress;
+ if (job.type === 'B' && est.est_bytes > 0) {
+ bytes_progress = document.createElement('DIV');
+ bytes_progress.className = 'progressbar';
+ bytes_progress.title = '<%[ Progress bar displays estimated values ]%>';
+ var bytes_label = document.createElement('DIV');
+ bytes_label.className = 'progressbar-label';
+ var bytes_perc = ((100 * bytes) / est.est_bytes);
+ if (bytes_perc > 100) {
+ bytes_perc = 100;
+ }
+ bytes_label.textContent = Units.get_formatted_size(bytes) + ' / <%[ est. ]%> ' + Units.get_formatted_size(est.est_bytes) + ' (' + bytes_perc.toFixed(1) + '%' + ')';
+ bytes_progress.style.width = '70%';
+ bytes_progress.appendChild(bytes_label);
+ var bytes_bar = $(bytes_progress);
+ bytes_bar.progressbar({
+ max: est.est_bytes,
+ value: bytes
+ });
+ } else {
+ bytes_progress = '<%[ Not available ]%>';
+ }
+ this.add_row(table, '<%[ Byte progress bar: ]%>', bytes_progress);
+
+
+ // Progress bar files
+ var files_progress;
+ if (job.type === 'B' && est.est_files > 0) {
+ files_progress = document.createElement('DIV');
+ files_progress.className = 'progressbar';
+ files_progress.title = '<%[ Progress bar displays estimated values ]%>';
+ var files_label = document.createElement('DIV');
+ files_label.className = 'progressbar-label';
+ var files_perc = ((100 * files) / est.est_files);
+ if (files_perc > 100) {
+ files_perc = 100;
+ }
+ files_label.textContent = files + ' / <%[ est. ]%> ' + parseInt(est.est_files, 10) + ' (' + files_perc.toFixed(1) + '%' + ')';
+ files_progress.style.width = '70%';
+ files_progress.appendChild(files_label);
+ var files_bar = $(files_progress);
+ files_bar.progressbar({
+ max: est.est_files,
+ value: files
+ });
+ } else if (job.type === 'R' && job.hasOwnProperty('expected_files') && job.expected_files > 0) {
+ files_progress = document.createElement('DIV');
+ files_progress.className = 'progressbar';
+ var files_label = document.createElement('DIV');
+ files_label.className = 'progressbar-label';
+ var fexamined = parseInt(job.files_examined, 10);
+ var fexpected = parseInt(job.expected_files, 10);
+ var files_perc = ((100 * fexamined) / fexpected);
+ if (files_perc > 100) {
+ files_perc = 100;
+ }
+ files_label.textContent = fexamined + ' / ' + fexpected + ' (' + files_perc.toFixed(1) + '%' + ')';
+ files_progress.style.width = '70%';
+ files_progress.appendChild(files_label);
+ var files_bar = $(files_progress);
+ files_bar.progressbar({
+ max: fexpected,
+ value: fexamined
+ });
+ } else {
+ files_progress = '<%[ Not available ]%>';
+ }
+ this.add_row(table, '<%[ File progress bar: ]%>', files_progress);
+
+ // Read pool
+ if (job.read_pool) {
+ this.add_row(table, '<%[ Read pool: ]%>', job.read_pool);
+ }
+ // Read device
+ if (job.read_device) {
+ this.add_row(table, '<%[ Read device: ]%>', job.read_device);
+ }
+ // Read pool
+ if (job.read_volume) {
+ this.add_row(table, '<%[ Read volume: ]%>', job.read_volume);
+ }
+
+ // Write pool
+ if (job.write_pool) {
+ this.add_row(table, '<%[ Write pool: ]%>', job.write_pool);
+ }
+ // Write device
+ if (job.write_device) {
+ this.add_row(table, '<%[ Write device: ]%>', job.write_device);
+ }
+ // Write pool
+ if (job.write_volume) {
+ this.add_row(table, '<%[ Write volume: ]%>', job.write_volume);
+ }
+
+ // Job errors
+ this.add_row(table, '<%[ Job errors: ]%>', job.errors);
+
+ // Job bytes
+ var job_bytes = Units.get_formatted_size(job.jobbytes);
+ this.add_row(table, '<%[ Job bytes: ]%>', job_bytes);
+
+ // Examined files
+ this.add_row(table, '<%[ Job files: ]%>', job.jobfiles);
+
+ main_container.appendChild(header);
+ main_container.appendChild(container);
+ },
+ add_terminated_job: function(job_nb, job) {
+ var main_container = document.getElementById(this.ids.terminated);
+ var container = document.createElement('DIV');
+ container.className = [
+ this.css.terminated_job_table,
+ 'w3-border'
+ ].join(' ');
+ container.setAttribute('rel', 'job_terminated_' + job.jobid);
+ var table = document.createElement('TABLE');
+ table.className = 'w3-table w3-stripped status_table';
+ container.appendChild(table);
+
+ // arrow icon
+ var job_arrow_img = document.createElement('I');
+ job_arrow_img.className = 'w3-margin-right';
+
+ var header = document.createElement('DIV');
+ var open = document.querySelector('div[rel="header_job_terminated_' + job.jobid + '"]');
+ if (open) {
+ var data_open = open.getAttribute('data-open');
+ header.setAttribute('data-open', data_open);
+ if (data_open == 1) {
+ job_arrow_img.className += ' fas fa-chevron-up';
+ } else {
+ job_arrow_img.className += ' fas fa-chevron-down';
+ }
+ } else {
+ header.setAttribute('data-open', 0);
+ job_arrow_img.className += ' fas fa-chevron-down';
+ }
+ header.setAttribute('rel', 'header_job_terminated_' + job.jobid);
+ header.className = [
+ this.css.status_header,
+ this.css.terminated_job_header
+ ].join(' ');
+ // set default container visibility
+ if (header.getAttribute('data-open') == 0) {
+ container.style.display = 'none';
+ }
+ var self = this;
+ header.addEventListener('click', function(e) {
+ var container = document.querySelector('div[rel="job_terminated_' + job.jobid + '"]');
+ var open = this.getAttribute('data-open');
+ if (open == 1) {
+ $(container).slideUp();
+ this.setAttribute('data-open', 0);
+ job_arrow_img.className = 'fas fa-chevron-down w3-margin-right';
+ } else {
+ $(container).slideDown();
+ this.setAttribute('data-open', 1);
+ job_arrow_img.className = 'fas fa-chevron-up w3-margin-right';
+ }
+ });
+
+ // job label
+ var job_label = document.createElement('DIV');
+ job_label.className = 'w3-container w3-cell w3-mobile';
+ job_label.style.flexBasis = '770px';
+ job_label.appendChild(job_arrow_img);
+ var job_label_txt = document.createTextNode('<%[ Job: ]%> #' + (job_nb+1) + ' ' + job.job);
+ job_label.appendChild(job_label_txt);
+ header.appendChild(job_label);
+
+ // device terminated
+ var job_terminated = document.createElement('DIV')
+ job_terminated.className = 'w3-container w3-cell w3-mobile';
+ var job_terminated_img = document.createElement('I');
+ var job_terminated_label = document.createElement('SPAN');
+ job_terminated_label.innerHTML = '<%[ Status: ]%> ';
+ var job_terminated_desc = document.createElement('SPAN');
+ job_terminated_desc.innerHTML = JobStatus.get_icon(job.status).outerHTML;
+ job_terminated.appendChild(job_terminated_label);
+ job_terminated.appendChild(job_terminated_img);
+ job_terminated.appendChild(job_terminated_desc);
+ header.appendChild(job_terminated);
+
+ // JobId
+ var jobid_img = document.createElement('I');
+ jobid_img.className = 'fa fa-external-link-alt fa-xs';
+ var jobid_a = document.createElement('A');
+ jobid_a.href = '/web/job/history/' + job.jobid + '/';
+ jobid_a.appendChild(jobid_img);
+ jobid_a.title = '<%[ Go to job with jobid %jobid ]%>'.replace('%jobid', job.jobid);
+ var jobid = job.jobid + ' ' + jobid_a.outerHTML;
+ this.add_row(table, 'JobId', jobid);
+
+ // Type
+ var type = JobType.get_type(job.type);
+ this.add_row(table, '<%[ Type: ]%>', type);
+
+ // Start time
+ var starttime = Units.format_date(job.starttime_epoch);
+ this.add_row(table, '<%[ Start time: ]%>', starttime);
+
+ // End time
+ var endtime = Units.format_date(job.endtime_epoch);
+ this.add_row(table, '<%[ End time: ]%>', endtime);
+
+ // Level
+ var level = job.type === 'R' ? '-' : JobLevel.get_level(job.level);
+ this.add_row(table, '<%[ Level: ]%>', level);
+
+ // Job errors
+ this.add_row(table, '<%[ Job errors: ]%>', job.errors);
+
+ // Job bytes
+ var job_bytes = Units.get_formatted_size(job.jobbytes);
+ this.add_row(table, '<%[ Job bytes: ]%>', job_bytes);
+
+ // Examined files
+ this.add_row(table, '<%[ Job files: ]%>', job.jobfiles);
+
+ var d = main_container.querySelector('div[rel="job_terminated_' + job.jobid + '"]');
+ if (d) {
+ main_container.replaceChild(container, d);
+ } else {
+ main_container.appendChild(header);
+ main_container.appendChild(container);
+ }
+ },
+ set_gauge: function(gauge, options, value) {
+ var opts = $.extend(true, {}, this.gauges.speed, options);
+ var gauge = new Gauge(gauge).setOptions(opts); // create gauge
+ gauge.maxValue = options.maxValue; // set max gauge value
+ gauge.setMinValue(0); // Prefer setter over gauge.minValue = 0
+ gauge.animationSpeed = options.animationSpeed; // set animation speed
+ gauge.set(value); // set actual value
+ },
+ set_job_gauge: function(jobid, value, gauge, name, open) {
+ value = parseInt(value, 10);
+ var value_kbps = value/1000; // covert to KB/s
+ var prev_job = this.get_running_job(jobid);
+ var max_value_kbps = 0;
+ if (prev_job) {
+ if (prev_job.hasOwnProperty(name)) {
+ max_value_kbps = prev_job[name];
+ }
+ }
+ if (value_kbps > max_value_kbps) {
+ max_value_kbps = value_kbps;
+ }
+
+ var val1 = 0;
+ var val2 = parseInt(max_value_kbps/100*20, 10);
+ var val3 = parseInt(max_value_kbps/100*40, 10);
+ var val4 = parseInt(max_value_kbps/100*60, 10);
+ var val5 = parseInt(max_value_kbps/100*80, 10);
+ var val6 = max_value_kbps;
+ var options = {
+ staticLabels: {
+ labels: [val1, val2, val3, val4, val5, val6] // Print labels at these values
+ },
+ staticZones: [
+ {strokeStyle: "#30B32D", min: 0, max: val4}, // Green
+ {strokeStyle: "#FFDD00", min: val4, max: val5}, // Yellow
+ {strokeStyle: "#F03E3E", min: val5, max: val6} // Red
+ ],
+ animationSpeed: (open ? 80 : 1),
+ maxValue: max_value_kbps
+ };
+ this.set_gauge(gauge, options, value_kbps);
+ if (prev_job) {
+ prev_job[name] = max_value_kbps;
+ this.update_running_job(prev_job);
+ }
+ },
+ set_refresh_timeout: function(timeout) {
+ timeout = parseInt(timeout, 10) * 1000;
+ if (isNaN(timeout)) {
+ return;
+ }
+ if (this.refresh_timeout !== null) {
+ clearTimeout(this.refresh_timeout);
+ }
+ if (timeout === 0) {
+ return;
+ }
+ this.refresh_timeout = setTimeout(function() {
+ this.update_status();
+ }.bind(this), timeout);
+ },
+ update_status: function() {
+ $('#<%=$this->StorageStatusBtn->ClientID%>').click();
+ },
+ is_status_supported: function() {
+ var supported = false;
+ var not_supported = document.getElementById(this.ids.status_not_supported);
+ var graphical_container = document.getElementById(this.ids.graphical_container);
+ if (this.data && this.data.hasOwnProperty('version') && this.data.version.hasOwnProperty('major') && this.data.version.major >= 9 && this.data.version.minor >= 0 && this.data.version.release >= 0) {
+ supported = true;
+ not_supported.style.display = 'none';
+ graphical_container.style.display = '';
+ } else if (not_supported.style.display == 'none') {
+ not_supported.style.display = '';
+ graphical_container.style.display = 'none';
+ W3SubTabs.open('status_storage_subtab_text', 'status_storage_text_output');
+ }
+ return supported;
+ },
+ get_device_jobs: function(device) {
+ var jobs = [];
+ if (this.data.hasOwnProperty('running')) {
+ for (var i = 0; i < this.data.running.length; i++) {
+ if (this.data.running[i].read_device === device || this.data.running[i].write_device === device) {
+ jobs.push(this.data.running[i]);
+ }
+ }
+ }
+ return jobs;
+ },
+ get_running_job: function(jobid) {
+ var job;
+ for (var i = 0; i < this.running_jobs.length; i++) {
+ if (this.running_jobs[i].jobid === jobid) {
+ job = this.running_jobs[i];
+ break;
+ }
+ }
+ return job;
+ },
+ update_running_job: function(job) {
+ var update = false;
+ for (var i = 0; i < this.running_jobs.length; i++) {
+ if (this.running_jobs[i].jobid === job.jobid) {
+ this.running_jobs[i] = job;
+ update = true;
+ break;
+ }
+ }
+ return update;
+ }
+};
+
+function hide_action_text_output(e) {
+ if (e.hasOwnProperty('originalEvent') && e.originalEvent.type == 'click') {
+ $('#storage_action_text_output').slideUp('fast');
+ }
+}
+
+function init_graphical_storage_status(data) {
+ oGraphicalStorageStatus.update(data);
+}
+function status_storage_show_error(error) {
+ var errmsg = error;
+ if (error === 'timeout') {
+ errmsg = '<%[ Status request timed out. The most probably the Bacula storage is not available or it is not running. ]%>';
+ }
+ var err_el = document.getElementById('status_storage_error');
+ err_el.textContent = errmsg;
+ err_el.style.display = '';
+}
+oGraphicalStorageStatus.init();
+MonitorParams = {
+ jobs: null
+};
+</script>
+ </div>
+ <div id="status_storage_text_output" class="w3-code subtab_item" style="display: none">
+ <pre><com:TActiveLabel ID="StorageLog" /></pre>
+ </div>
</div>
</div>
</div>