You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
325 lines
9.1 KiB
PHP
325 lines
9.1 KiB
PHP
<?php
|
|
/*
|
|
* CVM is more free software. It is licensed under the WTFPL, which
|
|
* allows you to do pretty much anything with it, without having to
|
|
* ask permission. Commercial use is allowed, and no attribution is
|
|
* required. We do politely request that you share your modifications
|
|
* to benefit other developers, but you are under no enforced
|
|
* obligation to do so :)
|
|
*
|
|
* Please read the accompanying LICENSE document for the full WTFPL
|
|
* licensing text.
|
|
*/
|
|
|
|
if(!isset($_CVM)) { die("Unauthorized."); }
|
|
|
|
class Container extends CPHPDatabaseRecordClass
|
|
{
|
|
public $table_name = "containers";
|
|
public $fill_query = "SELECT * FROM containers WHERE `Id` = '%d'";
|
|
public $verify_query = "SELECT * FROM containers WHERE `Id` = '%d'";
|
|
|
|
public $prototype = array(
|
|
'string' => array(
|
|
'Hostname' => "Hostname",
|
|
'InternalId' => "InternalId",
|
|
'RootPassword' => "RootPassword"
|
|
),
|
|
'numeric' => array(
|
|
'NodeId' => "NodeId",
|
|
'TemplateId' => "TemplateId",
|
|
'VirtualizationType' => "VirtualizationType",
|
|
'DiskSpace' => "DiskSpace",
|
|
'GuaranteedRam' => "GuaranteedRam",
|
|
'BurstableRam' => "BurstableRam",
|
|
'CpuCount' => "CpuCount",
|
|
'Status' => "Status",
|
|
'IncomingTrafficUsed' => "IncomingTrafficUsed",
|
|
'IncomingTrafficLast' => "IncomingTrafficLast",
|
|
'OutgoingTrafficUsed' => "OutgoingTrafficUsed",
|
|
'OutgoingTrafficLast' => "OutgoingTrafficLast",
|
|
'IncomingTrafficLimit' => "IncomingTrafficLimit",
|
|
'OutgoingTrafficLimit' => "OutgoingTrafficLimit",
|
|
'TotalTrafficLimit' => "TotalTrafficLimit"
|
|
),
|
|
'node' => array(
|
|
'Node' => "NodeId"
|
|
),
|
|
'template' => array(
|
|
'Template' => "TemplateId"
|
|
)
|
|
);
|
|
|
|
public function __get($name)
|
|
{
|
|
switch($name)
|
|
{
|
|
case "sRamUsed":
|
|
return $this->GetRamUsed();
|
|
break;
|
|
case "sDiskUsed":
|
|
return $this->GetDiskUsed();
|
|
break;
|
|
case "sBandwidthUsed":
|
|
return $this->GetBandwidthUsed();
|
|
break;
|
|
default:
|
|
return null;
|
|
break;
|
|
}
|
|
}
|
|
|
|
public function GetBandwidthUsed()
|
|
{
|
|
return ($this->sOutgoingTrafficUsed + $this->IncomingTrafficUsed) / (1024 * 1024);
|
|
}
|
|
|
|
public function Deploy()
|
|
{
|
|
$sRootPassword = random_string(20);
|
|
|
|
$this->uRootPassword = $sRootPassword;
|
|
$this->InsertIntoDatabase();
|
|
|
|
$command = shrink_command("vzctl create {$this->sInternalId}
|
|
--ostemplate {$this->sTemplate->sTemplateName}
|
|
");
|
|
|
|
$result = $this->sNode->ssh->RunCommand($command, false);
|
|
|
|
if($result->returncode == 0)
|
|
{
|
|
// TODO: set sensible values depending on container resource configuration
|
|
// http://wiki.openvz.org/UBC_consistency_check
|
|
// http://wiki.openvz.org/UBC_parameter_units
|
|
// http://wiki.openvz.org/UBC_configuration_examples
|
|
// http://wiki.openvz.org/UBC_parameters_table
|
|
|
|
$this->uStatus = CVM_STATUS_CREATED;
|
|
$this->InsertIntoDatabase();
|
|
|
|
$sKMemSize = $this->sGuaranteedRam * 250;
|
|
$sKMemSizeLimit = (int)($sKMemSize * 1.1);
|
|
$sLockedPages = (int)($this->sGuaranteedRam * 1.5);
|
|
$sShmPages = $sLockedPages * 64;
|
|
$sOomGuarPages = $this->sGuaranteedRam * 400;
|
|
$sTcpSock = $this->sGuaranteedRam * 3;
|
|
$sOtherSock = $this->sGuaranteedRam * 3;
|
|
$sFLock = (int)($this->sGuaranteedRam * 0.6);
|
|
$sFLockLimit = (int)($sFLock * 1.1);
|
|
$sTcpSndBuf = (int)($this->sGuaranteedRam * 20000);
|
|
$sTcpRcvBuf = (int)($this->sGuaranteedRam * 20000);
|
|
$sOtherBuf = (int)($this->sGuaranteedRam * 20000);
|
|
$sTcpLimit = (int)($sTcpBuf * 2);
|
|
$sDgramBuf = (int)($sTcpBuf / 40);
|
|
$sNumFile = $this->sGuaranteedRam * 32;
|
|
$sDCache = $this->sGuaranteedRam * 16000;
|
|
$sDCacheLimit = (int)($sDCache * 1.1);
|
|
$sAvgProc = (int)($this->sGuaranteedRam * 1.5);
|
|
|
|
$command = shrink_command("vzctl set {$this->sInternalId}
|
|
--onboot yes
|
|
--setmode restart
|
|
--hostname {$this->sHostname}
|
|
--nameserver 8.8.8.8
|
|
--nameserver 8.8.4.4
|
|
--numproc {$this->sCpuCount}
|
|
--vmguarpages {$this->sGuaranteedRam}M:unlimited
|
|
--privvmpages {$this->sBurstableRam}M:{$this->sBurstableRam}M
|
|
--quotatime 0
|
|
--diskspace {$this->sDiskSpace}M:{$this->sDiskSpace}M
|
|
--userpasswd root:{$sRootPassword}
|
|
--kmemsize {$sKMemSize}:{$sKMemSizeLimit}
|
|
--lockedpages {$sLockedPages}:{$sLockedPages}
|
|
--shmpages {$sShmPages}:{$sShmPages}
|
|
--physpages 0:unlimited
|
|
--oomguarpages {$sOomGuarPages}:unlimited
|
|
--numtcpsock {$sTcpSock}:{$sTcpSock}
|
|
--numflock {$sFLock}:{$sFLockLimit}
|
|
--numpty 32:32
|
|
--numsiginfo 512:512
|
|
--tcpsndbuf {$sTcpSndBuf}:{$sTcpSndBufLimit}
|
|
--tcprcvbuf {$sTcpRcvBuf}:{$sTcpRcvBufLimit}
|
|
--othersockbuf {$sOtherBuf}:{$sOtherBufLimit}
|
|
--dgramrcvbuf {$sDgramBuf}:{$sDgramBuf}
|
|
--numothersock {$sOtherSock}:{$sOtherSock}
|
|
--numfile {$sNumFile}:{$sNumFile}
|
|
--dcachesize {$sDCache}:{$sDCacheLimit}
|
|
--numiptent 128:128
|
|
--diskinodes 200000:220000
|
|
--avnumproc {$sAvgProc}:{$sAvgProc}
|
|
--save
|
|
");
|
|
|
|
/*
|
|
This may be useful if we turn out to have a kernel that supports vswap
|
|
|
|
$command = shrink_command("vzctl set {$this->sInternalId}
|
|
--onboot yes
|
|
--setmode restart
|
|
--hostname {$this->sHostname}
|
|
--nameserver 8.8.8.8
|
|
--nameserver 8.8.4.4
|
|
--numproc {$this->sCpuCount}
|
|
--quotatime 0
|
|
--diskspace {$this->sDiskSpace}M:{$this->sDiskSpace}M
|
|
--userpasswd root:{$sRootPassword}
|
|
--numtcpsock 360:360
|
|
--numflock 188:206
|
|
--numpty 16:16
|
|
--numsiginfo 256:256
|
|
--tcpsndbuf 1720320:2703360
|
|
--tcprcvbuf 1720320:2703360
|
|
--othersockbuf 1126080:2097152
|
|
--dgramrcvbuf 262144:262144
|
|
--numothersock 360:360
|
|
--numfile 9312:9312
|
|
--dcachesize 3409920:3624960
|
|
--numiptent 128:128
|
|
--diskinodes 200000:220000
|
|
--avnumproc 180:180
|
|
--ram {$this->sGuaranteedRam}
|
|
--swap {$this->sBurstableRam}
|
|
--save
|
|
");*/
|
|
|
|
$result = $this->sNode->ssh->RunCommand($command, false);
|
|
|
|
if($result->returncode == 0)
|
|
{
|
|
$this->uStatus = CVM_STATUS_CONFIGURED;
|
|
$this->InsertIntoDatabase();
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
throw new ContainerConfigureException($result->stderr, $result->returncode, $this->sInternalId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new ContainerCreateException($result->stderr, $result->returncode, $this->sInternalId);
|
|
}
|
|
}
|
|
|
|
public function Start()
|
|
{
|
|
$command = "vzctl start {$this->sInternalId}";
|
|
$result = $this->sNode->ssh->RunCommand($command, false);
|
|
|
|
if($result->returncode == 0)
|
|
{
|
|
$this->uStatus = CVM_STATUS_STARTED;
|
|
$this->InsertIntoDatabase();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
throw new ContainerStartException($result->stderr, $result->returncode, $this->sInternalId);
|
|
}
|
|
}
|
|
|
|
public function Stop()
|
|
{
|
|
$command = "vzctl stop {$this->sInternalId}";
|
|
$result = $this->sNode->ssh->RunCommand($command, false);
|
|
|
|
// vzctl is retarded enough to return exit status 0 when the command fails because the container isn't running, so we'll have to check the stderr for specific error string(s) as well. come on guys, it's 2012.
|
|
if($result->returncode == 0 && strpos($result->stderr, "Unable to stop") === false)
|
|
{
|
|
$this->uStatus = CVM_STATUS_STOPPED;
|
|
$this->InsertIntoDatabase();
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
throw new ContainerStopException($result->stderr, $result->returncode, $this->sInternalId);
|
|
}
|
|
}
|
|
|
|
public function AddIp($ip)
|
|
{
|
|
$command = shrink_command("vzctl set {$this->sInternalId}
|
|
--ipadd {$ip}
|
|
--save
|
|
");
|
|
|
|
$result = $this->sNode->ssh->RunCommand($command, false);
|
|
|
|
if($result->returncode == 0)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
throw new ContainerIpAddException($result->stderr, $result->returncode, $this->sInternalId);
|
|
}
|
|
}
|
|
|
|
public function RemoveIp($ip)
|
|
{
|
|
$command = shrink_command("vzctl set {$this->sInternalId}
|
|
--ipdel {$ip}
|
|
--save
|
|
");
|
|
|
|
$result = $this->sNode->ssh->RunCommand($command, false);
|
|
|
|
if($result->returncode == 0)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
throw new ContainerIpRemoveException($result->stderr, $result->returncode, $this->sInternalId);
|
|
}
|
|
}
|
|
|
|
public function UpdateTraffic()
|
|
{
|
|
$result = $this->sNode->ssh->RunCommand("vzctl exec {$this->sInternalId} cat /proc/net/dev | grep venet0", false);
|
|
|
|
if($result->returncode == 0)
|
|
{
|
|
$lines = split_lines($result->stdout);
|
|
$values = split_whitespace($lines[0]);
|
|
|
|
$uIncoming = $values[1];
|
|
$uOutgoing = $values[9];
|
|
|
|
if($uIncoming < (int)$this->sIncomingTrafficLast || $uOutgoing < (int)$this->sOutgoingTrafficLast)
|
|
{
|
|
// the counter has reset (wrap-around, reboot, etc.)
|
|
$uNewIncoming = $uIncoming;
|
|
$uNewOutgoing = $uOutgoing;
|
|
}
|
|
else
|
|
{
|
|
$uNewIncoming = $uIncoming - $this->sIncomingTrafficLast;
|
|
$uNewOutgoing = $uOutgoing - $this->sOutgoingTrafficLast;
|
|
}
|
|
|
|
$this->uIncomingTrafficUsed = $this->sIncomingTrafficUsed + $uNewIncoming;
|
|
$this->uOutgoingTrafficUsed = $this->sOutgoingTrafficUsed + $uNewOutgoing;
|
|
|
|
$this->uIncomingTrafficLast = $uIncoming;
|
|
$this->uOutgoingTrafficLast = $uOutgoing;
|
|
|
|
$this->InsertIntoDatabase();
|
|
}
|
|
else
|
|
{
|
|
throw new ContainerTrafficRetrieveException($result->stderr, $result->returncode, $this->sInternalId);
|
|
}
|
|
}
|
|
|
|
public function EnableTunTap()
|
|
{
|
|
// TODO: Finish EnableTunTap function, check whether tun module is available on host
|
|
$command = "vzctl set {$this->sInternalId} --devnodes net/tun:rw --save";
|
|
}
|
|
}
|
|
|
|
?>
|