http://modulesgarden.com * CONTACT -> contact@modulesgarden.com * * * This software is furnished under a license and may be used and copied * only in accordance with the terms of such license and with the * inclusion of the above copyright notice. This software or any other * copies thereof may not be provided or otherwise made available to any * other person. No title to and ownership of the software is hereby * transferred. * * * ******************************************************************** */ namespace MGProvision\Proxmox\v2\models; use MGProvision\Proxmox\v2\ProxmoxApiException; use \MGProvision\Proxmox\v2\repository\IpSetRepository; /** * Description of AbstractVm * * @author Pawel Kopec * @version 1.0.0 */ abstract class AbstractVm extends AbstractObject implements \MGProvision\Proxmox\v2\interfaces\VmInterface { protected $vmid; protected $node; protected $status; private $name; protected $config; public $ipSet; function __construct($node, $vmid = null) { $this->node = $node; if ($node !== null && $vmid !== null) { $this->vmid = $vmid; $this->validate(); } } /** * @throws ProxmoxApiException * @todo remove debug() function */ public function validate() { if (empty($this->vmid)){ throw new \MGProvision\Proxmox\v2\ProxmoxApiException("Field 'VMID' is empty"); } if (!is_numeric($this->vmid)) throw new \MGProvision\Proxmox\v2\ProxmoxApiException(sprintf("Field VMID '%s' is invalid", $this->vmid)); if (empty($this->node)) throw new \MGProvision\Proxmox\v2\ProxmoxApiException("Field 'Node' is empty"); } abstract function getVirtualization(); public function status($force = false) { if (!empty($this->status) && $force === false) return $this->status; return $this->status = $this->api()->get("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/status/current"); } public function config($force = false) { if (!empty($this->config) && $force === false) return $this->config; $this->config = $this->api()->get("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/config"); ksort($this->config); return $this->config; } public function updateConfig($config) { $res = $this->api()->put("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/config", (array) $config); $this->config = null; return $res; } public function resume() { return $this->api()->post("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/status/resume"); } public function shutdown() { return $this->api()->post("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/status/shutdown"); } public function start() { return $this->api()->post("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/status/start"); } public function stop() { return $this->api()->post("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/status/stop"); } public function delete() { $status = $this->status(true); if ($status['status'] == "running") { $this->stop(); sleep(5); } return $this->api()->delete("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}"); } public function restart() { $status = $this->status(true); if ($status['status'] == "running") { $this->stop(); sleep(15); } $end = time() + 250; while (time() < $end) { if ($this->isRunning()) { sleep(5); continue; } return $this->start(); } return $this->start(); } public function getVmid() { return $this->vmid; } public function getNode() { return $this->node; } public function setNode($node){ $this->node = $node; return $this; } /** * * @return \MGProvision\Proxmox\v2\models\Node */ public function node() { return new Node($this->node); } public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } public function parseResponse(&$response) { //set your own lang here } public function parseError(&$error, &$httpCode) { //parse error here $search = array("CT {$this->getVmid()}"); $replace = array($this->getName()); $error = str_replace($search, $replace, $error); } public function setApiParser() { $this->api()->setResponsePaser($this); } public function rrd($parameter) { return $this->api()->get("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/rrd", $parameter); } public function rrdData($parameter) { return $this->api()->get("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/rrddata", $parameter); } public function create($container) { $result = $this->api()->post("/nodes/{$this->node}/{$this->getVirtualization()}/", $container); $this->vmid = $container['vmid']; return $result; } public function getPath() { return "/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}"; } public function isRunning() { $status = $this->status(true); return $status['status'] == "running"; } public function spiceproxy() { return $this->api()->post("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/spiceproxy"); } public function hasSpiceproxy(){ if(!$this->isRunning()){ return false; } try{ return $this->spiceproxy(); }catch (ProxmoxApiException $ex){ if(preg_match("/Timeout while waiting for port/", $ex->getMessage())){ return true; } else if(!preg_match("/No spice port/", $ex->getMessage())){ return false; } return false; } } public function vncproxy($websocket = 0) { $setting = array(); if ($websocket) $setting['websocket'] = 1; return $this->api()->post("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/vncproxy", $setting); } public function deleteConfig($id) { $this->config = null; return $this->updateConfig(array("delete" => $id)); } public function backup($storage = 'local', $routing = "1", $maxFiles = null, $compress = null, $mode = null) { $data = array(); $data['all'] = "0"; $data['vmid'] = $this->vmid; $data['storage'] = $storage; $data['remove'] = $routing; if(is_numeric($maxFiles)){ $data['maxfiles'] = (int) $maxFiles; } if ($compress) $data['compress'] = $compress; if ($mode) $data['mode'] = $mode; return $this->api()->post("/nodes/{$this->node}/vzdump", $data); } /** * * @return \MGProvision\Proxmox\v2\models\FirewallOptions */ public function firewallOptions() { $obj = new FirewallOptions(); return $obj->setPath("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/firewall/options"); } public function findFreeDeviceId($busType) { $used = array(); $busType = strtolower($busType); foreach ($this->config(true) as $k => $v) { if (strpos($k, $busType) !== false) { $used[] = preg_replace("/[a-z]+/", "", $k); } } /** * ide 0-3 * sata 0-5 * virtio 0-15 * scsi 0-13 */ switch ($busType) { case 'ide': $to = 3; break; case 'sata': $to = 5; break; case 'virtio': $to = 15; break; case 'scsi': $to = 13; break; default: $to = 3; } for ($n = 0; $n <= $to; $n++) { if (!in_array($n, $used)) { return $n; } } return null; } public function addIpSet(IpSet $ipSet) { $ipSet->setPath($this->getPath() . "/firewall/ipset")->create(); } /** * Get IpSet * @return IpSet[] */ public function getIpSet() { if ($this->ipSet) { return $this->ipSet; } $repostitory = new IpSetRepository(); $repostitory->findByVm($this); $this->ipSet = $repostitory->fetch(); unset($repostitory); return $this->ipSet; } public function migrate(array $setting) { return $this->api()->post("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/migrate", $setting); } public function sshkeysName() { $sshkeys = rawurldecode($this->config()['sshkeys']); if (!$sshkeys) { return null; } $sshkeys = preg_replace('/\s+/', ' ', $sshkeys); $ex = explode(" ", $sshkeys); return $ex[2]; } public function isHaManaged(){ return $this->status()['ha']['managed']==1; } }