]> git.datanom.net - omvzfs.git/blame - old/OMVModuleZPool.php
Minor change to clarify shared folder creation.
[omvzfs.git] / old / OMVModuleZPool.php
CommitLineData
76e64919
MR
1<?php
2/*
3 * OMVZModulePool.php
4 *
5 * Copyright 2013 Michael Rasmussen <mir@datanom.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
21 */
22
23/**
24 * @class OMVModuleZPool.
25 */
26
c6268644
MR
27require ('OMVModulePoolType.php');
28require ('OMVModulePoolAction.php');
76e64919
MR
29
30class OMVModuleZPool {
31
32 private $params;
33 private $log;
34 private $mirror_log;
35 private $cache;
36 private $spare;
c6268644
MR
37 private $alloc;
38 private $status; // one of null, ok, degraded, faulted, scrub, resilver
39 private $debug;
76e64919
MR
40
41 /**
42 * Constructor of class OMVModuleZPool.
43 * @param params Array which can contain all or a subset of
44 * the following fields:
c6268644
MR
45 * <ul>
46 * <li> atime Either true or false. <b>Default is true</b>.
47 * <li> compress Either true or false. <b>Default is false</b>.
48 * <li> dedub Either true or false. <b>Default is false</b>.
49 * <li> name Name for pool
50 * <li> size Size of pool in either MB or GB. 100M or 100G.
51 * <li> sync Either true or false. <b>Default is false</b>.
52 * <li> type See OMVModulePoolType.
53 * <li> vdevs Number of vdevs in pool. <b>Default is 1</b>.
54 * </ul>
55 * @param options Array which can contain all or a subset of
56 * the following fields:
57 * <ul>
58 * <li> log Array which contains the following fields:
59 * <ul>
60 * <li> disks Array of disks. Format: /dev/disk/by-id/.....
61 * <li> mirror Either true or false. <b>Default is false</b>.
62 * </ul>
63 * <li> cache Array which contains the following fields:
64 * <ul>
65 * <li> disks Array of disks. Format: /dev/disk/by-id/.... <b>Default use internal</b>.
66 * </ul>
67 * <li> spare Array of disks. Format: /dev/disk/by-id/...
68 * </ul>
76e64919
MR
69 * @param debug Print debug information to STDERR.
70 * @throws Exception.
71 */
c6268644 72 public function __construct(array $params = array(), array $options = array(), $debug = false) {
76e64919
MR
73 $this->params = array(
74 'atime' => 'on',
75 'compress' => 'off',
76 'dedub' => 'off',
77 'name' => '',
78 'size' => '0M',
79 'sync' => 'off',
80 'type' => OMVModulePoolType::OMVModulePoolType_TYPE_NONE,
81 'vdevs' => 1
82 );
c6268644 83 $this->debug = $debug;
76e64919
MR
84
85 foreach ($params as $key => $value) {
86 if (array_key_exists($key, $this->params)) {
87 $this->validate($key, $value);
88 $this->params[$key] = $value;
89 } else {
90 throw new Exception("$key: Not valid parameter");
91 }
92 }
93
c6268644
MR
94 foreach ($options as $key => $value) {
95 $this->validate($key, $value, true);
96 }
97
98 $this->status = null;
99
100 if ($this->debug) {
76e64919
MR
101 fprintf(STDERR, "OMVModuleZPool instantiate with the following params\n");
102 foreach ($this->params as $key => $value) {
103 $param = ($key == 'type') ? OMVModulePoolType::toString($value) : $value;
104 fprintf(STDERR, " %-8s => %s\n", $key, $param);
105 }
106 }
107 }
108
109 /**
110 * Create pool.
c6268644
MR
111 * @param disks Array of disks. Format: /dev/disk/by-id/...
112 * @param name Name for the pool.
113 * @param options Array which can contain all or a subset of
114 * the following fields:
115 * <ul>
116 * <li> log Array which contains the following fields:
117 * <ul>
118 * <li> disks Array of disks. Format: /dev/disk/by-id/...
119 * <li> mirror Either true or false. <b>Default is false</b>.
120 * </ul>
121 * <li> cache Array which contains the following fields:
122 * <ul>
123 * <li> disks Array of disks. Format: /dev/disk/by-id/... <b>Default use internal</b>.
124 * </ul>
125 * <li> spare Array of disks. Format: /dev/disk/by-id/...
126 * </ul>
127 * @throws Exception.
128 */
129 public function createPool(array $disks, $name = null, array $options = array()) {
130 return $this->updatePool(OMVModulePoolAction::OMVModulePoolAction_TYPE_CREATE,
131 $disks, count($disks), $name, $options);
132 }
133
134 /**
135 * Add pool.
136 * @param disks Array of disks. Format: /dev/disk/by-id/...
137 * @param name Name for the pool.
76e64919
MR
138 * @param options Array which can contain all or a subset of
139 * the following fields:
c6268644
MR
140 * <ul>
141 * <li> log Array which contains the following fields:
142 * <ul>
143 * <li> disks Array of disks. Format: /dev/disk/by-id/...
144 * <li> mirror Either true or false. <b>Default is false</b>.
145 * </ul>
146 * <li> cache Array which contains the following fields:
147 * <ul>
148 * <li> disks Array of disks. Format: /dev/disk/by-id/... <b>Default use internal</b>.
149 * </ul>
150 * <li> spare Array of disks. Format: /dev/disk/by-id/...
151 * </ul>
76e64919
MR
152 * @throws Exception.
153 */
c6268644
MR
154 public function addPool(array $disks, $name = null, array $options = array()) {
155 $this->initPool($name);
156 return $this->updatePool(OMVModulePoolAction::OMVModulePoolAction_TYPE_ADD,
157 $disks, count($disks), $name, $options);
158 }
159
160 public function removeDevice(array $disks, $name = null) {
161 }
162
163 public function destroyPool($name = null) {
164 }
165
166 public function scrubPool($name = null) {
167 }
168
169 public function exportPool($name = null){
170 }
171
172 public function importPool($name = null){
173 }
174
175 /*
176 * public function attachDevice($extingDisk, $newDisk, $name = null)
177 * public function detachDevice($disk, $name = null)
178 * public function onlineDevice($disk, $name = null)
179 * public function offlineDevice($disk, $name = null)
180 * public function replaceDevice($extingDisk, $newDisk, $name = null)
181 * public function upgradePool($name = null)
182 */
183
184 private function initPool($name = null) {
185 // Replace with OMVUtil::exec
186 $this->validateName($name);
187 }
188
189 private function validateName($name = null) {
190 $oldname = null;
191 if ($name != null) {
192 $oldname = $this->params['name'];
193 $this->params['name'] = $name;
194 }
195 if (! $this->params['name'] || ! preg_match('/^\w+$/', $this->params['name'])) {
196 if ($oldname) {
197 $this->params['name'] = $oldname;
198 }
199 throw new Exception("Name of pool cannot be null or empty");
200 }
201 }
202
203 /**
204 * Update pool.
205 * @param action Action to be taken. create or add.
206 * @param disks Array of disks. Format: /dev/disk/by-id/...
207 * @param disk_num Number of disk(s) in the pool.
208 * @param name Name for the pool.
209 * @param options Array which can contain all or a subset of
210 * the following fields:
211 * <ul>
212 * <li> log Array which contains the following fields:
213 * <ul>
214 * <li> disks Array of disks. Format: /dev/disk/by-id/...
215 * <li> mirror Either true or false. <b>Default is false</b>.
216 * </ul>
217 * <li> cache Array which contains the following fields:
218 * <ul>
219 * <li> disks Array of disks. Format: /dev/disk/by-id/... <b>Default use internal</b>.
220 * </ul>
221 * <li> spare Array of disks. Format: /dev/disk/by-id/...
222 * </ul>
223 * @throws Exception.
224 */
225 private function updatePool($action, array $disks, $disk_num, $name = null, array $options = array()) {
226 OMVModulePoolAction::toString($action);
227 $cmd = 'zpool ' . OMVModulePoolAction::getAction($action);
76e64919
MR
228 if ($disk_num < 1) {
229 throw new Exception("Pool must have at least 1 disk");
230 };
c6268644
MR
231 $this->validateName($name);
232 foreach ($options as $key => $value) {
233 $this->validate($key, $value, true);
234 }
235 switch ($action) {
236 case OMVModulePoolAction::OMVModulePoolAction_TYPE_CREATE:
237 $cmd .= ' ' . $this->params['name'];
238 break;
239 case OMVModulePoolAction::OMVModulePoolAction_TYPE_ADD:
240 $cmd .= ' ' . $this->params['name'];
241 break;
242 }
76e64919
MR
243 switch ($this->params['type']) {
244 case OMVModulePoolType::OMVModulePoolType_TYPE_NONE:
245 print "Create basic pool\n";
c6268644
MR
246 if ($this->params['vdevs'] != 1) {
247 throw new Exception("A basic zpool can only have 1 vdev");
76e64919 248 }
c6268644
MR
249 $vdev = '';
250 foreach ($disks as $disk) {
251 $vdev .= ($vdev) ? " $disk" : "$disk";
76e64919 252 }
c6268644 253 $cmd .= " $vdev";
76e64919
MR
254 break;
255 case OMVModulePoolType::OMVModulePoolType_TYPE_MIRROR:
256 print "Create mirrored pool\n";
257 if ($disk_num / $this->params['vdevs'] < 2 ||
258 ($disk_num / $this->params['vdevs']) % $this->params['vdevs']) {
259 throw new Exception("$disk_num disk(s) cannot be evenly distributed to ".
c6268644
MR
260 $this->params['vdevs']." vdev(s) and form a proper stripe or mirror");
261 }
262 $vdevs = array();
263 $disk_sum = $disk_num / $this->params['vdevs'];
264 $s = '';
265 for ($i = 1, $num = 0; $i <= $disk_num; $i++) {
266 $s .= ($s) ? " ${disks[$i-1]}" : "${disks[$i-1]}";
267 if ($i % $disk_sum == 0) {
268 $vdevs[$num++] = $s;
269 $s = '';
270 }
271 }
272 foreach ($vdevs as $vdev) {
273 $cmd .= " mirror $vdev";
76e64919
MR
274 }
275 break;
276 case OMVModulePoolType::OMVModulePoolType_TYPE_RAIDZ1:
277 print "Create raidz1 pool\n";
278 if ($disk_num / $this->params['vdevs'] < 3 ||
279 ($disk_num / $this->params['vdevs']) % $this->params['vdevs']) {
280 throw new Exception("$disk_num disk and ".$this->params['vdevs'].
281 " vdev(s) cannot provide mininum 3 disks per vdev for raidz1");
282 }
c6268644
MR
283 $vdevs = array();
284 $disk_sum = $disk_num / $this->params['vdevs'];
285 $s = '';
286 for ($i = 1, $num = 0; $i <= $disk_num; $i++) {
287 $s .= ($s) ? " ${disks[$i-1]}" : "${disks[$i-1]}";
288 if ($i % $disk_sum == 0) {
289 $vdevs[$num++] = $s;
290 $s = '';
291 }
292 }
293 foreach ($vdevs as $vdev) {
294 $cmd .= " raidz1 $vdev";
295 }
76e64919
MR
296 break;
297 case OMVModulePoolType::OMVModulePoolType_TYPE_RAIDZ2:
298 print "Create raidz2 pool\n";
c6268644 299 if ($disk_num / $this->params['vdevs'] < 4 ||
76e64919
MR
300 ($disk_num / $this->params['vdevs']) % $this->params['vdevs']) {
301 throw new Exception("$disk_num disk and ".$this->params['vdevs'].
c6268644
MR
302 " vdev(s) cannot provide mininum 4 disks per vdev for raidz2");
303 }
304 $vdevs = array();
305 $disk_sum = $disk_num / $this->params['vdevs'];
306 $s = '';
307 for ($i = 1, $num = 0; $i <= $disk_num; $i++) {
308 $s .= ($s) ? " ${disks[$i-1]}" : "${disks[$i-1]}";
309 if ($i % $disk_sum == 0) {
310 $vdevs[$num++] = $s;
311 $s = '';
312 }
313 }
314 foreach ($vdevs as $vdev) {
315 $cmd .= " raidz2 $vdev";
76e64919
MR
316 }
317 break;
318 case OMVModulePoolType::OMVModulePoolType_TYPE_RAIDZ3:
319 print "Create raidz3 pool\n";
c6268644 320 if ($disk_num / $this->params['vdevs'] < 5 ||
76e64919
MR
321 ($disk_num / $this->params['vdevs']) % $this->params['vdevs']) {
322 throw new Exception("$disk_num disk and ".$this->params['vdevs'].
c6268644
MR
323 " vdev(s) cannot provide mininum 5 disks per vdev for raidz3");
324 }
325 $vdevs = array();
326 $disk_sum = $disk_num / $this->params['vdevs'];
327 $s = '';
328 for ($i = 1, $num = 0; $i <= $disk_num; $i++) {
329 $s .= ($s) ? " ${disks[$i-1]}" : "${disks[$i-1]}";
330 if ($i % $disk_sum == 0) {
331 $vdevs[$num++] = $s;
332 $s = '';
333 }
334 }
335 foreach ($vdevs as $vdev) {
336 $cmd .= " raidz3 $vdev";
76e64919
MR
337 }
338 break;
339 }
c6268644
MR
340 foreach ($options as $key => $value) {
341 switch ($key) {
342 case 'log':
343 $cmd .= " log";
344 if ($value['mirror'] === true) {
345 $cmd .= " mirror";
346 }
347 foreach ($value['disks'] as $disk) {
348 $cmd .= " $disk";
349 }
76e64919 350 break;
c6268644
MR
351 case 'cache':
352 $cmd .= " cache";
353 foreach ($value as $disk) {
354 $cmd .= " $disk";
355 }
76e64919 356 break;
c6268644
MR
357 case 'spare':
358 $cmd .= " spare";
359 foreach ($value as $disk) {
360 $cmd .= " $disk";
361 }
76e64919 362 break;
c6268644
MR
363 }
364 }
365 if ($this->debug) {
366 fprintf(STDERR, "%s\n", $cmd);
367 }
368
369 return $cmd;
370 }
371
372 /**
373 * Validate options.
374 * @param key Option to validate.
375 * @param value Value for option to validate.
376 * @param type See OMVModulePoolType.
377 * @throws Exception if option is invalid.
378 */
379 private function validate($key, $value, $options = false) {
380 if ($options) {
381 switch ($key) {
382 case 'log':
383 if (! is_array($value) || ! array_key_exists('mirror', $value) ||
384 ! array_key_exists('disks', $value)) {
385 throw new Exception("log option missing disks array or mirror value");
386 }
387 if ($value['mirror'] === true && count($value['disks']) != 2) {
388 throw new Exception("Two disks is required to form a log mirror");
389 }
390 $this->log = $value['disks'];
391 $this->mirror_log = $value['mirror'];
392 break;
393 case 'cache':
394 if (! is_array($value)) {
395 throw new Exception("log option missing disks array or mirror value");
396 }
397 $this->cache = $value;
76e64919 398 break;
c6268644
MR
399 case 'spare':
400 if (! is_array($value)) {
401 throw new Exception("log option missing disks array or mirror value");
402 }
403 $this->spare = $value;
76e64919
MR
404 break;
405 default:
c6268644 406 throw new Exception("$key: Not valid option");
76e64919
MR
407 }
408 } else {
409 switch ($key) {
410 case 'atime':
411 case 'compress':
412 case 'dedub':
413 case 'sync':
414 if ($value != 'on' && $value != 'off') {
415 throw new Exception("$key: Value must be 'on' or 'off' found '$value'");
416 }
417 break;
418 case 'size':
419 if (! preg_match('/^\d+(M|G)$/', $value)) {
420 throw new Exception("$key: Value must have format '100M' or '100G' found '$value'");
421 }
422 break;
423 case 'type':
424 if (OMVModulePoolType::OMVModulePoolType_TYPE_NONE > $value ||
c6268644 425 OMVModulePoolType::OMVModulePoolType_TYPE_RAIDZ3 < $value) {
76e64919
MR
426 throw new Exception("$key: Value must be type of OMVPoolType found '$value'");
427 }
428 break;
429 case 'vdevs':
430 if (! preg_match('/^\d+$/', $value) || $value < 1) {
431 throw new Exception("$key: Value must be positive int found '$value'");
432 }
433 }
434 }
435 }
436}
This page took 0.10005 seconds and 5 git commands to generate.