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");
15 class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
16 public function getName() {
17 return "ZFS"; // RPC Service name. Same as in .js files
20 /* Initialize the RPC service. Different methods of the RPC service are declared here*/
21 public function initialize() {
22 $this->registerMethod("addPool");
23 $this->registerMethod("getObjectTree");
24 $this->registermethod("passParam");
25 $this->registermethod("addObject");
26 $this->registermethod("deleteObject");
27 $this->registermethod("getProperties");
28 $this->registermethod("setProperties");
29 $this->registermethod("inherit");
30 $this->registermethod("getSharedParams");
31 $this->registermethod("createShare");
34 public function addPool($params, $context) {
35 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
36 switch ($params['pooltype']) {
38 $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSPLAIN;
41 $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSMIRROR;
44 $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ1;
47 $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ2;
50 $pooltype = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ3;
53 throw new OMVModuleZFSException("Incorrect pool type specified");
56 $disks = preg_split("/[,;]/", $params['devices']);
57 $vdev = new OMVModuleZFSVdev($params['name'], $pooltype, $disks);
58 $pool = new OMVModuleZFSZpool($vdev);
59 //Ugly fix to solve the problem of blkid not displaying info on newly created pools
61 $pool->import($pool->getName());
64 public function getObjectTree($params, $context) {
65 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
66 $objects = OMVModuleZFSUtil::getZFSFlatArray();
68 foreach ($objects as $a){
69 $new[$a['parentid']][] = $a;
71 $tree = OMVModuleZFSUtil::createTree($new, $new['root']);
72 OMVModuleZFSUtil::addMissingOMVMntEnt(); //Adds missing ZFS filesystems to the OMV core
76 public function passParam($params, $context) {
77 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
78 //$msg = "Key=" . $params['key'] . ";Value=" . $params['value'] . ";";
79 //throw new OMVModuleZFSException($msg);
80 return array($params['key'] => $params['value']);
83 public function addObject($params, $context) {
84 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
85 switch ($params['type']) {
87 $name = $params['path'] . "/" . $params['name'];
88 $tmp = new OMVModuleZFSDataset($name);
91 $name = $params['path'] . "@" . $params['name'];
92 $tmp = new OMVModuleZFSSnapshot($name);
95 $name = $params['path'] . "/" . $params['name'];
96 $tmp = new OMVModuleZFSZvol($name);
97 $tmp->create($params['size']);
100 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
105 public function deleteObject($params, $context) {
106 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
107 switch ($params['type']) {
110 $name = $params['name'];
111 $tmp = new OMVModuleZFSDataset($name);
115 $name = $params['name'];
116 $tmp = new OMVModuleZFSSnapshot($name);
120 $name = $params['name'];
121 $tmp = new OMVModuleZFSZvol($name);
125 $name = $params['name'];
126 $tmp = new OMVModuleZFSZpool($name);
130 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
135 public function getProperties($params, $context) {
136 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
138 $name = $params['name'];
139 switch ($params['type']) {
142 $tmp = new OMVModuleZFSDataset($name);
145 $tmp = new OMVModuleZFSSnapshot($name);
148 $tmp = new OMVModuleZFSZvol($name);
151 $tmp = new OMVModuleZFSZpool($name);
154 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
157 $properties = $tmp->getProperties();
158 foreach ($properties as $propertyk => $propertyv) {
159 if (!(strcmp($propertyv['source'], "-") == 0)) {
160 $objects[] = array('property' => $propertyk,
161 'value' => $propertyv['value'],
162 'source' => $propertyv['source'],
163 'modified' => "false");
169 public function setProperties($params, $context) {
170 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
172 switch ($params['type']) {
175 $tmp = new OMVModuleZFSDataset($params['name']);
178 $tmp = new OMVModuleZFSSnapshot($params['name']);
181 $tmp = new OMVModuleZFSZvol($params['name']);
184 $tmp = new OMVModuleZFSZpool($params['name']);
187 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
190 foreach ($params['properties'] as $property) {
191 $objects[$property['property']] = $property['value'];
193 $tmp->setProperties($objects);
196 public function inherit($params, $context) {
197 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
198 // Create a background process.
199 $bgStatusFilename = $this->createBgProcStatus();
200 $pid = $this->fork();
201 if($pid > 0) { // Parent process.
202 $this->initializeBgProcStatus($bgStatusFilename, $pid);
203 return $bgStatusFilename;
207 $bgOutputFilename = $this->createBgProcOutput();
208 $this->updateBgProcStatus($bgStatusFilename, "outputfilename", $bgOutputFilename);
209 switch ($params['type']) {
212 $tmp = new OMVModuleZFSDataset($params['name']);
215 $tmp = new OMVModuleZFSSnapshot($params['name']);
218 $tmp = new OMVModuleZFSZvol($params['name']);
221 $tmp = new OMVModuleZFSZpool($params['name']);
224 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
227 $tmp->inherit($params['property']);
228 $this->finalizeBgProcStatus($bgStatusFilename, $output);
230 } catch(Exception $e) {
231 $this->finalizeBgProcStatus($bgStatusFilename, "", $e);
236 public function getSharedParams($params, $context) {
237 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
239 $ds = new OMVModuleZFSDataset($params['name']);
240 $mountpoint = $ds->getMountPoint();
242 "mountpoint" => $mountpoint,
243 "name" => $params['name'],
244 "type" => $params['type']);
247 public function createShare($params, $context) {
249 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
251 //Get the UUID of the Pool
252 $pooluuid = OMVModuleZFSUtil::getUUIDbyName($params['name']);
253 preg_match('/^([A-Za-z0-9]+)\/?.*$/', $params['name'], $result);
254 $poolname = $result[1];
257 //Get the mntent object and fetch it's uuid.
258 $xpath = "//system/fstab/mntent[fsname=" . $pooluuid . "]";
259 $object = $xmlConfig->get($xpath);
260 $mntentref = $object['uuid'];
262 // Prepare the configuration object. Use the name of the shared
263 // folder as the relative directory name of the share.
264 switch ($params['type']) {
266 $tmp = new OMVModuleZFSDataset($params['name']);
269 $tmp = new OMVModuleZFSDataset($params['name']);
272 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
276 $uuid = OMVUtil::uuid();
277 $pathName = $tmp->getMountPoint();
278 $subdirs = preg_split('/\//',$pathName);
279 $reldirpath = $subdirs[count($subdirs)-1];
282 "name" => $params['sharename'],
283 "comment" => $params['comment'],
284 "mntentref" => $mntentref,
285 "reldirpath" => $reldirpath
288 // Set the configuration object.
290 // Check uniqueness. The share name must be global unique because
291 // the name is also used when exporting a shared folder via NFS for
293 $xpath = sprintf("//system/shares/sharedfolder[name='%s']",
295 if(TRUE === $xmlConfig->exists($xpath)) {
296 throw new OMVException(OMVErrorMsg::E_CONFIG_OBJECT_UNIQUENESS,
297 gettext("A shared folder with the given name already exists"));
300 // Add empty list of privileges per default.
301 $object['privileges'] = array();
303 // Append object to configuration.
304 $success = $xmlConfig->set("//system/shares",
305 array("sharedfolder" => $object));
306 if(FALSE === $success) {
307 throw new OMVException(OMVErrorMsg::E_CONFIG_SET_OBJECT_FAILED);
310 // Append the file mode field to the notification object if set.
312 $object['mode'] = "775";
313 if(array_key_exists("mode", $params)) {
314 $object['mode'] = $params['mode'];
317 // Change group owner of directory to configured default group,
319 if(FALSE === chgrp($pathName, $GLOBALS['OMV_USERMGMT_DEFAULT_GROUP'])) {
320 throw new OMVException(OMVErrorMsg::E_MISC_FAILURE,
321 sprintf("Failed to set file group to '%s' for '%s'",
322 $GLOBALS['OMV_USERMGMT_DEFAULT_GROUP'], $pathName));
325 // Set the setgid bit. Setting this permission means that all files
326 // created in the folder will inherit the group of the folder rather
327 // than the primary group of the user who creates the file.
328 $mode = fileperms($pathName) | 02000;
329 if(FALSE === chmod($pathName, $mode)) {
330 throw new OMVException(OMVErrorMsg::E_MISC_FAILURE,
331 sprintf("Failed to set file mode to '%o' for '%s'",
335 // Notify configuration changes.
336 $dispatcher = &OMVNotifyDispatcher::getInstance();
337 $dispatcher->notify(OMV_NOTIFY_CREATE,"org.openmediavault.system.shares.sharedfolder", $object);
338 // Return the configuration object.
344 // Register the RPC service.
345 $rpcServiceMgr = &OMVRpcServiceMgr::getInstance(); // Get the "root" instance for the Services
346 $rpcServiceMgr->registerService(new OMVRpcServiceZFS()); // Register a new instance of the RPC service described above