andre vor 4 Jahren
Ursprung
Commit
c219aeb5c3

+ 31 - 6
composer.json

@@ -361,8 +361,10 @@ abstract class AbstractApi
         unset($prox_ch);
 
         // ModulesGarden
-        if ($this->whmcsDebugMode)     {
-            if (function_exists('logModuleCall'))   {
+        if ($this->whmcsDebugMode)
+        {
+            if (function_exists('logModuleCall'))
+            {
                 logModuleCall(
                         "proxmoxVPS", $action_path, $http_method . " https://{$this->pve_hostname}:{$this->port}/api2/json" . $action_path . "\n" . print_r($put_post_parameters, true), '', sprintf("HTTP %s %s",$this->httpCode, $action_response), array($this->pve_username, $this->pve_password)
                 );
@@ -575,14 +577,18 @@ abstract class AbstractApi
      * @param string $action_path
      * @return boolean | array
      */
-    public function delete($action_path)   {
-        if (!$this->constructor_success)  {
+    public function delete($action_path)
+    {
+        if (!$this->constructor_success)
+        {
             return false;
         }
 
         # We run this if we haven't queried for cluster nodes as yet, and cache it in the object.
-        if ($this->pve_cluster_node_list == null)     {
-            if ($this->reload_node_list() === false)  {
+        if ($this->pve_cluster_node_list == null)
+        {
+            if ($this->reload_node_list() === false)
+            {
                 return false;
             }
         }
@@ -641,5 +647,24 @@ abstract class AbstractApi
         return $this;
     }
 
+    /**
+     * @return mixed|string
+     */
+    public function getPort()
+    {
+        return $this->port;
+    }
+
+    /**
+     * @param mixed|string $port
+     * @return AbstractApi
+     */
+    public function setPort($port)
+    {
+        $this->port = $port;
+        return $this;
+    }
+
+
 
 }

+ 11 - 0
v2/Api.php

@@ -33,6 +33,7 @@ class Api extends AbstractApi
      */
     private static $instance;
     private $responsePaser;
+    const AUTH_COOKIE = 'PVEAuthCookie';
 
     public function __construct($pve_hostname, $pve_username, $pve_realm = "pam", $pve_password, $login=true)
     {
@@ -173,4 +174,14 @@ class Api extends AbstractApi
 
         return version_compare($this->getVersion(), "4.0", '>=');
     }
+
+    /**
+     * @return array
+     */
+    public function getAuthCookieAsArray(){
+        if(!$this->getLoginTicket()['ticket']){
+            throw  new \InvalidArgumentException("Auth Cookie is empty");
+        }
+        return [self::AUTH_COOKIE => $this->getLoginTicket()['ticket']];
+    }
 }

+ 9 - 0
v2/Factory.php

@@ -20,6 +20,8 @@
 
 namespace MGProvision\Proxmox\v2\models;
 
+use MGProvision\Proxmox\v2\Api;
+
 /**
  * Description of AbstractObject
  *
@@ -59,6 +61,13 @@ abstract class AbstractObject
         return $this->api = \MGProvision\Proxmox\v2\Api::getInstance();
     }
 
+    /**
+     * @return  Api
+     */
+    public function getApi(){
+        return $this->api;
+    }
+
     public static function asArray($proxmoxConfig)
     {
 

+ 31 - 5
v2/models/AbstractVm.php

@@ -128,7 +128,8 @@ abstract class AbstractVm extends AbstractObject implements \MGProvision\Proxmox
         return $this->api()->delete("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}");
     }
 
-    public function restart()  {
+    public function restart()
+    {
 
         $status = $this->status(true);
         if ($status['status'] == "running")
@@ -149,7 +150,8 @@ abstract class AbstractVm extends AbstractObject implements \MGProvision\Proxmox
         return $this->start();
     }
 
-    public function getVmid()  {
+    public function getVmid()
+    {
         return $this->vmid;
     }
 
@@ -276,9 +278,7 @@ abstract class AbstractVm extends AbstractObject implements \MGProvision\Proxmox
         $data['storage']  = $storage;
         $data['remove']   = $routing;
         if(is_numeric($maxFiles)){
-            if((int) $maxFiles > 0){
-                $data['maxfiles'] = (int) $maxFiles;
-            }
+            $data['maxfiles'] = (int) $maxFiles;
         }
         if ($compress)
             $data['compress'] = $compress;
@@ -384,4 +384,30 @@ abstract class AbstractVm extends AbstractObject implements \MGProvision\Proxmox
     public function isHaManaged(){
         return $this->status()['ha']['managed']==1;
     }
+
+    public function protectionOff()
+    {
+        return $this->updateConfig(array("protection" => "0"));
+    }
+
+    public function vncWebsocketPath($vncproxy){
+        $get =[
+            "port" => $vncproxy['port'],
+            "vncticket" => $vncproxy['ticket'],
+            ];
+        $url = "{$this->api()->getPveHostname()}:{$this->api()->getPort()}/api2/json/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/vncwebsocket?";
+        $url .="port=".$vncproxy['port']."&vncticket=".urlencode($vncproxy['ticket']);
+        return $url;
+    }
+
+    public function termproxy($serial = null)
+    {
+        $setting              = [];
+        if ($serial)
+            $setting['serial'] = $serial;
+        return $this->api()->post("/nodes/{$this->node}/{$this->getVirtualization()}/{$this->vmid}/termproxy", $setting);
+    }
+    public function isLockBackup(){
+        return $this->config(true)['lock']=='backup';
+    }
 }

+ 26 - 3
v2/models/Agent.php

@@ -44,6 +44,7 @@ class BackupSchedule extends AbstractObject
     protected $mode;
     protected $maxfiles;
     protected $node;
+    protected $schedule;
 
     public function getStarttime()
     {
@@ -209,9 +210,7 @@ class BackupSchedule extends AbstractObject
             "starttime" => $this->getStarttime(),
         );
         if($this->getMaxfiles()){
-            if((int) $this->getMaxfiles() > 0){
-                $data['maxfiles'] = (int) $this->getMaxfiles();
-            }
+            $data['maxfiles'] = (int) $this->getMaxfiles();
         }
 
         if ($this->getStorage())
@@ -250,6 +249,12 @@ class BackupSchedule extends AbstractObject
 
     public function getAttributes()
     {
+        if($this->schedule){
+            $ex = explode(" ", $this->schedule);
+            $this->setDow($ex[0]);
+            $this->setStarttime($ex[1]);
+        }
+
         return array(
             'displayId' => preg_replace('/^(.*):/', '', $this->getId()),
             "starttime" => $this->getStarttime(),
@@ -261,4 +266,22 @@ class BackupSchedule extends AbstractObject
             "dow"       => $this->getDow()
         );
     }
+
+    /**
+     * @return mixed
+     */
+    public function getSchedule()
+    {
+        return $this->schedule;
+    }
+
+    /**
+     * @param mixed $schedule
+     * @return BackupSchedule
+     */
+    public function setSchedule($schedule)
+    {
+        $this->schedule = $schedule;
+        return $this;
+    }
 }

+ 1 - 1
v2/models/CdRom.php

@@ -74,7 +74,7 @@ class CloudInitDrive extends AbstractObject {
     }
 
     public function mount(){
-        return $this->api()->put($this->getPath(),[$this->id => "{$this->storage}:cloudinit,format=raw" ]);
+        return $this->api()->put($this->getPath(),[$this->id => "{$this->storage}:cloudinit" ]);
     }
 
 }

+ 42 - 0
v2/models/ClusterResource.php

@@ -36,6 +36,8 @@ class File extends AbstractObject
     protected $volid;
     protected $ctime;
     private $path;
+    protected $node;
+    protected $vmid;
 
     public function getContent()
     {
@@ -171,5 +173,45 @@ class File extends AbstractObject
         return $this;
     }
 
+    /**
+     * @return mixed
+     */
+    public function getNode()
+    {
+        return $this->node;
+    }
+
+    /**
+     * @param mixed $node
+     * @return File
+     */
+    public function setNode($node)
+    {
+        $this->node = $node;
+        return $this;
+    }
+
+    public function formatVolid()
+    {
+        $ex           = explode("/", $this->getVolid());
+        return end($ex);
+    }
+
+    public function getVmid()
+    {
+        return $this->vmid;
+    }
+
+    /**
+     * @param mixed $vmid
+     * @return File
+     */
+    public function setVmid($vmid)
+    {
+        $this->vmid = $vmid;
+        return $this;
+    }
+
+
 
 }

+ 5 - 0
v2/models/FirewallOptions.php

@@ -242,4 +242,9 @@ class FirewallRule extends AbstractObject
         return $this->api()->put($this->path, $this->fill());
     }
 
+    public function moveto($newPos){
+        if (empty($this->path))
+            throw new ProxmoxApiException('Firewall Rule [path] - property is missing and it is not optional');
+        return $this->api()->put($this->path, ['moveto'=> $newPos]);
+    }
 }

+ 12 - 2
v2/models/HaResource.php

@@ -333,7 +333,7 @@ class HardDisk extends AbstractObject{
         $config = [];
         $config[] = $this->getStorage().":".$this->getSize();
         $fields=['cache','discard','media','replicate','format','backup','mbps_rd','mbps_rd_max',
-            'mbps_wr','mbps_wr_max','iops_rd','iops_rd_max','iops_wr','iops_wr_max', 'iothread', 'ssd'];
+            'mbps_wr','mbps_wr_max','iops_rd','iops_rd_max','iops_wr','iops_wr_max', 'iothread'];
         $this->toConfig($fields, $config);
         $prameters = implode(",", $config);
         return $this->api()->put($this->getPath(), [$this->getId()=>  $prameters]);
@@ -437,4 +437,14 @@ class HardDisk extends AbstractObject{
         }
         return true;
     }
-}
+
+    public function move($delete=0){
+        $config = [
+            "disk"=> $this->getId(),
+            'storage' => $this->getStorage(),
+            'delete' => $delete
+        ];
+        $path =  str_replace("/config", "/move_disk", $this->getPath());
+        return $this->api()->post($path ,$config );
+    }
+}

