]> git.datanom.net - omvzfs.git/blob - src/Utils.php
4ccf60f8f58b776dbcd48814d51ae7419040bb5f
[omvzfs.git] / src / Utils.php
1 <?php
2 require_once("Exception.php");
3 require_once("openmediavault/util.inc");
4 require_once("Dataset.php");
5 require_once("Zvol.php");
6 require_once("Vdev.php");
7 require_once("Zpool.php");
8
9 /**
10 * Helper class for ZFS module
11 */
12 class OMVModuleZFSUtil {
13
14 /**
15 * Sets a GPT label on a disk to prevent the zpool command from generating
16 * errors.
17 *
18 */
19 public static function setGPTLabel($disk) {
20 $cmd = "parted " . $disk . " mklabel gpt 2>&1";
21 OMVModuleZFSUtil::exec($cmd,$out,$res);
22 }
23
24 /**
25 * Manages relocation of ZFS filesystem mountpoints in the OMV backend.
26 * Needed when the user changes mountpoint of a filesystem in the GUI.
27 *
28 */
29 public static function relocateFilesystem($name) {
30 global $xmlConfig;
31 $poolname = OMVModuleZFSUtil::getPoolname($name);
32 $pooluuid = OMVModuleZFSUtil::getUUIDbyName($poolname);
33 $ds = new OMVModuleZFSDataset($name);
34 $dir = $ds->getMountPoint();
35 $xpath = "//system/fstab/mntent[fsname='" . $pooluuid . "' and dir='" . $dir . "' and type='zfs']";
36 $object = $xmlConfig->get($xpath);
37 $object['dir'] = $property['value'];
38 $xmlConfig->replace($xpath, $object);
39 return null;
40 }
41
42 /**
43 * Clears all ZFS labels on specified devices.
44 * Needed for blkid to display proper data.
45 *
46 */
47 public static function clearZFSLabel($disks) {
48 foreach ($disks as $disk) {
49 $cmd = "zpool labelclear /dev/" . $disk . "1";
50 OMVModuleZFSUtil::exec($cmd,$out,$res);
51 }
52 return null;
53 }
54
55 /**
56 * Return all disks in /dev/sdXX used by the pool
57 *
58 * @return array An array with all the disks
59 */
60 public static function getDevDisksByPool($name) {
61 $pool = new OMVModuleZFSZpool($name);
62 $disks = array();
63 $vdevs = $pool->getVdevs();
64 foreach ($vdevs as $vdev) {
65 $vdisks = $vdev->getDisks();
66 foreach ($vdisks as $vdisk) {
67 if (preg_match('/^[a-z0-9]+$/', $vdisk)) {
68 $disks[] = $vdisk;
69 continue;
70 }
71 $cmd = "ls -la /dev/disk/by-path/" . $vdisk;
72 unset($out);
73 OMVModuleZFSUtil::exec($cmd,$out,$res);
74 if (count($out) === 1) {
75 if (preg_match('/^.*\/([a-z0-9]+)$/', $out[0], $match)) {
76 $disks[] = $match[1];
77 }
78 }
79 }
80 }
81 return($disks);
82 }
83
84 /**
85 * Deletes all shared folders pointing to the specifc path
86 *
87 */
88 public static function deleteShares($name) {
89 global $xmlConfig;
90 $poolname = OMVModuleZFSUtil::getPoolname($name);
91 $pooluuid = OMVModuleZFSUtil::getUUIDbyName($poolname);
92 $ds = new OMVModuleZFSDataset($name);
93 $dir = $ds->getMountPoint();
94 $xpath = "//system/fstab/mntent[fsname='" . $pooluuid . "' and dir='" . $dir . "' and type='zfs']";
95 $mountpoint = $xmlConfig->get($xpath);
96 $mntentuuid = $mountpoint['uuid'];
97 $xpath = "//system/shares/sharedfolder[mntentref='" . $mntentuuid . "']";
98 $objects = $xmlConfig->getList($xpath);
99 foreach ($objects as $object) {
100 $tmpxpath = sprintf("//*[contains(name(),'sharedfolderref')]".
101 "[contains(.,'%s')]", $object['uuid']);
102 if ($xmlConfig->exists($tmpxpath)) {
103 throw new OMVModuleZFSException("The Filesystem is shared and in use. Please delete all references and try again.");
104 }
105 }
106 $xmlConfig->delete($xpath);
107 $dispatcher = &OMVNotifyDispatcher::getInstance();
108 $dispatcher->notify(OMV_NOTIFY_DELETE,"org.openmediavault.system.shares.sharedfolder",$object);
109 }
110
111 /**
112 * Get the relative path by complete path
113 *
114 * @return string Relative path of the complet path
115 */
116 public static function getReldirpath($path) {
117 $subdirs = preg_split('/\//',$path);
118 $reldirpath = "";
119 for ($i=2;$i<count($subdirs);$i++) {
120 $reldirpath .= $subdirs[$i] . "/";
121 }
122 return(rtrim($reldirpath, "/"));
123
124 }
125
126 /**
127 * Get /dev/disk/by-path from /dev/sdX
128 *
129 * @return string Disk identifier
130 */
131 public static function getDiskPath($disk) {
132 preg_match("/^.*\/([A-Za-z0-9]+)$/", $disk, $identifier);
133 $cmd = "ls -la /dev/disk/by-path | grep '$identifier[1]$'";
134 OMVModuleZFSUtil::exec($cmd, $out, $res);
135 if (is_array($out)) {
136 $cols = preg_split('/[\s]+/', $out[0]);
137 return($cols[count($cols)-3]);
138 }
139 }
140
141
142 /**
143 * Get poolname from name of dataset/volume etc.
144 *
145 * @return string Name of the pool
146 */
147 public static function getPoolname($name) {
148 $tmp = preg_split('/[\/]+/', $name);
149 return($tmp[0]);
150 }
151
152 /**
153 * Get UUID of ZFS pool by name
154 *
155 * @return string UUID of the pool
156 */
157 public static function getUUIDbyName($poolname) {
158 $cmd = "zpool get guid " . $poolname . " 2>&1";
159 OMVModuleZFSUtil::exec($cmd, $out, $res);
160 if (isset($out)) {
161 $headers = preg_split('/[\s]+/', $out[0]);
162 for ($i=0; $i<count($headers); $i++) {
163 if (strcmp($headers[$i], "VALUE") === 0) {
164 $valuecol=$i;
165 break;
166 }
167 }
168 $line = preg_split('/[\s]+/', $out[1]);
169 return $line[$valuecol];
170 }
171 return null;
172 }
173
174 /**
175 * Add any missing ZFS filesystems to the OMV backend
176 *
177 */
178 public static function addMissingOMVMntEnt() {
179 global $xmlConfig;
180 $cmd = "zfs list -H -o name -t filesystem";
181 OMVModuleZFSUtil::exec($cmd, $out, $res);
182 foreach($out as $name) {
183 if (preg_match('/[\/]+/', $name)) {
184 $poolname = OMVModuleZFSUtil::getPoolname($name);
185 $pooluuid = OMVModuleZFSUtil::getUUIDbyName($poolname);
186 $ds = new OMVModuleZFSDataset($name);
187 $dir = $ds->getMountPoint();
188 $xpath = "//system/fstab/mntent[fsname='" . $pooluuid . "' and dir='" . $dir . "' and type='zfs']";
189 if (!($xmlConfig->exists($xpath))) {
190 $uuid = OMVUtil::uuid();
191 $object = array(
192 "uuid" => $uuid,
193 "fsname" => $pooluuid,
194 "dir" => $dir,
195 "type" => "zfs",
196 "opts" => "rw,relatime,xattr,noacl",
197 "freq" => "0",
198 "passno" => "0",
199 "hidden" => "1"
200 );
201 $xmlConfig->set("//system/fstab",array("mntent" => $object));
202 }
203 }
204 }
205 return null;
206 }
207
208 /**
209 * Get an array with all ZFS objects
210 *
211 * @return An array with all ZFS objects
212 */
213 public static function getZFSFlatArray() {
214 $prefix = "root/pool-";
215 $objects = array();
216 $cmd = "zfs list -H -t all -o name,type 2>&1";
217 $expanded = true;
218 OMVModuleZFSUtil::exec($cmd,$out,$res);
219 foreach ($out as $line) {
220 $parts = preg_split('/\t/',$line);
221 $path = $parts[0];
222 $type = $parts[1];
223 $subdirs = preg_split('/\//',$path);
224 $root = $subdirs[0];
225 $tmp = array();
226
227 switch ($type) {
228 case "filesystem":
229 if (strpos($path,'/') === false) {
230 //This is a Pool
231 $tmp = array('id'=>$prefix . $path,
232 'parentid'=>'root',
233 'name'=>$path,
234 'type'=>'Pool',
235 'icon'=>'images/raid.png',
236 'expanded'=>$expanded,
237 'path'=>$path);
238 $pool = new OMVModuleZFSZpool($path);
239 $tmp['origin'] = "n/a";
240 $tmp['size'] = $pool->getSize();
241 $tmp['used'] = $pool->getAttribute("allocated");
242 $tmp['available'] = $pool->getAttribute("free");
243 $tmp['mountpoint'] = $pool->getMountPoint();
244 array_push($objects,$tmp);
245 } else {
246 //This is a Filesystem
247 preg_match('/(.*)\/(.*)$/', $path, $result);
248 $tmp = array('id'=>$prefix . $path,
249 'parentid'=>$prefix . $result[1],
250 'name'=>$result[2],
251 'icon'=>"images/filesystem.png",
252 'path'=>$path,
253 'expanded'=>$expanded);
254 $ds = new OMVModuleZFSDataset($path);
255 if ($ds->isClone()) {
256 //This is a cloned Filesystem
257 $tmp['origin'] = $ds->getOrigin();
258 } else {
259 //This is a standard Filesystem.
260 $tmp['origin'] = "n/a";
261 }
262 $tmp['type']= ucfirst($type);
263 $tmp['size'] = "n/a";
264 $used = $ds->getProperty("used");
265 $tmp['used'] = $used['value'];
266 $available = $ds->getProperty("available");
267 $tmp['available'] = $available['value'];
268 $tmp['mountpoint'] = $ds->getMountPoint();
269 array_push($objects,$tmp);
270 }
271 break;
272
273 case "volume":
274 preg_match('/(.*)\/(.*)$/', $path, $result);
275 $tmp = array('id'=>$prefix . $path,
276 'parentid'=>$prefix . $result[1],
277 'name'=>$result[2],
278 'type'=>ucfirst($type),
279 'icon'=>"images/save.png",
280 'path'=>$path,
281 'expanded'=>$expanded);
282 $vol = new OMVModuleZFSZvol($path);
283 if ($vol->isClone()) {
284 //This is a cloned Volume
285 $tmp['origin'] = $vol->getOrigin();
286 } else {
287 //This is a standard Volume
288 $tmp['origin'] = "n/a";
289 }
290 $tmp['type']= ucfirst($type);
291 $tmp['size'] = $vol->getSize();
292 $tmp['used'] = "n/a";
293 $tmp['available'] = "n/a";
294 $tmp['mountpoint'] = "n/a";
295 array_push($objects,$tmp);
296 break;
297
298 case "snapshot":
299 preg_match('/(.*)\@(.*)$/', $path, $result);
300 $subdirs = preg_split('/\//',$result[1]);
301 $root = $subdirs[0];
302 $tmp = array('id'=>$prefix . $path,
303 'parentid'=>$prefix . $result[1],
304 'name'=>$result[2],
305 'type'=>ucfirst($type),
306 'icon'=>'images/zfs_snap.png',
307 'path'=>$path,
308 'expanded'=>$expanded);
309 $tmp['origin'] = "n/a";
310 $tmp['size'] = "n/a";
311 $tmp['used'] = "n/a";
312 $tmp['available'] = "n/a";
313 $tmp['mountpoint'] = "n/a";
314 array_push($objects,$tmp);
315 break;
316
317 default:
318 break;
319 }
320 }
321 return $objects;
322 }
323
324 /**
325 * Create a tree structured array
326 *
327 * @param &$list The flat array to convert to a tree structure
328 * @param $parent Root node of the tree to create
329 * @return Tree structured array
330 *
331 */
332 public static function createTree(&$list, $parent){
333 $tree = array();
334 foreach ($parent as $k=>$l){
335 if(isset($list[$l['id']])){
336 $l['leaf'] = false;
337 $l['children'] = OMVModuleZFSUtil::createTree($list, $list[$l['id']]);
338 } else {
339 $l['leaf'] = true;
340 }
341 $tree[] = $l;
342 }
343 return $tree;
344 }
345
346 /**
347 * Get all Datasets as objects
348 *
349 * @return An array with all the Datasets
350 */
351 public static function getAllDatasets() {
352 $datasets = array();
353 $cmd = "zfs list -H -t filesystem -o name 2>&1";
354 OMVModuleZFSUtil::exec($cmd, $out, $res);
355 foreach ($out as $name) {
356 $ds = new OMVModuleZFSDataset($name);
357 array_push($datasets, $ds);
358 }
359 return $datasets;
360 }
361
362 /**
363 * Helper function to execute a command and throw an exception on error
364 * (requires stderr redirected to stdout for proper exception message).
365 *
366 * @param string $cmd Command to execute
367 * @param array &$out If provided will contain output in an array
368 * @param int &$res If provided will contain Exit status of the command
369 * @return string Last line of output when executing the command
370 * @throws OMVModuleZFSException
371 * @access public
372 */
373 public static function exec($cmd, &$out = null, &$res = null) {
374 $tmp = OMVUtil::exec($cmd, $out, $res);
375 if ($res) {
376 throw new OMVModuleZFSException(implode("\n", $out));
377 }
378 return $tmp;
379 }
380
381 }
382
383
384 ?>
This page took 0.099875 seconds and 4 git commands to generate.