]> git.datanom.net - omvzfs.git/blob - gui/rpc/zfs.inc
7a6b36410e58b4021a9fcc030a1f96163441f158
[omvzfs.git] / gui / rpc / zfs.inc
1 <?php
2
3 require_once("openmediavault/object.inc");
4 require_once("openmediavault/config.inc");
5 require_once("openmediavault/error.inc");
6 require_once("openmediavault/util.inc");
7 require_once("openmediavault/rpcservice.inc");
8 require_once("openmediavault/notify.inc");
9 require_once("zfs/Utils.php");
10 require_once("zfs/Dataset.php");
11 require_once("zfs/Snapshot.php");
12 require_once("zfs/Zvol.php");
13 require_once("zfs/Zpool.php");
14 require_once("zfs/NotifyListener.php");
15
16 class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
17 public function getName() {
18 return "ZFS"; // RPC Service name. Same as in .js files
19 }
20
21 /* Initialize the RPC service. Different methods of the RPC service are declared here*/
22 public function initialize() {
23 $this->registerMethod("addPool");
24 $this->registerMethod("getObjectTree");
25 $this->registermethod("passParam");
26 $this->registermethod("addObject");
27 $this->registermethod("deleteObject");
28 $this->registermethod("getProperties");
29 $this->registermethod("setProperties");
30 $this->registermethod("inherit");
31 $this->registermethod("getSharedParams");
32 $this->registermethod("createShare");
33 $this->registermethod("getObjectDetails");
34 }
35
36 public function addPool($params, $context) {
37 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
38 // Validate the parameters of the RPC service method.
39 $this->validateMethodParams($params, '{
40 "type":"object",
41 "properties":{
42 "pooltype":{"type":"string","enum":["basic","mirror",' .
43 '"raidz1","raidz2","raidz3"]},
44 "force":{"type":"boolean"},
45 "mountpoint":{"type":"string"},
46 "name":{"type":"string"},
47 "devices":{"type":"string"}
48 }
49 }');
50 switch ($params['pooltype']) {
51 case "basic":
52 $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSPLAIN;
53 break;
54 case "mirror":
55 $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSMIRROR;
56 break;
57 case "raidz1":
58 $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ1;
59 break;
60 case "raidz2":
61 $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ2;
62 break;
63 case "raidz3":
64 $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ3;
65 break;
66 default:
67 throw new OMVModuleZFSException("Incorrect pool type specified");
68 break;
69 }
70 //Check for user supplied options
71 $opts = "";
72 if ($params['force']) {
73 $opts .= "-f ";
74 }
75 if (strlen($params['mountpoint']) > 0) {
76 $opts .= "-m " . $params['mountpoint'] . " ";
77 }
78
79 //Use /dev/disk/by-path as deafult when creating new pools as suggested in ZoL FAQ.
80 $disks = preg_split("/[,;]/", $params['devices']);
81 if (file_exists("/dev/disk/by-path/")) {
82 $tmp_disks = array();
83 foreach ($disks as $disk) {
84 $tmp_disks[] = OMVModuleZFSUtil::getDiskPath($disk);
85 }
86 $disks = $tmp_disks;
87 }
88
89 $vdev = new OMVModuleZFSVdev($params['name'], $pooltype, $disks);
90 $pool = new OMVModuleZFSZpool($vdev, $opts);
91 //Ugly fix to solve the problem of blkid not displaying info on newly created pools
92 $pool->export();
93 $pool->import($pool->getName());
94 }
95
96 public function getObjectTree($params, $context) {
97 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
98 $objects = OMVModuleZFSUtil::getZFSFlatArray();
99 $new = array();
100 foreach ($objects as $a){
101 $new[$a['parentid']][] = $a;
102 }
103 $tree = OMVModuleZFSUtil::createTree($new, $new['root']);
104 OMVModuleZFSUtil::addMissingOMVMntEnt(); //Adds missing ZFS filesystems to the OMV core
105 return $tree;
106 }
107
108 public function passParam($params, $context) {
109 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
110 // Validate the parameters of the RPC service method.
111 $this->validateMethodParams($params, '{
112 "type":"object",
113 "properties":{
114 "key":{"type":"string"},
115 "value":{"type":"string"}
116 }
117 }');
118 return array($params['key'] => $params['value']);
119 }
120
121 public function addObject($params, $context) {
122 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
123 // Validate the parameters of the RPC service method.
124 $this->validateMethodParams($params, '{
125 "type":"object",
126 "properties":{
127 "type":{"type":"string","enum":["filesystem","snapshot",' .
128 '"volume"]},
129 "path":{"type":"string"},
130 "name":{"type":"string"},
131 "size":{"type":"string"}
132 }
133 }');
134 switch ($params['type']) {
135 case "filesystem":
136 $name = $params['path'] . "/" . $params['name'];
137 $tmp = new OMVModuleZFSDataset($name);
138 break;
139 case "snapshot":
140 $name = $params['path'] . "@" . $params['name'];
141 $tmp = new OMVModuleZFSSnapshot($name);
142 break;
143 case "volume":
144 $name = $params['path'] . "/" . $params['name'];
145 $tmp = new OMVModuleZFSZvol($name);
146 $tmp->create($params['size']);
147 break;
148 default:
149 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
150 break;
151 }
152 }
153
154 public function deleteObject($params, $context) {
155 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
156 // Validate the parameters of the RPC service method.
157 $this->validateMethodParams($params, '{
158 "type":"object",
159 "properties":{
160 "type":{"type":"string","enum":["Filesystem","Snapshot",' .
161 '"Volume","Clone","Pool"]},
162 "name":{"type":"string"}
163 }
164 }');
165 global $xmlConfig;
166 $name = $params['name'];
167 switch ($params['type']) {
168 case "Filesystem":
169 OMVModuleZFSUtil::deleteShares($name);
170 $tmp = new OMVModuleZFSDataset($name);
171 $tmp->destroy();
172 break;
173 case "Clone":
174 $tmp = new OMVModuleZFSDataset($name);
175 $tmp->destroy();
176 break;
177 case "Snapshot":
178 $tmp = new OMVModuleZFSSnapshot($name);
179 $tmp->destroy();
180 break;
181 case "Volume":
182 $tmp = new OMVModuleZFSZvol($name);
183 $tmp->destroy();
184 break;
185 case "Pool":
186 $disks = OMVModuleZFSUtil::getDevDisksByPool($name);
187 $pooluuid = OMVModuleZFSUtil::getUUIDbyName($name);
188 $tmp = new OMVModuleZFSZpool($name);
189 $tmp->destroy();
190 $xpath = "//system/fstab/mntent[fsname='" . $pooluuid . "' and type='zfs']";
191 $object = $xmlConfig->get($xpath);
192 $xmlConfig->delete($xpath);
193 $dispatcher = &OMVNotifyDispatcher::getInstance();
194 $dispatcher->notify(OMV_NOTIFY_DELETE,"org.openmediavault.system.fstab.mntent", $object);
195 OMVModuleZFSUtil::clearZFSLabel($disks);
196 break;
197 default:
198 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
199 break;
200 }
201 }
202
203 public function getProperties($params, $context) {
204 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
205 // Validate the parameters of the RPC service method.
206 $this->validateMethodParams($params, '{
207 "type":"object",
208 "properties":{
209 "type":{"type":"string"},
210 "name":{"type":"string"},
211 "start":{"type":"integer"},
212 "limit":{'.$GLOBALS['OMV_JSONSCHEMA_COUNTFIELD'].'},
213 "sortfield":{'.$GLOBALS['OMV_JSONSCHEMA_SORTFIELD'].'},
214 "sortdir":{'.$GLOBALS['OMV_JSONSCHEMA_SORTDIR'].'}
215 }
216 }');
217 $objects = array();
218 $name = $params['name'];
219 switch ($params['type']) {
220 case "Filesystem":
221 case "Clone":
222 $tmp = new OMVModuleZFSDataset($name);
223 break;
224 case "Snapshot":
225 $tmp = new OMVModuleZFSSnapshot($name);
226 break;
227 case "Volume":
228 $tmp = new OMVModuleZFSZvol($name);
229 break;
230 case "Pool":
231 $tmp = new OMVModuleZFSZpool($name);
232 break;
233 default:
234 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
235 break;
236 }
237 $properties = $tmp->getProperties();
238 foreach ($properties as $propertyk => $propertyv) {
239 if (!(strcmp($propertyv['source'], "-") == 0)) {
240 $objects[] = array('property' => $propertyk,
241 'value' => $propertyv['value'],
242 'source' => $propertyv['source'],
243 'modified' => "false");
244 }
245 }
246 return $objects;
247 }
248
249 public function setProperties($params, $context) {
250 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
251 // Validate the parameters of the RPC service method.
252 $this->validateMethodParams($params, '{
253 "type":"object",
254 "properties":{
255 "type":{"type":"string","enum":["Filesystem","Snapshot",' .
256 '"Volume","Clone","Pool"]},
257 "name":{"type":"string"},
258 "properties":{"type":"array","items":{
259 "type":"object",
260 "properties":{
261 "property":{"type":"string"},
262 "value":{"type":"string"}}}}
263 }
264 }');
265 $objects = array();
266 switch ($params['type']) {
267 case "Filesystem":
268 case "Clone":
269 $tmp = new OMVModuleZFSDataset($params['name']);
270 break;
271 case "Snapshot":
272 $tmp = new OMVModuleZFSSnapshot($params['name']);
273 break;
274 case "Volume":
275 $tmp = new OMVModuleZFSZvol($params['name']);
276 break;
277 case "Pool":
278 $tmp = new OMVModuleZFSZpool($params['name']);
279 break;
280 default:
281 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
282 break;
283 }
284 foreach ($params['properties'] as $property) {
285 $objects[$property['property']] = $property['value'];
286 }
287 $tmp->setProperties($objects);
288 }
289
290 public function inherit($params, $context) {
291 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
292 // Validate the parameters of the RPC service method.
293 $this->validateMethodParams($params, '{
294 "type":"object",
295 "properties":{
296 "type":{"type":"string","enum":["Filesystem","Snapshot",' .
297 '"Volume","Clone","Pool"]},
298 "name":{"type":"string"},
299 "property":{"type":"string"}
300 }
301 }');
302 // Create a background process.
303 $bgStatusFilename = $this->createBgProcStatus();
304 $pid = $this->fork();
305 if($pid > 0) { // Parent process.
306 $this->initializeBgProcStatus($bgStatusFilename, $pid);
307 return $bgStatusFilename;
308 }
309 // Child process.
310 try {
311 $bgOutputFilename = $this->createBgProcOutput();
312 $this->updateBgProcStatus($bgStatusFilename, "outputfilename", $bgOutputFilename);
313 switch ($params['type']) {
314 case "Filesystem":
315 case "Clone":
316 $tmp = new OMVModuleZFSDataset($params['name']);
317 break;
318 case "Snapshot":
319 $tmp = new OMVModuleZFSSnapshot($params['name']);
320 break;
321 case "Volume":
322 $tmp = new OMVModuleZFSZvol($params['name']);
323 break;
324 case "Pool":
325 $tmp = new OMVModuleZFSZpool($params['name']);
326 break;
327 default:
328 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
329 break;
330 }
331 $tmp->inherit($params['property']);
332 $this->finalizeBgProcStatus($bgStatusFilename, $output);
333 exit(0);
334 } catch(Exception $e) {
335 $this->finalizeBgProcStatus($bgStatusFilename, "", $e);
336 exit(1);
337 }
338 }
339
340 public function getSharedParams($params, $context) {
341 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
342 // Validate the parameters of the RPC service method.
343 $this->validateMethodParams($params, '{
344 "type":"object",
345 "properties":{
346 "type":{"type":"string"},
347 "name":{"type":"string"}
348 }
349 }');
350 $objects = array();
351 $ds = new OMVModuleZFSDataset($params['name']);
352 $mountpoint = $ds->getMountPoint();
353 return array(
354 "mountpoint" => $mountpoint,
355 "name" => $params['name'],
356 "type" => $params['type']);
357 }
358
359 public function createShare($params, $context) {
360 global $xmlConfig;
361 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
362 // Validate the parameters of the RPC service method.
363 $this->validateMethodParams($params, '{
364 "type":"object",
365 "properties":{
366 "name":{"type":"string"},
367 "type":{"type":"string","enum":["Filesystem","Clone"]},
368 "sharename":{'.$GLOBALS['OMV_JSONSCHEMA_SHARENAME'].'},
369 "comment":{"type":"string"},
370 "mode":{"type":"string","enum":["700","750","755",'.
371 '"770","775","777"],"optional":true},
372 "mountpoint":{"type":"string"}
373 }
374 }');
375
376 //Get the UUID of the Pool
377 $poolname = OMVModuleZFSUtil::getPoolname($params['name']);
378 $pooluuid = OMVModuleZFSUtil::getUUIDbyName($poolname);
379
380 //Get the mntent object and fetch it's uuid.
381 $xpath = "//system/fstab/mntent[fsname='" . $pooluuid . "']";
382 $mountpoint = $xmlConfig->get($xpath);
383 $mntentref = $mountpoint['uuid'];
384
385 // Prepare the configuration object. Use the name of the shared
386 // folder as the relative directory name of the share.
387 switch ($params['type']) {
388 case "Filesystem":
389 $tmp = new OMVModuleZFSDataset($params['name']);
390 break;
391 case "Clone":
392 $tmp = new OMVModuleZFSDataset($params['name']);
393 break;
394 default:
395 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
396 break;
397 }
398
399 $uuid = OMVUtil::uuid();
400 $pathName = $tmp->getMountPoint();
401 $reldirpath = OMVModuleZFSUtil::getReldirpath($pathName);
402 $object = array(
403 "uuid" => $uuid,
404 "name" => $params['sharename'],
405 "comment" => $params['comment'],
406 "mntentref" => $mntentref,
407 "reldirpath" => $reldirpath
408 );
409
410 // Set the configuration object.
411 $success = FALSE;
412 // Check uniqueness. The share name must be global unique because
413 // the name is also used when exporting a shared folder via NFS for
414 // example.
415 $xpath = sprintf("//system/shares/sharedfolder[name='%s']",
416 $params['name']);
417 if(TRUE === $xmlConfig->exists($xpath)) {
418 throw new OMVException(OMVErrorMsg::E_CONFIG_OBJECT_UNIQUENESS,
419 gettext("A shared folder with the given name already exists"));
420 }
421
422 // Add empty list of privileges per default.
423 $object['privileges'] = array();
424
425 // Append object to configuration.
426 $success = $xmlConfig->set("//system/shares",
427 array("sharedfolder" => $object));
428 if(FALSE === $success) {
429 throw new OMVException(OMVErrorMsg::E_CONFIG_SET_OBJECT_FAILED);
430 }
431
432 // Append the file mode field to the notification object if set.
433 // Defaults to 775.
434 $object['mode'] = "775";
435 if(array_key_exists("mode", $params)) {
436 $object['mode'] = $params['mode'];
437 }
438
439 // Change group owner of directory to configured default group,
440 // e.g. 'users'.
441 if(FALSE === chgrp($pathName, $GLOBALS['OMV_USERMGMT_DEFAULT_GROUP'])) {
442 throw new OMVException(OMVErrorMsg::E_MISC_FAILURE,
443 sprintf("Failed to set file group to '%s' for '%s'",
444 $GLOBALS['OMV_USERMGMT_DEFAULT_GROUP'], $pathName));
445 }
446
447 // Set the setgid bit. Setting this permission means that all files
448 // created in the folder will inherit the group of the folder rather
449 // than the primary group of the user who creates the file.
450 $mode = fileperms($pathName) | 02000;
451 if(FALSE === chmod($pathName, $mode)) {
452 throw new OMVException(OMVErrorMsg::E_MISC_FAILURE,
453 sprintf("Failed to set file mode to '%o' for '%s'",
454 $mode, $pathName));
455 }
456
457 // Notify configuration changes.
458 $dispatcher = &OMVNotifyDispatcher::getInstance();
459 $dispatcher->notify(OMV_NOTIFY_CREATE,"org.openmediavault.system.shares.sharedfolder", $object);
460 // Return the configuration object.
461 return $object;
462 }
463
464 public function getObjectDetails($params, $context) {
465 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
466 // Validate the parameters of the RPC service method.
467 $this->validateMethodParams($params, '{
468 "type":"object",
469 "properties":{
470 "name":{"type":"string"},
471 "type":{"type":"string"}
472 }
473 }');
474 $output = "";
475 switch ($params['type']) {
476 case "Filesystem":
477 $output .= "Filesystem details (zfs get all):\n\r\n\r";
478 $cmd = "zfs get all {$params['name']}";
479 break;
480 case "Volume":
481 $output .= "Volume details (zfs get all):\n\r\n\r";
482 $cmd = "zfs get all {$params['name']}";
483 break;
484 case "Snapshot":
485 $output .= "Snapshot details (zfs get all):\n\r\n\r";
486 $cmd = "zfs get all {$params['name']}";
487 break;
488 case "Pool":
489 $output .= "Pool details (zpool get all):\n\r\n\r";
490 $cmd = "zpool get all {$params['name']}";
491 break;
492 default:
493 throw new OMVModuleZFSException("Incorrect type provided");
494 }
495 OMVModuleZFSUtil::exec($cmd,$out,$res);
496 $output .= implode("\n\r", $out);
497 return array("details" => $output);
498 }
499 }
500
501 // Register the RPC service.
502 $rpcServiceMgr = &OMVRpcServiceMgr::getInstance(); // Get the "root" instance for the Services
503 $rpcServiceMgr->registerService(new OMVRpcServiceZFS()); // Register a new instance of the RPC service described above
504 ?>
505
This page took 0.088259 seconds and 4 git commands to generate.