+ 0 - 26
v2/models/IpCidr.php

@@ -264,32 +264,6 @@ class Kvm extends AbstractVm implements \MGProvision\Proxmox\v2\interfaces\KvmIn
         return $disks;
     }
 
-    /**
-     * @return HardDisk[]
-     */
-    public function getUnusedHardDisks()
-    {
-        $disks  = array();
-        $config = $this->config(true);
-        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");
-            $disks[] = $hdd;
-        }
-        return $disks;
-    }
-
     /**
      * 
      * @return HardDisk

+ 9 - 0
v2/models/Lxc.php

@@ -221,4 +221,13 @@ class Lxc extends AbstractVm implements \MGProvision\Proxmox\v2\interfaces\LxcIn
     public function getHardDiskRepostiory(){
         return $this->getMounPoints();
     }
+
+    public function getMasterHardDisk(){
+        foreach ($this->getMounPoints()->fetch() as $mounPoint){
+            if($mounPoint->isMaster()){
+                return $mounPoint;
+            }
+        }
+        throw new \MGProvision\Proxmox\v2\ProxmoxApiException("Master Hard Disk not found");
+    }
 }

+ 32 - 2
v2/models/MountPoint.php

@@ -39,6 +39,7 @@ class MountPoint extends AbstractObject
     protected $location;
     protected $name;
     protected $gb;
+    protected $storage;
 
     public function __construct($id, $config = null)
     {
@@ -47,9 +48,12 @@ class MountPoint extends AbstractObject
         {
             $config             = self::asArray($config);
             $config['location'] = key($config);
-            $matches['0']       = str_replace(['-'], [" "], $matches['0']);
-            $config['name']     = ucfirst($matches['0']);
+            $ex = explode(":", $config['location'] );
+            $config['storage'] = $ex[0];
             $this->setAttributes($config);
+            if(!$config['size']){
+                $this->setSize($ex[1]."G");
+            }
             if ($id == 'rootfs')
             {
                 $this->setBackup(1);
@@ -265,5 +269,31 @@ class MountPoint extends AbstractObject
         return $this->getId() == "rootfs";
     }
 
+    /**
+     * @return mixed
+     */
+    public function getStorage()
+    {
+        return $this->storage;
+    }
+
+    /**
+     * @param mixed $storage
+     * @return MountPoint
+     */
+    public function setStorage($storage)
+    {
+        $this->storage = $storage;
+        return $this;
+    }
 
