]>
git.datanom.net - omvzfs.git/blob - src/Zpool.php
2 require_once("Vdev.php");
3 require_once("Snapshot.php");
4 require_once("Dataset.php");
5 require_once("Zvol.php");
6 require_once("Exception.php");
9 * Class containing information about the pool
11 * @author Michael Rasmussen
13 * @copyright Michael Rasmussen <mir@datanom.net>
15 class OMVModuleZFSZpool
extends OMVModuleAbstract
16 implements OMVINotifyListener
{
31 * @association OMVModuleZFSVdev to vdevs
40 * @association OMVModuleZFSVdev to spare
49 * @association OMVModuleZFSVdev to log
58 * @association OMVModuleZFSVdev to cache
73 * @var string $mountPoint
81 * @var array $features
88 * Array of OMVModuleZFSSnapshot.
90 * @var array $snapshot
92 * @association OMVModuleZFSSnapshot to snapshot
97 * Array of OMVModuleZFSDataset
99 * @var Dataset $dataset
101 * @association OMVModuleZFSDataset to dataset
106 * Array of OMVModuleZFSZvol
110 * @association OMVModuleZFSZvol to zvol
118 * @param $vdev OMVModuleZFSVdev or array(OMVModuleZFSVdev)
119 * @throws OMVModuleZFSException
122 public function __construct($vdev) {
125 if (is_array($vdev)) {
126 $cmd = $this->getCommandString($vdev);
127 $name = $vdev[0]->getPool();
128 $type = $vdev[0]->getType();
129 } else if ($vdev instanceof OMVModuleZFSVdev
) {
130 $cmd = $this->getCommandString(array($vdev));
131 $name = $vdev->getPool();
132 $type = $vdev->getType();
134 // Assume we make an instance of an existing pool
135 $create_pool = false;
138 $this->vdevs
= array();
142 $this->features
= array();
144 $cmd = "zpool create $name $cmd";
146 OMVUtil
::exec($cmd, $output, $result);
148 throw new OMVModuleZFSException($output);
153 $this->vdevs
= $vdev;
155 array_push ($this->vdevs
, $vdev);
156 $this->size
= $this->getAttribute("size");
157 $this->mountPoint
= $this->getAttribute("mountpoint");
160 $this->assemblePool($vdev);
170 public function getName() {
180 public function getVdevs() {
187 * @param array $vdev array of OMVModuleZFSVdev
189 * @throws OMVModuleZFSException
192 public function addVdev(array $vdevs) {
193 $cmd = "zpool add " . $this->name
. " " . $this->getCommandString($vdevs);
194 OMVUtil
::exec($cmd, $output, $result);
196 throw new OMVModuleZFSException($output);
198 $this->vdevs
= array_merge($this->vdevs
, $vdevs);
199 $this->size
= $this->getAttribute("size");
205 * @param OMVModuleZFSVdev $vdev
207 * @throws OMVModuleZFSException
210 public function removeVdev(OMVModuleZFSVdev
$vdev) {
211 throw new OMVModuleZFSException("Cannot remove vdevs from a pool");
217 * @param OMVModuleZFSVdev $cache
219 * @throws OMVModuleZFSException
222 public function addCache(OMVModuleZFSVdev
$cache) {
223 if ($cache->getType() != OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
)
224 throw new OMVModuleZFSException("Only a plain Vdev can be added as cache");
226 $cmd = "zpool add " . $this->name
. " cache " . $this->getCommandString($vdevs);
227 OMVUtil
::exec($cmd, $output, $result);
229 throw new OMVModuleZFSException($output);
231 $disks = $cache->getDisks();
232 foreach ($disks as $disk) {
233 array_push ($this->cache
, $disk);
240 * @param array $disks
242 * @throws OMVModuleZFSException
245 public function removeCache(array $disks = null) {
247 $disks = $this->cache
;
249 foreach ($disks as $disk)
250 $dist_str .= "$disk ";
252 $cmd = "zpool remove " . $this->name
. " $dist_str";
253 OMVUtil
::exec($cmd, $output, $result);
255 throw new OMVModuleZFSException($output);
257 foreach ($disks as $disk)
258 $this->cache
= $this->removeDisk($this->cache
, $disk);
268 public function getCache() {
275 * @param OMVModuleZFSVdev $log
277 * @throws OMVModuleZFSException
280 public function addLog(OMVModuleZFSVdev
$log) {
281 if ($log->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN ||
282 $log->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
) {
283 $cmd = "zpool add " . $this->name
. " log " . $this->getCommandString($vdevs);
284 OMVUtil
::exec($cmd, $output, $result);
286 throw new OMVModuleZFSException($output);
290 throw new OMVModuleZFSException("Only a plain Vdev or mirror Vdev can be added as log");
297 * @throws OMVModuleZFSException
300 public function removeLog() {
301 foreach ($this->log
as $vdev) {
302 if ($vdev->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
) {
303 $cmd = "zpool remove " . $this->name
. " mirror-$i";
305 $disks = $vdev->getDisks();
306 foreach ($disks as $disk)
307 $dist_str .= "$disk ";
308 $cmd = "zpool remove " . $this->name
. " $disk_str";
310 OMVUtil
::exec($cmd, $output, $result);
312 throw new OMVModuleZFSException($output);
314 $this->log
= array();
324 public function getLog() {
331 * @param OMVModuleZFSVdev $spares
333 * @throws OMVModuleZFSException
336 public function addSpare(OMVModuleZFSVdev
$spares) {
337 if ($spares->getType() != OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
)
338 throw new OMVModuleZFSException("Only a plain Vdev can be added as spares");
340 $cmd = "zpool add " . $this->name
. " spare " . $this->getCommandString($vdevs);
341 OMVUtil
::exec($cmd, $output, $result);
343 throw new OMVModuleZFSException($output);
345 $disks = $spares->getDisks();
346 foreach ($disks as $disk) {
347 array_push ($this->spare
, $disk);
354 * @param array $disks
356 * @throws OMVModuleZFSException
359 public function removeSpare(array $disks = null) {
361 $disks = $this->spare
;
363 foreach ($disks as $disk)
364 $dist_str .= "$disk ";
366 $cmd = "zpool remove " . $this->name
. " $dist_str";
367 OMVUtil
::exec($cmd, $output, $result);
369 throw new OMVModuleZFSException($output);
371 foreach ($disks as $disk)
372 $this->spare
= $this->removeDisk($this->spare
, $disk);
382 public function getSpares() {
392 public function getSize() {
402 public function getMountPoint() {
403 return $this->mountPoint
;
409 * @param array $features
411 * @throws OMVModuleZFSException
414 public function setFeatures(array $features) {
415 foreach ($features as $feature => $value) {
416 $cmd = "zpool set $feature=$value " . $this->name
;
417 OMVUtil
::exec($cmd, $output, $result);
419 throw new OMVModuleZFSException($output);
421 $this->features
= $this->getAllAttributes();
425 * We only return array of features for which the user can
428 * @return array of features
431 public function getFeatures() {
434 'recordsize', /* default 131072. 512 <= n^2 <= 131072*/
435 'checksum', /* on | off */
436 'compression', /* off | lzjb | gzip | zle | lz4 */
437 'atime', /* on | off */
438 'aclmode', /* discard | groupmask | passthrough | restricted */
439 'aclinherit', /* discard | noallow | restricted | passthrough | passthrough-x */
440 'casesensitivity', /* sensitive | insensitive | mixed */
441 'primarycache', /* all | none | metadata */
442 'secondarycache', /* all | none | metadata */
443 'logbias', /* latency | throughput */
444 'dedup', /* on | off */
445 'sync' /* standard | always | disabled */
447 if (array_count_values($this->features
) < 1)
448 $this->features
= getAllAttributes();
449 foreach ($this->features
as $attr => $val) {
450 if (in_array($attr, $featureSet))
451 $attrs[$attr] = $val;
461 * @throws OMVModuleZFSException
464 public function export() {
465 $cmd = "zpool export " . $this->name
;
466 OMVUtil
::exec($cmd, $output, $result);
468 throw new OMVModuleZFSException($output);
474 * @param string $name
476 * @throws OMVModuleZFSException
479 public function import($name = null) {
481 $cmd = "zpool import $name";
483 $cmd = "zpool import";
484 OMVUtil
::exec($cmd, $output, $result);
486 throw new OMVModuleZFSException($output);
493 * @throws OMVModuleZFSException
496 public function scrub() {
497 $cmd = "zpool scrub " . $this->name
;
498 OMVUtil
::exec($cmd, $output, $result);
500 throw new OMVModuleZFSException($output);
507 * @throws OMVModuleZFSException
510 public function status() {
511 $cmd = "zpool status " . $this->name
;
512 OMVUtil
::exec($cmd, $output, $result);
514 throw new OMVModuleZFSException($output);
517 public function bindListeners(OMVNotifyDispatcher
$dispatcher) {
518 // Update service if configuration has been modified
519 $dispatcher->addListener(
521 "org.openmediavault.services.nfs",
522 array($this, "onUpdateNFSService"));
523 $dispatcher->addListener(
525 "org.openmediavault.services.nfs.shares.share",
526 array($this, "onCreateNFSShare"));
527 $dispatcher->addListener(
529 "org.openmediavault.services.nfs.shares.share",
530 array($this, "onDeleteNFSShare"));
531 $dispatcher->addListener(
533 "org.openmediavault.services.nfs.shares.share",
534 array($this, "onUpdateNFSShare"));
539 * org.openmediavault.services.nfs
541 * @param string event
544 public function onUpdateNFSService($args) {
545 $this->debug(sprintf("onUpdateNFSService args=%s", var_export($args, true)));
550 * org.openmediavault.services.nfs.shares.share
552 * @param string event
555 public function onCreateNFSShare($args) {
556 $this->debug(sprintf("onCreateNFSShare args=%s", var_export($args, true)));
561 * org.openmediavault.services.nfs.shares.share
563 * @param string event
566 public function onDeleteNFSShare($args) {
567 $this->debug(sprintf("onDeleteNFSShare args=%s", var_export($args, true)));
572 * org.openmediavault.services.nfs.shares.share
574 * @param string event
577 public function onUpdateNFSShare($args) {
578 $this->debug(sprintf("onUpdateNFSShare args=%s", var_export($args, true)));
582 * Convert array of Vdev to command string
584 * @param array $vdevs
586 * @throws OMVMODULEZFSException
588 private function getCommandString(array $vdevs) {
591 foreach ($vdevs as $vdev) {
592 if (is_object($vdev) == false)
593 throw new OMVMODULEZFSException("Not object of class OMVModuleZFSVdev");
594 if (is_a($vdev, OMVModuleZFSVdev
) == false)
595 throw new OMVMODULEZFSException("Object is not of class OMVModuleZFSVdev");
596 $type = $vdev->getType();
600 case OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
: break;
601 case OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
: $command = "mirror"; break;
602 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
: $command = "raidz1"; break;
603 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
: $command = "raidz2"; break;
604 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
: $command = "raidz3"; break;
606 throw new OMVMODULEZFSException("Unknown Vdev type");
608 $disks = $vdev->getDisks();
610 foreach($disks as $disk) {
611 $diskStr .= " $disk";
614 array_push ($adds, $command . $diskStr);
617 return join(" ", $adds);
621 * Get an attribute from pool
623 * @param string $attribute
624 * @return string value
626 private function getAttribute($attribute) {
627 $cmd = "zpool list -H -o $attribute {$this->name}";
628 OMVUtil
::exec($cmd, $output, $result);
630 $cmd = "zfs list -H -o $attribute {$this->name}";
631 OMVUtil
::exec($cmd, $output, $result);
640 * Get all attributes from pool
641 * @return array of attributes
642 * @throws OMVModuleZFSException
644 private function getAllAttributes() {
646 $cmd = "zfs get -H all {$this->name}";
648 OMVUtil
::exec($cmd, $output, $result);
650 throw new OMVModuleZFSException($output);
651 $res = preg_match_all("/$pool\s+(\w+)\s+([\w\d\.]+).*/", $output, $matches, PREG_SET_ORDER
);
652 if ($res == false ||
$res == 0)
653 throw new OMVModuleZFSException("Error return by zpool get all: $output");
654 foreach ($matches as $match) {
655 $attrs[$match[1]] = $match[2];
662 * Remove a disk from array
664 * @param array $array
665 * @param string $disk
668 private function removeDisk(array $array, $disk) {
669 $new_disks = array();
671 foreach ($array as $item) {
672 if (strcmp($item, $disk) != 0)
673 array_push ($new_disks, $item);
680 * Construct existing pool
682 * @param string $name
684 * @throws OMVModuleZFSException
686 private function assemblePool($name) {
687 $cmd = "zpool list -Hv $name";
688 $types = 'mirror|raidz1|raidz2|raidz3';
695 OMVUtil
::exec($cmd, $output, $result);
697 throw new OMVModuleZFSException($output);
698 $res = preg_match("/$name\s+([\w\d]+)\s+.*/", $output, $matches);
699 if ($res == false ||
$res == 0)
700 throw new OMVModuleZFSException("Error return by zpool list: $output");
703 $lines = split("\n", $output);
704 foreach($lines as $line) {
706 if (preg_match("/^\s*NAME/", $line))
710 if (preg_match("/^\s*$/", $line)) {
712 output($part, $type, $dev);
715 } else if (preg_match("/^\s*($name|logs|cache|spares)/", $line, $match)) {
717 output($part, $type, $dev);
725 if (preg_match("/^\s*($types)/", $line, $match)) {
728 output(null, $type, $dev);
732 } else if (preg_match("/^\s*([\w\d]+)\s+/", $line, $match)) {
734 $dev .= " $match[1]";
740 if (preg_match("/^\s*([\w\d]+)\s+/", $line, $match)) {
742 $dev .= " $match[1]";
749 if (preg_match("/^\s*([\w\d]+)\s+/", $line, $match)) {
751 $dev .= " $match[1]";
757 throw new Exception("$part: Unknown pool part");
762 $this->size
= $this->getAttribute("size");
763 $this->mountPoint
= $this->getAttribute("mountpoint");
767 * Create pool config from parsed input
769 * @param string $part
770 * @param string $type
773 * @throws OMVModuleZFSException
775 private function output($part, $type, $dev) {
776 $disks = split(" ", $dev);
779 if ($type && $type != 'mirror')
780 throw new Exception("$type: Logs can only be mirror or plain");
782 $this->log
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
, $disks);
784 $this->log
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
788 throw new Exception("$type: cache can only be plain");
789 $this->cache
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
793 throw new Exception("$type: spares can only be plain");
794 $this->spare
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
800 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
, $disks));
801 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
;
804 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
, $disks));
805 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
;
808 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
, $disks));
809 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
;
812 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
, $disks));
813 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
;
817 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks));
818 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
;
This page took 0.247898 seconds and 6 git commands to generate.