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",
- store: [
- [ "filesystem", "Filesystem" ],
- [ "snapshot", "Snapshot" ],
- [ "volume", "Volume" ]
- ],
+ store: store,
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");
+ var cloneField = this.findField("clonename");
+ var nameField = this.findField("name");
switch(value) {
case "volume":
sizeField.show();
- sizeField.allowBlank = false;
+ sizeField.allowBlank = false;
+ cloneField.hide();
+ nameField.show();
break;
+ case "clone":
+ sizeField.hide();
+ sizeField.allowBlank = true;
+ cloneField.show();
+ nameField.hide();
default:
sizeField.hide();
- sizeField.allowBlank = true;
+ sizeField.allowBlank = true;
+ cloneField.hide();
+ nameField.show();
break;
}
sizeField.validate();
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",
+ id: "name",
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",
+ id: "size",
hidden: true,
fieldLabel: _("Size"),
allowBlank: true,
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',
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'];
+ } else {
+ return 'Clone';
}
}
},{
Ext.create("OMV.module.admin.storage.zfs.AddObject", {
title: _("Add Object"),
path: record.get("path"),
+ parenttype: record.get("type"),
listeners: {
scope: me,
submit: function() {
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) {
- if("Snapshot" == record.get("type")) {
+ if("Clone" == record.get("type")) {
tbarBtnDisabled["addobj"] = true;
tbarBtnHidden["addobj"] = true;
return false;
"type":"object",
"properties":{
"type":{"type":"string","enum":["filesystem","snapshot",' .
- '"volume"]},
+ '"volume","clone"]},
"path":{"type":"string"},
"name":{"type":"string"},
- "size":{"type":"string"}
+ "size":{"type":"string"},
+ "clonename":{"type":"string"}
}
}');
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);
"type":"object",
"properties":{
"type":{"type":"string","enum":["Filesystem","Snapshot",' .
- '"Volume","Clone","Pool"]},
+ '"Volume","Pool"]},
"name":{"type":"string"}
}
}');
$tmp = new OMVModuleZFSDataset($name);
$tmp->destroy();
break;
- case "Clone":
- $tmp = new OMVModuleZFSDataset($name);
- $tmp->destroy();
- break;
case "Snapshot":
$tmp = new OMVModuleZFSSnapshot($name);
$tmp->destroy();
$name = $params['name'];
switch ($params['type']) {
case "Filesystem":
- case "Clone":
$tmp = new OMVModuleZFSDataset($name);
break;
case "Snapshot":
"type":"object",
"properties":{
"type":{"type":"string","enum":["Filesystem","Snapshot",' .
- '"Volume","Clone","Pool"]},
+ '"Volume","Pool"]},
"name":{"type":"string"},
"properties":{"type":"array","items":{
"type":"object",
global $xmlConfig;
switch ($params['type']) {
case "Filesystem":
- case "Clone":
$tmp = new OMVModuleZFSDataset($params['name']);
break;
case "Snapshot":
"type":"object",
"properties":{
"type":{"type":"string","enum":["Filesystem","Snapshot",' .
- '"Volume","Clone","Pool"]},
+ '"Volume","Pool"]},
"name":{"type":"string"},
"property":{"type":"string"}
}
$this->updateBgProcStatus($bgStatusFilename, "outputfilename", $bgOutputFilename);
switch ($params['type']) {
case "Filesystem":
- case "Clone":
$tmp = new OMVModuleZFSDataset($params['name']);
break;
case "Snapshot":
"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",'.
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;
'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");
$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['type']= ucfirst($type);
+ $tmp['origin'] = "n/a";
}
+ $tmp['type']= ucfirst($type);
$tmp['size'] = "n/a";
$used = $ds->getProperty("used");
$tmp['used'] = $used['value'];
'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";
'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";
$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