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