]>
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("VdevType.php");
9 require_once("Utils.php");
10 require_once("Exception.php");
13 * Class containing information about the pool
15 * @author Michael Rasmussen
17 * @copyright Michael Rasmussen <mir@datanom.net>
19 class OMVModuleZFSZpool
extends OMVModuleAbstract
20 implements OMVINotifyListener
{
35 * @association OMVModuleZFSVdev to vdevs
44 * @association OMVModuleZFSVdev to spare
53 * @association OMVModuleZFSVdev to log
62 * @association OMVModuleZFSVdev to cache
77 * @var string $mountPoint
85 * @var array $features
92 * Array of OMVModuleZFSSnapshot.
94 * @var array $snapshot
96 * @association OMVModuleZFSSnapshot to snapshot
101 * Array of OMVModuleZFSDataset
103 * @var Dataset $dataset
105 * @association OMVModuleZFSDataset to dataset
110 * Array of OMVModuleZFSZvol
114 * @association OMVModuleZFSZvol to zvol
122 * @param $vdev OMVModuleZFSVdev or array(OMVModuleZFSVdev)
123 * @throws OMVModuleZFSException
126 public function __construct($vdev) {
129 if (is_array($vdev)) {
130 $cmd = $this->getCommandString($vdev);
131 $name = $vdev[0]->getPool();
132 $type = $vdev[0]->getType();
133 } else if ($vdev instanceof OMVModuleZFSVdev
) {
134 $cmd = $this->getCommandString(array($vdev));
135 $name = $vdev->getPool();
136 $type = $vdev->getType();
138 // Assume we make an instance of an existing pool
139 $create_pool = false;
142 $this->vdevs
= array();
146 $this->features
= array();
148 $cmd = "zpool create $name $cmd 2>&1";
150 OMVUtil
::exec($cmd, $output, $result);
152 throw new OMVModuleZFSException(implode("\n", $output));
157 $this->vdevs
= $vdev;
159 array_push ($this->vdevs
, $vdev);
160 $this->size
= $this->getAttribute("size");
161 $this->mountPoint
= $this->getAttribute("mountpoint");
164 $this->assemblePool($vdev);
174 public function getName() {
184 public function getVdevs() {
191 * @param array $vdev array of OMVModuleZFSVdev
193 * @throws OMVModuleZFSException
196 public function addVdev(array $vdevs) {
197 $cmd = "zpool add " . $this->name
. " " . $this->getCommandString($vdevs);
198 OMVUtil
::exec($cmd, $output, $result);
200 throw new OMVModuleZFSException($output);
202 $this->vdevs
= array_merge($this->vdevs
, $vdevs);
203 $this->size
= $this->getAttribute("size");
209 * @param OMVModuleZFSVdev $vdev
211 * @throws OMVModuleZFSException
214 public function removeVdev(OMVModuleZFSVdev
$vdev) {
215 throw new OMVModuleZFSException("Cannot remove vdevs from a pool");
221 * @param OMVModuleZFSVdev $cache
223 * @throws OMVModuleZFSException
226 public function addCache(OMVModuleZFSVdev
$cache) {
227 if ($cache->getType() != OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
)
228 throw new OMVModuleZFSException("Only a plain Vdev can be added as cache");
230 $cmd = "zpool add " . $this->name
. " cache " . $this->getCommandString($vdevs);
231 OMVUtil
::exec($cmd, $output, $result);
233 throw new OMVModuleZFSException($output);
235 $disks = $cache->getDisks();
236 foreach ($disks as $disk) {
237 array_push ($this->cache
, $disk);
244 * @param array $disks
246 * @throws OMVModuleZFSException
249 public function removeCache(array $disks = null) {
251 $disks = $this->cache
;
253 foreach ($disks as $disk)
254 $dist_str .= "$disk ";
256 $cmd = "zpool remove " . $this->name
. " $dist_str";
257 OMVUtil
::exec($cmd, $output, $result);
259 throw new OMVModuleZFSException($output);
261 foreach ($disks as $disk)
262 $this->cache
= $this->removeDisk($this->cache
, $disk);
272 public function getCache() {
279 * @param OMVModuleZFSVdev $log
281 * @throws OMVModuleZFSException
284 public function addLog(OMVModuleZFSVdev
$log) {
285 if ($log->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN ||
286 $log->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
) {
287 $cmd = "zpool add " . $this->name
. " log " . $this->getCommandString($vdevs);
288 OMVUtil
::exec($cmd, $output, $result);
290 throw new OMVModuleZFSException($output);
294 throw new OMVModuleZFSException("Only a plain Vdev or mirror Vdev can be added as log");
301 * @throws OMVModuleZFSException
304 public function removeLog() {
305 foreach ($this->log
as $vdev) {
306 if ($vdev->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
) {
307 $cmd = "zpool remove " . $this->name
. " mirror-$i";
309 $disks = $vdev->getDisks();
310 foreach ($disks as $disk)
311 $dist_str .= "$disk ";
312 $cmd = "zpool remove " . $this->name
. " $disk_str";
314 OMVUtil
::exec($cmd, $output, $result);
316 throw new OMVModuleZFSException($output);
318 $this->log
= array();
328 public function getLog() {
335 * @param OMVModuleZFSVdev $spares
337 * @throws OMVModuleZFSException
340 public function addSpare(OMVModuleZFSVdev
$spares) {
341 if ($spares->getType() != OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
)
342 throw new OMVModuleZFSException("Only a plain Vdev can be added as spares");
344 $cmd = "zpool add " . $this->name
. " spare " . $this->getCommandString($vdevs);
345 OMVUtil
::exec($cmd, $output, $result);
347 throw new OMVModuleZFSException($output);
349 $disks = $spares->getDisks();
350 foreach ($disks as $disk) {
351 array_push ($this->spare
, $disk);
358 * @param array $disks
360 * @throws OMVModuleZFSException
363 public function removeSpare(array $disks = null) {
365 $disks = $this->spare
;
367 foreach ($disks as $disk)
368 $dist_str .= "$disk ";
370 $cmd = "zpool remove " . $this->name
. " $dist_str";
371 OMVUtil
::exec($cmd, $output, $result);
373 throw new OMVModuleZFSException($output);
375 foreach ($disks as $disk)
376 $this->spare
= $this->removeDisk($this->spare
, $disk);
386 public function getSpares() {
396 public function getSize() {
406 public function getMountPoint() {
407 return $this->mountPoint
;
413 * @param array $features
415 * @throws OMVModuleZFSException
418 public function setFeatures(array $features) {
419 foreach ($features as $feature => $value) {
420 $cmd = "zpool set $feature=$value " . $this->name
;
421 OMVUtil
::exec($cmd, $output, $result);
423 throw new OMVModuleZFSException($output);
425 $this->features
= $this->getAllAttributes();
429 * We only return array of features for which the user can
432 * @return array of features
435 public function getFeatures($internal = true) {
438 'recordsize', /* default 131072. 512 <= n^2 <= 131072*/
439 'checksum', /* on | off */
440 'compression', /* off | lzjb | gzip | zle | lz4 */
441 'atime', /* on | off */
442 'aclmode', /* discard | groupmask | passthrough | restricted */
443 'aclinherit', /* discard | noallow | restricted | passthrough | passthrough-x */
444 'casesensitivity', /* sensitive | insensitive | mixed */
445 'primarycache', /* all | none | metadata */
446 'secondarycache', /* all | none | metadata */
447 'logbias', /* latency | throughput */
448 'dedup', /* on | off */
449 'sync' /* standard | always | disabled */
451 if (count($this->features
) < 1)
452 $this->features
= $this->getAllAttributes();
454 foreach ($this->features
as $attr => $val) {
455 if (in_array($attr, $featureSet))
456 $attrs[$attr] = $val['value'];
459 foreach ($this->features
as $attr => $val) {
460 if (in_array($attr, $featureSet))
461 $attrs[$attr] = $val;
472 * @throws OMVModuleZFSException
475 public function export() {
476 $cmd = "zpool export " . $this->name
;
477 OMVUtil
::exec($cmd, $output, $result);
479 throw new OMVModuleZFSException($output);
485 * @param string $name
487 * @throws OMVModuleZFSException
490 public function import($name = null) {
492 $cmd = "zpool import $name";
494 $cmd = "zpool import";
495 OMVUtil
::exec($cmd, $output, $result);
497 throw new OMVModuleZFSException($output);
504 * @throws OMVModuleZFSException
507 public function scrub() {
508 $cmd = "zpool scrub " . $this->name
;
509 OMVUtil
::exec($cmd, $output, $result);
511 throw new OMVModuleZFSException($output);
518 * @throws OMVModuleZFSException
521 public function status() {
522 $cmd = "zpool status " . $this->name
;
523 OMVUtil
::exec($cmd, $output, $result);
525 throw new OMVModuleZFSException($output);
528 public function bindListeners(OMVNotifyDispatcher
$dispatcher) {
529 // Update service if configuration has been modified
530 $dispatcher->addListener(
532 "org.openmediavault.services.nfs",
533 array($this, "onUpdateNFSService"));
534 $dispatcher->addListener(
536 "org.openmediavault.services.nfs.shares.share",
537 array($this, "onCreateNFSShare"));
538 $dispatcher->addListener(
540 "org.openmediavault.services.nfs.shares.share",
541 array($this, "onDeleteNFSShare"));
542 $dispatcher->addListener(
544 "org.openmediavault.services.nfs.shares.share",
545 array($this, "onUpdateNFSShare"));
550 * org.openmediavault.services.nfs
552 * @param string event
555 public function onUpdateNFSService($args) {
556 $this->debug(sprintf("onUpdateNFSService args=%s", var_export($args, true)));
561 * org.openmediavault.services.nfs.shares.share
563 * @param string event
566 public function onCreateNFSShare($args) {
567 $this->debug(sprintf("onCreateNFSShare args=%s", var_export($args, true)));
572 * org.openmediavault.services.nfs.shares.share
574 * @param string event
577 public function onDeleteNFSShare($args) {
578 $this->debug(sprintf("onDeleteNFSShare args=%s", var_export($args, true)));
583 * org.openmediavault.services.nfs.shares.share
585 * @param string event
588 public function onUpdateNFSShare($args) {
589 $this->debug(sprintf("onUpdateNFSShare args=%s", var_export($args, true)));
593 * Get a single property value associated with the Dataset
595 * @param string $property Name of the property to fetch
596 * @return array The returned array with the property. The property is an associative array with
597 * two elements, <value> and <source>.
600 public function getProperty($property) {
601 $attrs = $this->getFeatures(false);
602 return $attrs["$property"];
606 * Get an associative array of all properties associated with the Snapshot
608 * @return array $properties Each entry is an associative array with two elements
609 * <value> and <source>
612 public function getProperties() {
613 $attrs = $this->getFeatures(false);
618 * Sets a number of Dataset properties. If a property is already set it will be updated with the new value.
620 * @param array $properties An associative array with properties to set
624 public function setProperties($properties) {
625 foreach ($properties as $newpropertyk => $newpropertyv) {
626 $cmd = "zfs set " . $newpropertyk . "=" . $newpropertyv . " " . $this->name
. " 2>&1";
627 OMVModuleZFSUtil
::exec($cmd,$out,$res);
628 $attr = $this->getAttribute($newpropertyk);
629 $this->features
[$newpropertyk] = $attr;
634 * Destroy the Dataset.
639 public function destroy() {
640 $cmd = "zpool destroy " . $this->name
. " 2>&1";
641 $this->exec($cmd,$out,$res);
645 * Clears a previously set proporty and specifies that it should be
646 * inherited from it's parent.
648 * @param string $property Name of the property to inherit.
652 public function inherit($property) {
653 $cmd = "zfs inherit " . $property . " " . $this->name
. " 2>&1";
654 $this->exec($cmd,$out,$res);
655 $attr = $this->getAttribute($newpropertyk);
656 $this->features
[$newpropertyk] = $attr;
660 * Convert array of Vdev to command string
662 * @param array $vdevs
664 * @throws OMVMODULEZFSException
666 private function getCommandString(array $vdevs) {
669 foreach ($vdevs as $vdev) {
670 if (is_object($vdev) == false)
671 throw new OMVMODULEZFSException("Not object of class OMVModuleZFSVdev");
672 if (is_a($vdev, OMVModuleZFSVdev
) == false)
673 throw new OMVMODULEZFSException("Object is not of class OMVModuleZFSVdev");
674 $type = $vdev->getType();
678 case OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
: break;
679 case OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
: $command = "mirror"; break;
680 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
: $command = "raidz1"; break;
681 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
: $command = "raidz2"; break;
682 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
: $command = "raidz3"; break;
684 throw new OMVMODULEZFSException("Unknown Vdev type");
686 $disks = $vdev->getDisks();
688 foreach($disks as $disk) {
689 $diskStr .= " $disk";
692 array_push ($adds, $command . $diskStr);
695 return implode(" ", $adds);
699 * Get an attribute from pool
701 * @param string $attribute
702 * @return string value
704 private function getAttribute($attribute) {
705 $cmd = "zpool list -H -o $attribute {$this->name}";
706 OMVUtil
::exec($cmd, $output, $result);
708 $cmd = "zfs list -H -o $attribute {$this->name}";
709 OMVUtil
::exec($cmd, $output, $result);
718 * Get all attributes from pool
719 * @return array of attributes
720 * @throws OMVModuleZFSException
722 private function getAllAttributes() {
724 $cmd = "zfs get -H all {$this->name}";
727 OMVUtil
::exec($cmd, $output, $result);
728 } catch (OMVModuleZFSException
$e) {}
730 throw new OMVModuleZFSException($output);
731 $output = implode("\n", $output);
732 $res = preg_match_all("/{$this->name}\s+(\w+)\s+([\w\d\.]+)\s+(\w+).*/", $output, $matches, PREG_SET_ORDER
);
733 if ($res == false ||
$res == 0)
734 throw new OMVModuleZFSException("Error return by zpool get all: $output");
735 foreach ($matches as $match) {
736 $attrs[$match[1]] = array('value' => $match[2], 'source' => $match[3]);
743 * Get all Dataset properties from commandline and update object properties attribute
748 private function updateAllProperties() {
749 $this->features
= $this->getAllAttributes();
753 * Remove a disk from array
755 * @param array $array
756 * @param string $disk
759 private function removeDisk(array $array, $disk) {
760 $new_disks = array();
762 foreach ($array as $item) {
763 if (strcmp($item, $disk) != 0)
764 array_push ($new_disks, $item);
771 * Construct existing pool
773 * @param string $name
775 * @throws OMVModuleZFSException
777 private function assemblePool($name) {
778 $cmd = "zpool status -v $name";
779 $types = 'mirror|raidz1|raidz2|raidz3';
786 OMVUtil
::exec($cmd, $output, $result);
788 throw new OMVModuleZFSException($output);
791 foreach($output as $line) {
792 if (! strstr($line, PHP_EOL
))
795 if (preg_match("/^\s*NAME/", $line))
799 if (preg_match("/^\s*$/", $line)) {
801 $this->output($part, $type, $dev);
804 } else if (preg_match("/^\s*($name|logs|cache|spares)/", $line, $match)) {
806 $this->output($part, $type, $dev);
814 if (preg_match("/^\s*($types)/", $line, $match)) {
817 $this->output(null, $type, $dev);
821 } else if (preg_match("/^\s*([\w\d-]+)\s+/", $line, $match)) {
823 $dev .= " $match[1]";
829 if (preg_match("/^\s*([\w\d-]+)\s+/", $line, $match)) {
831 $dev .= " $match[1]";
838 if (preg_match("/^\s*([\w\d-]+)\s+/", $line, $match)) {
840 $dev .= " $match[1]";
846 throw new Exception("$part: Unknown pool part");
851 $this->size
= $this->getAttribute("size");
852 $this->mountPoint
= $this->getAttribute("mountpoint");
856 * Create pool config from parsed input
858 * @param string $part
859 * @param string $type
862 * @throws OMVModuleZFSException
864 private function output($part, $type, $dev) {
865 $disks = split(" ", $dev);
868 if ($type && $type != 'mirror')
869 throw new Exception("$type: Logs can only be mirror or plain");
871 $this->log
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
, $disks);
873 $this->log
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
877 throw new Exception("$type: cache can only be plain");
878 $this->cache
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
882 throw new Exception("$type: spares can only be plain");
883 $this->spare
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
889 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
, $disks));
890 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
;
893 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
, $disks));
894 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
;
897 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
, $disks));
898 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
;
901 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
, $disks));
902 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
;
906 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks));
907 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
;
This page took 0.228311 seconds and 6 git commands to generate.