]> git.datanom.net - omvzfs.git/blob - src/Zpool.php
Move root to storage
[omvzfs.git] / src / Zpool.php
1 <?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");
7
8 /**
9 * Class containing information about the pool
10 *
11 * @author Michael Rasmussen
12 * @version 0.1
13 * @copyright Michael Rasmussen <mir@datanom.net>
14 */
15 class OMVModuleZFSZpool extends OMVModuleAbstract
16 implements OMVNotifyListener {
17 // Attributes
18 /**
19 * Name of pool
20 *
21 * @var string $name
22 * @access private
23 */
24 private $name;
25
26 /**
27 * List of Vdev
28 *
29 * @var array $vdevs
30 * @access private
31 * @association OMVModuleZFSVdev to vdevs
32 */
33 private $vdevs;
34
35 /**
36 * List of spares
37 *
38 * @var array $spare
39 * @access private
40 * @association OMVModuleZFSVdev to spare
41 */
42 private $spare;
43
44 /**
45 * List of log
46 *
47 * @var array $log
48 * @access private
49 * @association OMVModuleZFSVdev to log
50 */
51 private $log;
52
53 /**
54 * List of cache
55 *
56 * @var array $cache
57 * @access private
58 * @association OMVModuleZFSVdev to cache
59 */
60 private $cache;
61
62 /**
63 * Pool size
64 *
65 * @var int $size
66 * @access private
67 */
68 private $size;
69
70 /**
71 * Pool's mountpoint
72 *
73 * @var string $mountPoint
74 * @access private
75 */
76 private $mountPoint;
77
78 /**
79 * List of features
80 *
81 * @var array $features
82 * @access private
83 */
84 private $features;
85
86 // Associations
87 /**
88 * Array of OMVModuleZFSSnapshot.
89 *
90 * @var array $snapshot
91 * @access private
92 * @association OMVModuleZFSSnapshot to snapshot
93 */
94 private $snapshot;
95
96 /**
97 * Array of OMVModuleZFSDataset
98 *
99 * @var Dataset $dataset
100 * @access private
101 * @association OMVModuleZFSDataset to dataset
102 */
103 private $dataset;
104
105 /**
106 * Array of OMVModuleZFSZvol
107 *
108 * @var Zvol $zvol
109 * @access private
110 * @association OMVModuleZFSZvol to zvol
111 */
112 private $zvol;
113
114 // Operations
115 /**
116 * Constructor
117 *
118 * @param $vdev OMVModuleZFSVdev or array(OMVModuleZFSVdev)
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
155 /**
156 * Get pool name
157 *
158 * @return string
159 * @access public
160 */
161 public function getName() {
162 return $this->name;
163 }
164
165 /**
166 * Get array of Vdev
167 *
168 * @return array
169 * @access public
170 */
171 public function getVdevs() {
172 return $this->vdevs;
173 }
174
175 /**
176 * Add Vdev to pool
177 *
178 * @param array $vdev array of OMVModuleZFSVdev
179 * @return void
180 * @throws OMVModuleZFSException
181 * @access public
182 */
183 public function addVdev(array $vdevs) {
184 $cmd = "zpool add " . $this->name . " " . $this->getCommandString($vdevs);
185 OMVUtil::exec($cmd, $output, $result);
186 if ($result)
187 throw new OMVModuleZFSException($output);
188 else
189 $this->vdevs = array_merge($this->vdevs, $vdevs);
190 $this->size = $this->getAttribute("size");
191 }
192
193 /**
194 * XXX
195 *
196 * @param OMVModuleZFSVdev $vdev
197 * @return void
198 * @throws OMVModuleZFSException
199 * @access public
200 */
201 public function removeVdev(OMVModuleZFSVdev $vdev) {
202 throw new OMVModuleZFSException("Cannot remove vdevs from a pool");
203 }
204
205 /**
206 * XXX
207 *
208 * @param OMVModuleZFSVdev $cache
209 * @return void
210 * @throws OMVModuleZFSException
211 * @access public
212 */
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
217 $cmd = "zpool add " . $this->name . " cache " . $this->getCommandString($vdevs);
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 }
226 }
227
228 /**
229 * XXX
230 *
231 * @param array $disks
232 * @return void
233 * @throws OMVModuleZFSException
234 * @access public
235 */
236 public function removeCache(array $disks = null) {
237 if (! $disks)
238 $disks = $this->cache;
239
240 foreach ($disks as $disk)
241 $dist_str .= "$disk ";
242
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);
250 }
251 }
252
253 /**
254 * XXX
255 *
256 * @return Cache
257 * @access public
258 */
259 public function getCache() {
260 return $this->cache;
261 }
262
263 /**
264 * XXX
265 *
266 * @param OMVModuleZFSVdev $log
267 * @return void
268 * @access public
269 */
270 public function addLog(OMVModuleZFSVdev $log) {
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");
281 }
282
283 /**
284 * XXX
285 *
286 * @return void
287 * @access public
288 */
289 public function removeLog() {
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 }
305 }
306
307 /**
308 * XXX
309 *
310 * @return Log
311 * @access public
312 */
313 public function getLog() {
314 return $this->log;
315 }
316
317 /**
318 * XXX
319 *
320 * @param OMVModuleZFSVdev $spares
321 * @return void
322 * @access public
323 */
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 }
337 }
338
339 /**
340 * XXX
341 *
342 * @param array $disks
343 * @return void
344 * @access public
345 */
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 }
361 }
362
363 /**
364 * XXX
365 *
366 * @return list<Disk>
367 * @access public
368 */
369 public function getSpares() {
370 return $this->spare;
371 }
372
373 /**
374 * XXX
375 *
376 * @return int
377 * @access public
378 */
379 public function getSize() {
380 return $this->size;
381 }
382
383 /**
384 * XXX
385 *
386 * @return string
387 * @access public
388 */
389 public function getMountPoint() {
390 return $this->mountPoint;
391 }
392
393 /**
394 * XXX
395 *
396 * @param array $features
397 * @return void
398 * @access public
399 */
400 public function setFeatures(array $features) {
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();
408 }
409
410 /**
411 * We only return array of features for which the user can
412 * change in GUI.
413 *
414 * @return array of features
415 * @access public
416 */
417 public function getFeatures() {
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;
441 }
442
443 /**
444 * XXX
445 *
446 * @return void
447 * @access public
448 */
449 public function export() {
450 $cmd = "zpool export " . $this->name;
451 OMVUtil::exec($cmd, $output, $result);
452 if ($result)
453 throw new OMVModuleZFSException($output);
454 }
455
456 /**
457 * XXX
458 *
459 * @param string $name
460 * @return void
461 * @access public
462 */
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);
471 }
472
473 /**
474 * XXX
475 *
476 * @return void
477 * @access public
478 */
479 public function scrub() {
480 $cmd = "zpool scrub " . $this->name;
481 OMVUtil::exec($cmd, $output, $result);
482 if ($result)
483 throw new OMVModuleZFSException($output);
484 }
485
486 /**
487 * XXX
488 *
489 * @return string
490 * @access public
491 */
492 public function status() {
493 $cmd = "zpool status " . $this->name;
494 OMVUtil::exec($cmd, $output, $result);
495 if ($result)
496 throw new OMVModuleZFSException($output);
497 }
498
499 public function bindListeners(OMVNotifyDispatcher $dispatcher) {
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"));
517 }
518
519 /**
520 * XXX
521 * org.openmediavault.services.nfs
522 *
523 * @param string event
524 * @access public
525 */
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)));
561 }
562
563 /**
564 * Convert array of Vdev to command string
565 *
566 * @param array $vdevs
567 * @return string
568 * @throws OMVMODULEZFSException
569 */
570 private function getCommandString(array $vdevs) {
571 $adds = array();
572
573 foreach ($vdevs as $vdev) {
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");
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);
600 }
601
602 /**
603 * Get an attribute from pool
604 *
605 * @param string $attribute
606 * @return string value
607 */
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;
619 }
620
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
642 /**
643 * Remove a disk from array
644 *
645 * @param array $array
646 * @param string $disk
647 * @return array
648 */
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;
658 }
659 }
660
661 ?>
This page took 0.14444 seconds and 6 git commands to generate.