]> git.datanom.net - omvzfs.git/blame - src/Zpool.php
First complete implementation of Zpool class
[omvzfs.git] / src / Zpool.php
CommitLineData
f891182f 1<?php
b76f4e17
MR
2require_once("Vdev.php");
3require_once("Snapshot.php");
4require_once("Dataset.php");
5require_once("Zvol.php");
6require_once("Exception.php");
f891182f
MR
7
8/**
b76f4e17 9 * Class containing information about the pool
f891182f 10 *
b76f4e17
MR
11 * @author Michael Rasmussen
12 * @version 0.1
13 * @copyright Michael Rasmussen <mir@datanom.net>
f891182f 14 */
b76f4e17
MR
15class OMVModuleZFSZpool extends OMVModuleAbstract
16 implements OMVNotifyListener {
f891182f
MR
17 // Attributes
18 /**
b76f4e17 19 * Name of pool
f891182f
MR
20 *
21 * @var string $name
22 * @access private
23 */
b76f4e17 24 private $name;
f891182f
MR
25
26 /**
b76f4e17 27 * List of Vdev
f891182f 28 *
b76f4e17 29 * @var array $vdevs
f891182f 30 * @access private
e39afba8 31 * @association OMVModuleZFSVdev to vdevs
f891182f 32 */
b76f4e17 33 private $vdevs;
f891182f
MR
34
35 /**
b76f4e17 36 * List of spares
f891182f 37 *
b76f4e17 38 * @var array $spare
f891182f 39 * @access private
e39afba8 40 * @association OMVModuleZFSVdev to spare
f891182f 41 */
b76f4e17 42 private $spare;
f891182f
MR
43
44 /**
b76f4e17 45 * List of log
f891182f 46 *
b76f4e17 47 * @var array $log
f891182f 48 * @access private
e39afba8 49 * @association OMVModuleZFSVdev to log
f891182f 50 */
b76f4e17 51 private $log;
f891182f
MR
52
53 /**
b76f4e17 54 * List of cache
f891182f 55 *
b76f4e17 56 * @var array $cache
f891182f 57 * @access private
e39afba8 58 * @association OMVModuleZFSVdev to cache
f891182f 59 */
b76f4e17 60 private $cache;
f891182f
MR
61
62 /**
b76f4e17 63 * Pool size
f891182f
MR
64 *
65 * @var int $size
66 * @access private
67 */
b76f4e17 68 private $size;
f891182f
MR
69
70 /**
b76f4e17 71 * Pool's mountpoint
f891182f
MR
72 *
73 * @var string $mountPoint
74 * @access private
75 */
b76f4e17 76 private $mountPoint;
f891182f
MR
77
78 /**
b76f4e17 79 * List of features
f891182f 80 *
b76f4e17 81 * @var array $features
f891182f
MR
82 * @access private
83 */
b76f4e17 84 private $features;
f891182f
MR
85
86 // Associations
87 /**
b76f4e17 88 * Array of OMVModuleZFSSnapshot.
f891182f 89 *
b76f4e17 90 * @var array $snapshot
f891182f 91 * @access private
e39afba8 92 * @association OMVModuleZFSSnapshot to snapshot
f891182f 93 */
b76f4e17 94 private $snapshot;
f891182f
MR
95
96 /**
b76f4e17 97 * Array of OMVModuleZFSDataset
f891182f 98 *
b76f4e17 99 * @var Dataset $dataset
f891182f 100 * @access private
e39afba8 101 * @association OMVModuleZFSDataset to dataset
f891182f 102 */
b76f4e17 103 private $dataset;
f891182f
MR
104
105 /**
b76f4e17 106 * Array of OMVModuleZFSZvol
f891182f 107 *
b76f4e17 108 * @var Zvol $zvol
f891182f 109 * @access private
e39afba8 110 * @association OMVModuleZFSZvol to zvol
f891182f 111 */
b76f4e17 112 private $zvol;
f891182f
MR
113
114 // Operations
b76f4e17
MR
115 /**
116 * Constructor
117 *
e39afba8 118 * @param $vdev OMVModuleZFSVdev or array(OMVModuleZFSVdev)
b76f4e17
MR
119 * @throws OMVModuleZFSException
120 */
121
122 public function __construct($vdev) {
123 if (is_array($vdev)) {
124 $cmd = $this->getCommandString($vdev);
125 $name = $vdev[0]->getPool();
126 $type = $vdev[0]->getType();
127 }
128 else {
129 $cmd = $this->getCommandString(array($vdev));
130 $name = $vdev->getPool();
131 $type = $vdev->getType();
132 }
133 $cmd = "zpool create $name $cmd";
134
135 OMVUtil::exec($cmd, $output, $result);
136 if ($result)
137 throw new OMVModuleZFSException($output);
138 else {
139 $this->vdevs = array();
140 $this->spare = array();
141 $this->log = array();
142 $this->cache = array();
143 $this->features = array();
144 $this->name = $name;
145 $this->type = $type;
146 if (is_array($vdev))
147 $this->vdevs = $vdev;
148 else
149 array_push ($this->vdevs, $vdev);
150 $this->size = $this->getAttribute("size");
151 $this->mountPoint = $this->getAttribute("mountpoint");
152 }
153 }
154
f891182f 155 /**
b76f4e17 156 * Get pool name
f891182f 157 *
b76f4e17 158 * @return string
f891182f
MR
159 * @access public
160 */
161 public function getName() {
b76f4e17 162 return $this->name;
f891182f
MR
163 }
164
165 /**
b76f4e17 166 * Get array of Vdev
f891182f 167 *
b76f4e17 168 * @return array
f891182f
MR
169 * @access public
170 */
171 public function getVdevs() {
b76f4e17 172 return $this->vdevs;
f891182f
MR
173 }
174
175 /**
b76f4e17 176 * Add Vdev to pool
f891182f 177 *
b76f4e17
MR
178 * @param array $vdev array of OMVModuleZFSVdev
179 * @return void
180 * @throws OMVModuleZFSException
f891182f
MR
181 * @access public
182 */
b76f4e17 183 public function addVdev(array $vdevs) {
e39afba8 184 $cmd = "zpool add " . $this->name . " " . $this->getCommandString($vdevs);
b76f4e17
MR
185 OMVUtil::exec($cmd, $output, $result);
186 if ($result)
187 throw new OMVModuleZFSException($output);
188 else
189 $this->vdevs = array_merge($this->vdevs, $vdevs);
e39afba8 190 $this->size = $this->getAttribute("size");
f891182f
MR
191 }
192
193 /**
194 * XXX
195 *
b76f4e17
MR
196 * @param OMVModuleZFSVdev $vdev
197 * @return void
198 * @throws OMVModuleZFSException
f891182f
MR
199 * @access public
200 */
b76f4e17
MR
201 public function removeVdev(OMVModuleZFSVdev $vdev) {
202 throw new OMVModuleZFSException("Cannot remove vdevs from a pool");
f891182f
MR
203 }
204
205 /**
206 * XXX
207 *
b76f4e17
MR
208 * @param OMVModuleZFSVdev $cache
209 * @return void
210 * @throws OMVModuleZFSException
f891182f
MR
211 * @access public
212 */
b76f4e17
MR
213 public function addCache(OMVModuleZFSVdev $cache) {
214 if ($cache->getType() != OMVModuleZFSVdevType::OMVMODULEZFSPLAIN)
215 throw new OMVModuleZFSException("Only a plain Vdev can be added as cache");
216
e39afba8 217 $cmd = "zpool add " . $this->name . " cache " . $this->getCommandString($vdevs);
b76f4e17
MR
218 OMVUtil::exec($cmd, $output, $result);
219 if ($result)
220 throw new OMVModuleZFSException($output);
221
222 $disks = $cache->getDisks();
223 foreach ($disks as $disk) {
224 array_push ($this->cache, $disk);
225 }
f891182f
MR
226 }
227
228 /**
229 * XXX
230 *
b76f4e17
MR
231 * @param array $disks
232 * @return void
233 * @throws OMVModuleZFSException
f891182f
MR
234 * @access public
235 */
b76f4e17 236 public function removeCache(array $disks = null) {
b76f4e17
MR
237 if (! $disks)
238 $disks = $this->cache;
239
e39afba8
MR
240 foreach ($disks as $disk)
241 $dist_str .= "$disk ";
b76f4e17 242
e39afba8
MR
243 $cmd = "zpool remove " . $this->name . " $dist_str";
244 OMVUtil::exec($cmd, $output, $result);
245 if ($result)
246 throw new OMVModuleZFSException($output);
247 else {
248 foreach ($disks as $disk)
249 $this->cache = $this->removeDisk($this->cache, $disk);
b76f4e17 250 }
f891182f
MR
251 }
252
253 /**
254 * XXX
255 *
b76f4e17 256 * @return Cache
f891182f
MR
257 * @access public
258 */
259 public function getCache() {
b76f4e17 260 return $this->cache;
f891182f
MR
261 }
262
263 /**
264 * XXX
265 *
b76f4e17
MR
266 * @param OMVModuleZFSVdev $log
267 * @return void
f891182f
MR
268 * @access public
269 */
b76f4e17 270 public function addLog(OMVModuleZFSVdev $log) {
e39afba8
MR
271 if ($log->getType() == OMVModuleZFSVdevType::OMVMODULEZFSPLAIN ||
272 $log->getType() == OMVModuleZFSVdevType::OMVMODULEZFSMIRROR) {
273 $cmd = "zpool add " . $this->name . " log " . $this->getCommandString($vdevs);
274 OMVUtil::exec($cmd, $output, $result);
275 if ($result)
276 throw new OMVModuleZFSException($output);
277
278 $this->log = $log;
279 } else
280 throw new OMVModuleZFSException("Only a plain Vdev or mirror Vdev can be added as log");
f891182f
MR
281 }
282
283 /**
284 * XXX
285 *
b76f4e17 286 * @return void
f891182f
MR
287 * @access public
288 */
289 public function removeLog() {
e39afba8
MR
290 foreach ($this->log as $vdev) {
291 if ($vdev->getType() == OMVModuleZFSVdevType::OMVMODULEZFSMIRROR) {
292 $cmd = "zpool remove " . $this->name . " mirror-$i";
293 } else {
294 $disks = $vdev->getDisks();
295 foreach ($disks as $disk)
296 $dist_str .= "$disk ";
297 $cmd = "zpool remove " . $this->name . " $disk_str";
298 }
299 OMVUtil::exec($cmd, $output, $result);
300 if ($result)
301 throw new OMVModuleZFSException($output);
302 else
303 $this->log = array();
304 }
f891182f
MR
305 }
306
307 /**
308 * XXX
309 *
b76f4e17 310 * @return Log
f891182f
MR
311 * @access public
312 */
313 public function getLog() {
e39afba8 314 return $this->log;
f891182f
MR
315 }
316
317 /**
318 * XXX
319 *
e39afba8 320 * @param OMVModuleZFSVdev $spares
b76f4e17 321 * @return void
f891182f
MR
322 * @access public
323 */
e39afba8
MR
324 public function addSpare(OMVModuleZFSVdev $spares) {
325 if ($spares->getType() != OMVModuleZFSVdevType::OMVMODULEZFSPLAIN)
326 throw new OMVModuleZFSException("Only a plain Vdev can be added as spares");
327
328 $cmd = "zpool add " . $this->name . " spare " . $this->getCommandString($vdevs);
329 OMVUtil::exec($cmd, $output, $result);
330 if ($result)
331 throw new OMVModuleZFSException($output);
332
333 $disks = $spares->getDisks();
334 foreach ($disks as $disk) {
335 array_push ($this->spare, $disk);
336 }
f891182f
MR
337 }
338
339 /**
340 * XXX
341 *
e39afba8 342 * @param array $disks
b76f4e17 343 * @return void
f891182f
MR
344 * @access public
345 */
e39afba8
MR
346 public function removeSpare(array $disks = null) {
347 if (! $disks)
348 $disks = $this->spare;
349
350 foreach ($disks as $disk)
351 $dist_str .= "$disk ";
352
353 $cmd = "zpool remove " . $this->name . " $dist_str";
354 OMVUtil::exec($cmd, $output, $result);
355 if ($result)
356 throw new OMVModuleZFSException($output);
357 else {
358 foreach ($disks as $disk)
359 $this->spare = $this->removeDisk($this->spare, $disk);
360 }
f891182f
MR
361 }
362
363 /**
364 * XXX
365 *
b76f4e17 366 * @return list<Disk>
f891182f
MR
367 * @access public
368 */
369 public function getSpares() {
e39afba8 370 return $this->spare;
f891182f
MR
371 }
372
373 /**
374 * XXX
375 *
b76f4e17 376 * @return int
f891182f
MR
377 * @access public
378 */
379 public function getSize() {
e39afba8 380 return $this->size;
f891182f
MR
381 }
382
383 /**
384 * XXX
385 *
b76f4e17 386 * @return string
f891182f
MR
387 * @access public
388 */
389 public function getMountPoint() {
e39afba8 390 return $this->mountPoint;
f891182f
MR
391 }
392
393 /**
394 * XXX
395 *
b76f4e17
MR
396 * @param array $features
397 * @return void
f891182f
MR
398 * @access public
399 */
b76f4e17 400 public function setFeatures(array $features) {
e39afba8
MR
401 foreach ($features as $feature => $value) {
402 $cmd = "zpool set $feature=$value " . $this->name;
403 OMVUtil::exec($cmd, $output, $result);
404 if ($result)
405 throw new OMVModuleZFSException($output);
406 }
407 $this->features = $this->getAllAttributes();
f891182f
MR
408 }
409
410 /**
e39afba8
MR
411 * We only return array of features for which the user can
412 * change in GUI.
f891182f 413 *
e39afba8 414 * @return array of features
f891182f
MR
415 * @access public
416 */
417 public function getFeatures() {
e39afba8
MR
418 $attrs = array();
419 $featureSet = array(
420 'recordsize', /* default 131072. 512 <= n^2 <= 131072*/
421 'checksum', /* on | off */
422 'compression', /* off | lzjb | gzip | zle | lz4 */
423 'atime', /* on | off */
424 'aclmode', /* discard | groupmask | passthrough | restricted */
425 'aclinherit', /* discard | noallow | restricted | passthrough | passthrough-x */
426 'casesensitivity', /* sensitive | insensitive | mixed */
427 'primarycache', /* all | none | metadata */
428 'secondarycache', /* all | none | metadata */
429 'logbias', /* latency | throughput */
430 'dedup', /* on | off */
431 'sync' /* standard | always | disabled */
432 );
433 if (array_count_values($this->features) < 1)
434 $this->features = getAllAttributes();
435 foreach ($this->features as $attr => $val) {
436 if (in_array($attr, $featureSet))
437 $attrs[$attr] = $val;
438 }
439
440 return $attrs;
f891182f
MR
441 }
442
443 /**
444 * XXX
445 *
b76f4e17 446 * @return void
f891182f
MR
447 * @access public
448 */
449 public function export() {
e39afba8
MR
450 $cmd = "zpool export " . $this->name;
451 OMVUtil::exec($cmd, $output, $result);
452 if ($result)
453 throw new OMVModuleZFSException($output);
f891182f
MR
454 }
455
456 /**
457 * XXX
458 *
b76f4e17
MR
459 * @param string $name
460 * @return void
f891182f
MR
461 * @access public
462 */
e39afba8
MR
463 public function import($name = null) {
464 if ($name)
465 $cmd = "zpool import $name";
466 else
467 $cmd = "zpool import";
468 OMVUtil::exec($cmd, $output, $result);
469 if ($result)
470 throw new OMVModuleZFSException($output);
f891182f
MR
471 }
472
473 /**
474 * XXX
475 *
b76f4e17 476 * @return void
f891182f
MR
477 * @access public
478 */
479 public function scrub() {
e39afba8
MR
480 $cmd = "zpool scrub " . $this->name;
481 OMVUtil::exec($cmd, $output, $result);
482 if ($result)
483 throw new OMVModuleZFSException($output);
f891182f
MR
484 }
485
486 /**
487 * XXX
488 *
b76f4e17 489 * @return string
f891182f
MR
490 * @access public
491 */
492 public function status() {
e39afba8
MR
493 $cmd = "zpool status " . $this->name;
494 OMVUtil::exec($cmd, $output, $result);
495 if ($result)
496 throw new OMVModuleZFSException($output);
f891182f
MR
497 }
498
b76f4e17 499 public function bindListeners(OMVNotifyDispatcher $dispatcher) {
e39afba8
MR
500 // Update service if configuration has been modified
501 $dispatcher->addListener(
502 OMV_NOTIFY_MODIFY,
503 "org.openmediavault.services.nfs",
504 array($this, "onUpdateNFSService"));
505 $dispatcher->addListener(
506 OMV_NOTIFY_CREATE,
507 "org.openmediavault.services.nfs.shares.share",
508 array($this, "onCreateNFSShare"));
509 $dispatcher->addListener(
510 OMV_NOTIFY_DELETE,
511 "org.openmediavault.services.nfs.shares.share",
512 array($this, "onDeleteNFSShare"));
513 $dispatcher->addListener(
514 OMV_NOTIFY_MODIFY,
515 "org.openmediavault.services.nfs.shares.share",
516 array($this, "onUpdateNFSShare"));
b76f4e17
MR
517 }
518
f891182f
MR
519 /**
520 * XXX
e39afba8 521 * org.openmediavault.services.nfs
f891182f
MR
522 *
523 * @param string event
524 * @access public
525 */
e39afba8
MR
526 public function onUpdateNFSService($args) {
527 $this->debug(sprintf("onUpdateNFSService args=%s", var_export($args, true)));
528 }
529
530 /**
531 * XXX
532 * org.openmediavault.services.nfs.shares.share
533 *
534 * @param string event
535 * @access public
536 */
537 public function onCreateNFSShare($args) {
538 $this->debug(sprintf("onCreateNFSShare args=%s", var_export($args, true)));
539 }
540
541 /**
542 * XXX
543 * org.openmediavault.services.nfs.shares.share
544 *
545 * @param string event
546 * @access public
547 */
548 public function onDeleteNFSShare($args) {
549 $this->debug(sprintf("onDeleteNFSShare args=%s", var_export($args, true)));
550 }
551
552 /**
553 * XXX
554 * org.openmediavault.services.nfs.shares.share
555 *
556 * @param string event
557 * @access public
558 */
559 public function onUpdateNFSShare($args) {
560 $this->debug(sprintf("onUpdateNFSShare args=%s", var_export($args, true)));
f891182f
MR
561 }
562
563 /**
b76f4e17 564 * Convert array of Vdev to command string
f891182f 565 *
b76f4e17
MR
566 * @param array $vdevs
567 * @return string
568 * @throws OMVMODULEZFSException
f891182f 569 */
b76f4e17
MR
570 private function getCommandString(array $vdevs) {
571 $adds = array();
572
573 foreach ($vdevs as $vdev) {
e39afba8
MR
574 if (is_object($vdev) == false)
575 throw new OMVMODULEZFSException("Not object of class OMVModuleZFSVdev");
576 if (is_a($vdev, OMVModuleZFSVdev) == false)
577 throw new OMVMODULEZFSException("Object is not of class OMVModuleZFSVdev");
b76f4e17
MR
578 $type = $vdev->getType();
579 $command = "";
580
581 switch ($type) {
582 case OMVModuleZFSVdevType::OMVMODULEZFSPLAIN: break;
583 case OMVModuleZFSVdevType::OMVMODULEZFSMIRROR: $command = "mirror"; break;
584 case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ1: $command = "raidz1"; break;
585 case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ2: $command = "raidz2"; break;
586 case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ3: $command = "raidz3"; break;
587 default:
588 throw new OMVMODULEZFSException("Unknown Vdev type");
589 }
590 $disks = $vdev->getDisks();
591 $diskStr = "";
592 foreach($disks as $disk) {
593 $diskStr .= " $disk";
594 }
595
596 array_push ($adds, $command . $diskStr);
597 }
598
599 return join(" ", $adds);
f891182f
MR
600 }
601
602 /**
b76f4e17 603 * Get an attribute from pool
f891182f 604 *
b76f4e17
MR
605 * @param string $attribute
606 * @return string value
f891182f 607 */
b76f4e17
MR
608 private function getAttribute($attribute) {
609 $cmd = "zpool list -H -o $attribute {$this->name}";
610 OMVUtil::exec($cmd, $output, $result);
611 if ($result) {
612 $cmd = "zfs list -H -o $attribute {$this->name}";
613 OMVUtil::exec($cmd, $output, $result);
614 if ($result)
615 return null;
616 }
617
618 return $output;
f891182f
MR
619 }
620
e39afba8
MR
621 /**
622 * Get all attributes from pool
623 * @return array of attributes
624 */
625 private function getAllAttributes() {
626 $attrs = array();
627 $cmd = "zfs get -H all {$this->name}";
628
629 OMVUtil::exec($cmd, $output, $result);
630 if ($result)
631 throw new OMVModuleZFSException($output);
632 $res = preg_match_all("/$pool\s+(\w+)\s+([\w\d\.]+).*/", $output, $matches, PREG_SET_ORDER);
633 if ($res == false || $res == 0)
634 throw new OMVModuleZFSException("Error return by zpool get all: $output");
635 foreach ($matches as $match) {
636 $attrs[$match[1]] = $match[2];
637 }
638
639 return $attrs;
640 }
641
f891182f 642 /**
b76f4e17 643 * Remove a disk from array
f891182f 644 *
b76f4e17
MR
645 * @param array $array
646 * @param string $disk
647 * @return array
f891182f 648 */
b76f4e17
MR
649 private function removeDisk(array $array, $disk) {
650 $new_disks = array();
651
652 foreach ($array as $item) {
653 if (strcmp($item, $disk) != 0)
654 array_push ($new_disks, $item);
655 }
656
657 return $new_disks;
f891182f
MR
658 }
659}
660
661?>
This page took 0.137657 seconds and 5 git commands to generate.