}
});
+Ext.define("OMV.module.admin.storage.zfs.ExpandPool", {
+ extend: "OMV.workspace.window.Form",
+ uses: [
+ "OMV.data.Store",
+ "OMV.data.Model",
+ "OMV.data.proxy.Rpc",
+ "OMV.data.reader.RpcArray"
+ ],
+
+ rpcService: "ZFS",
+ rpcSetMethod: "expandPool",
+ width: 550,
+ height: 350,
+ autoLoadData: true,
+
+ getFormItems: function() {
+ var me = this;
+ return [{
+ xtype: "textfield",
+ name: "name",
+ fieldLabel: _("Name"),
+ allowBlank: false,
+ readOnly: true,
+ value: me.name
+ },{
+ xtype: "textfield",
+ name: "pool_type",
+ fieldLabel: _("Pool type"),
+ allowBlank: false,
+ readOnly: true,
+ value: me.pool_type
+ },{
+ xtype: "checkboxgridfield",
+ name: "devices",
+ fieldLabel: _("Devices"),
+ valueField: "devicefile",
+ listeners: {
+ scope: me,
+ change: function(e, eOpts) {
+ var deviceField = this.findField("devices");
+ if (me.pool_type == "Basic") {
+ deviceField.minSelections = 1;
+ } else {
+ deviceField.minSelections = me.nr_disks;
+ deviceField.maxSelections = me.nr_disks;
+ }
+ }
+ },
+ useStringValue: true,
+ height: 130,
+ store: Ext.create("OMV.data.Store", {
+ autoLoad: true,
+ model: OMV.data.Model.createImplicit({
+ idProperty: "devicefile",
+ fields: [
+ { name: "devicefile", type: "string" },
+ { name: "size", type: "string" },
+ { name: "vendor", type: "string" },
+ { name: "serialnumber", type: "string" }
+ ]
+ }),
+ proxy: {
+ type: "rpc",
+ appendSortParams: false,
+ rpcData: {
+ service: "RaidMgmt",
+ method: "getCandidates"
+ }
+ },
+ sorters: [{
+ direction: "ASC",
+ property: "devicefile"
+ }]
+ }),
+ gridConfig: {
+ stateful: true,
+ stateId: "04942d40-4ee3-11e4-916c-0800200c9a66",
+ columns: [{
+ text: _("Device"),
+ sortable: true,
+ dataIndex: "devicefile",
+ stateId: "devicefile",
+ flex: 1
+ },{
+ xtype: "binaryunitcolumn",
+ text: _("Capacity"),
+ sortable: true,
+ dataIndex: "size",
+ stateId: "size",
+ width: 50,
+ flex: 1
+ },{
+ text: _("Vendor"),
+ sortable: true,
+ dataIndex: "vendor",
+ stateId: "vendor",
+ flex: 1
+ },{
+ text: _("Serial Number"),
+ sortable: true,
+ dataIndex: "serialnumber",
+ stateId: "serialnumber",
+ flex: 1
+ }]
+ }
+ }];
+ }
+});
Ext.define("OMV.module.admin.storage.zfs.EditProperties", {
dataIndex: 'type',
sortable: true,
flex: 1,
- stateId: 'type'
+ stateId: 'type',
+ renderer: function(value, p, r){
+ if (r.data['type'] == "Pool") {
+ return r.data['type'] + ' (' + r.data['pool_type'] + ')';
+ } else {
+ return r.data['type'];
+ }
+ }
},{
text: _("Size"),
dataIndex: 'size',
{ name: "id", type: "string" },
{ name: "path", type: "string" },
{ name: "origin", type: "string", defaultValue: "none" },
- { name: "shared", type: "string", defaultValue: "false" }
+ { name: "shared", type: "string", defaultValue: "false" },
+ { name: "pool_type", type: "string"},
+ { name: "nr_disks", type: "string"}
]
}),
proxy: {
type: record.get("type")
}).show();
},
+
+ onExpandPoolButton: function() {
+ var me = this;
+ var sm = me.getSelectionModel();
+ var records = sm.getSelection();
+ var record = records[0];
+ Ext.create("OMV.module.admin.storage.zfs.ExpandPool", {
+ title: _("Expand Pool"),
+ name: record.get("path"),
+ type: record.get("type"),
+ pool_type: record.get("pool_type"),
+ nr_disks: record.get("nr_disks"),
+ listeners: {
+ scope: me,
+ submit: function() {
+ this.doReload();
+ }
+ }
+ }).show();
+ },
doDeletion: function(record) {
var me = this;
hideDownButton: true,
hideApplyButton: true,
hideRefreshButton: true,
+ hideExpandPoolButton: true,
addButtonText: _("Add Pool"),
addObjButtonText: _("Add Object"),
+ expandPoolButtonText: _("Expand"),
editButtonText: _("Edit"),
deleteButtonText: _("Delete"),
upButtonText: _("Up"),
handler: Ext.Function.bind(me.onAddObjButton, me, [ me ]),
scope: me,
disabled: true
+ },{
+ id: me.getId() + "-expand",
+ xtype: "button",
+ text: me.expandPoolButtonText,
+ icon: "images/zfs_expand.png",
+ iconCls: Ext.baseCSSPrefix + "btn-icon-16x16",
+ hidden: me.hideExpandPoolButton,
+ handler: Ext.Function.bind(me.onExpandPoolButton, me, [ me ]),
+ scope: me,
+ disabled: true
},{
id: me.getId() + "-delete",
xtype: "button",
var me = this;
if(me.hideTopToolbar)
return;
- var tbarBtnName = [ "addobj", "edit", "delete", "up", "down" ];
+ var tbarBtnName = [ "addobj", "edit", "delete", "up", "down", "expand" ];
var tbarBtnDisabled = {
"addobj": false,
"edit": false,
"delete": false,
+ "expand": false,
"up": true,
- "down": true
+ "down": true,
};
var tbarBtnHidden = {
"addobj": true,
"edit": true,
"delete": true,
+ "expand": true,
"up": true,
"down": true
};
tbarBtnDisabled["delete"] = true;
tbarBtnDisabled["up"] = true;
tbarBtnDisabled["down"] = true;
+ tbarBtnDisabled["expand"] = true;
tbarBtnHidden["addobj"] = true;
tbarBtnHidden["edit"] = true;
tbarBtnHidden["delete"] = true;
+ tbarBtnHidden["expand"] = true;
} else if(records.length == 1) {
tbarBtnDisabled["addobj"] = false;
tbarBtnDisabled["edit"] = false;
tbarBtnDisabled["delete"] = false;
tbarBtnDisabled["up"] = false;
tbarBtnDisabled["down"] = false;
+ tbarBtnDisabled["expand"] = false;
tbarBtnHidden["addobj"] = false;
tbarBtnHidden["edit"] = false;
tbarBtnHidden["delete"] = false;
+ tbarBtnHidden["expand"] = false;
} else {
tbarBtnDisabled["addobj"] = true;
tbarBtnDisabled["edit"] = true;
tbarBtnDisabled["delete"] = false;
tbarBtnDisabled["up"] = false;
tbarBtnDisabled["down"] = false;
+ tbarBtnDisabled["expand"] = true;
tbarBtnHidden["addobj"] = true;
tbarBtnHidden["edit"] = true;
tbarBtnHidden["delete"] = false;
+ tbarBtnHidden["expand"] = true;
}
//Disable 'AddObj' button if selected row is a Snapshot
Ext.Array.each(records, function(record) {
return false;
}
});
+
+ //Disable 'ExpandPool' button if selected row is not a Pool
+ Ext.Array.each(records, function(record) {
+ if(!("Pool" == record.get("type"))) {
+ tbarBtnDisabled["expand"] = true;
+ tbarBtnHidden["expand"] = true;
+ return false;
+ }
+ });
// Update the button controls.
Ext.Array.each(tbarBtnName, function(name) {
$this->registermethod("getSharedParams");
$this->registermethod("createShare");
$this->registermethod("getObjectDetails");
+ $this->registermethod("expandPool");
}
public function addPool($params, $context) {
$output .= implode("\n\r", $out);
return array("details" => $output);
}
+
+ public function expandPool($params, $context) {
+ $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
+ // Validate the parameters of the RPC service method.
+ $this->validateMethodParams($params, '{
+ "type":"object",
+ "properties":{
+ "pool_type":{"type":"string","enum":["Basic","Mirror",' .
+ '"Raidz1","Raidz2","Raidz3"]},
+ "name":{"type":"string"},
+ "devices":{"type":"string"}
+ }
+ }');
+ $pool = new OMVModuleZFSZpool($params['name']);
+ switch ($params['pool_type']) {
+ case "Basic":
+ $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSPLAIN;
+ break;
+ case "Mirror":
+ $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSMIRROR;
+ break;
+ case "Raidz1":
+ $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ1;
+ break;
+ case "Raidz2":
+ $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ2;
+ break;
+ case "Raidz3":
+ $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ3;
+ break;
+ default:
+ throw new OMVModuleZFSException("Incorrect pool type specified");
+ break;
+ }
+ //Use /dev/disk/by-path as deafult when creating new pools as suggested in ZoL FAQ.
+ $disks = preg_split("/[,;]/", $params['devices']);
+ if (file_exists("/dev/disk/by-path/")) {
+ $tmp_disks = array();
+ foreach ($disks as $disk) {
+ $tmp_disks[] = OMVModuleZFSUtil::getDiskPath($disk);
+ }
+ $disks = $tmp_disks;
+ }
+ $vdev[] = new OMVModuleZFSVdev($params['name'], $pooltype, $disks);
+ $pool->addVdev($vdev);
+ //Ugly fix to solve the problem of blkid not displaying info on newly created pools
+ $pool->export();
+ $pool->import($pool->getName());
+ }
}
// Register the RPC service.
$tmp['used'] = $pool->getAttribute("allocated");
$tmp['available'] = $pool->getAttribute("free");
$tmp['mountpoint'] = $pool->getMountPoint();
+ $vdevs = $pool->getVdevs();
+ $vdev_type = $vdevs[0]->getType();
+ switch ($vdev_type) {
+ case OMVModuleZFSVdevType::OMVMODULEZFSMIRROR:
+ $pool_type = "Mirror";
+ break;
+ case OMVModuleZFSVdevType::OMVMODULEZFSPLAIN:
+ $pool_type = "Basic";
+ break;
+ case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ1:
+ $pool_type = "Raidz1";
+ break;
+ case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ2:
+ $pool_type = "Raidz2";
+ break;
+ case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ3:
+ $pool_type = "Raidz3";
+ break;
+ }
+ $tmp['pool_type'] = $pool_type;
+ $tmp['nr_disks'] = count($vdevs[0]->getDisks());
array_push($objects,$tmp);
} else {
//This is a Filesystem
$available = $ds->getProperty("available");
$tmp['available'] = $available['value'];
$tmp['mountpoint'] = $ds->getMountPoint();
+ $tmp['pool_type'] = "n/a";
+ $tmp['nr_disks'] = "n/a";
array_push($objects,$tmp);
}
break;
$tmp['used'] = "n/a";
$tmp['available'] = "n/a";
$tmp['mountpoint'] = "n/a";
+ $tmp['pool_type'] = "n/a";
+ $tmp['nr_disks'] = "n/a";
array_push($objects,$tmp);
break;
$tmp['used'] = "n/a";
$tmp['available'] = "n/a";
$tmp['mountpoint'] = "n/a";
+ $tmp['pool_type'] = "n/a";
+ $tmp['nr_disks'] = "n/a";
array_push($objects,$tmp);
break;