]>
Commit | Line | Data |
---|---|---|
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 | * This vdev type | |
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 | * @throws OMVModuleZFSException | |
46 | */ | |
47 | ||
48 | public function __construct($pool, $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 | default: | |
69 | throw new OMVModuleZFSException("$type: Unknown zpool type"); | |
70 | } | |
71 | $this->pool = $pool; | |
72 | $this->disks = $disks; | |
73 | $this->type = $type; | |
74 | } | |
75 | ||
76 | /** | |
77 | * Helper function to execute an external program. | |
78 | * @param command The command that will be executed. | |
79 | * @param output If the output argument is present, then the specified | |
80 | * array will be filled with every line of output from the command. | |
81 | * Trailing whitespace, such as \n, is not included in this array. | |
82 | * @return The exit code of the command. | |
83 | * @throws E_EXEC_FAILED | |
84 | */ | |
85 | private function exec($command, &$output = NULL) { | |
86 | OMVUtil::exec($command, $output, $result); | |
87 | return $result; | |
88 | } | |
89 | ||
90 | private function safeExec($disk, $add = true, $change = false) { | |
91 | $result = 1; | |
92 | ||
93 | if ($add) { | |
94 | if ($change || $this->type == OMVModuleZFSVdevType::OMVMODULEZFSMIRROR) { | |
95 | $disk1 = $this->disks[0]; | |
96 | $result = exec("zpool attach {$this->pool} $disk1 $disk", $err); | |
97 | } else { | |
98 | $result = exec("zpool add {$this->pool} $disk", $err); | |
99 | } | |
100 | } else { | |
101 | if ($this->type == OMVModuleZFSVdevType::OMVMODULEZFSMIRROR) { | |
102 | $disk1 = $this->disks[0]; | |
103 | if (($res = exec("zpool offline {$this->pool} $disk", $err)) > 0) | |
104 | $result = $res; | |
105 | else | |
106 | $result = exec("zpool detach {$this->pool} $disk", $err); | |
107 | } else { | |
108 | $result = 1; | |
109 | $err = "Cannot remove $disk from {$this->pool}"; | |
110 | } | |
111 | } | |
112 | ||
113 | return ($result) ? $err : null; | |
114 | } | |
115 | ||
116 | /** | |
117 | * Add a disk to this Vdev | |
118 | * | |
119 | * @param $disk the disk | |
120 | * @throws OMVModuleZFSException | |
121 | * @access public | |
122 | */ | |
123 | public function addDisk($disk, $changeType = false) { | |
124 | if ($this->type != OMVModuleZFSVdevType::OMVMODULEZFSPLAIN || | |
125 | $this->type != OMVModuleZFSVdevType::OMVMODULEZFSMIRROR) | |
126 | throw new OMVModuleZFSException("A Raidz Vdev cannot be changed"); | |
127 | ||
128 | if (in_array($disk, $this->disks)) | |
129 | throw new OMVModuleZFSException("$disk: Already part of Vdev"); | |
130 | ||
131 | if ($this->type == OMVModuleZFSVdevType::OMVMODULEZFSPLAIN && | |
132 | count($this->disks) < 2 && $changeType) { | |
133 | $this->type = OMVModuleZFSVdevType::OMVMODULEZFSMIRROR; | |
134 | } | |
135 | ||
136 | if (($err = safeExec($disk, true, $changeType)) != null) | |
137 | throw new OMVModuleZFSException($err); | |
138 | else | |
139 | array_push($this->disks, $disk); | |
140 | } | |
141 | ||
142 | /** | |
143 | * Remove a disk from Vdev | |
144 | * | |
145 | * @param $disk disk to remove | |
146 | * @throws OMVModuleZFSException | |
147 | * @access public | |
148 | */ | |
149 | public function removeDisk($disk, $changeType = false) { | |
150 | $new_disks = array(); | |
151 | ||
152 | if ($this->type != OMVModuleZFSVdevType::OMVMODULEZFSMIRROR) | |
153 | throw new OMVModuleZFSException("Only inactive hot spares," . | |
154 | "cache, top-level, or log devices can be removed"); | |
155 | ||
156 | if (count($this->disks) < 3 && ! $changeType) | |
157 | throw new OMVModuleZFSException("A mirror must contain at least 2 disks"); | |
158 | ||
159 | if (! in_array($disk, $this->disks)) | |
160 | throw new OMVModuleZFSException("$disk: Not part of Vdev"); | |
161 | ||
162 | if (($err = safeExec($disk, false, $changeType)) != null) | |
163 | throw new OMVModuleZFSException($err); | |
164 | else { | |
165 | foreach ($this->disks as $_disk) { | |
166 | if (strcmp($_disk, $disk) != 0) | |
167 | array_push($new_disks, $_disk); | |
168 | } | |
169 | } | |
170 | ||
171 | $this->disks = $new_disks; | |
172 | } | |
173 | ||
174 | /** | |
175 | * Get disk array | |
176 | * | |
177 | * @return array with disks | |
178 | * @access public | |
179 | */ | |
180 | public function getDisks() { | |
181 | return $this->disks; | |
182 | } | |
183 | ||
184 | /** | |
185 | * Get pool | |
186 | * | |
187 | * @return string pool | |
188 | * @access public | |
189 | */ | |
190 | public function getPool() { | |
191 | return $this->pool; | |
192 | } | |
193 | ||
194 | /** | |
195 | * Get type | |
196 | * | |
197 | * @return OMVModuleZFSVdevType | |
198 | * @access public | |
199 | */ | |
200 | public function getType() { | |
201 | return $this->type; | |
202 | } | |
203 | ||
204 | } | |
205 | ||
206 | ?> |