]>
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
{
34 * @association OMVModuleZFSVdev to vdevs
43 * @association OMVModuleZFSVdev to spare
52 * @association OMVModuleZFSVdev to log
61 * @association OMVModuleZFSVdev to cache
76 * @var string $mountPoint
84 * @var array $features
91 * Array of OMVModuleZFSSnapshot.
93 * @var array $snapshot
95 * @association OMVModuleZFSSnapshot to snapshot
100 * Array of OMVModuleZFSDataset
102 * @var Dataset $dataset
104 * @association OMVModuleZFSDataset to dataset
109 * Array of OMVModuleZFSZvol
113 * @association OMVModuleZFSZvol to zvol
121 * @param $vdev OMVModuleZFSVdev or array(OMVModuleZFSVdev)
122 * @throws OMVModuleZFSException
125 public function __construct($vdev, $opts = "") {
128 if (is_array($vdev)) {
129 $cmd = $this->getCommandString($vdev);
130 $name = $vdev[0]->getPool();
131 $type = $vdev[0]->getType();
132 } else if ($vdev instanceof OMVModuleZFSVdev
) {
133 $cmd = $this->getCommandString(array($vdev));
134 $name = $vdev->getPool();
135 $type = $vdev->getType();
137 // Assume we make an instance of an existing pool
138 $create_pool = false;
141 $this->vdevs
= array();
145 $this->features
= array();
147 $cmd = "zpool create $opts$name $cmd 2>&1";
149 OMVUtil
::exec($cmd, $output, $result);
151 throw new OMVModuleZFSException(implode("\n", $output));
156 $this->vdevs
= $vdev;
158 array_push ($this->vdevs
, $vdev);
159 $this->size
= $this->getAttribute("size");
160 $this->mountPoint
= $this->getAttribute("mountpoint");
163 $this->assemblePool($vdev);
173 public function getName() {
183 public function getVdevs() {
190 * @param array $vdev array of OMVModuleZFSVdev
192 * @throws OMVModuleZFSException
195 public function addVdev(array $vdevs, $opts= "") {
196 $cmd = "zpool add " . $this->name
. " " . $opts . $this->getCommandString($vdevs) . " 2>&1";
197 OMVUtil
::exec($cmd, $output, $result);
199 throw new OMVModuleZFSException(implode("\n", $output));
201 $this->vdevs
= array_merge($this->vdevs
, $vdevs);
202 $this->size
= $this->getAttribute("size");
208 * @param OMVModuleZFSVdev $vdev
210 * @throws OMVModuleZFSException
213 public function removeVdev(OMVModuleZFSVdev
$vdev) {
214 throw new OMVModuleZFSException("Cannot remove vdevs from a pool");
220 * @param OMVModuleZFSVdev $cache
222 * @throws OMVModuleZFSException
225 public function addCache(OMVModuleZFSVdev
$cache) {
226 if ($cache->getType() != OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
)
227 throw new OMVModuleZFSException("Only a plain Vdev can be added as cache");
229 $cmd = "zpool add " . $this->name
. " cache " . $this->getCommandString($vdevs);
230 OMVUtil
::exec($cmd, $output, $result);
232 throw new OMVModuleZFSException($output);
234 $disks = $cache->getDisks();
235 foreach ($disks as $disk) {
236 array_push ($this->cache
, $disk);
243 * @param array $disks
245 * @throws OMVModuleZFSException
248 public function removeCache(array $disks = null) {
250 $disks = $this->cache
;
252 foreach ($disks as $disk)
253 $dist_str .= "$disk ";
255 $cmd = "zpool remove " . $this->name
. " $dist_str";
256 OMVUtil
::exec($cmd, $output, $result);
258 throw new OMVModuleZFSException($output);
260 foreach ($disks as $disk)
261 $this->cache
= $this->removeDisk($this->cache
, $disk);
271 public function getCache() {
278 * @param OMVModuleZFSVdev $log
280 * @throws OMVModuleZFSException
283 public function addLog(OMVModuleZFSVdev
$log) {
284 if ($log->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN ||
285 $log->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
) {
286 $cmd = "zpool add " . $this->name
. " log " . $this->getCommandString($vdevs);
287 OMVUtil
::exec($cmd, $output, $result);
289 throw new OMVModuleZFSException($output);
293 throw new OMVModuleZFSException("Only a plain Vdev or mirror Vdev can be added as log");
300 * @throws OMVModuleZFSException
303 public function removeLog() {
304 foreach ($this->log
as $vdev) {
305 if ($vdev->getType() == OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
) {
306 $cmd = "zpool remove " . $this->name
. " mirror-$i";
308 $disks = $vdev->getDisks();
309 foreach ($disks as $disk)
310 $dist_str .= "$disk ";
311 $cmd = "zpool remove " . $this->name
. " $disk_str";
313 OMVUtil
::exec($cmd, $output, $result);
315 throw new OMVModuleZFSException($output);
317 $this->log
= array();
327 public function getLog() {
334 * @param OMVModuleZFSVdev $spares
336 * @throws OMVModuleZFSException
339 public function addSpare(OMVModuleZFSVdev
$spares) {
340 if ($spares->getType() != OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
)
341 throw new OMVModuleZFSException("Only a plain Vdev can be added as spares");
343 $cmd = "zpool add " . $this->name
. " spare " . $this->getCommandString($vdevs);
344 OMVUtil
::exec($cmd, $output, $result);
346 throw new OMVModuleZFSException($output);
348 $disks = $spares->getDisks();
349 foreach ($disks as $disk) {
350 array_push ($this->spare
, $disk);
357 * @param array $disks
359 * @throws OMVModuleZFSException
362 public function removeSpare(array $disks = null) {
364 $disks = $this->spare
;
366 foreach ($disks as $disk)
367 $dist_str .= "$disk ";
369 $cmd = "zpool remove " . $this->name
. " $dist_str";
370 OMVUtil
::exec($cmd, $output, $result);
372 throw new OMVModuleZFSException($output);
374 foreach ($disks as $disk)
375 $this->spare
= $this->removeDisk($this->spare
, $disk);
385 public function getSpares() {
395 public function getSize() {
405 public function getMountPoint() {
406 return $this->mountPoint
;
412 * @param array $features
414 * @throws OMVModuleZFSException
417 public function setFeatures(array $features) {
418 foreach ($features as $feature => $value) {
419 $cmd = "zpool set $feature=$value " . $this->name
;
420 OMVUtil
::exec($cmd, $output, $result);
422 throw new OMVModuleZFSException($output);
424 $this->features
= $this->getAllAttributes();
428 * We only return array of features for which the user can
431 * @return array of features
434 public function getFeatures($internal = true) {
437 'recordsize', /* default 131072. 512 <= n^2 <= 131072*/
438 'checksum', /* on | off */
439 'compression', /* off | lzjb | gzip | zle | lz4 */
440 'atime', /* on | off */
441 'aclmode', /* discard | groupmask | passthrough | restricted */
442 'aclinherit', /* discard | noallow | restricted | passthrough | passthrough-x */
443 'casesensitivity', /* sensitive | insensitive | mixed */
444 'primarycache', /* all | none | metadata */
445 'secondarycache', /* all | none | metadata */
446 'logbias', /* latency | throughput */
447 'dedup', /* on | off */
448 'sync' /* standard | always | disabled */
450 if (count($this->features
) < 1)
451 $this->features
= $this->getAllAttributes();
453 foreach ($this->features
as $attr => $val) {
454 if (in_array($attr, $featureSet))
455 $attrs[$attr] = $val['value'];
458 foreach ($this->features
as $attr => $val) {
459 if (in_array($attr, $featureSet))
460 $attrs[$attr] = $val;
471 * @throws OMVModuleZFSException
474 public function export() {
475 $cmd = "zpool export " . $this->name
;
476 OMVUtil
::exec($cmd, $output, $result);
478 throw new OMVModuleZFSException($output);
484 * @param string $name
486 * @throws OMVModuleZFSException
489 public function import($name = null) {
491 $cmd = "zpool import $name";
493 $cmd = "zpool import";
494 OMVUtil
::exec($cmd, $output, $result);
496 throw new OMVModuleZFSException($output);
503 * @throws OMVModuleZFSException
506 public function scrub() {
507 $cmd = "zpool scrub " . $this->name
;
508 OMVUtil
::exec($cmd, $output, $result);
510 throw new OMVModuleZFSException($output);
517 * @throws OMVModuleZFSException
520 public function status() {
521 $cmd = "zpool status " . $this->name
;
522 OMVUtil
::exec($cmd, $output, $result);
524 throw new OMVModuleZFSException($output);
528 * Get a single property value associated with the Dataset
530 * @param string $property Name of the property to fetch
531 * @return array The returned array with the property. The property is an associative array with
532 * two elements, <value> and <source>.
535 public function getProperty($property) {
536 $attrs = $this->getFeatures(false);
537 return $attrs["$property"];
541 * Get an associative array of all properties associated with the Snapshot
543 * @return array $properties Each entry is an associative array with two elements
544 * <value> and <source>
547 public function getProperties() {
548 $attrs = $this->getFeatures(false);
553 * Sets a number of Dataset properties. If a property is already set it will be updated with the new value.
555 * @param array $properties An associative array with properties to set
559 public function setProperties($properties) {
560 foreach ($properties as $newpropertyk => $newpropertyv) {
561 $cmd = "zfs set " . $newpropertyk . "=" . $newpropertyv . " " . $this->name
. " 2>&1";
562 OMVModuleZFSUtil
::exec($cmd,$out,$res);
563 $attr = $this->getAttribute($newpropertyk);
564 $this->features
[$newpropertyk] = $attr;
569 * Destroy the Dataset.
574 public function destroy() {
575 $cmd = "zpool destroy " . $this->name
. " 2>&1";
576 $this->exec($cmd,$out,$res);
580 * Clears a previously set proporty and specifies that it should be
581 * inherited from it's parent.
583 * @param string $property Name of the property to inherit.
587 public function inherit($property) {
588 $cmd = "zfs inherit " . $property . " " . $this->name
. " 2>&1";
589 $this->exec($cmd,$out,$res);
590 $attr = $this->getAttribute($newpropertyk);
591 $this->features
[$newpropertyk] = $attr;
595 * Convert array of Vdev to command string
597 * @param array $vdevs
599 * @throws OMVMODULEZFSException
601 private function getCommandString(array $vdevs) {
604 foreach ($vdevs as $vdev) {
605 if (is_object($vdev) == false)
606 throw new OMVMODULEZFSException("Not object of class OMVModuleZFSVdev");
607 if (is_a($vdev, OMVModuleZFSVdev
) == false)
608 throw new OMVMODULEZFSException("Object is not of class OMVModuleZFSVdev");
609 $type = $vdev->getType();
613 case OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
: break;
614 case OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
: $command = "mirror"; break;
615 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
: $command = "raidz1"; break;
616 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
: $command = "raidz2"; break;
617 case OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
: $command = "raidz3"; break;
619 throw new OMVMODULEZFSException("Unknown Vdev type");
621 $disks = $vdev->getDisks();
623 foreach($disks as $disk) {
624 $diskStr .= " $disk";
627 array_push ($adds, $command . $diskStr);
630 return implode(" ", $adds);
634 * Get an attribute from pool
636 * @param string $attribute
637 * @return string value
639 public function getAttribute($attribute) {
640 $cmd = "zpool list -H -o $attribute {$this->name}";
641 OMVUtil
::exec($cmd, $output, $result);
643 $cmd = "zfs list -H -o $attribute {$this->name}";
644 OMVUtil
::exec($cmd, $output, $result);
653 * Get all attributes from pool
654 * @return array of attributes
655 * @throws OMVModuleZFSException
657 private function getAllAttributes() {
659 $cmd = "zfs get -H all {$this->name}";
662 OMVUtil
::exec($cmd, $output, $result);
663 } catch (OMVModuleZFSException
$e) {}
665 throw new OMVModuleZFSException($output);
666 $output = implode("\n", $output);
667 $res = preg_match_all("/{$this->name}\s+(\w+)\s+([\w\d\.]+)\s+(\w+).*/", $output, $matches, PREG_SET_ORDER
);
668 if ($res == false ||
$res == 0)
669 throw new OMVModuleZFSException("Error return by zpool get all: $output");
670 foreach ($matches as $match) {
671 $attrs[$match[1]] = array('value' => $match[2], 'source' => $match[3]);
678 * Get all Dataset properties from commandline and update object properties attribute
683 private function updateAllProperties() {
684 $this->features
= $this->getAllAttributes();
688 * Remove a disk from array
690 * @param array $array
691 * @param string $disk
694 private function removeDisk(array $array, $disk) {
695 $new_disks = array();
697 foreach ($array as $item) {
698 if (strcmp($item, $disk) != 0)
699 array_push ($new_disks, $item);
706 * Construct existing pool
708 * @param string $name
710 * @throws OMVModuleZFSException
712 private function assemblePool($name) {
713 $cmd = "zpool status -v $name";
714 $types = 'mirror|raidz1|raidz2|raidz3';
721 OMVUtil
::exec($cmd, $output, $result);
723 throw new OMVModuleZFSException($output);
726 foreach($output as $line) {
727 if (! strstr($line, PHP_EOL
))
730 if (preg_match("/^\s*NAME/", $line))
734 if (preg_match("/^\s*$/", $line)) {
736 $this->output($part, $type, $dev);
739 } else if (preg_match("/^\s*($name|logs|cache|spares)/", $line, $match)) {
741 $this->output($part, $type, $dev);
749 if (preg_match("/^\s*($types)/", $line, $match)) {
752 $this->output(null, $type, $dev);
756 } else if (preg_match("/^\s*([\w\d-a-z0-9\:\.\-]+)\s+/", $line, $match)) {
758 $dev .= " $match[1]";
764 if (preg_match("/^\s*([\w\d-]+)\s+/", $line, $match)) {
766 $dev .= " $match[1]";
773 if (preg_match("/^\s*([\w\d-]+)\s+/", $line, $match)) {
775 $dev .= " $match[1]";
781 throw new Exception("$part: Unknown pool part");
786 $this->size
= $this->getAttribute("size");
787 $this->mountPoint
= $this->getAttribute("mountpoint");
791 * Create pool config from parsed input
793 * @param string $part
794 * @param string $type
797 * @throws OMVModuleZFSException
799 private function output($part, $type, $dev) {
800 $disks = split(" ", $dev);
803 if ($type && $type != 'mirror')
804 throw new Exception("$type: Logs can only be mirror or plain");
806 $this->log
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
, $disks);
808 $this->log
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
812 throw new Exception("$type: cache can only be plain");
813 $this->cache
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
817 throw new Exception("$type: spares can only be plain");
818 $this->spare
= new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks);
824 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
, $disks));
825 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSMIRROR
;
828 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
, $disks));
829 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ1
;
832 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
, $disks));
833 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ2
;
836 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
, $disks));
837 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSRAIDZ3
;
841 array_push($this->vdevs
, new OMVModuleZFSVdev($this->name
, OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
, $disks));
842 $this->type
= OMVModuleZFSVdevType
::OMVMODULEZFSPLAIN
;
This page took 0.173194 seconds and 6 git commands to generate.