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