/* * 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 . */ import { settings, elements, apiGet, apiPost, apiPut, parseParams, setupHeader } from "/global.js"; (function() { // Element names specific to this page elements.binbash = "binbash"; elements.bootDeviceCustom = "boot-device-custom"; elements.bootDeviceStandard = "boot-device-standard"; elements.custom = "custom"; elements["default"] = "default"; elements.devtmpfsHelper = "devtmpfs-helper"; elements.devtmpfsHelperNo = "devtmpfs-helper-no"; elements.disks = "disks"; elements.distroHelper = "distro-helper"; elements.distroHelperNo = "distro-helper-no"; elements.fullvirt = "fullvirt"; elements.fullvirtHide = "fullvirt-hide"; elements.initrd = "initrd"; elements.kernel = "kernel"; elements.label = "label"; elements.limit = "limit"; elements.linodeLabel = "linode-label"; elements.linodeTag = "linode-tag"; elements.linodeTagLink = "linode-tag-link"; elements.maxMem = "max-mem"; elements.memLimit = "mem-limit"; elements.modulesHelper = "modules-helper"; elements.modulesHelperNo = "modules-helper-no"; elements.networkHelper = "network-helper"; elements.networkHelperNo = "network-helper-no"; elements.noLimit = "no-limit"; elements.notes = "notes"; elements.paravirt = "paravirt"; elements.saveButton = "save-button"; elements.sda = "sda"; elements.sdb = "sdb"; elements.sdc = "sdc"; elements.sdd = "sdd"; elements.sde = "sde"; elements.sdf = "sdf"; elements.sdg = "sdg"; elements.sdh = "sdh"; elements.single = "single"; elements.standard = "standard"; elements.subnav = "subnav-link"; elements.subnavActive = "subnav-link-active"; elements.updatedbHelper = "updatedb-helper"; elements.updatedbHelperNo = "updatedb-helper-no"; elements.volumes = "volumes"; // Data recieved from API calls var data = {}; data.config = {}; data.disks = []; data.kernels = []; data.linode = {}; data.volumes = []; // Static references to UI elements var ui = {}; ui.binbash = {}; ui.bootDeviceCustom = {}; ui.bootDeviceStandard = {}; ui.custom = {}; ui["default"] = {}; ui.devtmpfsHelper = {}; ui.devtmpfsHelperNo = {}; ui.disks = []; ui.distroHelper = {}; ui.distroHelperNo = {}; ui.fullvirt = {}; ui.fullvirtHide = []; ui.initrd = {}; ui.kernel = {}; ui.label = {}; ui.limit = {}; ui.linodeLabel = {}; ui.linodeTag = {}; ui.linodeTagLink = {}; ui.maxMem = {}; ui.memLimit = {}; ui.modulesHelper = {}; ui.modulesHelperNo = {}; ui.networkHelper = {}; ui.networkHelperNo = {}; ui.noLimit = {}; ui.notes = {}; ui.paravirt = {}; ui.saveButton = {}; ui.sda = {}; ui.sdb = {}; ui.sdc = {}; ui.sdd = {}; ui.sde = {}; ui.sdf = {}; ui.sdg = {}; ui.sdh = {}; ui.single = {}; ui.standard = {}; ui.updatedbHelper = {}; ui.updatedbHelperNo = {}; ui.volumes = []; // Temporary state var state = { "haveDisks": false, "haveVolumes": false }; // Callback for config API call var displayConfig = function(response) { data.config = response; // Label and notes ui.label.value = data.config.label; ui.notes.value = data.config.comments; // Virtualization mode if (data.config.virt_mode == "paravirt") ui.paravirt.checked = true; else if (data.config.virt_mode == "fullvirt") ui.fullvirt.checked = true; showHideFullvirt(null); // Kernel if (data.kernels.length) ui.kernel.value = data.config.kernel; // Run level if (data.config.run_level == "default") ui["default"].checked = true; else if (data.config.run_level == "single") ui.single.checked = true; else if (data.config.run_level == "binbash") ui.binbash.checked = true; // Memory limit if (data.config.memory_limit == 0) { ui.noLimit.checked = true; } else { ui.limit.checked = true; ui.memLimit.value = data.config.memory_limit; } // Disk configuration if (state.haveDisks && state.haveVolumes) displayDrives(); if (data.config.initrd) ui.initrd.value = data.config.initrd; if (/^\/dev\/sd[a-h]$/.test(data.config.root_device)) { ui.standard.checked = true; ui.bootDeviceStandard.value = data.config.root_device; } else { ui.custom.checked = true; ui.bootDeviceCustom.value = data.config.root_device; } // Helpers if (data.config.helpers.distro) ui.distroHelper.checked = true; else ui.distroHelperNo.checked = true; if (data.config.helpers.updatedb_disabled) ui.updatedbHelper.checked = true; else ui.updatedbHelperNo.checked = true; if (data.config.helpers.modules_dep) ui.modulesHelper.checked = true; else ui.modulesHelperNo.checked = true; if (data.config.helpers.devtmpfs_automount) ui.devtmpfsHelper.checked = true; else ui.devtmpfsHelperNo.checked = true; if (data.config.helpers.network) ui.networkHelper.checked = true; else ui.networkHelperNo.checked = true; ui.saveButton.disabled = false; }; // 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"; } // Display memory limits ui.maxMem.innerHTML = data.linode.specs.memory; ui.memLimit.max = data.linode.specs.memory; // Get list of volumes apiGet("/volumes", displayVolumes, null); }; // Callback for linode disks API call var displayDisks = function(response) { // Add disks to array data.disks = data.disks.concat(response.data); // Request the next page if there are more if (response.page != response.pages) { apiGet("/linode/instances/" + data.params.lid + "/disks?page=" + (response.page + 1), displayDisks, null); return; } state.haveDisks = true; // Add disks to selectors for (var i = data.disks.length - 1; i >= 0; i--) { var disk = document.createElement("option"); disk.value = "disk-" + data.disks[i].id; disk.innerHTML = data.disks[i].label; for (var j = 0; j < ui.disks.length; j++) ui.disks[j].prepend(disk.cloneNode(true)); } if (data.config.devices && state.haveVolumes) displayDrives(); }; // Sets the values for the drive selectors var displayDrives = function() { for (var drive in data.config.devices) { if (!data.config.devices[drive]) continue; if (data.config.devices[drive].disk_id) ui[drive].value = "disk-" + data.config.devices[drive].disk_id; else if (data.config.devices[drive].volume_id) ui[drive].value = "volume-" + data.config.devices[drive].volume_id; } }; // Callback for linode kernels API call var displayKernels = function(response) { // Add kernels to array data.kernels = data.kernels.concat(response.data); // Request the next page if there are more if (response.page != response.pages) { apiGet("/linode/kernels?page=" + (response.page + 1), displayKernels, null); return; } // Add kernels to selector for (var i = 0; i < data.kernels.length; i++) { var kernel = document.createElement("option"); kernel.value = data.kernels[i].id; kernel.innerHTML = data.kernels[i].label; ui.kernel.appendChild(kernel); if (data.params.cid == 0 && data.kernels[i].id == settings.preferredKernel) ui.kernel.value = data.kernels[i].id; } if (data.config.kernel) ui.kernel.value = data.config.kernel; }; // Callback for account settings API call var displaySettings = function(response) { if (response.network_helper) ui.networkHelper.checked = true; else ui.networkHelperNo.checked = true; }; // Callback for volumes API call var displayVolumes = function(response) { // Add volumes to array data.volumes = data.volumes.concat(response.data); // Request the next page if there are more if (response.page != response.pages) { apiGet("/volumes?page=" + (response.page + 1), displayVolumes, null); return; } state.haveVolumes = true; // Add volumes from this Linode's region to selectors for (var i = 0; i < data.volumes.length; i++) { if (data.volumes[i].region != data.linode.region) continue; if (data.volumes[i].linode_id && data.volumes[i].linode_id != data.params.lid) continue; var volume = document.createElement("option"); volume.value = "volume-" + data.volumes[i].id; volume.innerHTML = data.volumes[i].label; for (var j = 0; j < ui.volumes.length; j++) ui.volumes[j].appendChild(volume.cloneNode(true)); } if (data.config.devices && state.haveDisks) displayDrives(); }; // Save button handler var handleSave = function(event) { if (event.currentTarget.disabled) return; var req = { "label": ui.label.value, "comments": ui.notes.value, "kernel": ui.kernel.value, "devices": {}, "helpers": { "distro": ui.distroHelper.checked, "updatedb_disabled": ui.updatedbHelper.checked, "modules_dep": ui.modulesHelper.checked, "devtmpfs_automount": ui.devtmpfsHelper.checked, "network": ui.networkHelper.checked } }; if (ui.paravirt.checked) req.virt_mode = "paravirt"; else if (ui.fullvirt.checked) req.virt_mode = "fullvirt"; if (ui["default"].checked) req.run_level = "default"; else if (ui.single.checked) req.run_level = "single"; else if (ui.binbash.checked) req.run_level = "binbash"; if (ui.noLimit.checked) req.memory_limit = 0; else req.memory_limit = parseInt(ui.memLimit.value); if (ui.sda.value.startsWith("disk-")) req.devices.sda = { "disk_id": parseInt(ui.sda.value.substring(5)) }; else if (ui.sda.value.startsWith("volume-")) req.devices.sda = { "volume_id": parseInt(ui.sda.value.substring(7)) }; if (ui.sdb.value.startsWith("disk-")) req.devices.sdb = { "disk_id": parseInt(ui.sdb.value.substring(5)) }; else if (ui.sdb.value.startsWith("volume-")) req.devices.sdb = { "volume_id": parseInt(ui.sdb.value.substring(7)) }; if (ui.sdc.value.startsWith("disk-")) req.devices.sdc = { "disk_id": parseInt(ui.sdc.value.substring(5)) }; else if (ui.sdc.value.startsWith("volume-")) req.devices.sdc = { "volume_id": parseInt(ui.sdc.value.substring(7)) }; if (ui.sdd.value.startsWith("disk-")) req.devices.sdd = { "disk_id": parseInt(ui.sdd.value.substring(5)) }; else if (ui.sdd.value.startsWith("volume-")) req.devices.sdd = { "volume_id": parseInt(ui.sdd.value.substring(7)) }; if (ui.paravirt.checked) { if (ui.sde.value.startsWith("disk-")) req.devices.sde = { "disk_id": parseInt(ui.sde.value.substring(5)) }; else if (ui.sde.value.startsWith("volume-")) req.devices.sde = { "volume_id": parseInt(ui.sde.value.substring(7)) }; if (ui.sdf.value.startsWith("disk-")) req.devices.sdf = { "disk_id": parseInt(ui.sdf.value.substring(5)) }; else if (ui.sdf.value.startsWith("volume-")) req.devices.sdf = { "volume_id": parseInt(ui.sdf.value.substring(7)) }; if (ui.sdg.value.startsWith("disk-")) req.devices.sdg = { "disk_id": parseInt(ui.sdg.value.substring(5)) }; else if (ui.sdg.value.startsWith("volume-")) req.devices.sdg = { "volume_id": parseInt(ui.sdg.value.substring(7)) }; if (ui.sdh.value.startsWith("disk-")) req.devices.sdh = { "disk_id": parseInt(ui.sdh.value.substring(5)) }; else if (ui.sdh.value.startsWith("volume-")) req.devices.sdh = { "volume_id": parseInt(ui.sdh.value.substring(7)) }; } var initrd = parseInt(ui.initrd.value); if (initrd == 0) req.initrd = null; else req.initrd = initrd; if (ui.standard.checked) req.root_device = ui.bootDeviceStandard.value; else req.root_device = ui.bootDeviceCustom.value; if (data.params.cid == 0) { apiPost("/linode/instances/" + data.params.lid + "/configs", req, function(response) { location.href = "/linodes/dashboard?lid=" + data.params.lid; }); } else { apiPut("/linode/instances/" + data.params.lid + "/configs/" + data.params.cid, req, function(response) { location.href = "/linodes/dashboard?lid=" + data.params.lid; }); } }; // 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 config ID if (!data.params.cid) { alert("No config 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=00", data.params.lid); anchors[i].href = anchors[i].href.replace("lid=0", "lid=" + data.params.lid); } // Highlight the dashboard subnav link var subnavLinks = document.getElementsByClassName(elements.subnav); for (var i = 0; i < subnavLinks.length; i++) { if (subnavLinks[i].pathname == "/linodes/dashboard") subnavLinks[i].className += " " + elements.subnavActive; } // Get element references ui.binbash = document.getElementById(elements.binbash); ui.bootDeviceCustom = document.getElementById(elements.bootDeviceCustom); ui.bootDeviceStandard = document.getElementById(elements.bootDeviceStandard); ui.custom = document.getElementById(elements.custom); ui["default"] = document.getElementById(elements["default"]); ui.devtmpfsHelper = document.getElementById(elements.devtmpfsHelper); ui.devtmpfsHelperNo = document.getElementById(elements.devtmpfsHelperNo); ui.disks = document.getElementsByClassName(elements.disks); ui.distroHelper = document.getElementById(elements.distroHelper); ui.distroHelperNo = document.getElementById(elements.distroHelperNo); ui.fullvirt = document.getElementById(elements.fullvirt); ui.fullvirtHide = document.getElementsByClassName(elements.fullvirtHide); ui.initrd = document.getElementById(elements.initrd); ui.kernel = document.getElementById(elements.kernel); ui.label = document.getElementById(elements.label); ui.limit = document.getElementById(elements.limit); ui.linodeLabel = document.getElementById(elements.linodeLabel); ui.linodeTag = document.getElementById(elements.linodeTag); ui.linodeTagLink = document.getElementById(elements.linodeTagLink); ui.maxMem = document.getElementById(elements.maxMem); ui.memLimit = document.getElementById(elements.memLimit); ui.modulesHelper = document.getElementById(elements.modulesHelper); ui.modulesHelperNo = document.getElementById(elements.modulesHelperNo); ui.networkHelper = document.getElementById(elements.networkHelper); ui.networkHelperNo = document.getElementById(elements.networkHelperNo); ui.noLimit = document.getElementById(elements.noLimit); ui.notes = document.getElementById(elements.notes); ui.paravirt = document.getElementById(elements.paravirt); ui.saveButton = document.getElementById(elements.saveButton); ui.sda = document.getElementById(elements.sda); ui.sdb = document.getElementById(elements.sdb); ui.sdc = document.getElementById(elements.sdc); ui.sdd = document.getElementById(elements.sdd); ui.sde = document.getElementById(elements.sde); ui.sdf = document.getElementById(elements.sdf); ui.sdg = document.getElementById(elements.sdg); ui.sdh = document.getElementById(elements.sdh); ui.single = document.getElementById(elements.single); ui.standard = document.getElementById(elements.standard); ui.updatedbHelper = document.getElementById(elements.updatedbHelper); ui.updatedbHelperNo = document.getElementById(elements.updatedbHelperNo); ui.volumes = document.getElementsByClassName(elements.volumes); // Register event handlers ui.fullvirt.addEventListener("input", showHideFullvirt); ui.paravirt.addEventListener("input", showHideFullvirt); ui.saveButton.addEventListener("click", handleSave); // Get data from API apiGet("/linode/instances/" + data.params.lid, displayDetails, null); apiGet("/linode/kernels", displayKernels, null); apiGet("/linode/instances/" + data.params.lid + "/disks", displayDisks, null); if (data.params.cid == 0) { apiGet("/account/settings", displaySettings, null); ui.saveButton.disabled = false; } else { apiGet("/linode/instances/" + data.params.lid + "/configs/" + data.params.cid, displayConfig, null); } }; // Show/hide rows for fullvirt var showHideFullvirt = function(event) { var display = "table-row"; if (ui.fullvirt.checked) display = "none"; for (var i = 0; i < ui.fullvirtHide.length; i++) ui.fullvirtHide[i].style.display = display; }; // Attach onload handler window.addEventListener("load", setup); })();