+
+ /**
+ * Get an associative array of all properties associated with the Snapshot
+ *
+ * @return array $properties Each entry is an associative array with two elements
+ * <value> and <source>
+ * @access public
+ */
+ public function getProperties() {
+ $attrs = $this->getFeatures(false);
+ return $attrs;
+ }
+
+ /**
+ * Sets a number of Dataset properties. If a property is already set it will be updated with the new value.
+ *
+ * @param array $properties An associative array with properties to set
+ * @return void
+ * @access public
+ */
+ public function setProperties($properties) {
+ foreach ($properties as $newpropertyk => $newpropertyv) {
+ $cmd = "zfs set " . $newpropertyk . "=" . $newpropertyv . " " . $this->name . " 2>&1";
+ OMVModuleZFSUtil::exec($cmd,$out,$res);
+ $attr = $this->getAttribute($newpropertyk);
+ $this->features[$newpropertyk] = $attr;
+ }
+ }
+
+ /**
+ * Destroy the Dataset.
+ *
+ * @return void
+ * @access public
+ */
+ public function destroy() {
+ $cmd = "zpool destroy " . $this->name . " 2>&1";
+ $this->exec($cmd,$out,$res);
+ }
+
+ /**
+ * Clears a previously set proporty and specifies that it should be
+ * inherited from it's parent.
+ *
+ * @param string $property Name of the property to inherit.
+ * @return void
+ * @access public
+ */
+ public function inherit($property) {
+ $cmd = "zfs inherit " . $property . " " . $this->name . " 2>&1";
+ $this->exec($cmd,$out,$res);
+ $attr = $this->getAttribute($newpropertyk);
+ $this->features[$newpropertyk] = $attr;
+ }
+
+ /**
+ * Convert array of Vdev to command string
+ *
+ * @param array $vdevs
+ * @return string
+ * @throws OMVMODULEZFSException
+ */
+ private function getCommandString(array $vdevs) {
+ $adds = array();
+
+ foreach ($vdevs as $vdev) {
+ if (is_object($vdev) == false)
+ throw new OMVMODULEZFSException("Not object of class OMVModuleZFSVdev");
+ if (is_a($vdev, OMVModuleZFSVdev) == false)
+ throw new OMVMODULEZFSException("Object is not of class OMVModuleZFSVdev");
+ $type = $vdev->getType();
+ $command = "";
+
+ switch ($type) {
+ case OMVModuleZFSVdevType::OMVMODULEZFSPLAIN: break;
+ case OMVModuleZFSVdevType::OMVMODULEZFSMIRROR: $command = "mirror"; break;
+ case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ1: $command = "raidz1"; break;
+ case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ2: $command = "raidz2"; break;
+ case OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ3: $command = "raidz3"; break;
+ default:
+ throw new OMVMODULEZFSException("Unknown Vdev type");
+ }
+ $disks = $vdev->getDisks();
+ $diskStr = "";
+ foreach($disks as $disk) {
+ $diskStr .= " $disk";
+ }
+
+ array_push ($adds, $command . $diskStr);
+ }
+
+ return implode(" ", $adds);
+ }
+
+ /**
+ * Get an attribute from pool
+ *
+ * @param string $attribute
+ * @return string value
+ */
+ private function getAttribute($attribute) {
+ $cmd = "zpool list -H -o $attribute {$this->name}";
+ OMVUtil::exec($cmd, $output, $result);
+ if ($result) {
+ $cmd = "zfs list -H -o $attribute {$this->name}";
+ OMVUtil::exec($cmd, $output, $result);
+ if ($result)
+ return null;
+ }
+
+ return $output;
+ }
+
+ /**
+ * Get all attributes from pool
+ * @return array of attributes
+ * @throws OMVModuleZFSException
+ */
+ private function getAllAttributes() {
+ $attrs = array();
+ $cmd = "zfs get -H all {$this->name}";
+
+ try {
+ OMVUtil::exec($cmd, $output, $result);
+ } catch (OMVModuleZFSException $e) {}
+ if ($result)
+ throw new OMVModuleZFSException($output);
+ $output = implode("\n", $output);
+ $res = preg_match_all("/{$this->name}\s+(\w+)\s+([\w\d\.]+)\s+(\w+).*/", $output, $matches, PREG_SET_ORDER);
+ if ($res == false || $res == 0)
+ throw new OMVModuleZFSException("Error return by zpool get all: $output");
+ foreach ($matches as $match) {
+ $attrs[$match[1]] = array('value' => $match[2], 'source' => $match[3]);
+ }
+
+ return $attrs;
+ }
+
+ /**
+ * Get all Dataset properties from commandline and update object properties attribute
+ *
+ * @return void
+ * @access private
+ */
+ private function updateAllProperties() {
+ $this->features = $this->getAllAttributes();
+ }
+
+ /**
+ * Remove a disk from array
+ *
+ * @param array $array
+ * @param string $disk
+ * @return array
+ */
+ private function removeDisk(array $array, $disk) {
+ $new_disks = array();
+
+ foreach ($array as $item) {
+ if (strcmp($item, $disk) != 0)
+ array_push ($new_disks, $item);
+ }
+
+ return $new_disks;
+ }
+
+ /**
+ * Construct existing pool
+ *
+ * @param string $name
+ * @return void
+ * @throws OMVModuleZFSException
+ */
+ private function assemblePool($name) {
+ $cmd = "zpool status -v $name";
+ $types = 'mirror|raidz1|raidz2|raidz3';
+ $dev = null;
+ $type = null;
+ $log = false;
+ $cache = false;
+ $start = true;
+
+ OMVUtil::exec($cmd, $output, $result);
+ if ($result)
+ throw new OMVModuleZFSException($output);
+
+ $this->name = $name;
+ foreach($output as $line) {
+ if (! strstr($line, PHP_EOL))
+ $line .= PHP_EOL;
+ if ($start) {
+ if (preg_match("/^\s*NAME/", $line))
+ $start = false;
+ continue;
+ } else {
+ if (preg_match("/^\s*$/", $line)) {
+ if ($dev) {
+ $this->output($part, $type, $dev);
+ }
+ break;
+ } else if (preg_match("/^\s*($name|logs|cache|spares)/", $line, $match)) {
+ if ($dev) {
+ $this->output($part, $type, $dev);
+ $dev = null;
+ $type = null;
+ }
+ $part = $match[1];
+ } else {
+ switch ($part) {
+ case $name:
+ if (preg_match("/^\s*($types)/", $line, $match)) {
+ /* new vdev */
+ if ($type) {
+ $this->output(null, $type, $dev);
+ $dev = null;
+ }
+ $type = $match[1];
+ } else if (preg_match("/^\s*([\w\d-]+)\s+/", $line, $match)) {
+ if ($dev)
+ $dev .= " $match[1]";
+ else
+ $dev = "$match[1]";
+ }
+ break;
+ case 'logs':
+ if (preg_match("/^\s*([\w\d-]+)\s+/", $line, $match)) {
+ if ($dev)
+ $dev .= " $match[1]";
+ else
+ $dev = "$match[1]";
+ }
+ break;
+ case 'cache':
+ case 'spares':
+ if (preg_match("/^\s*([\w\d-]+)\s+/", $line, $match)) {
+ if ($dev)
+ $dev .= " $match[1]";
+ else
+ $dev = "$match[1]";
+ }
+ break;
+ default:
+ throw new Exception("$part: Unknown pool part");
+ }
+ }
+ }
+ }
+ $this->size = $this->getAttribute("size");
+ $this->mountPoint = $this->getAttribute("mountpoint");
+ }
+
+ /**
+ * Create pool config from parsed input
+ *
+ * @param string $part
+ * @param string $type
+ * @param string $dev
+ * @return void
+ * @throws OMVModuleZFSException
+ */
+ private function output($part, $type, $dev) {
+ $disks = split(" ", $dev);
+ switch ($part) {
+ case 'logs':
+ if ($type && $type != 'mirror')
+ throw new Exception("$type: Logs can only be mirror or plain");
+ if ($type)
+ $this->log = new OMVModuleZFSVdev($this->name, OMVModuleZFSVdevType::OMVMODULEZFSMIRROR, $disks);
+ else
+ $this->log = new OMVModuleZFSVdev($this->name, OMVModuleZFSVdevType::OMVMODULEZFSPLAIN, $disks);
+ break;
+ case 'cache':
+ if ($type)
+ throw new Exception("$type: cache can only be plain");
+ $this->cache = new OMVModuleZFSVdev($this->name, OMVModuleZFSVdevType::OMVMODULEZFSPLAIN, $disks);
+ break;
+ case 'spares':
+ if ($type)
+ throw new Exception("$type: spares can only be plain");
+ $this->spare = new OMVModuleZFSVdev($this->name, OMVModuleZFSVdevType::OMVMODULEZFSPLAIN, $disks);
+ break;
+ default:
+ if ($type) {
+ switch ($type) {
+ case 'mirror':
+ array_push($this->vdevs, new OMVModuleZFSVdev($this->name, OMVModuleZFSVdevType::OMVMODULEZFSMIRROR, $disks));
+ $this->type = OMVModuleZFSVdevType::OMVMODULEZFSMIRROR;
+ break;
+ case 'raidz1':
+ array_push($this->vdevs, new OMVModuleZFSVdev($this->name, OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ1, $disks));
+ $this->type = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ1;
+ break;
+ case 'raidz2':
+ array_push($this->vdevs, new OMVModuleZFSVdev($this->name, OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ2, $disks));
+ $this->type = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ2;
+ break;
+ case 'raidz3':
+ array_push($this->vdevs, new OMVModuleZFSVdev($this->name, OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ3, $disks));
+ $this->type = OMVModuleZFSVdevType::OMVMODULEZFSRAIDZ3;
+ break;
+ }
+ } else {
+ array_push($this->vdevs, new OMVModuleZFSVdev($this->name, OMVModuleZFSVdevType::OMVMODULEZFSPLAIN, $disks));
+ $this->type = OMVModuleZFSVdevType::OMVMODULEZFSPLAIN;
+ }
+ break;
+ }
+ }
+