fixing LXC management on multiple servers
This commit is contained in:
parent
56422e0795
commit
5ea431a421
|
@ -3,29 +3,38 @@
|
||||||
require_once("../class/config.php");
|
require_once("../class/config.php");
|
||||||
|
|
||||||
$fields = array (
|
$fields = array (
|
||||||
"action" => array ("get", "string", ''),
|
"action" => array ("request", "string", ''),
|
||||||
"script" => array ("get", "boolean", 0),
|
"script" => array ("request", "boolean", 0),
|
||||||
);
|
);
|
||||||
getFields($fields);
|
getFields($fields);
|
||||||
|
|
||||||
if (in_array($action, array('start', 'stop', 'monit'))) {
|
if (in_array($action, array('start', 'stop', 'monit'))) {
|
||||||
$res = $hooks->invoke($action, array(), 'lxc');
|
$res = $hooks->invoke($action, array(), 'lxc');
|
||||||
}
|
}
|
||||||
|
switch ($action) {
|
||||||
|
case "start":
|
||||||
|
$lxc->start();
|
||||||
|
break;
|
||||||
|
case "stop":
|
||||||
|
$lxc->stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($lxc->error && !$script) {
|
||||||
|
$error=$lxc->error;
|
||||||
|
}
|
||||||
|
|
||||||
$infos = $lxc->getvm();
|
$infos = $lxc->getvm();
|
||||||
|
|
||||||
if ($script) {
|
if ($script) {
|
||||||
|
header("Content-Type: text/plain");
|
||||||
if (isset($res)) {
|
if (isset($res)) {
|
||||||
echo "ACTION:".$action."\n";
|
echo "ACTION:".$action."\n";
|
||||||
echo "RETURN:".intval($res['lxc'])."\n";
|
echo "RETURN:".intval($res['lxc'])."\n";
|
||||||
}
|
}
|
||||||
if ($infos) {
|
if ($infos) {
|
||||||
echo "VM_STATUS:OK\n";
|
echo "VM_STATUS:OK\n";
|
||||||
echo "VM_START:".$infos['date_start']."\n";
|
echo "VM_START:".$infos['starttime']."\n";
|
||||||
echo "VM_RETURN_CODE:".intval($infos['serialized_object']['error'])."\n";
|
echo "VM_HOSTNAME:".$infos['hostname']."\n";
|
||||||
echo "VM_ID:".$infos['serialized_object']['vm']."\n";
|
|
||||||
echo "VM_HOSTNAME:".$infos['serialized_object']['hostname']."\n";
|
|
||||||
echo "VM_MSG:".$infos['serialized_object']['msg']."\n";
|
|
||||||
} else {
|
} else {
|
||||||
echo "VM_STATUS:NONE\n";
|
echo "VM_STATUS:NONE\n";
|
||||||
}
|
}
|
||||||
|
@ -41,33 +50,42 @@ include_once("head.php");
|
||||||
<hr/>
|
<hr/>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<?php if (isset($res) && ! $res['lxc']) { ?>
|
<?php if ($error) { ?>
|
||||||
<div>
|
<div>
|
||||||
<span class="error">
|
<span class="error">
|
||||||
<?php echo $err->errstr(); ?>
|
<?php echo implode('<br />', $error); ?>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
<?php } //isset $res ?>
|
<?php } ?>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<?php if (empty($infos)) {
|
<?php if (empty($infos)) {
|
||||||
echo '<span class="error">';
|
?>
|
||||||
__("You can start a virtual machine.");
|
<p class="error"><?php __("You can start a virtual machine."); ?></p>
|
||||||
echo "<a href='vm.php?action=start'>"._("Click here to do so.")."</a>";
|
<form method="post" action="vm.php">
|
||||||
echo '</span>';
|
<input type="hidden" name="action" value="start" />
|
||||||
|
<input type="submit" class="inb" name="go" value="<?php __("Click here to start a virtual machine."); ?>" />
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
} else {
|
} else {
|
||||||
echo "<table class='tedit'>";
|
echo "<table class='tedit'>";
|
||||||
echo "<tr><th>"._("Hostname")."</th><td>".$infos['serialized_object']['hostname']."</td></tr>";
|
echo "<tr><th>"._("Hostname")."</th><td>".$infos['hostname']."</td></tr>";
|
||||||
echo "<tr><th>"._("Start time")."</th><td>".$infos['date_start']."</td></tr>";
|
echo "<tr><th>"._("Start time")."</th><td>".date('Y-m-d H:i:s',$infos['starttime'])."</td></tr>";
|
||||||
echo "<tr><th>"._("Usefull command")."</th><td><pre>";
|
echo "<tr><th>"._("SSH Fingerprint")."</th><td style=\"font-family: Courier, fixed;\">".implode('<br />',$infos['ssh-keys'])."</td></tr>";
|
||||||
echo "ssh ".$mem->user['login']."@".$infos['serialized_object']['hostname']."\n";
|
echo "<tr><th>"._("Useful command")."</th><td><pre>";
|
||||||
echo "rsync ".$mem->user['login']."@".$infos['serialized_object']['hostname']."\n";
|
echo "ssh ".$mem->user['login']."@".$infos['hostname']."\n";
|
||||||
|
echo "rsync ".$mem->user['login']."@".$infos['hostname']."\n";
|
||||||
echo "</pre></td></tr>";
|
echo "</pre></td></tr>";
|
||||||
echo "<tr><td colspan='2'><a href='vm.php?action=stop'>"._("Click here to stop the machine")."</a></td></tr>";
|
echo "</table>";
|
||||||
echo "</table>";
|
?>
|
||||||
|
<p class="error"><?php __("You can stop your virtual machine."); ?></p>
|
||||||
|
<form method="post" action="vm.php">
|
||||||
|
<input type="hidden" name="action" value="stop" />
|
||||||
|
<input type="submit" class="inb" name="go" value="<?php __("Click here to stop your running virtual machine."); ?>" />
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
} // empty infos ?>
|
} // empty infos ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,47 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
include_once(dirname(__FILE__) . '/vm.class.php');
|
/*
|
||||||
# include('vm.php'); // This one fails ...
|
----------------------------------------------------------------------
|
||||||
|
AlternC - Web Hosting System
|
||||||
|
Copyright (C) 2000-2013 by the AlternC Development Team.
|
||||||
|
https://alternc.org/
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
LICENSE
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License (GPL)
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program 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.
|
||||||
|
|
||||||
|
To read the license please visit http://www.gnu.org/copyleft/gpl.html
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
Purpose of file: Manage LXC-based virtual machine through an inetd-based protocol
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
include_once(dirname(__FILE__) . '/vm.class.php');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manage AlternC's virtual machine start/stop using our own inetd-based protocol.
|
||||||
|
*/
|
||||||
|
class m_lxc implements vm {
|
||||||
|
|
||||||
|
|
||||||
class m_lxc implements vm
|
|
||||||
{
|
|
||||||
public $IP;
|
public $IP;
|
||||||
public $PORT;
|
public $PORT;
|
||||||
public $TIMEOUT = 5;
|
public $TIMEOUT = 5;
|
||||||
public $error = array();
|
public $error = array();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor, initialize the class informations from AlternC's variables
|
||||||
|
*/
|
||||||
function m_lxc() {
|
function m_lxc() {
|
||||||
$this->IP = variable_get('lxc_ip', '', "IP address of the Alternc's LXC server. If empty, no LXC server.");
|
$this->IP = variable_get('lxc_ip', '', "IP address of the Alternc's LXC server. If empty, no LXC server.");
|
||||||
$this->PORT = variable_get('lxc_port', '6504', "Port of the Alternc's LXC server");
|
$this->PORT = variable_get('lxc_port', '6504', "Port of the Alternc's LXC server");
|
||||||
|
@ -18,8 +50,11 @@ class m_lxc implements vm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HOOK: add the "Console Access" to AlternC's main menu
|
||||||
|
*/
|
||||||
function hook_menu() {
|
function hook_menu() {
|
||||||
if ( empty($this->IP)) return ; # No menu if no server
|
if ( empty($this->IP)) return ; // No menu if no server
|
||||||
|
|
||||||
$obj = array(
|
$obj = array(
|
||||||
'title' => _("Console access"),
|
'title' => _("Console access"),
|
||||||
|
@ -31,6 +66,10 @@ class m_lxc implements vm
|
||||||
return $obj;
|
return $obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HOOK: remove VM history for AlternC account
|
||||||
|
*/
|
||||||
function hook_admin_del_member() {
|
function hook_admin_del_member() {
|
||||||
global $db,$err,$cuid;
|
global $db,$err,$cuid;
|
||||||
$err->log("lxc","alternc_del_member");
|
$err->log("lxc","alternc_del_member");
|
||||||
|
@ -38,70 +77,53 @@ class m_lxc implements vm
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop VMs running since more than MAXTIME hours
|
|
||||||
function stop_expired($force=false) {
|
|
||||||
global $mem,$err;
|
|
||||||
# Need to be distinct of $db (calling subfunctions)
|
|
||||||
$db2 = new DB_system();
|
|
||||||
|
|
||||||
if (! $mem->checkright() ) {
|
|
||||||
$err->raise("lxc",_("-- Only administrators can do that! --"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
# If force, maxtime = 0
|
|
||||||
$time = ($force?0:$this->maxtime);
|
|
||||||
|
|
||||||
$db2->query("select * from vm_history where date_end is null and date_start < subdate( now() , interval $time hour);");
|
|
||||||
|
|
||||||
while ($db2->next_record()) {
|
|
||||||
$mem->su($db2->Record['uid']);
|
|
||||||
$this->stop();
|
|
||||||
$mem->unsu();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to a remote VM manager instance
|
||||||
|
* $params are the parameters to send as serialized data
|
||||||
|
* to the listening server.
|
||||||
|
* Return the unserialized response data, if the message has been sent successfully
|
||||||
|
* or FALSE if an error occurred. In that case $error[] is set.
|
||||||
|
*/
|
||||||
private function sendMessage($params) {
|
private function sendMessage($params) {
|
||||||
|
global $L_FQDN;
|
||||||
$fp = fsockopen($this->IP, $this->PORT, $errno, $errstr, $this->TIMEOUT);
|
$fp = fsockopen($this->IP, $this->PORT, $errno, $errstr, $this->TIMEOUT);
|
||||||
if (!$fp)
|
if (!$fp) {
|
||||||
{
|
|
||||||
$this->error[] = 'Unable to connect';
|
$this->error[] = 'Unable to connect';
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
// Authenticate:
|
||||||
|
$params['server']=$L_FQDN;
|
||||||
|
$params['key']=$this->KEY;
|
||||||
|
|
||||||
$msg = sprintf("%s\n", serialize($params) );
|
$msg = sprintf("%s\n", serialize($params) );
|
||||||
if (fwrite ($fp, $msg) < 0)
|
if (fwrite ($fp, $msg) < 0) {
|
||||||
{
|
|
||||||
$this->error[] = 'Unable to send data';
|
$this->error[] = 'Unable to send data';
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
$resp = '';
|
$resp = '';
|
||||||
#while (($resp .= fgets($fp, 4096)) !== FALSE);
|
|
||||||
$resp = fgets($fp, 4096);
|
$resp = fgets($fp, 4096);
|
||||||
fclose ($fp);
|
fclose ($fp);
|
||||||
|
|
||||||
return $resp;
|
$data = @unserialize($resp);
|
||||||
|
|
||||||
if (stripos($resp, 'error') > 0)
|
if (isset($data['error']) && $data['error']>0) {
|
||||||
{
|
|
||||||
$data = unserialize($resp);
|
|
||||||
$this->error[] = $data['msg'];
|
$this->error[] = $data['msg'];
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return $resp;
|
return $resp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function start($login = FALSE, $pass = FALSE, $uid = FALSE)
|
|
||||||
{
|
/**
|
||||||
|
* START a Virtual Machine on the remote VM manager
|
||||||
|
* for user $login having hashed password $pass and uid $uid
|
||||||
|
*/
|
||||||
|
public function start($login = FALSE, $pass = FALSE, $uid = FALSE) {
|
||||||
global $mem, $db, $err, $mysql;
|
global $mem, $db, $err, $mysql;
|
||||||
|
|
||||||
if ($this->getvm() !== FALSE)
|
if ($this->getvm() !== FALSE) {
|
||||||
{
|
|
||||||
$err->raise('lxc', _('VM already started'));
|
$err->raise('lxc', _('VM already started'));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -114,10 +136,9 @@ class m_lxc implements vm
|
||||||
$msgg['mysql_host'] = $mysql->dbus->Host;
|
$msgg['mysql_host'] = $mysql->dbus->Host;
|
||||||
|
|
||||||
$res = $this->sendMessage($msgg);
|
$res = $this->sendMessage($msgg);
|
||||||
if ($res === FALSE)
|
if ($res === FALSE) {
|
||||||
return $this->error;
|
return $this->error;
|
||||||
else
|
} else {
|
||||||
{
|
|
||||||
$data = unserialize($res);
|
$data = unserialize($res);
|
||||||
$error = $data['error'];
|
$error = $data['error'];
|
||||||
$hostname = $data['hostname'];
|
$hostname = $data['hostname'];
|
||||||
|
@ -125,70 +146,44 @@ class m_lxc implements vm
|
||||||
$date_start = 'NOW()';
|
$date_start = 'NOW()';
|
||||||
$uid = $mem->user['uid'];
|
$uid = $mem->user['uid'];
|
||||||
|
|
||||||
if ((int)$data['error'] != 0)
|
if ((int)$data['error'] != 0) {
|
||||||
{
|
|
||||||
$err->raise('lxc', _($data['msg']));
|
$err->raise('lxc', _($data['msg']));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
$db->query("INSERT INTO vm_history (ip,date_start,uid,serialized_object) VALUES ('$hostname', $date_start, '$uid', '$res')");
|
$db->query("INSERT INTO vm_history (ip,date_start,uid,serialized_object) VALUES ('$hostname', $date_start, '$uid', '$res')");
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function monit()
|
/**
|
||||||
{
|
*
|
||||||
echo "1 / 5 used ";
|
*/
|
||||||
}
|
public function getvm($login = FALSE) {
|
||||||
|
|
||||||
public function getvm()
|
|
||||||
{
|
|
||||||
global $db, $mem, $cuid;
|
global $db, $mem, $cuid;
|
||||||
|
|
||||||
$db->query("SELECT * FROM vm_history WHERE date_end IS NULL AND uid= $cuid ORDER BY id DESC LIMIT 1");
|
$login = $login ? $login : $mem->user['login'];
|
||||||
|
$msgg = array('action'=>'get', 'login'=>$login);
|
||||||
if ($db->next_record()){
|
$res = $this->sendMessage($msgg);
|
||||||
$db->Record['serialized_object'] = unserialize($db->Record['serialized_object']);
|
if (!$res) return FALSE;
|
||||||
return $db->Record;
|
return unserialize($res);
|
||||||
}
|
|
||||||
else {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Stop all VMs
|
|
||||||
public function stopall() {
|
|
||||||
global $mem, $db, $err;
|
|
||||||
|
|
||||||
if (! $mem->checkright() ) {
|
/**
|
||||||
$err->raise("lxc",_("-- Only administrators can do that! --"));
|
* Stop the currently running VM
|
||||||
return false;
|
*/
|
||||||
}
|
public function stop() {
|
||||||
|
|
||||||
if ($this->sendMessage(array('action' => 'stopall' )) === FALSE)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return $db->query("UPDATE vm_history SET date_end = NOW() WHERE date_end is null;");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function stop()
|
|
||||||
{
|
|
||||||
global $db, $mem;
|
global $db, $mem;
|
||||||
|
|
||||||
$vm = $this->getvm();
|
$vm = $this->getvm();
|
||||||
|
|
||||||
if ($vm === FALSE)
|
if ($vm === FALSE)
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
$vm_id = $vm['serialized_object']['vm'];
|
|
||||||
$uid = $mem->user['uid'];
|
|
||||||
$vid = $vm['id'];
|
|
||||||
|
|
||||||
if ($this->sendMessage(array('action' => 'stop', 'vm' => $vm_id)) === FALSE)
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return $db->query("UPDATE vm_history SET date_end = NOW() WHERE uid = '$uid' AND id = '$vid' LIMIT 1");
|
if ($this->sendMessage(array('action' => 'stop', 'vm' => $vm['vm'])) === FALSE)
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
} // class m_lxc
|
||||||
|
|
Loading…
Reference in New Issue