2020-01-10 00:24:59 -05:00
/ *
* 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 = [ ] ;
2024-05-06 16:57:12 -04:00
data . region = { } ;
2020-01-10 00:24:59 -05:00
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 ) {
2024-05-06 16:57:12 -04:00
plan . innerHTML = linode . type ;
2020-01-10 00:24:59 -05:00
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" ) ;
2024-05-06 16:57:12 -04:00
if ( data . region . label && data . region . label . length )
location . innerHTML = data . region . label ;
else if ( regionNames [ linode . region ] )
2020-01-10 00:24:59 -05:00
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 ;
2024-05-06 16:57:12 -04:00
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 ) ;
2020-01-10 00:24:59 -05:00
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" ;
2024-05-06 16:57:12 -04:00
if ( state . haveTypes )
2020-01-10 00:24:59 -05:00
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 = {
2024-05-06 16:57:12 -04:00
"region" : data . backup . region
2020-01-10 00:24:59 -05:00
} ;
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 ) ;
}
} ;
2024-05-06 16:57:12 -04:00
// 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 ;
}
} ;
2020-01-10 00:24:59 -05:00
// 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 ;
2024-05-06 16:57:12 -04:00
if ( data . backup . id )
2020-01-10 00:24:59 -05:00
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 ,
2024-05-06 16:57:12 -04:00
"region" : data . backup . region ,
2020-01-10 00:24:59 -05:00
"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 ) ;
}
2024-05-06 16:57:12 -04:00
updateSpace ( null ) ;
2020-01-10 00:24:59 -05:00
ui . newLinode . disabled = false ;
var filter = {
2024-05-06 16:57:12 -04:00
"region" : data . backup . region
2020-01-10 00:24:59 -05:00
} ;
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
2024-05-06 16:57:12 -04:00
ui . destPlan . addEventListener ( "input" , updateSpace ) ;
2020-01-10 00:24:59 -05:00
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
2024-05-06 16:57:12 -04:00
var updateSpace = function ( event )
2020-01-10 00:24:59 -05:00
{
// 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 ) ;
} ) ( ) ;