]>
git.datanom.net - omvzfs.git/blob - src/Zpool.php
2 require_once('openmediavault/object.inc');
3 require_once('openmediavault/module.inc');
4 require_once("Vdev.php");
5 require_once("Snapshot.php");
6 require_once("Dataset.php");
7 require_once("Zvol.php");
8 require_once("Exception.php");
11 * Class containing information about the pool
13 * @author Michael Rasmussen
15 * @copyright Michael Rasmussen <mir@datanom.net>
17 class OMVModuleZFSZpool
extends OMVModuleAbstract
18 implements OMVINotifyListener
{
33 * @association OMVModuleZFSVdev to vdevs
42 * @association OMVModuleZFSVdev to spare
51 * @association OMVModuleZFSVdev to log
60 * @association OMVModuleZFSVdev to cache
75 * @var string $mountPoint
83 * @var array $features
90 * Array of OMVModuleZFSSnapshot.
92 * @var array $snapshot
94 * @association OMVModuleZFSSnapshot to snapshot
99 * Array of OMVModuleZFSDataset
101 * @var Dataset $dataset
103 * @association OMVModuleZFSDataset to dataset
108 * Array of OMVModuleZFSZvol
112 * @association OMVModuleZFSZvol to zvol
120 * @param $vdev OMVModuleZFSVdev or array(OMVModuleZFSVdev)
121 * @throws OMVModuleZFSException
124 public function __construct($vdev) {
127 if (is_array($vdev)) {
128 $cmd = $this->getCommandString($vdev);
129 $name = $vdev[0]->getPool();
130 $type = $vdev[0]->getType();
131 } else if ($vdev instanceof OMVModuleZFSVdev
) {
132 $cmd = $this->getCommandString(array($vdev));
133 $name = $vdev->getPool();
134 $type = $vdev->getType();
136 // Assume we make an instance of an existing pool
137 $create_pool = false;
140 $this->vdevs
= array();
144 $this->features
= array();
146 $cmd = "zpool create $name $cmd";
148 OMVUtil
::exec($cmd, $output, $result);
150 throw new OMVModuleZFSException($output);
155 $this->vdevs
= $vdev;
157 array_push ($this->vdevs
, $vdev);
158 $this->size
= $this->getAttribute("size");
159 $this->mountPoint
= $this->getAttribute("mountpoint");
162 $this->assemblePool($vdev);
172 public function getName() {
182 public function getVdevs() {
189 * @param array $vdev array of OMVModuleZFSVdev
191 * @throws OMVModuleZFSException
194 public function addVdev(array $vdevs) {
195 $cmd = "zpool add " . $this->name
. " " . $this->getCommandString($vdevs);
196 OMVUtil
::exec($cmd, $output, $result);
198 throw new OMVModuleZFSException($output);
200 $this->vdevs
= array_merge($this->vdevs
, $vdevs);
201 $this->size
= $this->getAttribute("size");
207 * @param OMVModuleZFSVdev $vdev
209 * @throws OMVModuleZFSException
212 public function removeVdev(OMVModuleZFSVdev
$vdev) {
213 throw new OMVModuleZFSException("Cannot remove vdevs from a pool");
219 * @param OMVModuleZFSVdev $cache
221 * @throws OMVModuleZFSException
224 public function addCache(OMVModuleZFSVdev
$cache) {
225 if ($cache->getType() != OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
)
226 throw new OMVModuleZFSException("Only a plain Vdev can be added as cache");
228 $cmd = "zpool add " . $this->name
. " cache " . $this->getCommandString($vdevs);
229 OMVUtil
::exec($cmd, $output, $result);
231 throw new OMVModuleZFSException($output);
233 $disks = $cache->getDisks();
234 foreach ($disks as $disk) {
235 array_push ($this->cache
, $disk);
242 * @param array $disks
244 * @throws OMVModuleZFSException
247 public function removeCache(array $disks = null) {
249 $disks = $this->cache
;
251 foreach ($disks as $disk)
252 $dist_str .= "$disk ";
254 $cmd = "zpool remove " . $this->name
. " $dist_str";
255 OMVUtil
::exec($cmd, $output, $result);
257 throw new OMVModuleZFSException($output);
259 foreach ($disks as $disk)
260 $this->cache
= $this->removeDisk($this->cache
, $disk);
270 public function getCache() {
277 * @param OMVModuleZFSVdev $log
279 * @throws OMVModuleZFSException
282 public function addLog(OMVModuleZFSVdev
$log) {
283 if ($log->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN ||
284 $log->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
) {
285 $cmd = "zpool add " . $this->name
. " log " . $this->getCommandString($vdevs);
286 OMVUtil
::exec($cmd, $output, $result);
288 throw new OMVModuleZFSException($output);
292 throw new OMVModuleZFSException("Only a plain Vdev or mirror Vdev can be added as log");
299 * @throws OMVModuleZFSException
302 public function removeLog() {
303 foreach ($this->log
as $vdev) {
304 if ($vdev->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
) {
305 $cmd = "zpool remove " . $this->name
. " mirror-$i";
307 $disks = $vdev->getDisks();
308 foreach ($disks as $disk)
309 $dist_str .= "$disk ";
310 $cmd = "zpool remove " . $this->name
. " $disk_str";
312 OMVUtil
::exec($cmd, $output, $result);
314 throw new OMVModuleZFSException($output);
316 $this->log
= array();
326 public function getLog() {
333 * @param OMVModuleZFSVdev $spares
335 * @throws OMVModuleZFSException
338 public function addSpare(OMVModuleZFSVdev
$spares) {
339 if ($spares->getType() != OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
)
340 throw new OMVModuleZFSException("Only a plain Vdev can be added as spares");
342 $cmd = "zpool add " . $this->name
. " spare " . $this->getCommandString($vdevs);
343 OMVUtil
::exec($cmd, $output, $result);
345 throw new OMVModuleZFSException($output);
347 $disks = $spares->getDisks();
348 foreach ($disks as $disk) {
349 array_push ($this->spare
, $disk);
356 * @param array $disks
358 * @throws OMVModuleZFSException
361 public function removeSpare(array $disks = null) {
363 $disks = $this->spare
;
365 foreach ($disks as $disk)
366 $dist_str .= "$disk ";
368 $cmd = "zpool remove " . $this->name
. " $dist_str";
369 OMVUtil
::exec($cmd, $output, $result);
371 throw new OMVModuleZFSException($output);
373 foreach ($disks as $disk)
374 $this->spare
= $this->removeDisk($this->spare
, $disk);
384 public function getSpares() {
394 public function getSize() {
404 public function getMountPoint() {
405 return $this->mountPoint
;
411 * @param array $features
413 * @throws OMVModuleZFSException
416 public function setFeatures(array $features) {
417 foreach ($features as $feature => $value) {
418 $cmd = "zpool set $feature=$value " . $this->name
;
419 OMVUtil
::exec($cmd, $output, $result);
421 throw new OMVModuleZFSException($output);
423 $this->features
= $this->getAllAttributes();
427 * We only return array of features for which the user can
430 * @return array of features
433 public function getFeatures() {
436 'recordsize', /* default 131072. 512 <= n^2 <= 131072*/
437 'checksum', /* on | off */
438 'compression', /* off | lzjb | gzip | zle | lz4 */
439 'atime', /* on | off */
440 'aclmode', /* discard | groupmask | passthrough | restricted */
441 'aclinherit', /* discard | noallow | restricted | passthrough | passthrough-x */
442 'casesensitivity', /* sensitive | insensitive | mixed */
443 'primarycache', /* all | none | metadata */
444 'secondarycache', /* all | none | metadata */
445 'logbias', /* latency | throughput */
446 'dedup', /* on | off */
447 'sync' /* standard | always | disabled */
449 if (count($this->features
) < 1)
450 $this->features
= $this->getAllAttributes();
451 foreach ($this->features
as $attr => $val) {
452 if (in_array($attr, $featureSet))
453 $attrs[$attr] = $val;
463 * @throws OMVModuleZFSException
466 public function export() {
467 $cmd = "zpool export " . $this->name
;
468 OMVUtil
::exec($cmd, $output, $result);
470 throw new OMVModuleZFSException($output);
476 * @param string $name
478 * @throws OMVModuleZFSException
481 public function import($name = null) {
483 $cmd = "zpool import $name";
485 $cmd = "zpool import";
486 OMVUtil
::exec($cmd, $output, $result);
488 throw new OMVModuleZFSException($output);
495 * @throws OMVModuleZFSException
498 public function scrub() {
499 $cmd = "zpool scrub " . $this->name
;
500 OMVUtil
::exec($cmd, $output, $result);
502 throw new OMVModuleZFSException($output);
509 * @throws OMVModuleZFSException
512 public function status() {
513 $cmd = "zpool status " . $this->name
;
514 OMVUtil
::exec($cmd, $output, $result);
516 throw new OMVModuleZFSException($output);
519 public function bindListeners(OMVNotifyDispatcher
$dispatcher) {
520 // Update service if configuration has been modified
521 $dispatcher->addListener(
523 "org.openmediavault.services.nfs",
524 array($this, "onUpdateNFSService"));
525 $dispatcher->addListener(
527 "org.openmediavault.services.nfs.shares.share",
528 array($this, "onCreateNFSShare"));
529 $dispatcher->addListener(
531 "org.openmediavault.services.nfs.shares.share",
532 array($this, "onDeleteNFSShare"));
533 $dispatcher->addListener(
535 "org.openmediavault.services.nfs.shares.share",
536 array($this, "onUpdateNFSShare"));
541 * org.openmediavault.services.nfs
543 * @param string event
546 public function onUpdateNFSService($args) {
547 $this->debug(sprintf("onUpdateNFSService args=%s", var_export($args, true)));
552 * org.openmediavault.services.nfs.shares.share
554 * @param string event
557 public function onCreateNFSShare($args) {
558 $this->debug(sprintf("onCreateNFSShare args=%s", var_export($args, true)));
563 * org.openmediavault.services.nfs.shares.share
565 * @param string event
568 public function onDeleteNFSShare($args) {
569 $this->debug(sprintf("onDeleteNFSShare args=%s", var_export($args, true)));
574 * org.openmediavault.services.nfs.shares.share
576 * @param string event
579 public function onUpdateNFSShare($args) {
580 $this->debug(sprintf("onUpdateNFSShare args=%s", var_export($args, true)));
584 * Convert array of Vdev to command string
586 * @param array $vdevs
588 * @throws OMVMODULEZFSException
590 private function getCommandString(array $vdevs) {
593 foreach ($vdevs as $vdev) {
594 if (is_object($vdev) == false)
595 throw new OMVMODULEZFSException("Not object of class OMVModuleZFSVdev");
596 if (is_a($vdev, OMVModuleZFSVdev
) == false)
597 throw new OMVMODULEZFSException("Object is not of class OMVModuleZFSVdev");
598 $type = $vdev->getType();
602 case OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
: break;
603 case OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
: $command = "mirror"; break;
604 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
: $command = "raidz1"; break;
605 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
: $command = "raidz2"; break;
606 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
: $command = "raidz3"; break;
608 throw new OMVMODULEZFSException("Unknown Vdev type");
610 $disks = $vdev->getDisks();
612 foreach($disks as $disk) {
613 $diskStr .= " $disk";
616 array_push ($adds, $command . $diskStr);
619 return join(" ", $adds);
623 * Get an attribute from pool
625 * @param string $attribute
626 * @return string value
628 private function getAttribute($attribute) {
629 $cmd = "zpool list -H -o $attribute {$this->name}";
630 OMVUtil
::exec($cmd, $output, $result);
632 $cmd = "zfs list -H -o $attribute {$this->name}";
633 OMVUtil
::exec($cmd, $output, $result);
642 * Get all attributes from pool
643 * @return array of attributes
644 * @throws OMVModuleZFSException
646 private function getAllAttributes() {
648 $cmd = "zfs get -H all {$this->name}";
650 OMVUtil
::exec($cmd, $output, $result);
652 throw new OMVModuleZFSException($output);
653 $output = implode("\n", $output);
654 $res = preg_match_all("/{$this->name}\s+(\w+)\s+([\w\d\.]+).*/", $output, $matches, PREG_SET_ORDER
);
655 if ($res == false ||
$res == 0)
656 throw new OMVModuleZFSException("Error return by zpool get all: $output");
657 foreach ($matches as $match) {
658 $attrs[$match[1]] = $match[2];
665 * Remove a disk from array
667 * @param array $array
668 * @param string $disk
671 private function removeDisk(array $array, $disk) {
672 $new_disks = array();
674 foreach ($array as $item) {
675 if (strcmp($item, $disk) != 0)
676 array_push ($new_disks, $item);
683 * Construct existing pool
685 * @param string $name
687 * @throws OMVModuleZFSException
689 private function assemblePool($name) {
690 $cmd = "zpool status -v $name";
691 $types = 'mirror|raidz1|raidz2|raidz3';
698 OMVUtil
::exec($cmd, $output, $result);
700 throw new OMVModuleZFSException($output);
703 foreach($output as $line) {
704 if (! strstr($line, PHP_EOL
))
707 if (preg_match("/^\s*NAME/", $line))
711 if (preg_match("/^\s*$/", $line)) {
713 $this->output($part, $type, $dev);
716 } else if (preg_match("/^\s*($name|logs|cache|spares)/", $line, $match)) {
718 $this->output($part, $type, $dev);
726 if (preg_match("/^\s*($types)/", $line, $match)) {
729 $this->output(null, $type, $dev);
733 } else if (preg_match("/^\s*([\w\d-]+)\s+/", $line, $match)) {
735 $dev .= " $match[1]";
741 if (preg_match("/^\s*([\w\d-]+)\s+/", $line, $match)) {
743 $dev .= " $match[1]";
750 if (preg_match("/^\s*([\w\d-]+)\s+/", $line, $match)) {
752 $dev .= " $match[1]";
758 throw new Exception("$part: Unknown pool part");
763 $this->size
= $this->getAttribute("size");
764 $this->mountPoint
= $this->getAttribute("mountpoint");
768 * Create pool config from parsed input
770 * @param string $part
771 * @param string $type
774 * @throws OMVModuleZFSException
776 private function output($part, $type, $dev) {
777 $disks = split(" ", $dev);
780 if ($type && $type != 'mirror')
781 throw new Exception("$type: Logs can only be mirror or plain");
783 $this->log
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
, $disks);
785 $this->log
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
789 throw new Exception("$type: cache can only be plain");
790 $this->cache
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
794 throw new Exception("$type: spares can only be plain");
795 $this->spare
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
801 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
, $disks));
802 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
;
805 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
, $disks));
806 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
;
809 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
, $disks));
810 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
;
813 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
, $disks));
814 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
;
818 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks));
819 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
;
This page took 0.220953 seconds and 6 git commands to generate.