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