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\models\HardDisk; use MGProvision\Proxmox\v2\repository\CdRomRepository; use MGProvision\Proxmox\v2\repository\HardDiskRepostiory; use \MGProvision\Proxmox\v2\repository\IpConfigRepository; /** * Description of Kvm * * @author Pawel Kopec * @version 1.0.0 */ class Kvm extends AbstractVm implements \MGProvision\Proxmox\v2\interfaces\KvmInterface { public function getVirtualization() { return 'qemu'; } public function suspend() { return $this->api()->post("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/status/suspend"); } public function cdrom() { foreach ($this->config() as $k => $c) { if (strpos($c, "media=cdrom") !== false && !preg_match('/cloudinit/', $c)) { $c = explode(",", $c); $isoRaw = $c[0]; $c = explode(":iso/", $isoRaw); $iso = end($c); $iso = ucwords(str_replace(array("-", "_", ".iso"), array(" ", " ", ""), $iso)); return array( "iso" => $iso, "isoRaw" => $isoRaw, "bus" => $k ); } } } public function getBootOrder() { $config = $this->config(); //order=scsi0;ide1;scsi2 if($config['boot'] && preg_match("/order/",$config['boot'])){ list($key, $order) = explode("=", $config['boot']); return explode(";",$order); } $boot = array("c", "d", "n"); if (isset($config['boot'])) { $boot = str_split($config['boot']); } return $boot; } public function changeBootOrder($boot) { $data = array(); $data['boot'] = $boot; $this->config = null; return $this->api()->put("/nodes/{$this->node}/qemu/{$this->vmid}/config", $data); } public function changeIso($iso) { $cdrom = $this->cdrom(); if (!$cdrom['bus']) throw new \MGProvision\Proxmox\v2\ProxmoxApiException("CD-ROM volume not found"); $data = array(); $data[$cdrom['bus']] = "{$iso},media=cdrom"; $this->config = null; return $this->api()->put("/nodes/{$this->node}/qemu/{$this->vmid}/config", $data); } public function cloneVm($container) { return $this->api()->post("/nodes/{$this->node}/qemu/{$this->vmid}/clone", $container); } public function getIso() { $result = array(); foreach ($this->config() as $k => $c) { if (strpos($c, "media=cdrom") !== false && !preg_match('/cloudinit/', $c )) { $c = explode(",", $c); $isoRaw = $c[0]; $c = explode(":iso/", $isoRaw); $iso = end($c); $iso = ucwords(str_replace(array("-", "_", ".iso"), array(" ", " ", ""), $iso)); return array( "iso" => $iso, "isoRaw" => $isoRaw, "bus" => $k ); } } } public function updateCdrom($iso) { $cdrom = $this->cdrom(); if (!$cdrom['bus']) throw new \MGProvision\Proxmox\v2\ProxmoxApiException("CD-ROM volume not found"); $data = array(); $data[$cdrom['bus']] = "{$iso},media=cdrom"; $this->config = null; return $this->api()->put("/nodes/{$this->node}/qemu/{$this->vmid}/config", $data); } public function findFreeNetworDeviceId() { $config = $this->config(true); for($i=0; $i<=50; $i++){ if($config['net'.$i]){ continue; } return $i; } } public function findFreeIde($type) { $i = 0; $type = strtolower($type); foreach ($this->config(true) as $k => $v) { if (preg_match("/{$type}/", $k)) $i++; } return $i; } /** * @deprecated since version 2.4.0 * @return array */ public function getHdds() { $disks = array(); $isPrimary = false; $config = $this->config(); foreach ($config as $key => $val) { if (strpos($val, 'disk') !== false) { if (in_array($key, ['hotplug'])) { continue; } $sets = explode(",", $val); $disks[$key] = array("bus" => $key, "location" => current($sets), "format" => "", "backup" => "", "size" => "", "isPrimary" => false); foreach ($sets as $set) { list($k, $v) = explode("=", $set); $disks[$key][$k] = $v; if ($k == "size") { if (preg_match('/M/', $v)) {//MB => GB $disks[$key]['sizeRaw'] = (int) $v / 1024; } else if (preg_match('/T/', $v)) {//T => GB $disks[$key]['sizeRaw'] = (int) $v * 1024; } else {//GB $disks[$key]['sizeRaw'] = (int) $v; } } } if (empty($disks[$key]['format']) && preg_match('/disk-[0-9]\./', $sets['0'])) { $disks[$key]['format'] = preg_replace('/(.*)\./', '', $sets['0']); } if (isset($config['bootdisk']) && $key == $config['bootdisk']) { $disks[$key] ['isPrimary'] = true; $isPrimary = true; } else if (!isset($config['bootdisk']) && !$isPrimary && strpos($disks[$key] ['location'], 'disk-0') !== false) { $disks[$key] ['isPrimary'] = true; $isPrimary = true; } $matches = array(); preg_match('/disk-[0-9]/', $disks[$key] ['location'], $matches); if ($matches[0]) $disks[$key] ['name'] = $matches[0]; } } ksort($disks); return $disks; } /** * @return HardDisk[] */ public function getHardDisks() { $disks = array(); $config = $this->config(true); $boot = (array) $this->getBootOrder(); $bootDisk = reset($boot ); foreach ($config as $id => $value) { if (in_array($id, ['hotplug','agent'])) { continue; } if(preg_match("/unused/", $id)){ continue; } if (!preg_match('/disk/', $value)) { continue; } $hdd = (new HardDisk($id, $value))->setPath("/nodes/{$this->node}/qemu/{$this->vmid}/config"); if (isset($config['bootdisk'])) { $hdd->setMaster($config['bootdisk'] == $id); }elseif ($bootDisk ){ $hdd->setMaster($bootDisk == $id); } $disks[] = $hdd; } return $disks; } /** * * @return HardDisk * @throws \MGProvision\Proxmox */ public function getMasterHardDisk() { $hdds = []; $configs = $this->config(); $boot = (array) $this->getBootOrder(); $bootDisk = reset($boot ); foreach ($configs as $id => $config) { if (!HardDisk::isConfigValid($id, $config)) { continue; } $hdd = new HardDisk($id, $config); $hdd->setPath("/nodes/{$this->node}/qemu/{$this->vmid}/config"); if (isset($configs['bootdisk'])) { $hdd->setMaster($configs['bootdisk'] == $id); }elseif ($bootDisk ){ $hdd->setMaster($bootDisk == $id); } if ($hdd->isMaster()) { return $hdd; } $hdds[] = $hdd; } foreach ($hdds as $hdd) { if(preg_match('/unused/', $hdd->getId())){ continue; } return $hdd; } throw new \MGProvision\Proxmox\v2\ProxmoxApiException("Master Hard Disk not found"); } public function resizeHdd(array $setting) { return $this->api()->put("/nodes/{$this->node}/qemu/{$this->vmid}/resize", $setting); } public function getMasterHddSize() { $hdds = $this->getHdds(); foreach ($hdds as $hdd) { if ($hdd['isPrimary']) { return $hdd['sizeRaw']; } } throw new \MGProvision\Proxmox\v2\ProxmoxApiException("Master Disk no found!"); } /** * @param $id * @return \MGProvision\Proxmox\v2\models\HardDisk * @throws \Exception */ public function findHardDiskById($id) { foreach($this->getHardDisks() as $disk) { if($disk->getId() == $id) { return $disk; } } throw new \Exception('Cannot find disk'); } public function getSlaveHddsSize($skip = null) { $size = 0; foreach ($this->getHdds() as $hdd) { if ($hdd['isPrimary'] || $skip == $hdd['bus']) continue; $size += $hdd['sizeRaw']; } return $size; } /** * * @param type $findBridge * @param type $force * @return \MGProvision\Proxmox\v2\models\NetworkDeviceKvm[] */ public function getNetworkDevices($findBridge = null, $force = true) { $networks = array(); foreach ($this->config($force) as $k => $v) { if (!preg_match('/net/', $k)) continue; $network = new NetworkDeviceKvm($k, $v); if ($findBridge && $network->getBridge() !== $findBridge) continue; $networks[] = $network; } return $networks; } public function getMacAddresses($findBridge = null, $force = false) { $macs = array(); foreach ($this->getNetworkDevices($findBridge, $force) as $network) { $macs[] = $network->getMacAddress(); } return $macs; } /** * * @param \MGProvision\Proxmox\v2\models\NetworkDeviceKvm[] $networkDevices */ public function updateNetworkDevices($networkDevices) { $container = array(); foreach ($networkDevices as $networkDevice) { $container[$networkDevice->getId()] = $networkDevice->asConfig(); } return $this->updateConfig($container); } public function getReinstallConfig() { $setting = array(); foreach ($this->config(true) as $k => $v) { $setting[$k] = $v; } unset($setting['digest']); return $setting; } public function restore($archive) { try { if ($this->isRunning()) { $this->stop(); sleep(5); } } catch (\Exception $ex) {//error i.e.: Configuration file 'nodes/proxmox/lxc/117.conf' does not exist if ($ex->getCode() != 500) { throw $ex; } } $container = array( 'vmid' => $this->vmid, 'archive' => $archive, 'force' => 1, ); return $this->api()->post("/nodes/{$this->node}/qemu", $container); } /** * * @return \MGProvision\Proxmox\v2\models\SnapshotKvm */ public function snapshot($name = null) { $snap = new SnapshotKvm(); $path = "/nodes/{$this->getNode()}/{$this->getVirtualization()}/{$this->getVmid()}/snapshot"; if ($name !== null) { $path .= "/{$name}"; } $snap->setPath($path); return $snap; } public function convertToTemplate() { return $this->api()->post("/nodes/{$this->node}/qemu/{$this->vmid}/template"); } public function findNetworkDevice($macAddress) { foreach ($this->getNetworkDevices() as $nd) { if ($nd->getMacAddress() == $macAddress) { return $nd; } } return null; } public function deleteNetworkDevice(NetworkDeviceKvm $networkDevice) { $this->deleteConfig($networkDevice->getId()); } /** * * @param HardDisk $hardDisks * @return array */ public function updateHardDisks($hardDisks) { $container = array(); foreach ($hardDisks as $hardDisk) { $container[$hardDisk->getId()] = $hardDisk->asConfig(); } return $this->updateConfig($container); } /** * * @return IpConfigRepository */ public function getIpConfig() { $repostiory = new IpConfigRepository; $repostiory->findByPath("/nodes/{$this->node}/qemu/{$this->vmid}/config"); return $repostiory; } public function getCdRom() { $repostiory = new CdRomRepository(); $repostiory->findByPath("/nodes/{$this->node}/qemu/{$this->vmid}/config"); return $repostiory; } /** * @return Agent */ public function agent() { return (new Agent())->setPath("/nodes/{$this->node}/qemu/{$this->vmid}/agent"); } public function getCdRomRepository(){ $repostiory = new CdRomRepository(); $repostiory->findByPath("/nodes/{$this->node}/qemu/{$this->vmid}/config"); return $repostiory; } public function hasCloudInit(){ $repostiory = new CdRomRepository(); $repostiory->findByPath("/nodes/{$this->node}/qemu/{$this->vmid}/config"); return $repostiory->hasCloudInit(); } /** * @return HardDiskRepostiory * @throws \MGProvision\Proxmox\v2\ProxmoxApiException */ public function getHardDiskRepostiory(){ $repository = new HardDiskRepostiory(); $repository->setApi($this->api()); $repository->findByPath($this->getPath() . '/config'); return $repository; } }