lmc/linodes/backup_details/backup_details.js

466 lines
14 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* This file is part of Linode Manager Classic.
*
* Linode Manager Classic is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Linode Manager Classic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Linode Manager Classic. If not, see <https://www.gnu.org/licenses/>.
*/
import { settings, elements, apiGet, apiPost, parseParams, regionNames, setupHeader, timeString } from "/global.js";
(function()
{
// Element names specific to this page
elements.backupAge = "backup-age";
elements.backupConfigs = "backup-configs";
elements.backupDate = "backup-date";
elements.backupDisks = "backup-disks";
elements.backupLabel = "backup-label";
elements.backupLocation = "backup-location";
elements.backupSize = "backup-size";
elements.backupType = "backup-type";
elements.destLabel = "dest-label";
elements.destLinodes = "dest-linodes";
elements.destLocation = "dest-location";
elements.destPlan = "dest-plan";
elements.destSpace = "dest-space";
elements.linodeLabel = "linode-label";
elements.linodeTag = "linode-tag";
elements.linodeTagLink = "linode-tag-link";
elements.loading = "loading-linodes";
elements.lmcRow = "lmc-tr3";
elements.newLinode = "new-linode";
elements.restorePrefix = "restore-";
elements.selectPrefix = "select-";
elements.subnav = "subnav-link";
elements.subnavActive = "subnav-link-active";
elements.unallocatedPrefix = "unallocated-";
// Data recieved from API calls
var data = {};
data.backup = {};
data.linode = {};
data.linodes = [];
data.region = {};
data.types = [];
// Static references to UI elements
var ui = {};
ui.backupAge = {};
ui.backupConfigs = {};
ui.backupDate = {};
ui.backupDisks = {};
ui.backupLabel = {};
ui.backupLocation = {};
ui.backupSize = {};
ui.backupType = {};
ui.destLabel = {};
ui.destLinodes = {};
ui.destLocation = {};
ui.destPlan = {};
ui.destSpace = {};
ui.linodeLabel = {};
ui.linodeTag = {};
ui.linodeTagLink = {};
ui.loading = {};
ui.newLinode = {};
// Temporary state
var state = {};
state.haveTypes = false;
// Generate a linode table row
var createLinodeRow = function(linode)
{
var row = document.createElement("tr");
row.className = elements.lmcRow;
var label = document.createElement("td");
label.innerHTML = linode.label;
row.appendChild(label);
var plan = document.createElement("td");
if (linode.type) {
plan.innerHTML = linode.type;
for (var i = 0; i < data.types.length; i++) {
if (data.types[i].id == linode.type) {
plan.innerHTML = data.types[i].label;
break;
}
}
} else {
plan.innerHTML = "Unknown";
}
if (plan.innerHTML == "")
translatePlan(linode.type, plan);
row.appendChild(plan);
var location = document.createElement("td");
if (data.region.label && data.region.label.length)
location.innerHTML = data.region.label;
else if (regionNames[linode.region])
location.innerHTML = regionNames[linode.region];
else
location.innerHTML = linode.region;
row.appendChild(location);
var freeSpace = document.createElement("td");
freeSpace.id = elements.unallocatedPrefix + linode.id;
row.appendChild(freeSpace);
var select = document.createElement("td");
select.id = elements.selectPrefix + linode.id;
row.appendChild(select);
return row;
};
// Callback for backup details API call
var displayBackup = function(response)
{
data.backup = response;
// Populate info table
if (data.backup.label)
ui.backupLabel.innerHTML = data.backup.label;
var now = new Date();
var backupStart = new Date(data.backup.created + "Z");
ui.backupDate.innerHTML = backupStart.toLocaleString();
ui.backupAge.innerHTML = timeString(now - backupStart, true);
ui.backupType.innerHTML = data.backup.type;
if (regionNames[data.backup.region]) {
ui.backupLocation.innerHTML = regionNames[data.backup.region];
ui.destLocation.innerHTML = regionNames[data.backup.region];
} else {
ui.backupLocation.innerHTML = data.backup.region;
ui.destLocation.innerHTML = data.backup.region;
}
apiGet("/regions/" + data.backup.region, displayRegion, null);
for (var i = 0; i < data.backup.configs.length; i++) {
var li = document.createElement("li");
li.innerHTML = data.backup.configs[i];
ui.backupConfigs.appendChild(li);
}
data.backup.totalSize = 0;
for (var i = 0; i < data.backup.disks.length; i++) {
data.backup.totalSize += data.backup.disks[i].size;
var li = document.createElement("li");
li.innerHTML = data.backup.disks[i].label + " (" + data.backup.disks[i].filesystem + ") " + data.backup.disks[i].size + "MB";
ui.backupDisks.appendChild(li);
}
ui.backupSize.innerHTML = data.backup.totalSize + " MB";
if (state.haveTypes)
insertTypes();
};
// Callback for linode details API call
var displayDetails = function(response)
{
data.linode = response;
// Set page title and header stuff
document.title += " // " + data.linode.label;
ui.linodeLabel.innerHTML = data.linode.label;
if (data.linode.tags.length == 1) {
ui.linodeTagLink.href = "/linodes?tag=" + data.linode.tags[0];
ui.linodeTagLink.innerHTML = "(" + data.linode.tags[0] + ")";
ui.linodeTag.style.display = "inline";
}
};
// Callback for linode disks API call
var displayDisks = function(response)
{
// Find the linode this response is for
var lid = parseInt(response['_endpoint'].split("/")[3]);
var index = -1;
for (var i = 0; i < data.linodes.length; i++) {
if (data.linodes[i].id == lid) {
index = i;
break;
}
}
if (index == -1)
return;
// Add disks to array
data.linodes[index].disks = data.linodes[index].disks.concat(response.data);
// Request the next page if there are more pages
if (response.page != response.pages) {
apiGet("/linode/instances/" + data.linodes[index].id + "/disks?page=" + (response.page + 1), displayDisks, null);
return;
}
// Calculate Linode's free space
var free = data.linodes[index].specs.disk;
for (var i = 0; i < data.linodes[index].disks.length; i++)
free -= data.linodes[index].disks[i].size;
// Update table
var freeCell = document.getElementById(elements.unallocatedPrefix + data.linodes[index].id);
var selectCell = document.getElementById(elements.selectPrefix + data.linodes[index].id);
freeCell.innerHTML = free + " MB";
if (free >= data.backup.totalSize) {
var restoreLink = document.createElement("a");
restoreLink.id = elements.restorePrefix + data.linodes[index].id;
restoreLink.href = "#";
restoreLink.innerHTML = "Restore to this Linode";
restoreLink.addEventListener("click", handleRestore);
selectCell.appendChild(restoreLink);
} else {
selectCell.innerHTML = "--- not enough free space ---";
}
};
// Callback for linodes API call
var displayLinodes = function(response)
{
// Add linodes to array
data.linodes = data.linodes.concat(response.data);
// Request the next page if there are more pages
if (response.page != response.pages) {
var filter = {
"region": data.backup.region
};
apiGet("/linode/instances?page=" + (response.page + 1), displayLinodes, filter);
return;
}
ui.loading.remove();
for (var i = 0; i < data.linodes.length; i++) {
// Create row in the table
ui.destLinodes.appendChild(createLinodeRow(data.linodes[i]));
// Get the linode's disks
data.linodes[i].disks = [];
apiGet("/linode/instances/" + data.linodes[i].id + "/disks", displayDisks, null);
}
};
// Callback for region API call
var displayRegion = function(response)
{
data.region = response;
if (data.region.label && data.region.label.length) {
ui.backupLocation.innerHTML = response.label;
ui.destLocation.innerHTML = response.label;
}
};
// Callback for linode types API call
var displayTypes = function(response)
{
// Add types to array
data.types = data.types.concat(response.data);
// Request the next page if there are more pages
if (response.page != response.pages) {
apiGet("/linode/types?page=" + (response.page + 1), displayTypes, null);
return;
}
state.haveTypes = true;
if (data.backup.id)
insertTypes();
};
// Handler for create linode button
var handleCreate = function(event)
{
if (event.currentTarget.disabled)
return;
// Find the selected type
var index = -1;
for (var i = 0; i < data.types.length; i++) {
if (data.types[i].id == ui.destPlan.value) {
index = i;
break;
}
}
if (index == -1)
return;
if (!confirm("Create a new " + data.types[i].label + " from this backup? This new instance will cost $" + data.types[i].price.monthly.toFixed(2) + " per month and backups will be enabled per your global account setting."))
return;
var req = {
"label": ui.destLabel.value,
"type": ui.destPlan.value,
"region": data.backup.region,
"backup_id": data.backup.id
};
var callback = function(response)
{
location.href = "/linodes/dashboard?lid=" + response.id;
};
apiPost("/linode/instances", req, callback);
};
// Handler for backup restore links
var handleRestore = function(event)
{
// Find the linode associated with this link
var lid = parseInt(event.currentTarget.id.replace(elements.restorePrefix, ""));
var index = -1;
for (var i = 0; i < data.linodes.length; i++) {
if (data.linodes[i].id == lid) {
index = i;
break;
}
}
if (index == -1)
return;
if (!confirm("Restore to Linode " + data.linodes[index].label + "?"))
return;
var req = {
"linode_id": lid,
"overwrite": false
};
var callback = function(response)
{
location.href = "/linodes/dashboard?lid=" + lid;
};
apiPost("/linode/instances/" + data.params.lid + "/backups/" + data.backup.id + "/restore", req, callback);
};
// Insert linode types into selector
var insertTypes = function()
{
for (var i = 0; i < data.types.length; i++) {
if (data.types[i].disk < data.backup.totalSize)
continue;
var option = document.createElement("option");
option.value = data.types[i].id;
option.innerHTML = data.types[i].label;
ui.destPlan.appendChild(option);
}
updateSpace(null);
ui.newLinode.disabled = false;
var filter = {
"region": data.backup.region
};
apiGet("/linode/instances", displayLinodes, filter);
};
// Initial setup
var setup = function()
{
// Parse URL parameters
data.params = parseParams();
// We need a Linode ID, so die if we don't have it
if (!data.params.lid) {
alert("No Linode ID supplied!");
return;
}
// We also need a backup ID
if (!data.params.bid) {
alert("No Backup ID supplied!");
return;
}
setupHeader();
// Update links on page to include proper Linode ID
var anchors = document.getElementsByTagName("a");
for (var i = 0; i < anchors.length; i++)
anchors[i].href = anchors[i].href.replace("lid=0", "lid=" + data.params.lid);
// Highlight the backups subnav link
var subnavLinks = document.getElementsByClassName(elements.subnav);
for (var i = 0; i < subnavLinks.length; i++) {
if (subnavLinks[i].pathname == "/linodes/backups")
subnavLinks[i].className += " " + elements.subnavActive;
}
// Get element references
ui.backupAge = document.getElementById(elements.backupAge);
ui.backupConfigs = document.getElementById(elements.backupConfigs);
ui.backupDate = document.getElementById(elements.backupDate);
ui.backupDisks = document.getElementById(elements.backupDisks);
ui.backupLabel = document.getElementById(elements.backupLabel);
ui.backupLocation = document.getElementById(elements.backupLocation);
ui.backupSize = document.getElementById(elements.backupSize);
ui.backupType = document.getElementById(elements.backupType);
ui.destLabel = document.getElementById(elements.destLabel);
ui.destLinodes = document.getElementById(elements.destLinodes);
ui.destLocation = document.getElementById(elements.destLocation);
ui.destPlan = document.getElementById(elements.destPlan);
ui.destSpace = document.getElementById(elements.destSpace);
ui.linodeLabel = document.getElementById(elements.linodeLabel);
ui.linodeTag = document.getElementById(elements.linodeTag);
ui.linodeTagLink = document.getElementById(elements.linodeTagLink);
ui.loading = document.getElementById(elements.loading);
ui.newLinode = document.getElementById(elements.newLinode);
// Register event handlers
ui.destPlan.addEventListener("input", updateSpace);
ui.newLinode.addEventListener("click", handleCreate);
// Get data from API
apiGet("/linode/instances/" + data.params.lid, displayDetails, null);
apiGet("/linode/instances/" + data.params.lid + "/backups/" + data.params.bid, displayBackup, null);
apiGet("/linode/types", displayTypes, null);
};
// Update the given element with the given type's label
var translatePlan = function(type, el)
{
var callback = function(response)
{
el.innerHTML = response.label;
};
apiGet("/linode/types/" + type, callback, null);
};
// Update the price display
var updateSpace = function(event)
{
// Find the selected type
var type = null;
for (var i = 0; i < data.types.length; i++) {
if (data.types[i].id == ui.destPlan.value) {
type = data.types[i];
break;
}
}
if (!type)
return;
ui.destSpace.innerHTML = type.disk;
};
// Attach onload handler
window.addEventListener("load", setup);
})();