]> git.datanom.net - omvzfs.git/blob - src/Vdev.php
Refactored to mimic zpool create
[omvzfs.git] / src / Vdev.php
1 <?php
2 require_once("Exception.php");
3 require_once("VdevType.php");
4 require_once("openmediavault/util.inc");
5
6 /**
7 * Contains a Vdev
8 *
9 * @author Michael Rasmussen
10 * @version 0.1
11 * @copyright Michael Rasmussen <mir@datanom.net>
12 */
13 class OMVModuleZFSVdev {
14 // Attributes
15 /**
16 * Array holding disks
17 *
18 * @var array $disks
19 * @access private
20 */
21 private $disks;
22
23 /**
24 * Name of pool
25 *
26 * @var string $pool pool name
27 * @access private
28 */
29 private $pool;
30
31 /**
32 * Array holding disks
33 *
34 * @var OMVModuleZFSVdevType $type Vdev type
35 * @access private
36 */
37 private $type;
38
39 // Associations
40 // Operations
41 /**
42 * Constructor
43 *
44 * @param $pool pool this mirror belongs to
45 */
46
47 public function __construct($pool, OMVModuleZFSVdevType $type, array $disks) {
48 switch ($type) {
49 case OMVModuleZFSVdevType::OMVMODULEZFSPLAIN:
50 break;
51 case OMVModuleZFSVdevType::OMVMODULEZFSMIRROR:
52 if (count($disks) < 2)
53 throw new OMVModuleZFSException("A mirror must contain at least 2 disks");
54 break;
55 case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ1:
56 if (count($disks) < 3)
57 throw new OMVModuleZFSException("A Raidz1 must contain at least 3 disks");
58 break;
59 case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ2:
60 if (count($disks) < 4)
61 throw new OMVModuleZFSException("A Raidz2 must contain at least 4 disks");
62 break;
63 case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ3:
64 if (count($disks) < 5)
65 throw new OMVModuleZFSException("A Raidz3 must contain at least 5 disks");
66 break;
67 }
68 $this->pool = $pool;
69 $this->disks = $disks;
70 $this->type = $type;
71 }
72
73 /**
74 * Helper function to execute an external program.
75 * @param command The command that will be executed.
76 * @param output If the output argument is present, then the specified
77 * array will be filled with every line of output from the command.
78 * Trailing whitespace, such as \n, is not included in this array.
79 * @return The exit code of the command.
80 * @throws E_EXEC_FAILED
81 */
82 private function exec($command, &$output = NULL) {
83 OMVUtil::exec($command, $output, $result);
84 return $result;
85 }
86
87 private function safeExec($disk, $add = true, $change = false) {
88 $result = 1;
89
90 if ($add) {
91 if ($change || $this->type == OMVModuleZFSVdevType::OMVMODULEZFSMIRROR) {
92 $disk1 = $this->disks[0];
93 $result = exec("zpool attach {$this->pool} $disk1 $disk", $err);
94 } else {
95 $result = exec("zpool add {$this->pool} $disk", $err);
96 }
97 } else {
98 if ($this->type == OMVModuleZFSVdevType::OMVMODULEZFSMIRROR) {
99 $disk1 = $this->disks[0];
100 if (($res = exec("zpool offline {$this->pool} $disk", $err)) > 0)
101 $result = $res;
102 else
103 $result = exec("zpool detach {$this->pool} $disk", $err);
104 } else {
105 $result = 1;
106 $err = "Cannot remove $disk from {$this->pool}";
107 }
108 }
109
110 return ($result) ? $err : null;
111 }
112
113 /**
114 * Add a disk to this Vdev
115 *
116 * @param $disk the disk
117 * @throws OMVModuleZFSException
118 * @access public
119 */
120 public function addDisk($disk, $changeType = false) {
121 if ($this->type != OMVModuleZFSVdevType::OMVMODULEZFSPLAIN ||
122 $this->type != OMVModuleZFSVdevType::OMVMODULEZFSMIRROR)
123 throw new OMVModuleZFSException("A Raidz Vdev cannot be changed");
124
125 if (in_array($disk, $this->disks))
126 throw new OMVModuleZFSException("$disk: Already part of Vdev");
127
128 if ($this->type == OMVModuleZFSVdevType::OMVMODULEZFSPLAIN &&
129 count($this->disks) < 2 && $changeType) {
130 $this->type = OMVModuleZFSVdevType::OMVMODULEZFSMIRROR;
131 }
132
133 if (($err = safeExec($disk, true, $changeType)) != null)
134 throw new OMVModuleZFSException($err);
135 else
136 array_push($this->disks, $disk);
137 }
138
139 /**
140 * Remove a disk from Vdev
141 *
142 * @param $disk disk to remove
143 * @throws OMVModuleZFSException
144 * @access public
145 */
146 public function removeDisk($disk, $changeType = false) {
147 $new_disks = array();
148
149 if ($this->type != OMVModuleZFSVdevType::OMVMODULEZFSMIRROR)
150 throw new OMVModuleZFSException("Only inactive hot spares," .
151 "cache, top-level, or log devices can be removed");
152
153 if (count($this->disks) < 3 && ! $changeType)
154 throw new OMVModuleZFSException("A mirror must contain at least 2 disks");
155
156 if (! in_array($disk, $this->disks))
157 throw new OMVModuleZFSException("$disk: Not part of Vdev");
158
159 if (($err = safeExec($disk, false, $changeType)) != null)
160 throw new OMVModuleZFSException($err);
161 else {
162 foreach ($this->disks as $_disk) {
163 if (strcmp($_disk, $disk) != 0)
164 array_push($new_disks, $_disk);
165 }
166 }
167
168 $this->disks = $new_disks;
169 }
170
171 /**
172 * Get disk array
173 *
174 * @return array with disks
175 * @access public
176 */
177 public function getDisks() {
178 return $this->disks;
179 }
180
181 /**
182 * Get pool
183 *
184 * @return string pool
185 * @access public
186 */
187 public function getPool() {
188 return $pool;
189 }
190
191 }
192
193 ?>
This page took 0.075632 seconds and 6 git commands to generate.