]> git.datanom.net - omvzfs.git/commitdiff
Support for cloned filesystems and volumes.
authorNiclas Berglind <nb@kjam.se>
Mon, 13 Oct 2014 14:28:30 +0000 (16:28 +0200)
committerMichael Rasmussen <mir@datanom.net>
Mon, 13 Oct 2014 22:41:26 +0000 (00:41 +0200)
Signed-off-by: Niclas Berglind <nb@kjam.se>
gui/js/omv/module/admin/storage/zfs/Overview.js
gui/js/omv/module/admin/storage/zfs/TreePanel.js
gui/rpc/zfs.inc
src/Utils.php
src/Zvol.php

index 4731124a7016385e636441a1f111fefa79fae95f..9db8915221f4ce396ea2fb1738f7607a7cf9b2e2 100644 (file)
@@ -221,32 +221,63 @@ Ext.define("OMV.module.admin.storage.zfs.AddObject", {
 
        getFormItems: function() {
                var me = this;
 
        getFormItems: function() {
                var me = this;
+       
+               var store = new Ext.data.ArrayStore({
+                       autoDestroy: true,
+                       storeId: 'my_store',
+               fields: [
+                       {name: 'value', type: 'string'},
+                       {name: 'display', type: 'string'}
+               ]
+               });
+       
+               var combodata;
+               if (me.parenttype === "Snapshot") {
+                       combodata = [["clone","Clone"]];
+               } else if (me.parenttype === "Volume") {
+                       combodata = [["snapshot", "Snapshot"]];
+               } else {
+                       combodata = [["filesystem","Filesystem"],
+                                               ["volume","Volume"],
+                                               ["snapshot","Snapshot"]];
+               }
+               store.loadData(combodata,false);
+
                return [{
                        xtype: "combo",
                        name: "type",
                        fieldLabel: _("Object Type"),
                        queryMode: "local",
                return [{
                        xtype: "combo",
                        name: "type",
                        fieldLabel: _("Object Type"),
                        queryMode: "local",
-                       store: [
-                               [ "filesystem", "Filesystem" ],
-                               [ "snapshot", "Snapshot" ],
-                               [ "volume", "Volume" ]
-                       ],
+                       store: store,
                        allowBlank: true,
                        editable: false,
                        triggerAction: "all",
                        allowBlank: true,
                        editable: false,
                        triggerAction: "all",
-                       value: "filesystem",
+                       valueField: "value",
+                       displayField: "display",
+                       value: combodata[0][0],
                        listeners: {
                                scope: me,
                                change: function(combo, value) {
                                        var sizeField = this.findField("size");
                        listeners: {
                                scope: me,
                                change: function(combo, value) {
                                        var sizeField = this.findField("size");
+                                       var cloneField = this.findField("clonename");
+                                       var nameField = this.findField("name");
                                        switch(value) {
                                                case "volume":
                                                        sizeField.show();
                                        switch(value) {
                                                case "volume":
                                                        sizeField.show();
-                                               sizeField.allowBlank = false;
+                                                       sizeField.allowBlank = false;
+                                                       cloneField.hide();
+                                                       nameField.show();
                                                break;
                                                break;
+                                               case "clone":
+                                                       sizeField.hide();
+                                                       sizeField.allowBlank = true;
+                                                       cloneField.show();
+                                                       nameField.hide();
                                                default:
                                                        sizeField.hide();
                                                default:
                                                        sizeField.hide();
-                                               sizeField.allowBlank = true;
+                                                       sizeField.allowBlank = true;
+                                                       cloneField.hide();
+                                                       nameField.show();
                                                break;
                                        }
                                        sizeField.validate();
                                                break;
                                        }
                                        sizeField.validate();
@@ -258,19 +289,68 @@ Ext.define("OMV.module.admin.storage.zfs.AddObject", {
                        fieldLabel: _("Prefix"),
                        allowBlank: false,
                        readOnly: true,
                        fieldLabel: _("Prefix"),
                        allowBlank: false,
                        readOnly: true,
-                       value: me.path
+                       value: me.path,
+                       listeners: {
+                               scope: me,
+                               beforerender: function(e, eOpts) {
+                                       var pathField = this.findField("path");
+                                       if (me.parenttype === "Snapshot") {
+                                               pathField.fieldLabel = _("Snapshot to clone");
+                                       } else {
+                                               pathField.fieldLabel = _("Prefix");
+                                       }
+                               }
+                       }
                },{
                        xtype: "textfield",
                        name: "name",
                },{
                        xtype: "textfield",
                        name: "name",
+                       id: "name",
                        fieldLabel: _("Name"),
                        allowBlank: false,
                        plugins: [{
                                ptype: "fieldinfo",
                                text: _("Name of the new object. Prefix will prepend the name. Please omit leading /")
                        fieldLabel: _("Name"),
                        allowBlank: false,
                        plugins: [{
                                ptype: "fieldinfo",
                                text: _("Name of the new object. Prefix will prepend the name. Please omit leading /")
-                       }]
+                       }],
+                       listeners: {
+                               scope: me,
+                               beforerender: function(e, eOpts) {
+                                       var nameField = this.findField("name");
+                                       if (me.parenttype === "Snapshot") {
+                                               nameField.hide();
+                                               nameField.allowBlank = true;
+                                       } else {
+                                               nameField.show();
+                                               nameField.allowBlank = false;
+                                       }
+                               }
+                       }
+               },{
+                       xtype: "textfield",
+                       name: "clonename",
+                       id: "clonename",
+                       fieldLabel: _("Clone name"),
+                       allowBlank: false,
+                       plugins: [{
+                               ptype: "fieldinfo",
+                               text: _("Name of the new Clone. It can be placed anywhere within the ZFS hierarchy.")
+                       }],
+                       listeners: {
+                               scope: me,
+                               beforerender: function(e, eOpts) {
+                                       var cloneField = this.findField("clonename");
+                                       if (me.parenttype === "Snapshot") {
+                                               cloneField.show();
+                                               cloneField.allowBlank = false;
+                                       } else {
+                                               cloneField.hide();
+                                               cloneField.allowBlank = true;
+                                       }
+                               }
+                       }
                },{
                        xtype: "textfield",
                        name: "size",
                },{
                        xtype: "textfield",
                        name: "size",
+                       id: "size",
                        hidden: true,
                        fieldLabel: _("Size"),
                        allowBlank: true,
                        hidden: true,
                        fieldLabel: _("Size"),
                        allowBlank: true,
@@ -713,7 +793,14 @@ Ext.define("OMV.module.admin.storage.zfs.Overview", {
                dataIndex: 'name',
                sortable: true,
                flex: 2,
                dataIndex: 'name',
                sortable: true,
                flex: 2,
-               stateId: 'name'
+               stateId: 'name',
+               renderer: function(value, p, r){
+                       if (r.data['origin'] === "n/a") {
+                               return r.data['name'];
+                       } else {
+                               return r.data['name'] + ' (' + r.data['origin'] + ')';
+                       }
+               }
        },{
                text: _("Type"),
                dataIndex: 'type',
        },{
                text: _("Type"),
                dataIndex: 'type',
@@ -721,10 +808,10 @@ Ext.define("OMV.module.admin.storage.zfs.Overview", {
                flex: 1,
                stateId: 'type',
                renderer: function(value, p, r){
                flex: 1,
                stateId: 'type',
                renderer: function(value, p, r){
-                       if (r.data['type'] == "Pool") {
-                               return r.data['type'] + ' (' + r.data['pool_type'] + ')';
-                       } else {
+                       if (r.data['origin'] === "n/a") {
                                return r.data['type'];
                                return r.data['type'];
+                       } else {
+                               return 'Clone';
                        }
                }
        },{
                        }
                }
        },{
@@ -856,6 +943,7 @@ Ext.define("OMV.module.admin.storage.zfs.Overview", {
                Ext.create("OMV.module.admin.storage.zfs.AddObject", {
                        title: _("Add Object"),
                        path: record.get("path"),
                Ext.create("OMV.module.admin.storage.zfs.AddObject", {
                        title: _("Add Object"),
                        path: record.get("path"),
+                       parenttype: record.get("type"),
                        listeners: {
                                scope: me,
                                submit: function() {
                        listeners: {
                                scope: me,
                                submit: function() {
index 373f5b6149be50e8db046d20dc15fd46279a12d6..56c3ec0f4ce0ba057d6715d4d3f99ed197d0e9f9 100644 (file)
@@ -337,9 +337,9 @@ Ext.define("OMV.module.admin.storage.zfs.TreePanel", {
                        tbarBtnHidden["delete"] = false;
                        tbarBtnHidden["expand"] = true;
                }
                        tbarBtnHidden["delete"] = false;
                        tbarBtnHidden["expand"] = true;
                }
-               //Disable 'AddObj' button if selected row is a Snapshot
+               //Disable 'AddObj' button if selected row is a Clone
                Ext.Array.each(records, function(record) {
                Ext.Array.each(records, function(record) {
-                       if("Snapshot" == record.get("type")) {
+                       if("Clone" == record.get("type")) {
                                tbarBtnDisabled["addobj"] = true;
                                tbarBtnHidden["addobj"] = true;
                        return false;
                                tbarBtnDisabled["addobj"] = true;
                                tbarBtnHidden["addobj"] = true;
                        return false;
index fda53b0209dcf00f43f6d0e09f35dddce28b35dd..bbab27ca3824b961d5dc8136ab5cc2406dd5e62a 100644 (file)
@@ -126,13 +126,18 @@ class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
                          "type":"object",
                          "properties":{
                                  "type":{"type":"string","enum":["filesystem","snapshot",' .
                          "type":"object",
                          "properties":{
                                  "type":{"type":"string","enum":["filesystem","snapshot",' .
-                                       '"volume"]},
+                                       '"volume","clone"]},
                                  "path":{"type":"string"},
                                  "name":{"type":"string"},
                                  "path":{"type":"string"},
                                  "name":{"type":"string"},
-                                 "size":{"type":"string"}
+                                 "size":{"type":"string"},
+                                 "clonename":{"type":"string"}
                          }
                  }');
                switch ($params['type']) {
                          }
                  }');
                switch ($params['type']) {
+               case "clone":
+                       $tmp = new OMVModuleZFSSnapshot($params['path']);
+                       $tmp->clonesnap($params['clonename']);
+                       break;
                case "filesystem":
                        $name = $params['path'] . "/" . $params['name'];
                        $tmp = new OMVModuleZFSDataset($name);
                case "filesystem":
                        $name = $params['path'] . "/" . $params['name'];
                        $tmp = new OMVModuleZFSDataset($name);
@@ -159,7 +164,7 @@ class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
                          "type":"object",
                          "properties":{
                                  "type":{"type":"string","enum":["Filesystem","Snapshot",' .
                          "type":"object",
                          "properties":{
                                  "type":{"type":"string","enum":["Filesystem","Snapshot",' .
-                                       '"Volume","Clone","Pool"]},
+                                       '"Volume","Pool"]},
                                  "name":{"type":"string"}
                          }
                  }');
                                  "name":{"type":"string"}
                          }
                  }');
@@ -171,10 +176,6 @@ class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
                        $tmp = new OMVModuleZFSDataset($name);
                        $tmp->destroy();
                        break;
                        $tmp = new OMVModuleZFSDataset($name);
                        $tmp->destroy();
                        break;
-               case "Clone":
-                       $tmp = new OMVModuleZFSDataset($name);
-                       $tmp->destroy();
-                       break;
                case "Snapshot":
                        $tmp = new OMVModuleZFSSnapshot($name);
                        $tmp->destroy();
                case "Snapshot":
                        $tmp = new OMVModuleZFSSnapshot($name);
                        $tmp->destroy();
@@ -217,7 +218,6 @@ class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
                $name = $params['name'];
                switch ($params['type']) {
                case "Filesystem":
                $name = $params['name'];
                switch ($params['type']) {
                case "Filesystem":
-               case "Clone":
                        $tmp = new OMVModuleZFSDataset($name);
                        break;
                case "Snapshot":
                        $tmp = new OMVModuleZFSDataset($name);
                        break;
                case "Snapshot":
@@ -252,7 +252,7 @@ class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
                        "type":"object",
                                "properties":{
                                        "type":{"type":"string","enum":["Filesystem","Snapshot",' .
                        "type":"object",
                                "properties":{
                                        "type":{"type":"string","enum":["Filesystem","Snapshot",' .
-                                               '"Volume","Clone","Pool"]},
+                                               '"Volume","Pool"]},
                                        "name":{"type":"string"},
                                        "properties":{"type":"array","items":{
                                                "type":"object",
                                        "name":{"type":"string"},
                                        "properties":{"type":"array","items":{
                                                "type":"object",
@@ -264,7 +264,6 @@ class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
                global $xmlConfig;
                switch ($params['type']) {
                case "Filesystem":
                global $xmlConfig;
                switch ($params['type']) {
                case "Filesystem":
-               case "Clone":
                        $tmp = new OMVModuleZFSDataset($params['name']);
                        break;
                case "Snapshot":
                        $tmp = new OMVModuleZFSDataset($params['name']);
                        break;
                case "Snapshot":
@@ -298,7 +297,7 @@ class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
                          "type":"object",
                          "properties":{
                                  "type":{"type":"string","enum":["Filesystem","Snapshot",' .
                          "type":"object",
                          "properties":{
                                  "type":{"type":"string","enum":["Filesystem","Snapshot",' .
-                                       '"Volume","Clone","Pool"]},
+                                       '"Volume","Pool"]},
                                  "name":{"type":"string"},
                                  "property":{"type":"string"}
                          }
                                  "name":{"type":"string"},
                                  "property":{"type":"string"}
                          }
@@ -316,7 +315,6 @@ class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
                        $this->updateBgProcStatus($bgStatusFilename, "outputfilename", $bgOutputFilename);
                        switch ($params['type']) {
                        case "Filesystem":
                        $this->updateBgProcStatus($bgStatusFilename, "outputfilename", $bgOutputFilename);
                        switch ($params['type']) {
                        case "Filesystem":
-                       case "Clone":
                                $tmp = new OMVModuleZFSDataset($params['name']);
                                break;
                        case "Snapshot":
                                $tmp = new OMVModuleZFSDataset($params['name']);
                                break;
                        case "Snapshot":
@@ -368,7 +366,7 @@ class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
                          "type":"object",
                          "properties":{
                                  "name":{"type":"string"},
                          "type":"object",
                          "properties":{
                                  "name":{"type":"string"},
-                                 "type":{"type":"string","enum":["Filesystem","Clone"]},
+                                 "type":{"type":"string","enum":["Filesystem"]},
                                  "sharename":{'.$GLOBALS['OMV_JSONSCHEMA_SHARENAME'].'},
                                  "comment":{"type":"string"},
                                  "mode":{"type":"string","enum":["700","750","755",'.
                                  "sharename":{'.$GLOBALS['OMV_JSONSCHEMA_SHARENAME'].'},
                                  "comment":{"type":"string"},
                                  "mode":{"type":"string","enum":["700","750","755",'.
@@ -391,9 +389,6 @@ class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
                case "Filesystem":
                        $tmp = new OMVModuleZFSDataset($params['name']);
                        break;
                case "Filesystem":
                        $tmp = new OMVModuleZFSDataset($params['name']);
                        break;
-               case "Clone":
-                       $tmp = new OMVModuleZFSDataset($params['name']);
-                       break;
                default:
                        throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
                        break;
                default:
                        throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
                        break;
index 58bdc7bc5ff94089dbf0dd666835abf760a2aedd..c7049dc752a570042ac2cb799e15db8ea689f2c3 100644 (file)
@@ -226,6 +226,7 @@ class OMVModuleZFSUtil {
                                                'expanded'=>$expanded,
                                                'path'=>$path);
                                        $pool = new OMVModuleZFSZpool($path);
                                                'expanded'=>$expanded,
                                                'path'=>$path);
                                        $pool = new OMVModuleZFSZpool($path);
+                                       $tmp['origin'] = "n/a";
                                        $tmp['size'] = $pool->getSize();
                                        $tmp['used'] = $pool->getAttribute("allocated");
                                        $tmp['available'] = $pool->getAttribute("free");
                                        $tmp['size'] = $pool->getSize();
                                        $tmp['used'] = $pool->getAttribute("allocated");
                                        $tmp['available'] = $pool->getAttribute("free");
@@ -243,12 +244,12 @@ class OMVModuleZFSUtil {
                                        $ds =  new OMVModuleZFSDataset($path);
                                        if ($ds->isClone()) {
                                                //This is a cloned Filesystem
                                        $ds =  new OMVModuleZFSDataset($path);
                                        if ($ds->isClone()) {
                                                //This is a cloned Filesystem
-                                               $tmp['type'] = "Clone";
                                                $tmp['origin'] = $ds->getOrigin();
                                        } else {
                                                //This is a standard Filesystem.
                                                $tmp['origin'] = $ds->getOrigin();
                                        } else {
                                                //This is a standard Filesystem.
-                                               $tmp['type']= ucfirst($type);
+                                               $tmp['origin'] = "n/a";
                                        }
                                        }
+                                       $tmp['type']= ucfirst($type);
                                        $tmp['size'] = "n/a";
                                        $used = $ds->getProperty("used");
                                        $tmp['used'] = $used['value'];
                                        $tmp['size'] = "n/a";
                                        $used = $ds->getProperty("used");
                                        $tmp['used'] = $used['value'];
@@ -268,7 +269,15 @@ class OMVModuleZFSUtil {
                                        'icon'=>"images/save.png",
                                        'path'=>$path,
                                        'expanded'=>$expanded);
                                        'icon'=>"images/save.png",
                                        'path'=>$path,
                                        'expanded'=>$expanded);
-                               $vol = new OMVModuleZFSZvol();
+                               $vol = new OMVModuleZFSZvol($path);
+                               if ($vol->isClone()) {
+                                       //This is a cloned Volume
+                                       $tmp['origin'] = $vol->getOrigin();
+                               } else {
+                                       //This is a standard Volume
+                                       $tmp['origin'] = "n/a";
+                               }
+                               $tmp['type']= ucfirst($type);
                                $tmp['size'] = $vol->getSize();
                                $tmp['used'] = "n/a";
                                $tmp['available'] = "n/a";
                                $tmp['size'] = $vol->getSize();
                                $tmp['used'] = "n/a";
                                $tmp['available'] = "n/a";
@@ -287,6 +296,7 @@ class OMVModuleZFSUtil {
                                        'icon'=>'images/zfs_snap.png',
                                        'path'=>$path,
                                        'expanded'=>$expanded);
                                        'icon'=>'images/zfs_snap.png',
                                        'path'=>$path,
                                        'expanded'=>$expanded);
+                               $tmp['origin'] = "n/a";
                                $tmp['size'] = "n/a";
                                $tmp['used'] = "n/a";
                                $tmp['available'] = "n/a";
                                $tmp['size'] = "n/a";
                                $tmp['used'] = "n/a";
                                $tmp['available'] = "n/a";
index e35af5ab0e8c874b424519696b550e98d0b43c6c..8b65ac0e9ea21af76b62994a067ffdd91c101bac 100644 (file)
@@ -265,6 +265,49 @@ class OMVModuleZFSZvol {
                $this->snapshots[$snap_name]->destroy();
                unset($this->snapshots[$snap_name]);
        }
                $this->snapshots[$snap_name]->destroy();
                unset($this->snapshots[$snap_name]);
        }
+       
+       /**
+       * Check if the Volume is a clone or not.
+       *
+       * @return bool
+       * @access public
+       */
+       public function isClone() {
+               $origin = $this->getProperty("origin");
+               if (strlen($origin["value"]) > 0) {
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+       * Get the origin of the Volume if it's a clone.
+       *
+       * @return string The name of the origin if it exists. Otherwise an empty string.
+       * @access public
+       */
+       public function getOrigin() {
+               if ($this->isClone()) {
+                       $origin = $this->getProperty("origin");
+                       return $origin['value'];
+               } else {
+                       return "";
+               }
+       }
+
+       /**
+       * Promotes the Volume if it's a clone.
+       *
+       * @return void
+       * @access public
+       */
+       public function promote() {
+               if ($this->isClone()) {
+                       $cmd = "zfs promote " . $this->name . " 2>&1";
+                       $this->exec($cmd,$out,$res);
+               }
+       }
 
        /**
         * Helper function to execute a command and throw an exception on error
 
        /**
         * Helper function to execute a command and throw an exception on error
This page took 0.057253 seconds and 5 git commands to generate.