]>
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, 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 | ||
114 | /** | |
115 | * Add a disk to this Vdev | |
116 | * | |
117 | * @param $disk the disk | |
118 | * @throws OMVModuleZFSException | |
119 | * @access public | |
120 | */ | |
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); | |
138 | } | |
139 | ||
140 | /** | |
141 | * Remove a disk from Vdev | |
142 | * | |
143 | * @param $disk disk to remove | |
144 | * @throws OMVModuleZFSException | |
145 | * @access public | |
146 | */ | |
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 | } | |
171 | ||
172 | /** | |
173 | * Get disk array | |
174 | * | |
175 | * @return array with disks | |
176 | * @access public | |
177 | */ | |
178 | public function getDisks() { | |
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; | |
190 | } | |
191 | ||
192 | /** | |
193 | * Get type | |
194 | * | |
195 | * @return OMVModuleZFSVdevType | |
196 | * @access public | |
197 | */ | |
198 | public function getType() { | |
199 | return $type; | |
200 | } | |
201 | ||
202 | } | |
203 | ||
204 | ?> |