+    public function move($delete=0){
+        $config = [
+            "volume" => $this->getId(),
+            'storage' => $this->getStorage(),
+            'delete' => $delete
+        ];
+        $path =  str_replace("/config", "/move_volume", $this->getPath());
+        return $this->api()->post($path ,$config );
+    }
 }

+ 43 - 31
v2/models/Network.php

@@ -28,7 +28,8 @@ use MGProvision\Proxmox\v2 as proxmox;
  * @author Pawel Kopec <pawelk@modulesgarden.com>
  * @version 1.0.0
  */
-class Snapshot extends AbstractObject {
+class Snapshot extends AbstractObject
+{
     private $path;
     protected $name;
     protected $description;
@@ -36,71 +37,78 @@ class Snapshot extends AbstractObject {
     protected $parent;
     protected $vmstate;
 
-    public function getName(){
+    public function getName()
+    {
         return $this->name;
     }
 
-    public function getDescription() {
+    public function getDescription()
+    {
         return $this->description;
     }
 
-    public function getSnaptime() {
+    public function getSnaptime()
+    {
         return $this->snaptime;
     }
 
-    public function getParent() {
+    public function getParent()
+    {
         return $this->parent;
     }
 
-    public function setName($name) {
+    public function setName($name)
+    {
         $this->name = $name;
         return $this;
     }
 
-    public function setDescription($description) {
+    public function setDescription($description)
+    {
         $this->description = $description;
         return $this;
     }
 
-    public function setSnaptime($snaptime) {
+    public function setSnaptime($snaptime)
+    {
         $this->snaptime = $snaptime;
         return $this;
     }
 
-    public function setParent($parent)  {
+    public function setParent($parent)
+    {
         $this->parent = $parent;
         return $this;
     }
 
-    public function getVmstate() {
+    public function getVmstate()
+    {
         return $this->vmstate;
     }
 
-    public function setVmstate($vmstate) {
+    public function setVmstate($vmstate)
+    {
         $this->vmstate = $vmstate;
         return $this;
     }
 
-    public function setPath($path) {
+    public function setPath($path)
+    {
 
-        if (!preg_match('/\/snapshot/', $path))  {
+        if (!preg_match('/\/snapshot/', $path))
+        {
             throw new proxmox\ProxmoxApiException(sprintf("Snapshot Path ('%s') is not valid", $path));
         }
 
         $this->path = $path;
         return $this;
     }
-    
-    public function getPath() {
-	return $this->path;
-    }
-    
 
-    public function create()  {
+    public function create()
+    {
 
-        if (empty($this->path)) {
+        if (empty($this->path))
             throw new proxmox\ProxmoxApiException('Snapshot [path] - property is missing and it is not optional');
-        }
         $request = array(
             "snapname"    => $this->getName(),
             "description" => $this->getDescription(),
@@ -111,28 +119,32 @@ class Snapshot extends AbstractObject {
         return $this->api()->post($this->path, $request);
     }
 
-    public function update()  {
-        if (empty($this->path)) {
+    public function update()
+    {
+
+        if (empty($this->path))
             throw new proxmox\ProxmoxApiException('Snapshot [path] - property is missing and it is not optional');
-        }
         return $this->api()->put($this->path . "/config", array("description" => $this->getDescription()));
     }
 
-    public function rollback() {
-        if (empty($this->path)) {
+    public function rollback()
+    {
+
+        if (empty($this->path))
             throw new proxmox\ProxmoxApiException('Snapshot [path] - property is missing and it is not optional');
-        }
         return $this->api()->post($this->path . '/rollback');
     }
 
-    public function delete() {
-        if (empty($this->path)) {
+    public function delete()
+    {
+
+        if (empty($this->path))
             throw new proxmox\ProxmoxApiException('Snapshot [path] - property is missing and it is not optional');
-        }
         return $this->api()->delete($this->path);
     }
 
-    public function getAttributes()  {
+    public function getAttributes()
+    {
 
         return array(
             "name"        => $this->getName(),

+ 13 - 6
v2/models/SnapshotKvm.php

@@ -96,7 +96,8 @@ class SnapshotKvm extends AbstractObject
     public function setPath($path)
     {
 
-        if (!preg_match('/\/snapshot/', $path))  {
+        if (!preg_match('/\/snapshot/', $path))
+        {
             throw new proxmox\ProxmoxApiException(sprintf("Snapshot Path ('%s') is not valid", $path));
         }
 
@@ -104,7 +105,8 @@ class SnapshotKvm extends AbstractObject
         return $this;
     }
 
-    public function create() {
+    public function create()
+    {
 
         if (empty($this->path))
             throw new proxmox\ProxmoxApiException('Snapshot [path] - property is missing and it is not optional');
@@ -117,27 +119,32 @@ class SnapshotKvm extends AbstractObject
         return $this->api()->post($this->path, $request);
     }
 
-    public function update()  {
+    public function update()
+    {
 
         if (empty($this->path))
             throw new proxmox\ProxmoxApiException('Snapshot [path] - property is missing and it is not optional');
         return $this->api()->put($this->path . "/config", array("description" => $this->getDescription()));
     }
 
-    public function rollback()  {
+    public function rollback()
+    {
 
         if (empty($this->path))
             throw new proxmox\ProxmoxApiException('Snapshot [path] - property is missing and it is not optional');
         return $this->api()->post($this->path . '/rollback');
     }
 
-    public function delete() {
+    public function delete()
+    {
+
         if (empty($this->path))
             throw new proxmox\ProxmoxApiException('Snapshot [path] - property is missing and it is not optional');
         return $this->api()->delete($this->path);
     }
 
-    public function getAttributes()  {
+    public function getAttributes()
+    {
 
         return array(
             "name"        => $this->getName(),

+ 108 - 86
v2/models/Storage.php

@@ -34,12 +34,12 @@ use ModulesGarden\ProxmoxAddon\App\Services\Utility;
  */
 class FileRepository extends AbstractRepository
 {
-    protected $content        = null;
-    protected $storages       = array();
-    protected $nodes          = array();
+    protected $content = null;
+    protected $storages = array();
+    protected $nodes = array();
     protected $vmid;
     private $templateKvm;
-    private $vmids            = array();
+    private $vmids = array();
     protected $filterNotMatch = [];
     protected $forceFetch = true;
     protected $filterPattern;
@@ -51,7 +51,7 @@ class FileRepository extends AbstractRepository
     }
 
     /**
-     * 
+     *
      * @param VmInterface $vm
      * @return \MGProvision\Proxmox\v2\repository\FileRepository
      */
@@ -59,91 +59,81 @@ class FileRepository extends AbstractRepository
     {
 
         $this->findByVmid($vm->getVmid())
-                ->findByNodes(array($vm->getNode()));
+            ->findByNodes(array($vm->getNode()));
 
         $this->findByContent('backup');
         return $this;
     }
 
     /**
-     * 
+     *
      * @param VmModel[] $vservers
      */
     public function findBackupByVmModel($vservers)
     {
 
         $nodes = array();
-        foreach ($vservers as $vserver)
-        {
-            if (!$vserver instanceof VmModel)
-            {
+        foreach ($vservers as $vserver) {
+            if (!$vserver instanceof VmModel) {
                 throw new \MGProvision\Proxmox\v2\ProxmoxApiException("Ukown  object: " . get_class($vserver));
             }
-            $nodes[]       = $vserver->node;
+            $nodes[] = $vserver->node;
             $this->vmids[] = $vserver->vmid;
         }
         $this->findByNodes($nodes)
-                ->findByContent('backup');
+            ->findByContent('backup');
         return $this;
     }
 
     /**
-     * 
+     *
      * @return File[]|TemplateKvm[]
      */
     public function fetch()
     {
 
-        if (!empty($this->fetch) || !$this->forceFetch)
-        {
+        if (!empty($this->fetch) && !$this->forceFetch) {
             return $this->fetch;
         }
-        $request            = array();
+        $request = array();
         if ($this->content)
             $request["content"] = $this->content;
         if ($this->vmid)
-            $request["vmid"]    = $this->vmid;
+            $request["vmid"] = $this->vmid;
 
-        $i           = 0;
+        $i = 0;
         $this->fetch = array();
-        foreach ($this->nodes as $node)
-        {
-            if (isset($this->vmids[$i]) && $this->vmids[$i])
-            {
+        foreach ($this->nodes as $node) {
+            if (isset($this->vmids[$i]) && $this->vmids[$i]) {
                 $request["vmid"] = $this->vmids[$i];
             }
-            foreach ($this->storages as $storage)
-            {
+            foreach ($this->storages as $storage) {
                 $vmid = null;
-                if($request["vmid"] &&  version_compare($this->api()->getVersion(), "5.4", '>=')){
+                if ($request["vmid"] && version_compare($this->api()->getVersion(), "5.4", '>=')) {
                     $vmid = $request["vmid"];
                     unset($request["vmid"]);
                 }
-                $path  = "/nodes/{$node}/storage/{$storage}/content";
+                $path = "/nodes/{$node}/storage/{$storage}/content";
                 $files = $this->api()->get($path, $request);
-                foreach ($files as $file)
-                {
-                    if(($vmid && $file['vmid'] && $file['vmid'] != $vmid ) || ($vmid && !$file['vmid'] && !preg_match("/\-{$vmid}\-/", $file['volid']))){
+                foreach ($files as $file) {
+                    if (($vmid && $file['vmid'] && $file['vmid'] != $vmid) || ($vmid && !$file['vmid'] && !preg_match("/\-{$vmid}\-/", $file['volid']))) {
                         continue;
                     }
-                    if ($this->filterNotMatch && preg_match("/{$this->filterNotMatch['volid']}/", $file['volid']))
-                    {
+                    if ($this->filterNotMatch && preg_match("/{$this->filterNotMatch['volid']}/", $file['volid'])) {
                         continue;
                     }
-                    if ($this->filterPattern && !preg_match($this->filterPattern, $file['volid']))
-                    {
+                    if (!empty($this->filterPattern) && !$this->matchFilterPattern($file)) {
                         continue;
                     }
 
-                    if ($this->templateKvm)
-                    {
+                    if ($this->templateKvm) {
                         $entityObj = $this->formatTemplateKvm($node, $file);
                         if (!$entityObj instanceof TemplateKvm)
                             continue;
-                    }else
-                    {
+                    } else {
                         $entityObj = new File();
                         $entityObj->setAttributes($file);
+                        $entityObj->setNode($node);
                     }
                     $entityObj->setPath(sprintf("{$path}/%s", $file['volid']));
                     $this->fetch[] = $entityObj;
@@ -162,9 +152,8 @@ class FileRepository extends AbstractRepository
 
     public function size()
     {
-        $size = (float) 0;
-        foreach ($this->fetch() as $entityObj)
-        {
+        $size = (float)0;
+        foreach ($this->fetch() as $entityObj) {
             $size += $entityObj->getSize();
         }
         return $size;
@@ -176,53 +165,45 @@ class FileRepository extends AbstractRepository
      */
     public function getSizeInGb()
     {
-        $size =  $this->size();
+        $size = $this->size();
         Utility::unitFormat($size, "bytes", "gb");
         return $size;
     }
 
 
-
     private function formatTemplateKvm($node, array $file)
     {
 
-        if (empty($file['vmid']))
-        {
+        if (empty($file['vmid'])) {
             return;
         }
-        try
-        {
+        try {
 
-            $vmid   = $file['vmid'];
+            $vmid = $file['vmid'];
             $status = $this->api()->get("/nodes/{$node}/qemu/{$vmid}/status/current", array());
-            if ($status['template'] != '1')
-            {
+            if ($status['template'] != '1') {
                 return;
             }
             $config = $this->api()->get("/nodes/{$node}/qemu/{$vmid}/config", array());
-            if (empty($config))
-            {
+            if (empty($config)) {
                 return;
             }
-            $attributes         = array();
+            $attributes = array();
             $attributes['node'] = $node;
-            $attributes         = array_merge($attributes, $file);
-            $attributes         = array_merge($attributes, $config);
-            $template           = new TemplateKvm();
+            $attributes = array_merge($attributes, $file);
+            $attributes = array_merge($attributes, $config);
+            $template = new TemplateKvm();
             $template->setAttributes($attributes);
             return $template;
-        }
-        catch (\Exception $ex)
-        {
-            
+        } catch (\Exception $ex) {
+
         }
     }
 
     public function fetchAsArray()
     {
         $data = array();
-        foreach ($this->fetch() as $entity)
-        {
+        foreach ($this->fetch() as $entity) {
             $data[$entity->getVolid()] = $entity->getFriendlyName();
         }
         return $data;
@@ -242,7 +223,7 @@ class FileRepository extends AbstractRepository
 
     public function findKvmTemplates()
     {
-        $this->content     = 'images';
+        $this->content = 'images';
         $this->templateKvm = true;
         return $this;
     }
@@ -259,7 +240,7 @@ class FileRepository extends AbstractRepository
         return $this;
     }
 
-    public function findByNodes(array  $nodes)
+    public function findByNodes(array $nodes)
     {
         $this->nodes = $nodes;
         return $this;
@@ -275,60 +256,58 @@ class FileRepository extends AbstractRepository
     {
         $this->reset();
         $backups = $this->fetch();
-        foreach ($backups as $b)
-        {
+        foreach ($backups as $b) {
             $b->delete();
         }
     }
 
     /**
-     * 
+     *
      * @return File|TemplateKvm|null
      */
     public function fetchLast()
     {
 
         $file = null;
-        foreach ($this->fetch() as $t)
-        {
-            if ($file === null)
-            {
+        foreach ($this->fetch() as $t) {
+            if ($file === null) {
                 $file = $t;
                 continue;
-            }
-            else if ($t->getTimestamp() > $file->getTimestamp())
-            {
+            } else if ($t->getTimestamp() > $file->getTimestamp()) {
                 $file = $t;
             }
         }
         return $file;
     }
 
-    public function findVolidNotIn(array $volids){
+    public function findVolidNotIn(array $volids)
+    {
         $this->filterNotMatch['volid'] = $volids;
         return $this;
     }
 
-    public function sortByTime(){
+    public function sortByTime()
+    {
         $keys = [];
         $orginal = $this->fetch();
-        foreach ($orginal as $key => $entity){
+        foreach ($orginal as $key => $entity) {
             $keys[$key] = $entity->getTimestamp();
         }
-        uasort($keys, function($a, $b){
+        uasort($keys, function ($a, $b) {
             if ($a == $b) {
                 return 0;
             }
             return ($a < $b) ? -1 : 1;
         });
-        $this->fetch=[];
-        foreach ($keys as $id => $entity){
+        $this->fetch = [];
+        foreach ($keys as $id => $entity) {
             $this->fetch[$id] = $orginal[$id];
         }
         return $this;
     }
 
-    public function remove($id){
+    public function remove($id)
+    {
         unset($this->fetch[$id]);
         return $this;
     }
@@ -339,19 +318,62 @@ class FileRepository extends AbstractRepository
         return $this;
     }
 
-    public function findSnippetsByServiceId($serviceId){
+    public function findSnippetsByServiceId($serviceId)
+    {
         $this->findSnippets();
-        $this->filterPattern = "/userconfig\-{$serviceId}\.yaml/";
+        $this->filterPattern = [
+            "/userconfig\-{$serviceId}\.yaml/",
+            "/meta\-{$serviceId}\.yaml/",
+            "/network\-{$serviceId}\.yaml/",
+        ];
         return $this;
     }
 
-    public function findSnippetsByVmModel(VmModel $vmModel){
+    public function findSnippetsByVmModel(VmModel $vmModel)
+    {
         $this->findSnippets();
-        $this->filterPattern = "/userconfig\-{$vmModel->hosting_id}\-{$vmModel->id}\.yaml/";
+        $this->filterPattern = [
+            "/userconfig\-{$vmModel->hosting_id}\-{$vmModel->id}\.yaml/",
+            "/meta\-{$vmModel->hosting_id}\-{$vmModel->id}\.yaml/",
+            "/network\-{$vmModel->hosting_id}\-{$vmModel->id}\.yaml/",
+        ];
         return $this;
     }
 
-    public function first(){
+    public function first()
+    {
         return $this->fetch()[0];
     }
+
+    public function findBackupQemuTemplates()
+    {
+        $this->findByContent('backup');
+        $this->filterPattern = "/qemu/";
+        $this->forceFetch = true;
+        return $this;
+    }
+
+    public function findBackupLxcTemplates()
+    {
+        $this->findByContent('backup');
+        $this->filterPattern = "/lxc/";
+        $this->forceFetch = true;
+        return $this;
+    }
+
+    private function matchFilterPattern($file)
+    {
+        if (is_string($this->filterPattern)) {
+            return preg_match($this->filterPattern, $file['volid']);
+        }
+        if (is_array($this->filterPattern)) {
+            foreach ($this->filterPattern as $pattern) {
+                if (preg_match($pattern, $file['volid'])) {
+                    return true;
+                }
+            }
+        }
+        return false;
+
+    }
 }

+ 11 - 0
v2/repository/FirewallRulesRepository.php

@@ -111,4 +111,15 @@ class FirewallRulesRepository extends AbstractRepository
             unset($rules);
         }
     }
+
+    public function fetchAsArray()
+    {
+        $data = [];
+        foreach ($this->fetch() as $rule){
+            $row = $rule->toArray();
+            unset($row['digest'], $row['path'], $row['api']);
+            $data[] = $row;
+        }
+        return $data;
+    }
 }

+ 10 - 0
v2/repository/HaResourceRepository.php

@@ -241,4 +241,14 @@ class NodeRepository extends AbstractRepository
         $this->online = (boolean) $online;
         return $this;
     }
+
+    public function fetchArray()
+    {
+        $data = array();
+        foreach ($this->fetch() as $entity)
+        {
+            $data[] = $entity->getNode();
+        }
+        return $data;
+    }
 }

+ 20 - 11
v2/repository/SnapshotRepository.php

@@ -48,7 +48,8 @@ class SnapshotRepository extends AbstractRepository
      * 
      * @param VmModel[] $vservers
      */
-    public function findByVmModel($vservers) {
+    public function findByVmModel($vservers)
+    {
 
         $nodes = array();
         foreach ($vservers as $vserver)
@@ -63,14 +64,16 @@ class SnapshotRepository extends AbstractRepository
         return $this;
     }
 
-    public function reset()  {
+    public function reset()
+    {
         parent::reset();
         $this->ignoreCurrent = false;
         $this->paths         = array();
         return $this;
     }
 
-    public function ignoreCurrent($ignoreCurrent) {
+    public function ignoreCurrent($ignoreCurrent)
+    {
         $this->ignoreCurrent = (boolean) $ignoreCurrent;
         return $this;
     }
@@ -78,7 +81,8 @@ class SnapshotRepository extends AbstractRepository
     /**
      * @return proxmox\models\SnapshotKvm
      */
-    public function getCurrent()  {
+    public function getCurrent()
+    {
         return $this->current;
     }
 
@@ -86,20 +90,26 @@ class SnapshotRepository extends AbstractRepository
      * @return proxmox\models\SnapshotKvm[]
      * @throws proxmox\ProxmoxApiException
      */
-    public function fetch() {
+    public function fetch()
+    {
 
-        if (!empty($this->fetch)) {
+        if (!empty($this->fetch))
+        {
             return $this->fetch;
         }
 
-        foreach ($this->paths as $path)   {
+        foreach ($this->paths as $path)
+        {
+
             $temp = $this->api()->get($path);
 
-            foreach ($temp as $snap)   {
-                $entityObj  = new Snapshot();
+            foreach ($temp as $snap)
+            {
+                $entityObj     = new Snapshot();
                 $entityObj->setAttributes($snap);
                 $entityObj->setPath(sprintf("{$path}/%s", $snap['name']));
-                if ($this->ignoreCurrent && $snap['name'] == "current")  {
+                if ($this->ignoreCurrent && $snap['name'] == "current")
+                {
                     $this->current = $entityObj;
                     continue;
                 }
@@ -108,7 +118,6 @@ class SnapshotRepository extends AbstractRepository
         }
         return $this->fetch;
     }
-    
 
     public function sortBySnaptime(){
         $keys = [];

+ 0 - 0
v2/repository/StorageRepository.php