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");
14 class OMVRpcServiceZFS extends OMVRpcServiceAbstract {
15 public function getName() { return "ZFS";} // RPC Service name. Same as in .js files
17 /* Initialize the RPC service. Different methods of the RPC service are declared here*/
18 public function initialize() {
19 $this->registerMethod("getObjectTree");
20 $this->registermethod("passParam");
21 $this->registermethod("addObject");
22 $this->registermethod("deleteObject");
23 $this->registermethod("getProperties");
24 $this->registermethod("setProperties");
25 $this->registermethod("inherit");
26 $this->registermethod("getSharedParams");
27 $this->registermethod("createShare");
30 public function getObjectTree($params, $context) {
31 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
32 $objects = OMVModuleZFSUtil::getZFSFlatArray();
34 foreach ($objects as $a){
35 $new[$a['parentid']][] = $a;
37 $tree = OMVModuleZFSUtil::createTree($new, $new['root']);
41 public function passParam($params, $context) {
42 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
43 //$msg = "Key=" . $params['key'] . ";Value=" . $params['value'] . ";";
44 //throw new OMVModuleZFSException($msg);
45 return array($params['key'] => $params['value']);
48 public function addObject($params, $context) {
49 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
50 switch ($params['type']) {
52 $name = $params['path'] . "/" . $params['name'];
53 $tmp = new OMVModuleZFSDataset($name);
56 $name = $params['path'] . "@" . $params['name'];
57 $tmp = new OMVModuleZFSSnapshot($name);
60 $name = $params['path'] . "/" . $params['name'];
61 $tmp = new OMVModuleZFSZvol($name);
62 $tmp->create($params['size']);
65 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
70 public function deleteObject($params, $context) {
71 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
72 switch ($params['type']) {
73 case "Filesystem" || "Clone":
74 $name = $params['name'];
75 $tmp = new OMVModuleZFSDataset($name);
79 $name = $params['name'];
80 $tmp = new OMVModuleZFSSnapshot($name);
84 $name = $params['name'];
85 $tmp = new OMVModuleZFSZvol($name);
89 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
94 public function getProperties($params, $context) {
95 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
97 $name = $params['name'];
98 switch ($params['type']) {
99 case "Filesystem" || "Clone":
100 $tmp = new OMVModuleZFSDataset($name);
103 $tmp = new OMVModuleZFSSnapshot($name);
106 $tmp = new OMVModuleZFSZvol($name);
109 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
112 $properties = $tmp->getProperties();
113 foreach ($properties as $propertyk => $propertyv) {
114 if (!(strcmp($propertyv['source'], "-") == 0)) {
115 $objects[] = array('property' => $propertyk,
116 'value' => $propertyv['value'],
117 'source' => $propertyv['source'],
118 'modified' => "false");
124 public function setProperties($params, $context) {
125 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
127 switch ($params['type']) {
128 case "Filesystem" || "Clone":
129 $tmp = new OMVModuleZFSDataset($params['name']);
132 $tmp = new OMVModuleZFSSnapshot($params['name']);
135 $tmp = new OMVModuleZFSZvol($params['name']);
138 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
141 foreach ($params['properties'] as $property) {
142 $objects[$property['property']] = $property['value'];
144 $tmp->setProperties($objects);
147 public function inherit($params, $context) {
148 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
149 // Create a background process.
150 $bgStatusFilename = $this->createBgProcStatus();
151 $pid = $this->fork();
152 if($pid > 0) { // Parent process.
153 $this->initializeBgProcStatus($bgStatusFilename, $pid);
154 return $bgStatusFilename;
158 $bgOutputFilename = $this->createBgProcOutput();
159 $this->updateBgProcStatus($bgStatusFilename, "outputfilename", $bgOutputFilename);
160 switch ($params['type']) {
161 case "Filesystem" || "Clone":
162 $tmp = new OMVModuleZFSDataset($params['name']);
165 $tmp = new OMVModuleZFSSnapshot($params['name']);
168 $tmp = new OMVModuleZFSZvol($params['name']);
171 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
174 $tmp->inherit($params['property']);
175 $this->finalizeBgProcStatus($bgStatusFilename, $output);
177 } catch(Exception $e) {
178 $this->finalizeBgProcStatus($bgStatusFilename, "", $e);
183 public function getSharedParams($params, $context) {
184 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
186 $ds = new OMVModuleZFSDataset($params['name']);
187 $mountpoint = $ds->getMountPoint();
189 "mountpoint" => $mountpoint,
190 "name" => $params['name'],
191 "type" => $params['type']);
194 public function createShare($params, $context) {
196 $this->validateMethodContext($context, array("role" => OMV_ROLE_ADMINISTRATOR));
198 //Get the UUID of the Pool
199 $pooluuid = OMVModuleZFSUtil::getUUIDbyName($params['name']);
200 preg_match('/^([A-Za-z0-9]+)\/?.*$/', $params['name'], $result);
201 $poolname = $result[1];
204 //Check if the UUID is already stored as an mntent object. If it isn't then create it.
205 $xpath = "//system/fstab/mntent[fsname=" . $pooluuid . "]";
206 $object = $xmlConfig->get($xpath);
207 if(is_null($object)) {
208 $uuid = OMVUtil::uuid();
209 $ds = new OMVModuleZFSDataset($poolname);
210 $dir = $ds->getMountPoint();
213 "fsname" => $pooluuid,
216 "opts" => "rw,relatime,xattr",
220 $xmlConfig->set("//system/fstab",array("mntent" => $object));
221 $dispatcher = &OMVNotifyDispatcher::getInstance();
222 $dispatcher->notify(OMV_NOTIFY_CREATE,"org.openmediavault.system.fstab.mntent", $object);
225 //Get the mntent object and fetch it's uuid.
226 $object = $xmlConfig->get($xpath);
227 $mntentref = $object['uuid'];
229 // Prepare the configuration object. Use the name of the shared
230 // folder as the relative directory name of the share.
231 switch ($params['type']) {
232 case "Filesystem" || "Clone":
233 $tmp = new OMVModuleZFSDataset($name);
236 throw new OMVModuleZFSException("Illegal type provided: " . $params['type']);
240 $uuid = OMVUtil::uuid();
241 $pathName = $tmp->getMountPoint();
242 $subdirs = preg_split('/\//',$pathName);
243 $reldirpath = $subdirs[count($subdirs)-1];
246 "name" => $params['sharename'],
247 "comment" => $params['comment'],
248 "mntentref" => $mntentref,
249 "reldirpath" => $reldirpath
252 // Set the configuration object.
254 // Check uniqueness. The share name must be global unique because
255 // the name is also used when exporting a shared folder via NFS for
257 $xpath = sprintf("//system/shares/sharedfolder[name='%s']",
259 if(TRUE === $xmlConfig->exists($xpath)) {
260 throw new OMVException(OMVErrorMsg::E_CONFIG_OBJECT_UNIQUENESS,
261 gettext("A shared folder with the given name already exists"));
264 // Add empty list of privileges per default.
265 $object['privileges'] = array();
267 // Append object to configuration.
268 $success = $xmlConfig->set("//system/shares",
269 array("sharedfolder" => $object));
270 if(FALSE === $success) {
271 throw new OMVException(OMVErrorMsg::E_CONFIG_SET_OBJECT_FAILED);
274 // Append the file mode field to the notification object if set.
276 $object['mode'] = "775";
277 if(array_key_exists("mode", $params)) {
278 $object['mode'] = $params['mode'];
281 // Change group owner of directory to configured default group,
283 if(FALSE === chgrp($pathName, $GLOBALS['OMV_USERMGMT_DEFAULT_GROUP'])) {
284 throw new OMVException(OMVErrorMsg::E_MISC_FAILURE,
285 sprintf("Failed to set file group to '%s' for '%s'",
286 $GLOBALS['OMV_USERMGMT_DEFAULT_GROUP'], $pathName));
289 // Set the setgid bit. Setting this permission means that all files
290 // created in the folder will inherit the group of the folder rather
291 // than the primary group of the user who creates the file.
292 $mode = fileperms($pathName) | 02000;
293 if(FALSE === chmod($pathName, $mode)) {
294 throw new OMVException(OMVErrorMsg::E_MISC_FAILURE,
295 sprintf("Failed to set file mode to '%o' for '%s'",
299 // Notify configuration changes.
300 $dispatcher = &OMVNotifyDispatcher::getInstance();
301 $dispatcher->notify(OMV_NOTIFY_CREATE,"org.openmediavault.system.shares.sharedfolder", $object);
302 // Return the configuration object.
309 // Register the RPC service.
310 $rpcServiceMgr = &OMVRpcServiceMgr::getInstance(); // Get the "root" instance for the Services
311 $rpcServiceMgr->registerService(new OMVRpcServiceZFS()); // Register a new instance of the RPC service described above