diff --git a/frontend/classes/setting.php b/frontend/classes/setting.php new file mode 100644 index 0000000..330df08 --- /dev/null +++ b/frontend/classes/setting.php @@ -0,0 +1,43 @@ + array( + "Key" => "Key", + "Value" => "Value" + ), + 'timestamp' => array( + "LastChanged" => "LastChanged" + ) + ); + + public static function ByKey($key, $cache_duration = 60) + { + return Setting::CreateFromQuery("SELECT * FROM settings WHERE `Key` = :Key", array(":Key" => $key), $cache_duration, true); + } + + public function ChangeValue($value) + { + $this->uValue = $value; + $this->uLastChanged = time(); + $this->InsertIntoDatabase(); + } +} diff --git a/frontend/classes/vps.php b/frontend/classes/vps.php index 2e074be..e9df5a5 100644 --- a/frontend/classes/vps.php +++ b/frontend/classes/vps.php @@ -43,6 +43,12 @@ class Vps extends CPHPDatabaseRecordClass 'OutgoingTrafficLimit' => "OutgoingTrafficLimit", 'TotalTrafficLimit' => "TotalTrafficLimit" ), + 'timestamp' => array( + "TerminationDate" => "TerminationDate" + ), + 'boolean' => array( + "IsTerminated" => "Terminated" + ), 'node' => array( 'Node' => "NodeId" ), @@ -264,7 +270,7 @@ class Vps extends CPHPDatabaseRecordClass } elseif($this->sStatus == CVM_STATUS_TERMINATED) { - throw new VpsSuspendedException("No operations can be performed on this VPS beacuse it is terminated.", 1, $this->sInternalId); + throw new VpsTerminatedException("No operations can be performed on this VPS beacuse it is terminated.", 1, $this->sInternalId); } else { @@ -534,7 +540,15 @@ class Vps extends CPHPDatabaseRecordClass public function Suspend() { - if($this->sStatus != CVM_STATUS_SUSPENDED) + if($this->sStatus == CVM_STATUS_SUSPENDED) + { + throw new VpsSuspendException("The VPS is already suspended.", 1, $this->sInternalId); + } + elseif($this->sStatus == CVM_STATUS_TERMINATED) + { + throw new VpsSuspendException("The VPS cannot be suspended because it is already terminated.", 1, $this->sInternalId); + } + else { try { @@ -547,10 +561,6 @@ class Vps extends CPHPDatabaseRecordClass throw new VpsSuspendException("Suspension failed as the VPS could not be stopped.", 1, $this->sInternalId, $e); } } - else - { - throw new VpsSuspendException("The VPS is already suspended.", 1, $this->sInternalId); - } } public function Unsuspend() @@ -574,6 +584,53 @@ class Vps extends CPHPDatabaseRecordClass } } + public function Terminate() + { + if($this->sStatus != CVM_STATUS_TERMINATED) + { + try + { + $this->Stop(); + } + catch (VpsStopException $e) + { + /*throw new VpsTerminateException("Termination failed as the VPS could not be stopped.", 1, $this->sInternalId, $e);*/ + /* TODO: Throw warning about being unable to stop it, after checking VPS status. */ + } + + $this->uStatus = CVM_STATUS_TERMINATED; + $this->uTerminationDate = time(); + $this->InsertIntoDatabase(); + } + else + { + throw new VpsTerminateException("The VPS is already terminated.", 1, $this->sInternalId); + } + } + + public function Unterminate() + { + if($this->sStatus == CVM_STATUS_TERMINATED) + { + try + { + $this->Start(true); + } + catch (VpsStartException $e) + { + /*throw new VpsUnterminateException("Untermination failed as the VPS could not be started.", 1, $this->sInternalId, $e);*/ + /* TODO: Throw warning about being unable to start it, after checking VPS status. */ + } + + $this->uStatus = CVM_STATUS_STARTED; + $this->InsertIntoDatabase(); + } + else + { + throw new VpsUnterminateException("The VPS is not terminated.", 1, $this->sInternalId); + } + } + public function AddIp($ip) { $command = array("sudo", "vzctl", "set", $this->sInternalId, "--ipadd", $ip, "--save"); diff --git a/frontend/includes/include.exceptions.php b/frontend/includes/include.exceptions.php index 09988f1..2e212cc 100644 --- a/frontend/includes/include.exceptions.php +++ b/frontend/includes/include.exceptions.php @@ -44,6 +44,8 @@ class VpsStartException extends VpsException {} class VpsStopException extends VpsException {} class VpsSuspendException extends VpsException {} class VpsUnsuspendException extends VpsException {} +class VpsTerminateException extends VpsException {} +class VpsUnterminateException extends VpsException {} class VpsSuspendedException extends VpsException {} class VpsTerminatedException extends VpsException {} class VpsDestroyException extends VpsException {} diff --git a/frontend/locales/english.lng b/frontend/locales/english.lng index 01262dd..24b25a0 100644 --- a/frontend/locales/english.lng +++ b/frontend/locales/english.lng @@ -166,6 +166,24 @@ error-unsuspend-error-title; Failed to unsuspend VPS error-unsuspend-error-text; The VPS could not be unsuspended. button-admin-vps-unsuspend; Unsuspend VPS +## Terminate VPS +title-admin-vps-terminate; Terminate VPS +vps-admin-terminate-text; Are you sure you wish to terminate this VPS? The VPS will be suspended immediately, and deleted after several hours. As long as it is not deleted, the termination can be undone. +error-terminate-success-title; VPS terminated +error-terminate-success-text; The VPS has been terminated and can no longer be used by the owner. +error-terminate-error-title; Failed to terminate VPS +error-terminate-error-text; The VPS could not be terminated. +button-admin-vps-terminate; Terminate VPS + +## Unterminate VPS +title-admin-vps-unterminate; Unterminate VPS +vps-admin-unterminate-text; Are you sure you wish to unterminate this VPS? The owner will be able to use it again. +error-unterminate-success-title; VPS unterminated +error-unterminate-success-text; The VPS has been unterminated and can now be used by the owner again. +error-unterminate-error-title; Failed to unterminate VPS +error-unterminate-error-text; The VPS could not be unterminated. +button-admin-vps-unterminate; Unterminate VPS + ## Transfer VPS title-admin-vps-transfer; Transfer VPS ownership button-admin-vps-transfer; Transfer VPS diff --git a/frontend/modules/admin/vps/terminate.php b/frontend/modules/admin/vps/terminate.php new file mode 100644 index 0000000..5548850 --- /dev/null +++ b/frontend/modules/admin/vps/terminate.php @@ -0,0 +1,77 @@ +RequireAccessLevel(30); + + $sVps = new Vps($router->uParameters[1]); + + if(isset($_POST['submit'])) + { + if($_POST['action'] == "terminate") + { + $sVps->Terminate(); + + $sMainContents .= NewTemplater::Render("{$sTheme}/shared/error/success", $locale->strings, array( + 'title' => $locale->strings['error-terminate-success-title'], + 'message' => $locale->strings['error-terminate-success-text'] + )); + } + elseif($_POST['action'] == "unterminate") + { + $sVps->Unterminate(); + + $sMainContents .= NewTemplater::Render("{$sTheme}/shared/error/success", $locale->strings, array( + 'title' => $locale->strings['error-unterminate-success-title'], + 'message' => $locale->strings['error-unterminate-success-text'] + )); + } + + $sVps->RefreshData(); + + /* TODO: Flash message and redirect to VPS lookup page. */ + } + + $sTerminated = ($sVps->sStatus == CVM_STATUS_TERMINATED) ? true : false; + + $sPageContents = NewTemplater::Render("{$sTheme}/admin/vps/terminate", $locale->strings, array( + 'id' => $sVps->sId, + 'terminated' => $sTerminated, + 'can-unterminate' => !$sVps->IsTerminated + )); +} +catch (NotFoundException $e) +{ + $sMainContents .= NewTemplater::Render("{$sTheme}/shared/error/error", $locale->strings, array( + 'title' => $locale->strings['error-notfound-title'], + 'message' => $locale->strings['error-notfound-text'] + )); +} +catch (VpsTerminateException $e) +{ + $sMainContents .= NewTemplater::Render("{$sTheme}/shared/error/error", $locale->strings, array( + 'title' => $locale->strings['error-terminate-error-title'], + 'message' => $locale->strings['error-terminate-error-text'] + )); +} +catch (VpsUnterminateException $e) +{ + $sMainContents .= NewTemplater::Render("{$sTheme}/shared/error/error", $locale->strings, array( + 'title' => $locale->strings['error-unterminate-error-title'], + 'message' => $locale->strings['error-unterminate-error-text'] + )); +} + diff --git a/frontend/templates/default/admin/vps/terminate.tpl b/frontend/templates/default/admin/vps/terminate.tpl new file mode 100644 index 0000000..f38842d --- /dev/null +++ b/frontend/templates/default/admin/vps/terminate.tpl @@ -0,0 +1,18 @@ +
+ diff --git a/installer/master/db_updates/1.sql b/installer/master/db_updates/1.sql new file mode 100644 index 0000000..44d2cb0 --- /dev/null +++ b/installer/master/db_updates/1.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS `settings` ( + `Id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `Key` varchar(120) NOT NULL, + `Value` text NOT NULL, + `LastChanged` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`Id`), + UNIQUE KEY `Key` (`Key`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/installer/master/db_updates/2.sql b/installer/master/db_updates/2.sql new file mode 100644 index 0000000..0a8e0c4 --- /dev/null +++ b/installer/master/db_updates/2.sql @@ -0,0 +1 @@ +ALTER TABLE `containers` ADD `TerminationDate` TIMESTAMP NULL; diff --git a/installer/master/db_updates/3.sql b/installer/master/db_updates/3.sql new file mode 100644 index 0000000..537ff49 --- /dev/null +++ b/installer/master/db_updates/3.sql @@ -0,0 +1 @@ +ALTER TABLE `containers` ADD `Terminated` BOOLEAN NOT NULL; diff --git a/installer/master/dump.sql b/installer/master/dump.sql index 22a7235..67b4d3a 100644 --- a/installer/master/dump.sql +++ b/installer/master/dump.sql @@ -32,8 +32,10 @@ CREATE TABLE IF NOT EXISTS `containers` ( `IncomingTrafficLimit` bigint(20) NOT NULL, `TotalTrafficLimit` bigint(20) NOT NULL, `UserId` bigint(20) NOT NULL, + `TerminationDate` timestamp NULL DEFAULT NULL, + `Terminated` tinyint(1) NOT NULL, PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `ip_assignments` ( `Id` bigint(20) NOT NULL AUTO_INCREMENT, @@ -58,6 +60,15 @@ CREATE TABLE IF NOT EXISTS `nodes` ( PRIMARY KEY (`Id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE IF NOT EXISTS `settings` ( + `Id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `Key` varchar(120) NOT NULL, + `Value` text NOT NULL, + `LastChanged` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`Id`), + UNIQUE KEY `Key` (`Key`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + CREATE TABLE IF NOT EXISTS `templates` ( `Id` int(11) NOT NULL AUTO_INCREMENT, `Name` varchar(200) NOT NULL, @@ -67,7 +78,7 @@ CREATE TABLE IF NOT EXISTS `templates` ( `Available` tinyint(1) NOT NULL, `Outdated` tinyint(1) NOT NULL, PRIMARY KEY (`Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `users` ( `Id` bigint(20) NOT NULL AUTO_INCREMENT,