From f686d6634af455881afa4b8e6d365f0ca0a58084 Mon Sep 17 00:00:00 2001
From: optimans <58222345+iamoptimans@users.noreply.github.com>
Date: Tue, 28 Apr 2020 22:16:16 +0800
Subject: [PATCH] 0.3.1.301
---
zfs/zfs.css | 4691 +++---
zfs/zfs.js | 41724 +++++++++++++++++++++++++-------------------------
2 files changed, 23210 insertions(+), 23205 deletions(-)
diff --git a/zfs/zfs.css b/zfs/zfs.css
index 78d1b07..2248519 100644
--- a/zfs/zfs.css
+++ b/zfs/zfs.css
@@ -1,2197 +1,2202 @@
-/*
- * This file is part of Cockpit ZFS Manager.
- *
- * Copyright (C) 2019-2020 OPTIMANS Pty Ltd.
- *
- * Cockpit ZFS Manager is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 3 of the License, or (at your option)
- * any later version.
- *
- * Cockpit ZFS Manager is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License along
- * with Cockpit ZFS Manager; If not, see .
- */
-
-
-/* Portions of Cockpit Storage 208 and PatternFly 4 styles appended */
-
-a.disabled,
-a[disabled],
-.btn.disabled,
-.btn[disabled],
-fieldset[disabled] .btn {
- cursor: not-allowed !important;
-}
-
-.btn-group > .dropdown-menu.dropdown-menu-right {
- margin-right: 0px !important;
- overflow-x: visible !important;
-}
-
-.blank-slate-ct {
- height: 100%;
- position: fixed;
- top: 0px;
- width: 100%;
-}
-
-/* Fix for extra long text in dropdown */
-.ct-form .dropdown-toggle {
- position: absolute;
-}
-
- /* Fix for extra long text in dropdown */
- .ct-form .dropdown-toggle > span {
- max-width: 100%;
- padding-right: 25px;
- text-align: left;
- }
-
-.ct-form-spacing {
- padding-top: 1.5rem;
-}
-
-.dialog-item-ct-popover,
-.dialog-item-ct-tooltip {
- margin-left: 0.5em;
- white-space: nowrap;
-}
-
-.dialog-wait-ct {
- margin-top: 7px;
-}
-
- .dialog-wait-ct .spinner {
- display: inline-block;
- }
-
- .dialog-wait-ct span {
- padding-left: 10px;
- vertical-align: 7px;
- }
-
-.dropdown.dropdown-kebab-pf > .dropdown-menu.dropdown-menu-right {
- margin-right: 15px !important;
- overflow-x: visible !important;
-}
-
-.list-group-ct-warning {
- color: var(--pf-global--danger-color--100);
-}
-
-.list-unstyled-ct {
- word-break:break-word;
-}
-
-.listing-ct .listing-ct-actionsmenu {
- width: 60px !important;
-}
-
- .listing-ct .listing-ct-actionsmenu .text-ct-locked {
- color: var(--color-button-primary);
- }
-
-.listing-ct .listing-ct-icon .pficon-ct-locked {
- color: var(--color-button-primary);
-}
-
-.listing-ct .pficon-ct-bootreadonly {
- color: var(--pf-global--primary-color--100);
-}
-
-.listing-ct .pficon-ct-altroot,
-.listing-ct .pficon-ct-readonly {
- color: var(--pf-global--secondary-color--100);
-}
-
-.listing-ct .listing-ct-icon .pficon-ct-upgrade {
- color: var(--pf-global--warning-color--100);
-}
-
-.listing-ct-wordwrap {
- word-break: break-all;
-}
-
-.listing-ct .listing-ct-icon {
- width: 35px !important;
-}
-
-.listing-ct .listing-ct-spinner {
- width: 50px !important;
-}
-
-.listing-ct .listing-ct-toggle:empty,
-.listing-ct .listing-ct-toggle-snapshots {
- width: 45px !important;
-}
-
-.listing-ct .listing-ct-body-spinner {
- padding: 1rem 1.5rem;
-}
-
-.listing-ct-item > .listing-ct-toggle + td {
- font-weight: bold;
-}
-
-.listing-ct-item > td > span.table-ct-head,
-.listing-ct-item > td.listing-ct-icon > span.table-ct-text,
-.table.table-ct-filesystems > tbody > tr > td > span.table-ct-head,
-.table.table-ct-snapshots > tbody > tr > td > span.table-ct-head,
-.table.table-ct-status-config > tbody > tr > td > span.table-ct-head,
-.table.table-ct-filesystems > tbody > tr > td > span.table-ct-text,
-.table.table-ct-snapshots > tbody > tr > td > span.table-ct-text,
-.table.table-ct-status-config > tbody > tr > td > span.table-ct-text {
- display: none;
-}
-
-.listing-ct-wide {
- table-layout: fixed;
-}
-
-.modal-content .ct-form .alert {
- line-height: var(--pf-global--LineHeight--md);
-}
-
-.modal-content .modal-ct-name {
- word-break: break-all;
-}
-
-.modal-ct-bodytext-1 {
- padding-bottom: 1.5rem;
-}
-
-.modal-ct-bodytext-2 {
- padding-bottom: 3rem;
-}
-
-.modal-ct-buttons {
- display: inline-block;
-}
-
-.open .dropdown-toggle.btn-default {
- color: var(--pf-global--Color--100);
-}
-
-.panel {
- border: 0px !important;
- margin-bottom: 0px;
-}
-
- .panel > .panel-heading > .panel-ct-heading .spinner.spinner-sm {
- float: left;
- }
-
-.pf-c-alert__description {
- word-break: break-all;
-}
-
- .pf-c-alert__description.break-word {
- word-break: break-word !important;
- }
-
-.pficon-ct-filesystems {
- margin-top: 5px;
-}
-
-.progress.progress-sm {
- display: list-item;
- margin-bottom: 0px;
-}
-
-.select-ct-disk-row {
- align-items: center;
- cursor: pointer;
- display: flex;
-}
-
- .select-ct-disk-row :nth-child(1) {
- margin-top: 0px;
- }
-
- .select-ct-disk-row :nth-child(2) {
- flex-grow: 1;
- margin-left: 10px;
- }
-
-.select-ct-disk-row-id {
- display: block !important;
- font-size: var(--pf-global--FontSize--xs);
- padding-right: 10px;
- word-break:break-all;
-}
-
-.select-ct-pool-row {
- align-items: center;
- cursor: pointer;
- display: flex;
-}
-
- .select-ct-pool-row :nth-child(1) {
- margin-top: 0px;
- }
-
- .select-ct-pool-row :nth-child(2) {
- flex-grow: 1;
- margin-left: 10px;
- }
-
-.select-ct-pool-row-guid {
- display: block !important;
- font-size: var(--pf-global--FontSize--xs);
- padding-right: 5px;
- word-break: break-all;
-}
-
+/*
+ * This file is part of Cockpit ZFS Manager.
+ *
+ * Copyright (C) 2019-2020 OPTIMANS Pty Ltd.
+ *
+ * Cockpit ZFS Manager is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Cockpit ZFS Manager is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with Cockpit ZFS Manager; If not, see .
+ */
+
+
+/* Portions of Cockpit Storage 208 and PatternFly 4 styles appended */
+
+a.disabled,
+a[disabled],
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+ cursor: not-allowed !important;
+}
+
+.btn-group > .dropdown-menu.dropdown-menu-right {
+ margin-right: 0px !important;
+ overflow-x: visible !important;
+}
+
+.blank-slate-ct {
+ height: 100%;
+ position: fixed;
+ top: 0px;
+ width: 100%;
+}
+
+/* Fix for extra long text in dropdown */
+.ct-form .dropdown-toggle {
+ position: absolute;
+}
+
+ /* Fix for extra long text in dropdown */
+ .ct-form .dropdown-toggle > span {
+ max-width: 100%;
+ padding-right: 25px;
+ text-align: left;
+ }
+
+.ct-form-spacing {
+ padding-top: 1.5rem;
+}
+
+.dialog-item-ct-popover,
+.dialog-item-ct-tooltip {
+ margin-left: 0.5em;
+ white-space: nowrap;
+}
+
+.dialog-wait-ct {
+ margin-top: 7px;
+}
+
+ .dialog-wait-ct .spinner {
+ display: inline-block;
+ }
+
+ .dialog-wait-ct span {
+ padding-left: 10px;
+ vertical-align: 7px;
+ }
+
+.dropdown.dropdown-kebab-pf > .dropdown-menu.dropdown-menu-right {
+ margin-right: 15px !important;
+ overflow-x: visible !important;
+}
+
+.list-group-ct-warning {
+ color: var(--pf-global--danger-color--100);
+}
+
+.list-unstyled-ct {
+ word-break:break-word;
+}
+
+.listing-ct .listing-ct-actionsmenu {
+ width: 60px !important;
+}
+
+ .listing-ct .listing-ct-actionsmenu .text-ct-locked {
+ color: var(--color-button-primary);
+ }
+
+.listing-ct .listing-ct-icon .pficon-ct-locked {
+ color: var(--color-button-primary);
+}
+
+.listing-ct .pficon-ct-bootreadonly {
+ color: var(--pf-global--primary-color--100);
+}
+
+.listing-ct .pficon-ct-altroot,
+.listing-ct .pficon-ct-readonly {
+ color: var(--pf-global--secondary-color--100);
+}
+
+.listing-ct .listing-ct-icon .pficon-ct-upgrade {
+ color: var(--pf-global--warning-color--100);
+}
+
+.listing-ct-wordwrap {
+ word-break: break-all;
+}
+
+.listing-ct .listing-ct-icon {
+ width: 35px !important;
+}
+
+.listing-ct .listing-ct-spinner {
+ width: 50px !important;
+}
+
+.listing-ct .listing-ct-toggle:empty,
+.listing-ct .listing-ct-toggle-snapshots {
+ width: 45px !important;
+}
+
+.listing-ct .listing-ct-body-spinner {
+ padding: 1rem 1.5rem;
+}
+
+.listing-ct-item > .listing-ct-toggle + td {
+ font-weight: bold;
+}
+
+.listing-ct-item > td > span.table-ct-head,
+.listing-ct-item > td.listing-ct-icon > span.table-ct-text,
+.table.table-ct-filesystems > tbody > tr > td > span.table-ct-head,
+.table.table-ct-snapshots > tbody > tr > td > span.table-ct-head,
+.table.table-ct-status-config > tbody > tr > td > span.table-ct-head,
+.table.table-ct-filesystems > tbody > tr > td > span.table-ct-text,
+.table.table-ct-snapshots > tbody > tr > td > span.table-ct-text,
+.table.table-ct-status-config > tbody > tr > td > span.table-ct-text {
+ display: none;
+}
+
+.listing-ct-wide {
+ table-layout: fixed;
+}
+
+.modal-content .ct-form .alert {
+ line-height: var(--pf-global--LineHeight--md);
+}
+
+.modal-content .modal-ct-name {
+ word-break: break-all;
+}
+
+.modal-ct-bodytext-1 {
+ padding-bottom: 1.5rem;
+}
+
+.modal-ct-bodytext-2 {
+ padding-bottom: 3rem;
+}
+
+.modal-ct-buttons {
+ display: inline-block;
+}
+
+/* Temp fix for modal buttons with Cockpit 217. 0.4 will be in React which will resolve this */
+.modal-footer {
+ text-align: right;
+}
+
+.open .dropdown-toggle.btn-default {
+ color: var(--pf-global--Color--100);
+}
+
+.panel {
+ border: 0px !important;
+ margin-bottom: 0px;
+}
+
+ .panel > .panel-heading > .panel-ct-heading .spinner.spinner-sm {
+ float: left;
+ }
+
+.pf-c-alert__description {
+ word-break: break-all;
+}
+
+ .pf-c-alert__description.break-word {
+ word-break: break-word !important;
+ }
+
+.pficon-ct-filesystems {
+ margin-top: 5px;
+}
+
+.progress.progress-sm {
+ display: list-item;
+ margin-bottom: 0px;
+}
+
+.select-ct-disk-row {
+ align-items: center;
+ cursor: pointer;
+ display: flex;
+}
+
+ .select-ct-disk-row :nth-child(1) {
+ margin-top: 0px;
+ }
+
+ .select-ct-disk-row :nth-child(2) {
+ flex-grow: 1;
+ margin-left: 10px;
+ }
+
+.select-ct-disk-row-id {
+ display: block !important;
+ font-size: var(--pf-global--FontSize--xs);
+ padding-right: 10px;
+ word-break:break-all;
+}
+
+.select-ct-pool-row {
+ align-items: center;
+ cursor: pointer;
+ display: flex;
+}
+
+ .select-ct-pool-row :nth-child(1) {
+ margin-top: 0px;
+ }
+
+ .select-ct-pool-row :nth-child(2) {
+ flex-grow: 1;
+ margin-left: 10px;
+ }
+
+.select-ct-pool-row-guid {
+ display: block !important;
+ font-size: var(--pf-global--FontSize--xs);
+ padding-right: 5px;
+ word-break: break-all;
+}
+
.select-ct-pool-row-health {
white-space: nowrap;
-}
-
-.select-ct-pool-row-identifier,
-.select-ct-pool-row-physec {
- font-size: var(--pf-global--FontSize--xs);
- margin-left: 0px !important;
-}
-
-.select-ct-filesystem-row {
- align-items: center;
- cursor: pointer;
- display: flex;
- word-break: break-all;
-}
-
- .select-ct-filesystem-row :nth-child(1) {
- margin-top: 0px;
- }
-
- .select-ct-filesystem-row :nth-child(2) {
- flex-grow: 1;
- margin-left: 10px;
- }
-
-.slider-pf {
- margin: 0 0 0 8px;
-}
-
- .slider-pf > .size-ct-text {
- display: inline;
- margin: 2px 2px 2px 8px;
- text-align: right;
- width: 5em;
- }
-
- .slider-pf > .size-ct-text .disabled {
- cursor: not-allowed !important;
- pointer-events: inherit !important;
- }
-
- .slider-pf > .dropdown {
- flex: 1 0 80px;
- }
-
- .slider-pf > .dropdown > .size-ct-unit > span {
- padding-right: 0px;
- }
-
- .slider-pf > span {
- padding-left: 5px;
- }
-
-.slider-selection {
- background-color: var(--color-link);
- background-image: linear-gradient(to bottom,var(--color-link) 0%,var(--color-link) 100%);
-}
-
-.slider.slider-horizontal {
- height: 16px;
- margin: 0 8px 0 0;
- width: 100%;
-}
-
- .slider.slider-horizontal .slider-track {
- height: 5px;
- left: 0;
- margin-top: -2px;
- top: 50%;
- width: 100%;
- }
-
-.slider-handle {
- background-color: var(--color-link) !important;
- background-image: linear-gradient(to bottom,var(--color-link) 0%,var(--color-link) 100%) !important;
- border: 0px;
- border-radius: 9px;
- cursor: pointer !important;
- height: 18px;
- margin: 0 0 0 -8px !important;
- width: 18px;
-}
-
- .slider-handle.disabled {
- background-color: var(--color-subtle-copy) !important;
- background-image: linear-gradient(to bottom,var(--color-subtle-copy) 0%,var(--color-subtle-copy) 100%) !important;
- cursor: not-allowed !important;
- }
-
-.slider-selection.disabled {
- background-color: var(--color-subtle-copy);
- background-image: linear-gradient(to bottom,var(--color-subtle-copy) 0%,var(--color-subtle-copy) 100%);
-}
-
-.slider-track {
- background-color: #ededed;
- border: 0px;
- box-shadow: none;
-}
-
- .slider-track.disabled {
- background-color: var(--color-subtle-copy);
- border: 0px;
- }
-
-.slider-track-high {
- background-color: #ededed;
-}
-
-.slider-track-low {
- background-color: var(--color-link);
- background-image: linear-gradient(to bottom,var(--color-link) 0%,var(--color-link) 100%);
-}
-
- .slider-track-low.disabled {
- background-color: var(--color-subtle-copy);
- background-image: linear-gradient(to bottom,var(--color-subtle-copy) 0%,var(--color-subtle-copy) 100%);
- }
-
-.table {
- table-layout: fixed !important;
-}
-
- .table > thead > tr > th,
- .table > tbody > tr > td {
- padding: 0.4rem;
- vertical-align: middle;
- }
-
- .table > tbody > tr > td.ct-spacing {
- padding-bottom: 1.7rem;
- }
-
- .table > tbody > tr > td.config-level-0-sub-hidden {
- padding: 0px !important;
- }
-
- .table > tbody > tr > td.config-level-1 {
- padding-left: 3em !important;
- }
-
- .table > tbody > tr > td.config-level-2 {
- padding-left: 5em !important;
- }
-
- .table > tbody > tr > td.config-level-3 {
- padding-left: 7em !important;
- }
-
- .table > tbody > tr > td.config-level-4 {
- padding-left: 9em !important;
- }
-
- .table > tbody > tr > td > span.config-count-danger {
- color: var(--pf-global--danger-color--100);
- }
-
- .table > tbody > tr > td > span.config-count-warning {
- color: var(--pf-global--warning-color--100);
- }
-
- .table[id^="table-storagepool-status-"] > thead,
- .table[id^="table-storagepool-status-"] > thead > tr,
- .table[id^="table-storagepool-status-"] > thead > tr > th {
- border: 0 none !important;
- height: 0 !important;
- opacity: 0 !important;
- padding: 0 !important;
- }
-
- .table.table-ct-snapshots {
- margin-bottom: 0px !important;
- }
-
-tbody > tr.listing-ct-item.listing-ct-storagepoolsnotfound {
- cursor: default !important;
-}
-
- tbody > tr.listing-ct-item.listing-ct-storagepoolsnotfound > td:first-child {
- padding-left: 50px;
- }
-
-tbody > tr.listing-ct-item-snapshots {
- border-bottom: 0px !important;
-}
-
-.toast-notifications-list-pf {
- top: 20px;
-}
-
-.toast-pf > span > span.toast-ct-description {
- word-break: break-all;
-}
-
- .toast-pf > span > span.toast-ct-description.break-word {
- word-break: break-word !important;
- }
-
-/* Fix for flashing tooltip */
-.tooltip {
- pointer-events: none !important;
- position: fixed;
-}
-
-.tooltip-inner {
- overflow-wrap: break-word;
-}
-
-@media screen and (max-width: 343px) {
- .dropdown-menu-right {
- left: auto;
- right: auto;
- }
-}
-
-@media screen and (max-width: 480px) {
- .dropdown-ct-status {
- left: auto !important;
- right: auto !important;
- }
-
- .panel > .panel-heading > .panel-ct-actions {
- text-align: left !important;
- }
-
- .panel > .panel-heading > .panel-ct-heading,
- .panel > .panel-heading > .panel-ct-heading > .panel-title {
- min-height: 32px;
- min-width: 100%;
- }
-}
-
-@media screen and (min-width: 401px) and (max-width: 525px) {
- .dropdown-menu-right {
- left: auto;
- right: auto;
- }
-}
-
-@media screen and (min-width: 481px) and (max-width: 525px) {
- .dropdown-ct-status {
- left: auto !important;
- right: 0 !important;
- }
-}
-
-@media screen and (max-width: 640px) {
- .dialog-wait-ct {
- margin-bottom: 0.5em;
- }
-
- .listing-ct > thead > tr:first-child {
- display: none;
- }
-
- .listing-ct-actions > div > button.btn,
- .listing-ct-actions > div > div.btn-group {
- margin-bottom: 5px !important;
- }
-
- .listing-ct-item > td {
- padding: 0.5rem !important;
- vertical-align: middle !important;
- }
-
- .listing-ct-item > td.listing-ct-actionsmenu {
- display: table-cell !important;
- }
-
- .listing-ct-item > td:not(:first-child),
- .listing-ct-item > th {
- display: block;
- max-width: 100% !important;
- }
-
- .listing-ct-item > td > span.table-ct-head,
- .table.table-ct-filesystems > tbody > tr > td > span.table-ct-head,
- .table.table-ct-snapshots > tbody > tr > td > span.table-ct-head,
- .table.table-ct-status-config > tbody > tr > td > span.table-ct-head {
- color: var(--color-subtle-copy);
- display: inherit !important;
- float: left;
- font-weight: normal;
- padding-right: 0.5em;
- }
-
- .listing-ct-item > td.listing-ct-icon > span.table-ct-text,
- .table.table-ct-filesystems > tbody > tr > td > span.table-ct-text,
- .table.table-ct-snapshots > tbody > tr > td > span.table-ct-text,
- .table.table-ct-status-config > tbody > tr > td > span.table-ct-text {
- display: inline-block !important;
- padding-right: 0.5em;
- }
-
- .listing-ct-item > td.listing-ct-icon,
- .table.table-ct-filesystems > tbody > tr > td.listing-ct-icon,
- .table.table-ct-snapshots > tbody > tr > td.listing-ct-icon,
- .listing-ct .listing-ct-icon {
- width: 100% !important;
- }
-
- .listing-ct-wide {
- table-layout: initial;
- }
-
- .panel {
- overflow-x: visible !important;
- }
-
- .panel > .panel-heading {
- position: inherit !important;
- }
-
- .panel > .panel-heading > .panel-actions > button.btn {
- margin-bottom: 5px !important;
- }
-
- .table tbody tr > :first-child {
- padding-left: 0.4rem !important;
- }
-
- .table > tbody > tr > td.config-level-0-sub {
- clear: both;
- }
-
- .table > tbody > tr > td.config-level-0-sub::after,
- .table > tbody > tr > td.config-level-1-sub::after,
- .table > tbody > tr > td.config-level-2-sub::after,
- .table > tbody > tr > td.config-level-3-sub::after,
- .table > tbody > tr > td.config-level-4-sub::after {
- content: "\00a0";
- }
-
- .table > tbody > tr > td.config-level-0-sub-hidden,
- .table > tbody > tr > td.config-level-1-sub-hidden {
- display: none !important;
- }
-
- .table > tbody > tr > td.config-level-1,
- .table > tbody > tr > td.config-level-1-sub {
- padding-left: 1.5em !important;
- }
-
- .table > tbody > tr > td.config-level-2,
- .table > tbody > tr > td.config-level-2-sub {
- padding-left: 3em !important;
- }
-
- .table > tbody > tr > td.config-level-3,
- .table > tbody > tr > td.config-level-3-sub {
- padding-left: 4.5em !important;
- }
-
- .table > tbody > tr > td.config-level-4,
- .table > tbody > tr > td.config-level-4-sub {
- padding-left: 6em !important;
- }
-
- .table-ct-filesystems > thead,
- .table-ct-snapshots > thead,
- .table-ct-status-config > thead {
- display: none;
- }
-
- .table-ct-filesystems > tbody > tr > td:not(:last-child),
- .table-ct-snapshots > tbody > tr > td:not(:last-child),
- .table-ct-status-config > tbody > tr > td:not(:nth-last-child(-n+2)) {
- display: block;
- max-width: 100% !important;
- }
-
- .table-ct-status-config > tbody > tr.table-ct-confighead {
- display: none;
- }
-
- .table-ct-status-config > tbody > tr > td.config-level-0-virtualdevice {
- display: table-cell !important;
- }
-}
-
-
-
-/*
- * This file is part of Cockpit.
- *
- * Copyright (C) 2015 Red Hat, Inc.
- *
- * Cockpit is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * Cockpit is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Cockpit; If not, see .
- */
-
-
-.btn-group, .btn-group-vertical {
- /* Fix button groups from wrapping in narrow widths */
- display: inline-flex;
-}
-
-.dropdown-menu > li > a.disabled,
-.dropdown-menu > li > a.disabled:hover,
-.dropdown-menu > li > a.disabled:focus {
- color: var(--color-subtle-copy);
-}
-
- .dropdown-menu > li > a.disabled:hover,
- .dropdown-menu > li > a.disabled:focus {
- text-decoration: none;
- background-color: transparent;
- background-image: none;
- border-color: transparent;
- filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
- cursor: default;
- }
-
-/* Limit dropdown menus to 90% of the viewport size */
-.dropdown-menu {
- height: auto;
- overflow-y: auto;
- max-height: 90vh;
-}
-
-/* Allow kebab menus to have a ^ with overflowing */
-/* Note: This means kebab menus cannot be _too_ long */
-.dropdown-kebab-pf > .dropdown-menu {
- overflow: visible;
-}
-
-.dialog-list-ct {
- max-height: 230px;
- overflow-x: auto;
- border: 1px solid var(--color-light-gray);
- margin-bottom: 0px;
-}
-
-:root {
- /* Custom font aliases */
- --font-family: var(--pf-global--FontFamily--sans-serif);
- --font-family-mono: var(--pf-global--FontFamily--monospace);
- --font-size: var(--pf-global--FontSize--md);
- --font-size-s: var(--pf-global--FontSize--sm);
- --font-size-xs: var(--pf-global--FontSize--xs);
- --font-size-l: var(--pf-global--FontSize--lg);
- --font-size-xl: var(--pf-global--FontSize--xl);
- --font-size-2xl: var(--pf-global--FontSize--2xl);
- --font-size-3xl: var(--pf-global--FontSize--3xl);
-
- /* Cockpit custom colors */
- --color-ct-light-red-1: #f8cccc;
- --color-ct-light-red-2: #f8acac;
- --color-ct-light-red-3: #f98383;
- --color-ct-brick-gold: #ffa763;
- --color-ct-brick-red: #a53131;
-
- --color-ct-nav: #1b1b1b;
- --color-ct-nav-sub: var(--pf-global--BackgroundColor--dark-300);
- --color-ct-nav-text: var(--pf-global--BackgroundColor--light-300);
- --color-ct-nav-active: var(--pf-global--BackgroundColor--dark-400);
- --color-ct-nav-active-text: var(--pf-global--BackgroundColor--light-100);
- --color-ct-nav-hover: var(--pf-global--BackgroundColor--dark-400);
- --color-ct-nav-hover-text: var(--pf-global--BackgroundColor--light-100);
- --color-ct-nav-border: var(--pf-global--BorderColor--100);
- --color-ct-nav-cover-up: linear-gradient(to bottom, var(--color-ct-nav-sub), rgba(21,21,21, 0));
- --color-ct-nav-cover-down: linear-gradient(to top, var(--color-ct-nav-sub), rgba(21,21,21, 0));
-
- --color-ct-nav-main: #1b1b1b;
- --color-ct-nav-main-text: var(--color-ct-nav-text);
- --color-ct-nav-main-border: var(--pf-global--BackgroundColor--dark-200);
- --color-ct-nav-main-active: var(--color-ct-nav-sub);
- --color-ct-nav-main-active-text: var(--color-ct-nav-active-text);
- --color-ct-nav-main-hover: var(--color-ct-nav-hover);
- --color-ct-nav-main-hover-text: var(--color-ct-nav-hover-text);
-
- --color-border: var(--pf-global--BorderColor--100);
-
- --color-ct-list-text: var(--color-text);
- --color-ct-list-link: var(--color-link);
- --color-ct-list-bg: var(--color-bg);
- --color-ct-list-border: var(--color-border);
- --color-ct-list-hover-text: var(--color-link);
- --color-ct-list-hover-bg: var(--pf-global--BackgroundColor--150);
- --color-ct-list-hover-border: var(--pf-global--BackgroundColor--150);
- --color-ct-list-hover-icon: var(--color-blue);
- --color-ct-list-selected-text: var(--color-link);
- --color-ct-list-selected-bg: var(--pf-global--BackgroundColor--150);
- --color-ct-list-selected-border: var(--pf-global--BackgroundColor--150);
- --color-ct-list-active-text: var(--color-link-focus);
- --color-ct-list-active-bg: var(--color-bg);
- --color-ct-list-active-border: var(--color-ct-list-border);
- --color-ct-list-critical-bg: var(--color-ct-light-red-1);
- --color-ct-list-critical-border: var(--color-ct-light-red-2);
- --color-ct-list-critical-bg-hover: var(--color-ct-light-red-2);
- --color-ct-list-critical-border-hover: var(--color-ct-light-red-3);
-
- --color-link-hover-bg: var(--color-light-blue-2);
- --color-link-hover-icon: var(--color-blue-5);
-
- /* Red Hat Digital Design System 2019 named colors */
- --color-red-hat-red: #ee0000;
- --color-red-1: #cc0000;
- --color-red-2: #a30000;
- --color-red-3: #820000;
- --color-dark-red-4: #5a0000;
- --color-dark-red-5: #460000;
- --color-dark-red-6: #320000;
- --color-black: #000000;
- --color-white: #ffffff;
- --color-dark-blue: #004153;
- --color-light-blue: #a3dbe8;
- --color-dark-gray: #4c4c4c;
- --color-light-gray: #dcdcdc;
- --color-purple: #3b0083;
- --color-gold: #f0ab00;
- --color-teal: #007987;
- --color-blue: #00b9e4;
- --color-green: #92d400;
- --color-storage: #ec7a08;
- --color-infra: #0088ce;
- --color-app-dev: #3f9c35;
- --color-light-blue-1: #e8f6f9;
- --color-light-blue-2: #d1edf4;
- --color-light-blue-3: #b6e2ec;
- --color-dark-blue-1: #80a0a9;
- --color-dark-blue-2: #4e7a86;
- --color-dark-blue-3: #1b5764;
- --color-blue-1: #d9f5fb;
- --color-blue-2: #c0edf7;
- --color-blue-3: #9ae4f3;
- --color-blue-4: #82ddf1;
- --color-blue-5: #68d6ee;
- --color-blue-6: #38c8e8;
- --color-teal-1: #d9ebed;
- --color-teal-2: #cbe4f1;
- --color-teal-3: #b3d7db;
- --color-teal-4: #9acacf;
- --color-teal-5: #68afb6;
- --color-teal-6: #36959e;
- --color-green-1: #eaf5cd;
- --color-green-2: #dff1b4;
- --color-green-3: #d4ec9c;
- --color-green-4: #cae883;
- --color-green-5: #b5df56;
- --color-green-6: #aadb40;
- --color-gold-1: #fcedcd;
- --color-gold-2: #fae5b4;
- --color-gold-3: #f9dc9c;
- --color-gold-4: #f8d384;
- --color-gold-5: #f5c255;
- --color-gold-6: #f2b22d;
- --color-purple-1: #e2daec;
- --color-purple-2: #cdc0df;
- --color-purple-3: #b09bcc;
- --color-purple-4: #9c82c0;
- --color-purple-5: #8869b3;
- --color-purple-6: #7551a6;
- --color-gray-1: #f0f0f0;
- --color-gray-2: #e6e6e6;
- --color-gray-3: #d2d2d2;
- --color-gray-4: #bebebe;
- --color-gray-5: #aaaaaa;
- --color-gray-6: #969696;
- --color-gray-7: #828282;
- --color-gray-8: #6e6e6e;
- --color-gray-9: #5a5a5a;
- --color-gray-10: #464646;
- --color-gray-11: #323232;
- --color-gray-12: #1e1e1e;
-
- /* Semantic colors */
- --color-fg: #151515;
- --color-bg: #fff;
- --color-text: var(--color-fg);
-
- --color-link: #0066cc;
- --color-link-visited: #0066cc;
- --color-link-hover: #004080;
- --color-link-focus: #004080;
- --color-link-dark: #73bcf7;
- --color-link-visited-dark: #73bcf7;
- --color-link-hover-dark: #2b9af3;
- --color-link-focus-dark: #2b9af3;
-
- --color-heading: #151515;
- --color-heading-dark: #ffffff;
- --color-body-copy: #151515;
- --color-body-copy-dark: #cccccc;
- --color-body-copy-dark-color: rbga(255,255,255,0.8);
- --color-subtle-copy: #72767b;
- --color-subtle-text-dark: #cccccc;
-
- --color-alert-success-bg: #ffffff;
- --color-alert-sucess-icon: #92d400;
- --color-alert-sucess-border: #92d400;
- --color-alert-success-text: #486b00;
- --color-alert-info-bg: #ffffff;
- --color-alert-info-icon: #39a5dc;
- --color-alert-info-border: #39a5dc;
- --color-alert-info-text: #004368;
- --color-alert-warning-bg: #ffffff;
- --color-alert-warning-icon: #f0ab00;
- --color-alert-warning-border: #f0ab00;
- --color-alert-warning-text: #795600;
- --color-alert-danger-bg: #ffffff;
- --color-alert-danger-icon: #c9190b;
- --color-alert-danger-border: #c9190b;
- --color-alert-danger-text: #7d1007;
-
- --color-low-severity-background: #ffffff;
- --color-low-severity-icon: #72767b;
- --color-low-severity-border: #72767b;
- --color-low-severity-text: #151515;
- --color-moderate-severity-background: #ffffff;
- --color-moderate-severity-icon: #f0ab00;
- --color-moderate-severity-border: #f0ab00;
- --color-moderate-severity-text: #795600;
- --color-important-severity-background: #ffffff;
- --color-important-severity-icon: #df7409;
- --color-important-severity-border: #df7409;
- --color-important-severity-text: #8f4c09;
- --color-critical-severity-background: #ffffff;
- --color-critical-severity-icon: #c9190b;
- --color-critical-severity-border: #c9190b;
- --color-critical-severity-text: #7d1007;
-
- --color-cta-default: #0066cc;
- --color-cta-default-hover: #004080;
- --color-cta-primary: #ee0000;
- --color-cta-primary-hover: #d40000;
- --color-cta-secondary: #151515;
- --color-cta-secondary-hover: #151515;
- --color-cta-accent: #0066cc;
- --color-cta-accent-hover: #0066cc;
-
- --color-button-text: #ffffff;
- --color-button-text-dark: #151515;
- --color-button-default: #151515;
- --color-button-default-hover: #151515;
- --color-button-primary: #0066cc;
- --color-button-primary-hover: #004080;
- --color-button-secondary: #0066cc;
- --color-button-secondary-hover: #0066cc;
- --color-button-disabled: #d2d2d2;
- --color-button-disabled-text: #72767b;
-
- --color-border-lighter: #d2d2d2;
- --color-border-default: #d2d2d2;
- --color-border-darker: #d2d2d2;
-
- --color-potential-band-color: #f0f0f0;
- --color-ui-hover-bg: #ededed;
- --color-ui-alternate-row-bg: #ededed;
-
- --color-label: #151515;
- --color-form-field-bottom-border: #8b8d8f;
- --color-form-field-border: #0066cc;
- --color-form-field-focus: #0066cc;
- --color-form-field-bg: #ffffff;
- --color-form-field-text: #151515;
- --color-form-field-error-border: #a30000;
- --color-form-field-error-bg: #ffffff;
- --color-form-field-error-text: #a30000;
- --color-form-field-active-border: #0066cc;
- --color-select-dropdown-bottom-border: #8b8d8f;
- --color-select-dropdown-bg: #ffffff;
- --color-select-dropdown-arrow-color: #151515;
- --color-select-dropdown-text-color: #151515;
-
- --color-breadcrumb-link: #0066cc;
- --color-breadcrumb-link-hover: #004080;
- --color-breadcrumb-text: #151515;
-
- --color-pagination-current-text: #393f44;
-
- --color-chips: #72767b;
- --color-chips-secondary: #72767b;
- --color-chips-hover: #72767b;
-
- --color-tab-link: #007bba;
- --color-tab-text: #007bba;
- --color-tab-indicator-color: #007bba;
- --color-tab-bg: #ffffff;
- --color-tab-border: #ededed;
- --color-tab-selected-text: #007bba;
- --color-tab-selected-indicator-color: #007bba;
- --color-tab-selected-bg: #ffffff;
- --color-tab-selected-border: #ededed;
-
- --color-tooltips-bg: #ffffff;
- --color-tooltips-text: #151515;
-
- --color-modal-bg: #ffffff;
- --color-modal-header-bg: #151515;
-
- --color-table-header-bg: #ffffff;
- --color-table-header-text: #393f44;
- --color-table-header-border: #ededed;
- --color-table-header-border-bottom: #ededed;
- --color-table-border: #ededed;
- --color-table-border-bottom: #ededed;
- --color-table-text: #393f44;
-}
-
-/* Table headers should not generate a double border */
-.panel .table thead tr th {
- border-bottom: none;
-}
-
-/* Fix panel heading alignment & mobile layout */
-.panel-heading {
- align-items: center;
- background: #f5f5f5;
- display: flex;
- flex-wrap: wrap;
- /* (28px small size widget height) + (0.5rem * 2) */
- min-height: calc(28px + 1rem);
- /* Modified for Cockpit ZFS Manager - Original: padding: 0.5rem 0.5rem 0.5rem 1rem; */
- padding: 0.5rem 1rem 0.5rem 1rem;
- position: relative;
- z-index: 100;
-}
-
-.panel-title {
- font: inherit;
- margin: 0;
- padding: 0;
-}
-
- .panel-title > a {
- color: var(--color-link);
- display: inline-block;
- }
-
- .panel-title > a:hover,
- .panel-title > a:focus {
- color: var(--alert-info-text);
- }
-
- /* Allow children in the title to wrap */
- .panel-title > h3,
- .panel-title > a,
- .panel-title > div,
- .panel-title > span {
- flex-shrink: 1;
- word-break: break-all;
- }
-
-.panel-heading > :last-child:not(:first-child),
-.panel-heading > .pull-right,
-.panel-heading > .panel-heading-actions {
- flex: auto;
- text-align: right;
-}
-
-.panel-heading > .pull-right {
- /* HACK: Pull right shouldn't be used to change document order. */
- /* This CSS _also_ changes document order to replicate the float. */
- /* Solution: Fix document order when pull-right is used. */
- order: 100;
-}
-
- .panel-heading > .pull-right:first-child ~ :last-child {
- /* Undo :last-child above for cases where pull-right is used before */
- text-align: left;
- }
-
-@media screen and (max-width: 640px) {
- /* Remove _most_ of the gaps on the sides of small screens */
- /* to maximize space, but still keep the boxy panel look */
- /* (container-fluid & page-ct adds 20px, so we remove 1/2 of that) */
- .page-ct > .panel,
- .container-fluid > .panel,
- .col-md-12 > .panel {
- margin-left: -10px;
- margin-right: -10px;
- }
-
- .panel {
- /* Background fade */
- --hi-color: #d1d1d1;
- --hi-color2: var(--color-gray-2);
- --bg-color: var(--color-bg);
- --hi-width: 20px;
- --hi-width3: calc(var(--hi-width) * 3);
- --transparent: rgba(255,255,255,0); /* WebKit needs white transparent */
- max-width: 100vw;
- overflow-x: auto;
- position: relative;
- background-image:
- linear-gradient(to left, var(--bg-color) var(--hi-width), var(--transparent) var(--hi-width3)),
- linear-gradient(to left, var(--hi-color) 1px, var(--transparent) 2px, var(--hi-color2) 4px, var(--bg-color) var(--hi-width)),
- linear-gradient(to right, var(--bg-color) var(--hi-width), var(--transparent) var(--hi-width3)),
- linear-gradient(to right, var(--hi-color) 1px, var(--transparent) 2px, var(--hi-color2) 4px, var(--bg-color) var(--hi-width));
- background-attachment: local, scroll, local, scroll;
- background-position: right, right, left, left;
- background-repeat: no-repeat;
- background-size: var(--hi-width3) 100%;
- }
-
- .panel > .panel-heading {
- /* WebKit still needs -webkit- prefix for sticky */
- position: -webkit-sticky;
- position: sticky;
- left: 0;
- top: 0;
- }
-
- .panel .table thead th {
- white-space: nowrap;
- }
-
- .panel .table:not(:hover):not(:focus):not(:active) {
- background: transparent;
- }
-
- .panel .table thead:not(:hover):not(:focus):not(:active) {
- background: transparent;
- }
-}
-
-/* Override the heavy patternfly headers */
-.table > thead {
- background-image: none;
- background-color: var(--color-bg);
-}
-
-/* Make things line up */
-.table tbody tr > :first-child,
-.table thead tr > :first-child {
- padding-left: 1rem;
-}
-
-.table tbody tr > :last-child,
-.table thead tr > :last-child {
- padding-right: 1rem;
-}
-
-label.onoff-ct {
- --switch-width: 40px;
- --switch-height: 24px;
- --switch-background: var(--color-gray-3);
- --switch-border-color: transparent;
- --switch-border-style: solid;
- --switch-border-width: 1px;
- --switch-text: inherit;
- --switch-dot-size: 14px;
- --switch-dot: var(--color-bg);
- position: relative;
- display: inline-flex;
- align-items: center;
- margin-bottom: 0;
- padding: 1px 0;
- /* Height is 24px; bump to 26px like other widgets */
- vertical-align: middle;
- /* Focus ring */
- /* Don't show the focus ring for mouse clicks (when hovering) */
- /* Subtly darken the inner part of the switch on hover */
-}
-
- label.onoff-ct > .switch-on,
- label.onoff-ct > .switch-off,
- label.onoff-ct > input ~ .switch-toggle,
- label.onoff-ct > input ~ .switch-toggle::after {
- transition: all 300ms ease-in-out;
- }
-
- label.onoff-ct > .switch-on,
- label.onoff-ct > .switch-off {
- color: var(--switch-text);
- margin-left: 0.5em;
- }
-
- label.onoff-ct > input {
- opacity: 0;
- position: absolute;
- /* Base toggle graphic */
- /* Hide unused switch label */
- }
-
- label.onoff-ct > input ~ .switch-toggle {
- --switch-dot-offset-x: calc(var(--switch-dot-size)/3 - var(--switch-border-width));
- --switch-dot-offset-y: calc(50% - 14px / 2);
- /* Don't let the border draw over the background */
- background-clip: content-box;
- background: var(--switch-background);
- border-radius: var(--switch-height);
- border: var(--switch-border-width) var(--switch-border-style) var(--switch-border-color);
- box-shadow: inset 0 0 0 1px transparent;
- width: var(--switch-width);
- height: var(--switch-height);
- display: inline-block;
- position: relative;
- margin: 0;
- cursor: pointer;
- /* Dot graphic */
- }
-
- label.onoff-ct > input ~ .switch-toggle::after {
- background: var(--switch-dot);
- box-shadow: 0 0 var(--switch-dot-offset-x) rgba(0, 0, 0, 0.2);
- display: inline-block;
- content: "";
- height: var(--switch-dot-size);
- width: var(--switch-dot-size);
- border-radius: 50%;
- top: var(--switch-dot-offset-y);
- left: var(--switch-dot-offset-x);
- position: absolute;
- pointer-events: none;
- }
-
- label.onoff-ct > input ~ .switch-off {
- --switch-text: var(--color-subtle-copy);
- }
-
- label.onoff-ct > input:checked ~ .switch-toggle {
- --switch-background: var(--color-link);
- --switch-dot-offset-x: calc(100% - var(--switch-dot-size) * 1.333333 + var(--switch-border-width));
- /* Modified for Cockpit ZFS Manager - New */
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10.583 6.35'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-width='.529' d='M2.252 3.365l.756.758L4.48 2.65' opacity='.75'/%3E%3C/svg%3E");
- }
-
- label.onoff-ct > input:checked ~ .switch-toggle:last-child {
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10.583 6.35'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-width='.529' d='M2.252 3.365l.756.758L4.48 2.65' opacity='.75'/%3E%3C/svg%3E");
- }
-
- label.onoff-ct > input:disabled ~ .switch-toggle {
- --switch-background: var(--color-subtle-copy);
- --switch-dot: var(--color-gray-3);
- }
-
- label.onoff-ct > input:disabled ~ * {
- cursor: not-allowed;
- }
-
- label.onoff-ct > input:checked ~ .switch-off,
- label.onoff-ct > input:not(:checked) ~ .switch-on {
- display: none;
- }
-
- label.onoff-ct :disabled ~ .switch-on,
- label.onoff-ct :disabled ~ .switch-off {
- --switch-text: var(--color-subtle-copy);
- }
-
- label.onoff-ct :focus ~ .switch-toggle::before {
- /* Approximate Chrome's focus ring, for non-Firefox browsers */
- border: 2px solid rgba(0, 98, 220, 0.4);
- border-radius: calc(var(--switch-width) - 10px);
- position: absolute;
- content: '';
- top: -4px;
- bottom: -4px;
- left: -4px;
- width: calc(var(--switch-width) + 6px);
- transition: all 300ms ease-in-out;
- /* HACK: Keyboard has nothing to transition from, but hover does */
- /* (as it changes the ring to transparent and back). */
- /* So we delay the hover to not have the focus ring on hover out. */
- /* This makes the focus ring show up for keyboard users, but not on a mouse click. */
- transition-delay: 600s;
- z-index: 1;
- }
-
-@-moz-document url-prefix() {
- label.onoff-ct :focus ~ .switch-toggle::before {
- /* Approximate Firefox's focus ring, for Firefox only */
- border: 1px dotted rgba(0, 0, 0, 0.75);
- }
-}
-
-label.onoff-ct :focus:hover ~ .switch-toggle::before {
- border-color: transparent;
-}
-
-label.onoff-ct:hover :not(:disabled) ~ .switch-toggle {
- box-shadow: inset 0 1px 5px 1px rgba(0, 0, 0, 0.15);
-}
-
-h1 label.onoff-ct {
- vertical-align: bottom;
-}
-
-/* Form layout */
-:root {
- --ct-form-columns: 2;
-}
-
-.ct-form {
- align-self: start;
- display: grid;
- grid-gap: 0.5rem 1.5rem;
- grid-template-columns: repeat(var(--ct-form-columns), max-content 1fr);
- justify-items: stretch;
- align-content: baseline;
-}
-
- .ct-form > .control-label {
- text-align: right;
- padding: 0;
- margin: 0;
- }
-
- .ct-form > :not(hr):not(p) {
- line-height: 2.25rem;
- }
-
- .ct-form > p {
- margin: 0;
- }
-
- .ct-form > :not(.control-label):not(hr):not(.ct-form-split):not(.ct-form-full) {
- grid-column: 2 / -1;
- }
-
- .ct-form > :not(.ct-form-relax):not(.spinner) {
- width: auto;
- }
-
- .ct-form > hr {
- border: none;
- grid-column: 1 / -1;
- height: 0.5rem;
- margin: 0;
- padding: 0;
- }
-
- .ct-form > input[size],
- .ct-form > .ct-validation-wrapper > input[size] {
- justify-self: start;
- }
-
- .ct-form > .ct-validation-wrapper {
- display: flex;
- flex-direction: column;
- }
-
- .ct-form input[type=number] {
- -webkit-appearance: textarea;
- }
-
- .ct-form > input,
- .ct-form > .ct-validation-wrapper > input,
- .ct-form > textarea,
- .ct-form > .ct-validation-wrapper > textarea,
- .ct-form > select,
- .ct-form > .ct-validation-wrapper > select,
- .ct-form > .bootstrap-select,
- .ct-form > .ct-validation-wrapper > .bootstrap-select,
- .ct-form > .ct-select,
- .ct-form > .ct-validation-wrapper > .ct-select,
- .ct-form > .dropdown,
- .ct-form > .ct-validation-wrapper > .dropdown,
- .ct-form > .combobox-container,
- .ct-form > .ct-validation-wrapper > .combobox-container,
- .ct-form > fieldset,
- .ct-form > .ct-validation-wrapper > fieldset,
- .ct-form > [role=group],
- .ct-form > .ct-validation-wrapper > [role=group],
- .ct-form > [data-field],
- .ct-form > .ct-validation-wrapper > [data-field],
- .ct-form > .form-group,
- .ct-form > .ct-validation-wrapper > .form-group,
- .ct-form > .btn-group,
- .ct-form > .ct-validation-wrapper > .btn-group,
- .ct-form > label.checkbox,
- .ct-form > .ct-validation-wrapper > label.checkbox,
- .ct-form > label.radio,
- .ct-form > .ct-validation-wrapper > label.radio,
- .ct-form > .checkbox-inline,
- .ct-form > .ct-validation-wrapper > .checkbox-inline,
- .ct-form > .radio-inline,
- .ct-form > .ct-validation-wrapper > .radio-inline {
- line-height: var(--pf-global--LineHeight--md);
- }
-
- .ct-form > :not(.ct-form-relax):not(.spinner) {
- width: auto !important;
- }
-
- .ct-form > [role=group],
- .ct-form > .ct-validation-wrapper > [role=group] {
- align-self: start;
- align-content: center;
- display: grid;
- grid-gap: 0.5rem;
- min-height: 2.25rem;
- justify-content: start;
- grid-template-columns: repeat(2, auto);
- }
-
- .ct-form > [role=group].ct-form-vertical > :not(.ct-form-split),
- .ct-form > .ct-validation-wrapper > [role=group].ct-form-vertical > :not(.ct-form-split) {
- grid-column: 1 / -1;
- }
-
- .ct-form > [role=group] > .checkbox,
- .ct-form > .ct-validation-wrapper > [role=group] > .checkbox,
- .ct-form > [role=group] > .radio,
- .ct-form > .ct-validation-wrapper > [role=group] > .radio {
- margin: 0;
- }
-
- .ct-form > [role=group] > .checkbox:first-child,
- .ct-form > .ct-validation-wrapper > [role=group] > .checkbox:first-child,
- .ct-form > [role=group] > .radio:first-child,
- .ct-form > .ct-validation-wrapper > [role=group] > .radio:first-child {
- margin-top: 0.5rem;
- }
-
- .ct-form > [role=group]:not(.ct-form-relax) > .dropdown,
- .ct-form > .ct-validation-wrapper > [role=group]:not(.ct-form-relax) > .dropdown,
- .ct-form > .ct-validation-wrapper > [data-field]:not(.ct-form-relax) > .dropdown {
- width: auto !important;
- }
-
- .ct-form > [role=group]:not(.ct-form-relax) > .ct-select,
- .ct-form > .ct-validation-wrapper > [role=group]:not(.ct-form-relax) > .ct-select,
- .ct-form > .ct-validation-wrapper > [data-field]:not(.ct-form-relax) > .ct-select {
- width: 100%;
- }
-
- .ct-form label.checkbox,
- .ct-form label.radio,
- .ct-form .checkbox > label,
- .ct-form .radio > label,
- .ct-form .checkbox-inline,
- .ct-form .radio-inline {
- display: inline-flex;
- padding-left: 0;
- padding-right: 1.5rem;
- align-items: center;
- }
-
- .ct-form label.checkbox > input[type="checkbox"],
- .ct-form label.radio > input[type="checkbox"],
- .ct-form .checkbox > label > input[type="checkbox"],
- .ct-form .radio > label > input[type="checkbox"],
- .ct-form .checkbox-inline > input[type="checkbox"],
- .ct-form .radio-inline > input[type="checkbox"],
- .ct-form label.checkbox > input[type="radio"],
- .ct-form label.radio > input[type="radio"],
- .ct-form .checkbox > label > input[type="radio"],
- .ct-form .radio > label > input[type="radio"],
- .ct-form .checkbox-inline > input[type="radio"],
- .ct-form .radio-inline > input[type="radio"] {
- margin: 0 0.5em 0 0;
- position: static;
- }
-
- .ct-form fieldset > .checkbox:first-child,
- .ct-form fieldset > .radio:first-child {
- margin-top: 0;
- }
-
- .ct-form fieldset > .checkbox:last-child,
- .ct-form fieldset > .radio:last-child {
- margin-bottom: 0;
- }
-
- .ct-form .list-group {
- margin-bottom: 0.5rem;
- }
-
- .ct-form > .ct-form-split {
- grid-column: auto / auto;
- }
-
- .ct-form > .ct-form-full {
- grid-column: 1 / -1;
- }
-
- .ct-form > .help-block {
- position: relative;
- margin-top: -0.5rem;
- }
-
- .ct-form .help-block {
- --help-line-height: calc(var(--pf-global--LineHeight--md) * 1rem);
- line-height: var(--help-line-height);
- }
-
- .ct-form .help-block:empty {
- display: none;
- }
-
- .ct-form .help-block .spinner {
- position: relative;
- top: calc((var(--help-line-height) - 16px - 2px) / 2);
- }
-
- .ct-form .ct-form-box {
- background: var(--color-gray-1);
- border-width: 1px;
- border-style: solid;
- border-color: var(--color-gray-5);
- padding: 0.5rem;
- padding-top: 1rem;
- width: 100%;
- }
-
-.ct-form-stretch {
- justify-content: stretch !important;
-}
-
-.ct-form-relax {
- justify-self: start;
-}
-
-.modal-dialog.modal-sm .ct-form > .ct-form-split {
- grid-column: 2 / -1;
-}
-
-@media (max-width: 640px) {
- .listing-ct-body,
- .modal {
- --ct-form-columns: 1;
- }
-}
-
-.ct-form-minmax {
- grid-template-columns: max-content min-content max-content 1fr;
-}
-
-.ct-form-maxmin {
- grid-template-columns: max-content 1fr max-content min-content;
-}
-
-@media (max-width: 480px) {
- .listing-ct-body .ct-form,
- .modal .ct-form {
- grid-template-columns: initial;
- }
-
- .listing-ct-body .ct-form > *,
- .modal .ct-form > * {
- grid-column: auto;
- max-width: 100%;
- }
-
- .listing-ct-body .ct-form > .control-label,
- .modal .ct-form > .control-label {
- padding: 0;
- text-align: left;
- }
-
- .listing-ct-body .ct-form > .control-label:not(:first-child),
- .modal .ct-form > .control-label:not(:first-child) {
- margin: 6px 0 0;
- }
-
- .listing-ct-body .ct-form > hr,
- .modal .ct-form > hr {
- height: 12px;
- }
-}
-
-/* Listing pattern */
-.ct-listing {
- font-size: var(--font-size-s);
- min-width: 65%;
- clear: both;
-}
-
- .ct-listing > header {
- display: flex;
- align-items: center;
- justify-content: start;
- flex-flow: wrap;
- }
-
- .ct-listing > header > :only-child {
- flex: auto;
- }
-
- .ct-listing + .ct-listing {
- margin-top: 1rem;
- }
-
-.listing-ct-heading,
-.listing-ct-actions {
- margin: 0.5rem 0;
-}
-
-.listing-ct-heading {
- flex: auto;
- padding: 0.25rem 1em 0.25rem 0;
-}
-
-.ct-listing > table > thead h3 {
- font-size: var(--pf-global--FontSize--2xl);
- padding: 1rem 0;
- font-weight: 400;
- margin-top: 0;
- position: relative;
-}
-
- .ct-listing > table > thead h3 > .pull-right {
- position: absolute;
- top: 50%;
- transform: translateY(-50%);
- right: 0;
- }
-
-.ct-listing > table > thead td {
- padding-top: 1rem;
-}
-
-.ct-listing > table > thead:first-child td {
- padding-top: 0;
-}
-
-.ct-listing > table > thead td > a {
- line-height: 30px;
- padding: 0.5rem 0 0.5rem;
-}
-
-.ct-listing > table > thead th {
- font-weight: normal;
- padding: 0.5rem 1rem;
- color: var(--color-subtle-copy);
-}
-
- .ct-listing > table > thead th:first-child {
- padding-left: 1rem;
- }
-
- .ct-listing > table > thead th:last-child {
- text-align: right;
- }
-
-/* A listing item is a row in the table */
-tbody > tr.listing-ct-item {
- border: 1px solid transparent;
- border-top: 1px solid var(--color-ct-list-border);
- border-bottom: 1px solid var(--color-ct-list-border);
- cursor: pointer;
-}
-
-.ct-listing > table > tbody:last-child {
- border-bottom: 1px solid var(--color-ct-list-border);
-}
-
-.ct-listing > table > tbody + thead {
- border-top: 1px solid var(--color-ct-list-border);
-}
-
-.ct-listing > table > tbody.open:last-child {
- border-bottom: none;
-}
-
-.ct-listing > table > tbody.open + thead {
- border-top: none;
-}
-
-tbody > tr.listing-ct-item.listing-ct-warning {
- background-color: var(--color-ct-light-red-1);
-}
-
-tbody.open > tr.listing-ct-item,
-tbody.open > tr.listing-ct-panel {
- background-color: var(--color-ct-list-active-bg);
- border-bottom: none;
- border-top: none;
- border-left: 1px solid var(--color-light-gray);
- border-right: 1px solid var(--color-light-gray);
- transition: all 200ms;
-}
-
- tbody.open > tr.listing-ct-item td,
- tbody.open > tr.listing-ct-item th {
- border-top: 1px solid var(--color-light-gray);
- }
-
-tbody.open td div.listing-ct-head {
- background-color: #fff;
-}
-
-tbody.open > .listing-ct-panel > td > .listing-ct-body {
- border: none;
- /* Modified for Cockpit ZFS Manager - Original: overflow: auto; */
- /* Do not display scrollbars when actions menu is open */
- overflow: inherit;
- /* Modified for Cockpit ZFS Manager - New */
- overflow-y: visible;
-}
-
-tbody.open > tr.listing-ct-panel + tr.listing-ct-body {
- border-top: none;
-}
-
-tbody.open > tr.listing-ct-panel td div.listing-ct-head {
- border: none;
- border-bottom: 1px solid var(--color-light-gray);
-}
-
-/* only highlight the row if navigation is available */
-tbody:not(.open) > tr.listing-ct-item:not(.listing-ct-nonavigate):hover {
- background-color: var(--color-ct-list-hover-bg);
-}
-
-/* if we can't navigate to a row but expand is available, highlight the caret */
-tbody:not(.open) > tr.listing-ct-item.listing-ct-nonavigate:hover td.listing-ct-toggle {
- color: var(--color-ct-list-hover-icon);
-}
-
-/* use hover color expanded rows even if navigation isn't available */
-tbody.open > tr.listing-ct-item:hover,
-/* Modified for Cockpit ZFS Manager - Original: tr.listing-ct-item.listing-ct-nonavigate:hover */
-tr.listing-ct-item.listing-ct-nonavigate:not(.listing-ct-storagepoolsnotfound):hover {
- background-color: var(--color-ct-list-hover-bg);
-}
-
-tr.listing-ct-item .listing-ct-toggle:not(:empty) {
- width: 35px;
- color: #393f44;
-}
-
-/* Highlight toggle color when hovered or if the row is open */
-.listing-ct-toggle:hover,
-tbody.open .listing-ct-toggle {
- color: var(--color-ct-list-active-bg);
-}
-
-.listing-ct > thead > tr > .listing-ct-toggle + th,
-.listing-ct-item > .listing-ct-toggle + td,
-.listing-ct-item > .listing-ct-toggle + th {
- padding-left: 0.25rem;
- position: relative;
-}
-
-td.listing-ct-toggle i {
- font-size: 17px;
-}
-
- td.listing-ct-toggle i:before {
- position: relative;
- content: "\F105";
- display: block;
- }
-
-/* Modified for Cockpit ZFS Manager - Original: tbody.open > td.listing-ct-toggle i:before */
-tbody.open > tr.listing-ct-item td.listing-ct-toggle i:before,
-/* Modified for Cockpit ZFS Manager - New */
-tbody.open > tr.listing-ct-item-snapshots .listing-ct-toggle-snapshots i:before {
- content: "\F107";
- animation: listingCtToggleOpen 100ms ease-in-out;
- top: 1px;
-}
-
-@keyframes listingCtToggleOpen {
- 0% {
- transform-origin: 50% 50%;
- transform: translate(0, -1px) rotate(-90deg);
- }
-
- 100% {
- transform: translate(0, 0) rotate(0);
- }
-}
-
-/* Listing items have decent padding ... */
-.listing-ct > thead > tr > th,
-tr.listing-ct-item > th,
-tr.listing-ct-item > td {
- padding: 0.75rem;
- vertical-align: text-top;
- /* baseline doesn't support wrapped lines */
-}
-
- tr.listing-ct-item > td > .btn {
- /* .btn has padding of 6px and 1px border */
- margin-top: -7px;
- margin-bottom: -7px;
- }
-
- tr.listing-ct-item > td > .btn-control-ct {
- /* Adapt for Cockpit's modified button, which is larger by 8px */
- margin-top: -3px;
- margin-bottom: -3px;
- }
-
-/* Listing actions can be used directly as a cell */
-tr.listing-ct-item td.listing-ct-actions,
-td.listing-ct-actions {
- padding: 0.25rem 0.5rem;
- text-align: right;
- float: none;
-}
-/* if the entire row is selected, highlight */
-tr.listing-ct-item.listing-ct-selected {
- background-color: #0088ce;
- color: #fff;
- border-color: #007ebf;
-}
-
- tr.listing-ct-item.listing-ct-selected:hover {
- background-color: #007ebf;
- border-color: #007ebf;
- }
-
- tr.listing-ct-item.listing-ct-selected .badge {
- background-color: #00537e;
- }
-
- tr.listing-ct-item.listing-ct-selected .badge:hover {
- background-color: #003e5f;
- }
-
-.listing-ct-head .listing-ct-actions {
- margin-top: -7px;
- order: -1;
-}
-
-/* Modified for Cockpit ZFS Manager - Original: tr.listing-ct-item td:last-child */
-.ct-listing > table > tbody > tr > td:last-child:not(:first-child) {
- text-align: right;
-}
-
-div.listing-ct-panel {
- box-shadow: 1px 1px 1px 1px #f5f5f5;
- margin-bottom: 1rem;
-}
-
-div.listing-ct-maybe {
- border: 1px dashed var(--color-light-gray-3);
- box-shadow: none;
-}
-
-div.listing-ct-head {
- padding: 0.5rem 0.5rem 0 0.5rem;
- background-color: #f5f5f5;
- border-color: var(--color-light-gray);
- border-style: solid;
- border-width: 1px 1px 0 1px;
- overflow: hidden;
- display: flex;
- flex-flow: row-reverse wrap;
- align-items: center;
-}
-
- div.listing-ct-head:last-child {
- padding-bottom: 0.5rem;
- }
-
-div.listing-ct-maybe div.listing-ct-head,
-div.listing-ct-maybe div.listing-ct-body {
- background-color: #fff;
- border: none;
-}
-
-tbody.active .listing-ct-head {
- border-top: 3px solid var(--color-link);
-}
-
-.listing-ct-head h3 {
- font-weight: normal;
- font-size: 18px;
- margin-top: 0px;
- margin-left: 0.25rem;
- margin-bottom: 0.5rem;
-}
-
- .listing-ct-head h3 i {
- float: left;
- padding-right: 7px;
- }
-
-.listing-ct-head .nav li a {
- font-size: 13px;
- /* Counteract listing-ct-head padding */
- margin-top: -0.5rem;
- margin: 0;
-}
-
-.listing-ct-head .nav-tabs {
- border-bottom: none;
-}
-
-.listing-ct-head .nav-tabs-pf {
- /* Counteract listing-ct-head padding */
- margin: -0.5rem 0 0 -0.5rem;
- flex: auto;
-}
-
-/* To display info instead of tabs */
-.listing-ct-head dl {
- display: inline-block;
- height: 1.6em;
- margin-bottom: 5px;
- white-space: nowrap;
- margin-right: 45px;
- margin-left: 5px;
-}
-
-.listing-ct-head dt {
- font-weight: normal;
- display: inline;
- margin-right: 0.5em;
- color: var(--color-subtle-copy);
-}
-
-.listing-ct-head dd {
- display: inline;
- color: black;
-}
-
-.listing-ct-body {
- /* Modified for Cockpit ZFS Manager - Original: padding: 1rem 1.5rem; */
- padding: 0px;
- border: 1px solid var(--color-light-gray);
- background-color: #fff;
-}
-
-.listing-ct-inline > td > .listing-ct-body {
- border: none;
- padding-top: 0px;
- padding-left: 1rem;
- padding-bottom: 0px;
-}
-
-.listing-ct-inline > h3 {
- border-top: 1px solid var(--color-light-gray);
- padding-top: 20px;
- margin-top: 30px;
-}
-
- .listing-ct-inline > h3:first-child {
- border-top: none;
- padding-top: 0px;
- margin-top: 20px;
- }
-
-.listing-ct-actions {
- float: right;
- min-height: 26px;
-}
-
-.listing-ct-status {
- float: right;
- clear: right;
-}
-
-.listing-ct-error {
- border-top: 1px solid var(--color-light-gray);
- border-left: 1px solid var(--color-light-gray);
- border-right: 1px solid var(--color-light-gray);
-}
-
- .listing-ct-error.alert {
- margin-bottom: 0;
- }
-
-.listing-ct-body tt {
- font-size: 12px;
-}
-
-.listing-ct-body dl {
- margin: 0;
-}
-
- .listing-ct-body dl dd dl.inline-dl dt,
- .listing-ct-body dt {
- clear: left;
- float: left;
- width: 100px;
- min-height: 26px;
- white-space: nowrap;
- text-overflow: ellipsis;
- color: var(--color-subtle-copy);
- font-weight: normal;
- }
-
-.listing-ct-body dt {
- text-align: right;
-}
-
-.listing-ct-body dl dd dl dt {
- text-align: left;
-}
-
-.listing-ct-body dd {
- margin-left: 110px;
- min-height: 26px;
- max-width: 1000px;
- text-overflow: ellipsis;
-}
-
-.listing-ct-body dl.full-width dt {
- text-align: left;
- min-width: none;
- max-width: none;
- float: none;
- width: auto;
-}
-
-.listing-ct-body dl.full-width dd {
- margin-left: 0px;
-}
-
-.ct-listing > table > tbody > tr > td:first-child {
- position: relative;
- transition: all 100ms ease-out;
-}
-
- .ct-listing > table > tbody > tr > td:first-child::before,
- .ct-listing > table > tbody > tr > td:first-child::after {
- content: "";
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- opacity: 0;
- pointer-events: none;
- transition: all 300ms;
- }
-
- .ct-listing > table > tbody > tr > td:first-child::after {
- right: auto;
- width: 0;
- background-color: var(--pf-global--active-color--100);
- }
-
-.ct-listing > table > tbody > tr:not(:first-child) > td:first-child::after {
- top: -1px;
-}
-
-.ct-listing > table > tbody.open > tr > td:first-child {
- transition: all 100ms ease-in;
-}
-
- .ct-listing > table > tbody.open > tr > td:first-child::before,
- .ct-listing > table > tbody.open > tr > td:first-child::after {
- opacity: 1;
- }
-
- .ct-listing > table > tbody.open > tr > td:first-child::after {
- width: 3px;
- }
-
-.ct-listing > table > tbody.open {
- transition: all 100ms ease-in;
- box-shadow: 0 0.3125rem 0.625rem -0.25rem rgba(3, 3, 3, 0.25);
-}
-
-/* By default these are hidden */
-/* (HACK: Special-case the user auth dialog) */
-tbody:not(.ssh-key-body) > tr.listing-ct-head,
-tbody > tr.listing-ct-panel,
-tbody > tr.listing-ct-body {
- display: none;
-}
-
- tbody:not(.ssh-key-body) > tr.listing-ct-head > td,
- tbody > tr.listing-ct-panel > td,
- tbody > tr.listing-ct-body > td {
- /* Compensate for the left-side blue highlight */
- padding-left: 3px;
- }
-
-/* ... unless they are in the right state */
-tbody.open > tr.listing-ct-head,
-tbody.open > tr.listing-ct-panel,
-tbody.open > tr.listing-ct-body {
- display: table-row;
-}
-
-/* Animate the listing head & the last visible body */
-/* (Switching tabs will adds new listing-ct-bodys & toggle visibility) */
-tbody.open div.listing-ct-head,
-tbody.open div.listing-ct-head + div.listing-ct-body:not([hidden]):last-child {
- animation: listingCtShow 100ms ease-in-out;
-}
-
-@keyframes listingCtShow {
- 0% {
- margin-bottom: 0;
- margin-top: 0;
- max-height: 0;
- opacity: 0;
- padding-bottom: 0;
- padding-top: 0;
- line-height: 0;
- }
-
- 50% {
- opacity: 0;
- line-height: 1;
- }
-
- 100% {
- max-height: 100vh;
- opacity: 1;
- }
-}
-
-/* Turn off animation if requested by the browser/OS (where supported) */
-@media (prefers-reduced-motion: reduce) {
- tbody.open td.listing-ct-toggle i:before,
- tbody.open div.listing-ct-head,
- tbody.open div.listing-ct-body {
- animation: none;
- }
-}
-
-tbody.open tr.listing-ct-head {
- border-color: var(--color-light-gray);
- border-style: solid;
- border-width: 1px 1px 0 1px;
- border-top: 3px solid var(--color-link);
- background-color: #f5f5f5;
-}
-
-tr.listing-ct-head + tr.listing-ct-head {
- border-top: none;
-}
-
- tr.listing-ct-head + tr.listing-ct-head td {
- padding: 0px 0.5rem 0px 0.5rem;
- }
-
-tr.listing-ct-body td {
- padding: 1rem 1.5rem;
- font-size: var(--font-size-s);
-}
-
-.listing-ct-empty {
- color: var(--color-subtle-copy);
- text-align: center;
- border-top: 1px solid var(--color-gray-2);
- border-bottom: 1px solid var(--color-gray-2);
-}
-
-/* Used at the end of a group of tbody to show an 'empty' message */
-thead.listing-ct-empty td,
-.ct-listing > table > thead.listing-ct-empty td {
- padding: 0.5rem;
-}
-
-tbody + thead.listing-ct-empty {
- display: none;
-}
-
-/* Listing pattern defaults to using full width of parent */
-.listing-ct-wide {
- width: 100%;
-}
-
-/* Listing pattern mod to redce the padding */
-.listing-ct-compact > thead > tr > th,
-.listing-ct-compact > tbody > tr > th,
-.listing-ct-compact > tbody > tr > td {
- padding: 0.25rem;
-}
-
-.listing-ct-compact > tbody > tr > .listing-ct-toggle:not(:empty) + th,
-.listing-ct-compact > tbody > tr > .listing-ct-toggle:not(:empty) + td {
- padding-left: 0.25rem;
-}
-
- .listing-ct-compact > tbody > tr > .listing-ct-toggle:not(:empty) + th::before,
- .listing-ct-compact > tbody > tr > .listing-ct-toggle:not(:empty) + td::before {
- top: 0.25rem;
- }
-
-div.listing-ct-head {
- overflow: visible;
-}
-
-.listing-ct-head .btn-group,
-.listing-ct-head button:not(.dropdown-toggle) {
- margin-left: 0.3em;
-}
-
-tbody tr.listing-ct-noexpand {
- cursor: default;
-}
-
-/* Fix up nav-tabs-pf to work properly */
-.nav-tabs-pf > li:first-child a {
- margin-left: 0px !important;
- padding-left: 1rem !important;
-}
-
-.nav-tabs-pf > li a:before {
- right: 0px !important;
-}
-
-.nav-tabs-pf > li > a:active:before,
-.nav-tabs-pf > li > a:focus:before,
-.nav-tabs-pf > li > a:hover:before,
-.nav-tabs-pf > li.active a:before {
- height: 3px;
- left: 0px;
-}
-
-/* Force word-wraps when words are too long */
-.listing-ct-item td,
-.listing-ct-item th,
-.listing-ct-body {
- overflow-wrap: break-word;
- hyphens: auto;
-}
-
-.listing-ct-item td,
-.listing-ct-item th {
- max-width: calc(100vw - 18rem);
-}
-
-.listing-ct-body {
- /* 42 = (20px padding + 1px border) * 2 */
- max-width: calc(100vw - 42px);
-}
-
-
-
-/*
- * This file is part of Cockpit.
- *
- * Copyright (C) 2015 Red Hat, Inc.
- *
- * Cockpit is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * Cockpit is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Cockpit; If not, see .
- */
-
-
+}
+
+.select-ct-pool-row-identifier,
+.select-ct-pool-row-physec {
+ font-size: var(--pf-global--FontSize--xs);
+ margin-left: 0px !important;
+}
+
+.select-ct-filesystem-row {
+ align-items: center;
+ cursor: pointer;
+ display: flex;
+ word-break: break-all;
+}
+
+ .select-ct-filesystem-row :nth-child(1) {
+ margin-top: 0px;
+ }
+
+ .select-ct-filesystem-row :nth-child(2) {
+ flex-grow: 1;
+ margin-left: 10px;
+ }
+
+.slider-pf {
+ margin: 0 0 0 8px;
+}
+
+ .slider-pf > .size-ct-text {
+ display: inline;
+ margin: 2px 2px 2px 8px;
+ text-align: right;
+ width: 5em;
+ }
+
+ .slider-pf > .size-ct-text .disabled {
+ cursor: not-allowed !important;
+ pointer-events: inherit !important;
+ }
+
+ .slider-pf > .dropdown {
+ flex: 1 0 80px;
+ }
+
+ .slider-pf > .dropdown > .size-ct-unit > span {
+ padding-right: 0px;
+ }
+
+ .slider-pf > span {
+ padding-left: 5px;
+ }
+
+.slider-selection {
+ background-color: var(--color-link);
+ background-image: linear-gradient(to bottom,var(--color-link) 0%,var(--color-link) 100%);
+}
+
+.slider.slider-horizontal {
+ height: 16px;
+ margin: 0 8px 0 0;
+ width: 100%;
+}
+
+ .slider.slider-horizontal .slider-track {
+ height: 5px;
+ left: 0;
+ margin-top: -2px;
+ top: 50%;
+ width: 100%;
+ }
+
+.slider-handle {
+ background-color: var(--color-link) !important;
+ background-image: linear-gradient(to bottom,var(--color-link) 0%,var(--color-link) 100%) !important;
+ border: 0px;
+ border-radius: 9px;
+ cursor: pointer !important;
+ height: 18px;
+ margin: 0 0 0 -8px !important;
+ width: 18px;
+}
+
+ .slider-handle.disabled {
+ background-color: var(--color-subtle-copy) !important;
+ background-image: linear-gradient(to bottom,var(--color-subtle-copy) 0%,var(--color-subtle-copy) 100%) !important;
+ cursor: not-allowed !important;
+ }
+
+.slider-selection.disabled {
+ background-color: var(--color-subtle-copy);
+ background-image: linear-gradient(to bottom,var(--color-subtle-copy) 0%,var(--color-subtle-copy) 100%);
+}
+
+.slider-track {
+ background-color: #ededed;
+ border: 0px;
+ box-shadow: none;
+}
+
+ .slider-track.disabled {
+ background-color: var(--color-subtle-copy);
+ border: 0px;
+ }
+
+.slider-track-high {
+ background-color: #ededed;
+}
+
+.slider-track-low {
+ background-color: var(--color-link);
+ background-image: linear-gradient(to bottom,var(--color-link) 0%,var(--color-link) 100%);
+}
+
+ .slider-track-low.disabled {
+ background-color: var(--color-subtle-copy);
+ background-image: linear-gradient(to bottom,var(--color-subtle-copy) 0%,var(--color-subtle-copy) 100%);
+ }
+
+.table {
+ table-layout: fixed !important;
+}
+
+ .table > thead > tr > th,
+ .table > tbody > tr > td {
+ padding: 0.4rem;
+ vertical-align: middle;
+ }
+
+ .table > tbody > tr > td.ct-spacing {
+ padding-bottom: 1.7rem;
+ }
+
+ .table > tbody > tr > td.config-level-0-sub-hidden {
+ padding: 0px !important;
+ }
+
+ .table > tbody > tr > td.config-level-1 {
+ padding-left: 3em !important;
+ }
+
+ .table > tbody > tr > td.config-level-2 {
+ padding-left: 5em !important;
+ }
+
+ .table > tbody > tr > td.config-level-3 {
+ padding-left: 7em !important;
+ }
+
+ .table > tbody > tr > td.config-level-4 {
+ padding-left: 9em !important;
+ }
+
+ .table > tbody > tr > td > span.config-count-danger {
+ color: var(--pf-global--danger-color--100);
+ }
+
+ .table > tbody > tr > td > span.config-count-warning {
+ color: var(--pf-global--warning-color--100);
+ }
+
+ .table[id^="table-storagepool-status-"] > thead,
+ .table[id^="table-storagepool-status-"] > thead > tr,
+ .table[id^="table-storagepool-status-"] > thead > tr > th {
+ border: 0 none !important;
+ height: 0 !important;
+ opacity: 0 !important;
+ padding: 0 !important;
+ }
+
+ .table.table-ct-snapshots {
+ margin-bottom: 0px !important;
+ }
+
+tbody > tr.listing-ct-item.listing-ct-storagepoolsnotfound {
+ cursor: default !important;
+}
+
+ tbody > tr.listing-ct-item.listing-ct-storagepoolsnotfound > td:first-child {
+ padding-left: 50px;
+ }
+
+tbody > tr.listing-ct-item-snapshots {
+ border-bottom: 0px !important;
+}
+
+.toast-notifications-list-pf {
+ top: 20px;
+}
+
+.toast-pf > span > span.toast-ct-description {
+ word-break: break-all;
+}
+
+ .toast-pf > span > span.toast-ct-description.break-word {
+ word-break: break-word !important;
+ }
+
+/* Fix for flashing tooltip */
+.tooltip {
+ pointer-events: none !important;
+ position: fixed;
+}
+
+.tooltip-inner {
+ overflow-wrap: break-word;
+}
+
+@media screen and (max-width: 343px) {
+ .dropdown-menu-right {
+ left: auto;
+ right: auto;
+ }
+}
+
+@media screen and (max-width: 480px) {
+ .dropdown-ct-status {
+ left: auto !important;
+ right: auto !important;
+ }
+
+ .panel > .panel-heading > .panel-ct-actions {
+ text-align: left !important;
+ }
+
+ .panel > .panel-heading > .panel-ct-heading,
+ .panel > .panel-heading > .panel-ct-heading > .panel-title {
+ min-height: 32px;
+ min-width: 100%;
+ }
+}
+
+@media screen and (min-width: 401px) and (max-width: 525px) {
+ .dropdown-menu-right {
+ left: auto;
+ right: auto;
+ }
+}
+
+@media screen and (min-width: 481px) and (max-width: 525px) {
+ .dropdown-ct-status {
+ left: auto !important;
+ right: 0 !important;
+ }
+}
+
+@media screen and (max-width: 640px) {
+ .dialog-wait-ct {
+ margin-bottom: 0.5em;
+ }
+
+ .listing-ct > thead > tr:first-child {
+ display: none;
+ }
+
+ .listing-ct-actions > div > button.btn,
+ .listing-ct-actions > div > div.btn-group {
+ margin-bottom: 5px !important;
+ }
+
+ .listing-ct-item > td {
+ padding: 0.5rem !important;
+ vertical-align: middle !important;
+ }
+
+ .listing-ct-item > td.listing-ct-actionsmenu {
+ display: table-cell !important;
+ }
+
+ .listing-ct-item > td:not(:first-child),
+ .listing-ct-item > th {
+ display: block;
+ max-width: 100% !important;
+ }
+
+ .listing-ct-item > td > span.table-ct-head,
+ .table.table-ct-filesystems > tbody > tr > td > span.table-ct-head,
+ .table.table-ct-snapshots > tbody > tr > td > span.table-ct-head,
+ .table.table-ct-status-config > tbody > tr > td > span.table-ct-head {
+ color: var(--color-subtle-copy);
+ display: inherit !important;
+ float: left;
+ font-weight: normal;
+ padding-right: 0.5em;
+ }
+
+ .listing-ct-item > td.listing-ct-icon > span.table-ct-text,
+ .table.table-ct-filesystems > tbody > tr > td > span.table-ct-text,
+ .table.table-ct-snapshots > tbody > tr > td > span.table-ct-text,
+ .table.table-ct-status-config > tbody > tr > td > span.table-ct-text {
+ display: inline-block !important;
+ padding-right: 0.5em;
+ }
+
+ .listing-ct-item > td.listing-ct-icon,
+ .table.table-ct-filesystems > tbody > tr > td.listing-ct-icon,
+ .table.table-ct-snapshots > tbody > tr > td.listing-ct-icon,
+ .listing-ct .listing-ct-icon {
+ width: 100% !important;
+ }
+
+ .listing-ct-wide {
+ table-layout: initial;
+ }
+
+ .panel {
+ overflow-x: visible !important;
+ }
+
+ .panel > .panel-heading {
+ position: inherit !important;
+ }
+
+ .panel > .panel-heading > .panel-actions > button.btn {
+ margin-bottom: 5px !important;
+ }
+
+ .table tbody tr > :first-child {
+ padding-left: 0.4rem !important;
+ }
+
+ .table > tbody > tr > td.config-level-0-sub {
+ clear: both;
+ }
+
+ .table > tbody > tr > td.config-level-0-sub::after,
+ .table > tbody > tr > td.config-level-1-sub::after,
+ .table > tbody > tr > td.config-level-2-sub::after,
+ .table > tbody > tr > td.config-level-3-sub::after,
+ .table > tbody > tr > td.config-level-4-sub::after {
+ content: "\00a0";
+ }
+
+ .table > tbody > tr > td.config-level-0-sub-hidden,
+ .table > tbody > tr > td.config-level-1-sub-hidden {
+ display: none !important;
+ }
+
+ .table > tbody > tr > td.config-level-1,
+ .table > tbody > tr > td.config-level-1-sub {
+ padding-left: 1.5em !important;
+ }
+
+ .table > tbody > tr > td.config-level-2,
+ .table > tbody > tr > td.config-level-2-sub {
+ padding-left: 3em !important;
+ }
+
+ .table > tbody > tr > td.config-level-3,
+ .table > tbody > tr > td.config-level-3-sub {
+ padding-left: 4.5em !important;
+ }
+
+ .table > tbody > tr > td.config-level-4,
+ .table > tbody > tr > td.config-level-4-sub {
+ padding-left: 6em !important;
+ }
+
+ .table-ct-filesystems > thead,
+ .table-ct-snapshots > thead,
+ .table-ct-status-config > thead {
+ display: none;
+ }
+
+ .table-ct-filesystems > tbody > tr > td:not(:last-child),
+ .table-ct-snapshots > tbody > tr > td:not(:last-child),
+ .table-ct-status-config > tbody > tr > td:not(:nth-last-child(-n+2)) {
+ display: block;
+ max-width: 100% !important;
+ }
+
+ .table-ct-status-config > tbody > tr.table-ct-confighead {
+ display: none;
+ }
+
+ .table-ct-status-config > tbody > tr > td.config-level-0-virtualdevice {
+ display: table-cell !important;
+ }
+}
+
+
+
+/*
+ * This file is part of Cockpit.
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * Cockpit is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * Cockpit is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Cockpit; If not, see .
+ */
+
+
+.btn-group, .btn-group-vertical {
+ /* Fix button groups from wrapping in narrow widths */
+ display: inline-flex;
+}
+
+.dropdown-menu > li > a.disabled,
+.dropdown-menu > li > a.disabled:hover,
+.dropdown-menu > li > a.disabled:focus {
+ color: var(--color-subtle-copy);
+}
+
+ .dropdown-menu > li > a.disabled:hover,
+ .dropdown-menu > li > a.disabled:focus {
+ text-decoration: none;
+ background-color: transparent;
+ background-image: none;
+ border-color: transparent;
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ cursor: default;
+ }
+
+/* Limit dropdown menus to 90% of the viewport size */
+.dropdown-menu {
+ height: auto;
+ overflow-y: auto;
+ max-height: 90vh;
+}
+
+/* Allow kebab menus to have a ^ with overflowing */
+/* Note: This means kebab menus cannot be _too_ long */
+.dropdown-kebab-pf > .dropdown-menu {
+ overflow: visible;
+}
+
+.dialog-list-ct {
+ max-height: 230px;
+ overflow-x: auto;
+ border: 1px solid var(--color-light-gray);
+ margin-bottom: 0px;
+}
+
+:root {
+ /* Custom font aliases */
+ --font-family: var(--pf-global--FontFamily--sans-serif);
+ --font-family-mono: var(--pf-global--FontFamily--monospace);
+ --font-size: var(--pf-global--FontSize--md);
+ --font-size-s: var(--pf-global--FontSize--sm);
+ --font-size-xs: var(--pf-global--FontSize--xs);
+ --font-size-l: var(--pf-global--FontSize--lg);
+ --font-size-xl: var(--pf-global--FontSize--xl);
+ --font-size-2xl: var(--pf-global--FontSize--2xl);
+ --font-size-3xl: var(--pf-global--FontSize--3xl);
+
+ /* Cockpit custom colors */
+ --color-ct-light-red-1: #f8cccc;
+ --color-ct-light-red-2: #f8acac;
+ --color-ct-light-red-3: #f98383;
+ --color-ct-brick-gold: #ffa763;
+ --color-ct-brick-red: #a53131;
+
+ --color-ct-nav: #1b1b1b;
+ --color-ct-nav-sub: var(--pf-global--BackgroundColor--dark-300);
+ --color-ct-nav-text: var(--pf-global--BackgroundColor--light-300);
+ --color-ct-nav-active: var(--pf-global--BackgroundColor--dark-400);
+ --color-ct-nav-active-text: var(--pf-global--BackgroundColor--light-100);
+ --color-ct-nav-hover: var(--pf-global--BackgroundColor--dark-400);
+ --color-ct-nav-hover-text: var(--pf-global--BackgroundColor--light-100);
+ --color-ct-nav-border: var(--pf-global--BorderColor--100);
+ --color-ct-nav-cover-up: linear-gradient(to bottom, var(--color-ct-nav-sub), rgba(21,21,21, 0));
+ --color-ct-nav-cover-down: linear-gradient(to top, var(--color-ct-nav-sub), rgba(21,21,21, 0));
+
+ --color-ct-nav-main: #1b1b1b;
+ --color-ct-nav-main-text: var(--color-ct-nav-text);
+ --color-ct-nav-main-border: var(--pf-global--BackgroundColor--dark-200);
+ --color-ct-nav-main-active: var(--color-ct-nav-sub);
+ --color-ct-nav-main-active-text: var(--color-ct-nav-active-text);
+ --color-ct-nav-main-hover: var(--color-ct-nav-hover);
+ --color-ct-nav-main-hover-text: var(--color-ct-nav-hover-text);
+
+ --color-border: var(--pf-global--BorderColor--100);
+
+ --color-ct-list-text: var(--color-text);
+ --color-ct-list-link: var(--color-link);
+ --color-ct-list-bg: var(--color-bg);
+ --color-ct-list-border: var(--color-border);
+ --color-ct-list-hover-text: var(--color-link);
+ --color-ct-list-hover-bg: var(--pf-global--BackgroundColor--150);
+ --color-ct-list-hover-border: var(--pf-global--BackgroundColor--150);
+ --color-ct-list-hover-icon: var(--color-blue);
+ --color-ct-list-selected-text: var(--color-link);
+ --color-ct-list-selected-bg: var(--pf-global--BackgroundColor--150);
+ --color-ct-list-selected-border: var(--pf-global--BackgroundColor--150);
+ --color-ct-list-active-text: var(--color-link-focus);
+ --color-ct-list-active-bg: var(--color-bg);
+ --color-ct-list-active-border: var(--color-ct-list-border);
+ --color-ct-list-critical-bg: var(--color-ct-light-red-1);
+ --color-ct-list-critical-border: var(--color-ct-light-red-2);
+ --color-ct-list-critical-bg-hover: var(--color-ct-light-red-2);
+ --color-ct-list-critical-border-hover: var(--color-ct-light-red-3);
+
+ --color-link-hover-bg: var(--color-light-blue-2);
+ --color-link-hover-icon: var(--color-blue-5);
+
+ /* Red Hat Digital Design System 2019 named colors */
+ --color-red-hat-red: #ee0000;
+ --color-red-1: #cc0000;
+ --color-red-2: #a30000;
+ --color-red-3: #820000;
+ --color-dark-red-4: #5a0000;
+ --color-dark-red-5: #460000;
+ --color-dark-red-6: #320000;
+ --color-black: #000000;
+ --color-white: #ffffff;
+ --color-dark-blue: #004153;
+ --color-light-blue: #a3dbe8;
+ --color-dark-gray: #4c4c4c;
+ --color-light-gray: #dcdcdc;
+ --color-purple: #3b0083;
+ --color-gold: #f0ab00;
+ --color-teal: #007987;
+ --color-blue: #00b9e4;
+ --color-green: #92d400;
+ --color-storage: #ec7a08;
+ --color-infra: #0088ce;
+ --color-app-dev: #3f9c35;
+ --color-light-blue-1: #e8f6f9;
+ --color-light-blue-2: #d1edf4;
+ --color-light-blue-3: #b6e2ec;
+ --color-dark-blue-1: #80a0a9;
+ --color-dark-blue-2: #4e7a86;
+ --color-dark-blue-3: #1b5764;
+ --color-blue-1: #d9f5fb;
+ --color-blue-2: #c0edf7;
+ --color-blue-3: #9ae4f3;
+ --color-blue-4: #82ddf1;
+ --color-blue-5: #68d6ee;
+ --color-blue-6: #38c8e8;
+ --color-teal-1: #d9ebed;
+ --color-teal-2: #cbe4f1;
+ --color-teal-3: #b3d7db;
+ --color-teal-4: #9acacf;
+ --color-teal-5: #68afb6;
+ --color-teal-6: #36959e;
+ --color-green-1: #eaf5cd;
+ --color-green-2: #dff1b4;
+ --color-green-3: #d4ec9c;
+ --color-green-4: #cae883;
+ --color-green-5: #b5df56;
+ --color-green-6: #aadb40;
+ --color-gold-1: #fcedcd;
+ --color-gold-2: #fae5b4;
+ --color-gold-3: #f9dc9c;
+ --color-gold-4: #f8d384;
+ --color-gold-5: #f5c255;
+ --color-gold-6: #f2b22d;
+ --color-purple-1: #e2daec;
+ --color-purple-2: #cdc0df;
+ --color-purple-3: #b09bcc;
+ --color-purple-4: #9c82c0;
+ --color-purple-5: #8869b3;
+ --color-purple-6: #7551a6;
+ --color-gray-1: #f0f0f0;
+ --color-gray-2: #e6e6e6;
+ --color-gray-3: #d2d2d2;
+ --color-gray-4: #bebebe;
+ --color-gray-5: #aaaaaa;
+ --color-gray-6: #969696;
+ --color-gray-7: #828282;
+ --color-gray-8: #6e6e6e;
+ --color-gray-9: #5a5a5a;
+ --color-gray-10: #464646;
+ --color-gray-11: #323232;
+ --color-gray-12: #1e1e1e;
+
+ /* Semantic colors */
+ --color-fg: #151515;
+ --color-bg: #fff;
+ --color-text: var(--color-fg);
+
+ --color-link: #0066cc;
+ --color-link-visited: #0066cc;
+ --color-link-hover: #004080;
+ --color-link-focus: #004080;
+ --color-link-dark: #73bcf7;
+ --color-link-visited-dark: #73bcf7;
+ --color-link-hover-dark: #2b9af3;
+ --color-link-focus-dark: #2b9af3;
+
+ --color-heading: #151515;
+ --color-heading-dark: #ffffff;
+ --color-body-copy: #151515;
+ --color-body-copy-dark: #cccccc;
+ --color-body-copy-dark-color: rbga(255,255,255,0.8);
+ --color-subtle-copy: #72767b;
+ --color-subtle-text-dark: #cccccc;
+
+ --color-alert-success-bg: #ffffff;
+ --color-alert-sucess-icon: #92d400;
+ --color-alert-sucess-border: #92d400;
+ --color-alert-success-text: #486b00;
+ --color-alert-info-bg: #ffffff;
+ --color-alert-info-icon: #39a5dc;
+ --color-alert-info-border: #39a5dc;
+ --color-alert-info-text: #004368;
+ --color-alert-warning-bg: #ffffff;
+ --color-alert-warning-icon: #f0ab00;
+ --color-alert-warning-border: #f0ab00;
+ --color-alert-warning-text: #795600;
+ --color-alert-danger-bg: #ffffff;
+ --color-alert-danger-icon: #c9190b;
+ --color-alert-danger-border: #c9190b;
+ --color-alert-danger-text: #7d1007;
+
+ --color-low-severity-background: #ffffff;
+ --color-low-severity-icon: #72767b;
+ --color-low-severity-border: #72767b;
+ --color-low-severity-text: #151515;
+ --color-moderate-severity-background: #ffffff;
+ --color-moderate-severity-icon: #f0ab00;
+ --color-moderate-severity-border: #f0ab00;
+ --color-moderate-severity-text: #795600;
+ --color-important-severity-background: #ffffff;
+ --color-important-severity-icon: #df7409;
+ --color-important-severity-border: #df7409;
+ --color-important-severity-text: #8f4c09;
+ --color-critical-severity-background: #ffffff;
+ --color-critical-severity-icon: #c9190b;
+ --color-critical-severity-border: #c9190b;
+ --color-critical-severity-text: #7d1007;
+
+ --color-cta-default: #0066cc;
+ --color-cta-default-hover: #004080;
+ --color-cta-primary: #ee0000;
+ --color-cta-primary-hover: #d40000;
+ --color-cta-secondary: #151515;
+ --color-cta-secondary-hover: #151515;
+ --color-cta-accent: #0066cc;
+ --color-cta-accent-hover: #0066cc;
+
+ --color-button-text: #ffffff;
+ --color-button-text-dark: #151515;
+ --color-button-default: #151515;
+ --color-button-default-hover: #151515;
+ --color-button-primary: #0066cc;
+ --color-button-primary-hover: #004080;
+ --color-button-secondary: #0066cc;
+ --color-button-secondary-hover: #0066cc;
+ --color-button-disabled: #d2d2d2;
+ --color-button-disabled-text: #72767b;
+
+ --color-border-lighter: #d2d2d2;
+ --color-border-default: #d2d2d2;
+ --color-border-darker: #d2d2d2;
+
+ --color-potential-band-color: #f0f0f0;
+ --color-ui-hover-bg: #ededed;
+ --color-ui-alternate-row-bg: #ededed;
+
+ --color-label: #151515;
+ --color-form-field-bottom-border: #8b8d8f;
+ --color-form-field-border: #0066cc;
+ --color-form-field-focus: #0066cc;
+ --color-form-field-bg: #ffffff;
+ --color-form-field-text: #151515;
+ --color-form-field-error-border: #a30000;
+ --color-form-field-error-bg: #ffffff;
+ --color-form-field-error-text: #a30000;
+ --color-form-field-active-border: #0066cc;
+ --color-select-dropdown-bottom-border: #8b8d8f;
+ --color-select-dropdown-bg: #ffffff;
+ --color-select-dropdown-arrow-color: #151515;
+ --color-select-dropdown-text-color: #151515;
+
+ --color-breadcrumb-link: #0066cc;
+ --color-breadcrumb-link-hover: #004080;
+ --color-breadcrumb-text: #151515;
+
+ --color-pagination-current-text: #393f44;
+
+ --color-chips: #72767b;
+ --color-chips-secondary: #72767b;
+ --color-chips-hover: #72767b;
+
+ --color-tab-link: #007bba;
+ --color-tab-text: #007bba;
+ --color-tab-indicator-color: #007bba;
+ --color-tab-bg: #ffffff;
+ --color-tab-border: #ededed;
+ --color-tab-selected-text: #007bba;
+ --color-tab-selected-indicator-color: #007bba;
+ --color-tab-selected-bg: #ffffff;
+ --color-tab-selected-border: #ededed;
+
+ --color-tooltips-bg: #ffffff;
+ --color-tooltips-text: #151515;
+
+ --color-modal-bg: #ffffff;
+ --color-modal-header-bg: #151515;
+
+ --color-table-header-bg: #ffffff;
+ --color-table-header-text: #393f44;
+ --color-table-header-border: #ededed;
+ --color-table-header-border-bottom: #ededed;
+ --color-table-border: #ededed;
+ --color-table-border-bottom: #ededed;
+ --color-table-text: #393f44;
+}
+
+/* Table headers should not generate a double border */
+.panel .table thead tr th {
+ border-bottom: none;
+}
+
+/* Fix panel heading alignment & mobile layout */
+.panel-heading {
+ align-items: center;
+ background: #f5f5f5;
+ display: flex;
+ flex-wrap: wrap;
+ /* (28px small size widget height) + (0.5rem * 2) */
+ min-height: calc(28px + 1rem);
+ /* Modified for Cockpit ZFS Manager - Original: padding: 0.5rem 0.5rem 0.5rem 1rem; */
+ padding: 0.5rem 1rem 0.5rem 1rem;
+ position: relative;
+ z-index: 100;
+}
+
+.panel-title {
+ font: inherit;
+ margin: 0;
+ padding: 0;
+}
+
+ .panel-title > a {
+ color: var(--color-link);
+ display: inline-block;
+ }
+
+ .panel-title > a:hover,
+ .panel-title > a:focus {
+ color: var(--alert-info-text);
+ }
+
+ /* Allow children in the title to wrap */
+ .panel-title > h3,
+ .panel-title > a,
+ .panel-title > div,
+ .panel-title > span {
+ flex-shrink: 1;
+ word-break: break-all;
+ }
+
+.panel-heading > :last-child:not(:first-child),
+.panel-heading > .pull-right,
+.panel-heading > .panel-heading-actions {
+ flex: auto;
+ text-align: right;
+}
+
+.panel-heading > .pull-right {
+ /* HACK: Pull right shouldn't be used to change document order. */
+ /* This CSS _also_ changes document order to replicate the float. */
+ /* Solution: Fix document order when pull-right is used. */
+ order: 100;
+}
+
+ .panel-heading > .pull-right:first-child ~ :last-child {
+ /* Undo :last-child above for cases where pull-right is used before */
+ text-align: left;
+ }
+
+@media screen and (max-width: 640px) {
+ /* Remove _most_ of the gaps on the sides of small screens */
+ /* to maximize space, but still keep the boxy panel look */
+ /* (container-fluid & page-ct adds 20px, so we remove 1/2 of that) */
+ .page-ct > .panel,
+ .container-fluid > .panel,
+ .col-md-12 > .panel {
+ margin-left: -10px;
+ margin-right: -10px;
+ }
+
+ .panel {
+ /* Background fade */
+ --hi-color: #d1d1d1;
+ --hi-color2: var(--color-gray-2);
+ --bg-color: var(--color-bg);
+ --hi-width: 20px;
+ --hi-width3: calc(var(--hi-width) * 3);
+ --transparent: rgba(255,255,255,0); /* WebKit needs white transparent */
+ max-width: 100vw;
+ overflow-x: auto;
+ position: relative;
+ background-image:
+ linear-gradient(to left, var(--bg-color) var(--hi-width), var(--transparent) var(--hi-width3)),
+ linear-gradient(to left, var(--hi-color) 1px, var(--transparent) 2px, var(--hi-color2) 4px, var(--bg-color) var(--hi-width)),
+ linear-gradient(to right, var(--bg-color) var(--hi-width), var(--transparent) var(--hi-width3)),
+ linear-gradient(to right, var(--hi-color) 1px, var(--transparent) 2px, var(--hi-color2) 4px, var(--bg-color) var(--hi-width));
+ background-attachment: local, scroll, local, scroll;
+ background-position: right, right, left, left;
+ background-repeat: no-repeat;
+ background-size: var(--hi-width3) 100%;
+ }
+
+ .panel > .panel-heading {
+ /* WebKit still needs -webkit- prefix for sticky */
+ position: -webkit-sticky;
+ position: sticky;
+ left: 0;
+ top: 0;
+ }
+
+ .panel .table thead th {
+ white-space: nowrap;
+ }
+
+ .panel .table:not(:hover):not(:focus):not(:active) {
+ background: transparent;
+ }
+
+ .panel .table thead:not(:hover):not(:focus):not(:active) {
+ background: transparent;
+ }
+}
+
+/* Override the heavy patternfly headers */
+.table > thead {
+ background-image: none;
+ background-color: var(--color-bg);
+}
+
+/* Make things line up */
+.table tbody tr > :first-child,
+.table thead tr > :first-child {
+ padding-left: 1rem;
+}
+
+.table tbody tr > :last-child,
+.table thead tr > :last-child {
+ padding-right: 1rem;
+}
+
+label.onoff-ct {
+ --switch-width: 40px;
+ --switch-height: 24px;
+ --switch-background: var(--color-gray-3);
+ --switch-border-color: transparent;
+ --switch-border-style: solid;
+ --switch-border-width: 1px;
+ --switch-text: inherit;
+ --switch-dot-size: 14px;
+ --switch-dot: var(--color-bg);
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ margin-bottom: 0;
+ padding: 1px 0;
+ /* Height is 24px; bump to 26px like other widgets */
+ vertical-align: middle;
+ /* Focus ring */
+ /* Don't show the focus ring for mouse clicks (when hovering) */
+ /* Subtly darken the inner part of the switch on hover */
+}
+
+ label.onoff-ct > .switch-on,
+ label.onoff-ct > .switch-off,
+ label.onoff-ct > input ~ .switch-toggle,
+ label.onoff-ct > input ~ .switch-toggle::after {
+ transition: all 300ms ease-in-out;
+ }
+
+ label.onoff-ct > .switch-on,
+ label.onoff-ct > .switch-off {
+ color: var(--switch-text);
+ margin-left: 0.5em;
+ }
+
+ label.onoff-ct > input {
+ opacity: 0;
+ position: absolute;
+ /* Base toggle graphic */
+ /* Hide unused switch label */
+ }
+
+ label.onoff-ct > input ~ .switch-toggle {
+ --switch-dot-offset-x: calc(var(--switch-dot-size)/3 - var(--switch-border-width));
+ --switch-dot-offset-y: calc(50% - 14px / 2);
+ /* Don't let the border draw over the background */
+ background-clip: content-box;
+ background: var(--switch-background);
+ border-radius: var(--switch-height);
+ border: var(--switch-border-width) var(--switch-border-style) var(--switch-border-color);
+ box-shadow: inset 0 0 0 1px transparent;
+ width: var(--switch-width);
+ height: var(--switch-height);
+ display: inline-block;
+ position: relative;
+ margin: 0;
+ cursor: pointer;
+ /* Dot graphic */
+ }
+
+ label.onoff-ct > input ~ .switch-toggle::after {
+ background: var(--switch-dot);
+ box-shadow: 0 0 var(--switch-dot-offset-x) rgba(0, 0, 0, 0.2);
+ display: inline-block;
+ content: "";
+ height: var(--switch-dot-size);
+ width: var(--switch-dot-size);
+ border-radius: 50%;
+ top: var(--switch-dot-offset-y);
+ left: var(--switch-dot-offset-x);
+ position: absolute;
+ pointer-events: none;
+ }
+
+ label.onoff-ct > input ~ .switch-off {
+ --switch-text: var(--color-subtle-copy);
+ }
+
+ label.onoff-ct > input:checked ~ .switch-toggle {
+ --switch-background: var(--color-link);
+ --switch-dot-offset-x: calc(100% - var(--switch-dot-size) * 1.333333 + var(--switch-border-width));
+ /* Modified for Cockpit ZFS Manager - New */
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10.583 6.35'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-width='.529' d='M2.252 3.365l.756.758L4.48 2.65' opacity='.75'/%3E%3C/svg%3E");
+ }
+
+ label.onoff-ct > input:checked ~ .switch-toggle:last-child {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10.583 6.35'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-width='.529' d='M2.252 3.365l.756.758L4.48 2.65' opacity='.75'/%3E%3C/svg%3E");
+ }
+
+ label.onoff-ct > input:disabled ~ .switch-toggle {
+ --switch-background: var(--color-subtle-copy);
+ --switch-dot: var(--color-gray-3);
+ }
+
+ label.onoff-ct > input:disabled ~ * {
+ cursor: not-allowed;
+ }
+
+ label.onoff-ct > input:checked ~ .switch-off,
+ label.onoff-ct > input:not(:checked) ~ .switch-on {
+ display: none;
+ }
+
+ label.onoff-ct :disabled ~ .switch-on,
+ label.onoff-ct :disabled ~ .switch-off {
+ --switch-text: var(--color-subtle-copy);
+ }
+
+ label.onoff-ct :focus ~ .switch-toggle::before {
+ /* Approximate Chrome's focus ring, for non-Firefox browsers */
+ border: 2px solid rgba(0, 98, 220, 0.4);
+ border-radius: calc(var(--switch-width) - 10px);
+ position: absolute;
+ content: '';
+ top: -4px;
+ bottom: -4px;
+ left: -4px;
+ width: calc(var(--switch-width) + 6px);
+ transition: all 300ms ease-in-out;
+ /* HACK: Keyboard has nothing to transition from, but hover does */
+ /* (as it changes the ring to transparent and back). */
+ /* So we delay the hover to not have the focus ring on hover out. */
+ /* This makes the focus ring show up for keyboard users, but not on a mouse click. */
+ transition-delay: 600s;
+ z-index: 1;
+ }
+
+@-moz-document url-prefix() {
+ label.onoff-ct :focus ~ .switch-toggle::before {
+ /* Approximate Firefox's focus ring, for Firefox only */
+ border: 1px dotted rgba(0, 0, 0, 0.75);
+ }
+}
+
+label.onoff-ct :focus:hover ~ .switch-toggle::before {
+ border-color: transparent;
+}
+
+label.onoff-ct:hover :not(:disabled) ~ .switch-toggle {
+ box-shadow: inset 0 1px 5px 1px rgba(0, 0, 0, 0.15);
+}
+
+h1 label.onoff-ct {
+ vertical-align: bottom;
+}
+
+/* Form layout */
+:root {
+ --ct-form-columns: 2;
+}
+
+.ct-form {
+ align-self: start;
+ display: grid;
+ grid-gap: 0.5rem 1.5rem;
+ grid-template-columns: repeat(var(--ct-form-columns), max-content 1fr);
+ justify-items: stretch;
+ align-content: baseline;
+}
+
+ .ct-form > .control-label {
+ text-align: right;
+ padding: 0;
+ margin: 0;
+ }
+
+ .ct-form > :not(hr):not(p) {
+ line-height: 2.25rem;
+ }
+
+ .ct-form > p {
+ margin: 0;
+ }
+
+ .ct-form > :not(.control-label):not(hr):not(.ct-form-split):not(.ct-form-full) {
+ grid-column: 2 / -1;
+ }
+
+ .ct-form > :not(.ct-form-relax):not(.spinner) {
+ width: auto;
+ }
+
+ .ct-form > hr {
+ border: none;
+ grid-column: 1 / -1;
+ height: 0.5rem;
+ margin: 0;
+ padding: 0;
+ }
+
+ .ct-form > input[size],
+ .ct-form > .ct-validation-wrapper > input[size] {
+ justify-self: start;
+ }
+
+ .ct-form > .ct-validation-wrapper {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .ct-form input[type=number] {
+ -webkit-appearance: textarea;
+ }
+
+ .ct-form > input,
+ .ct-form > .ct-validation-wrapper > input,
+ .ct-form > textarea,
+ .ct-form > .ct-validation-wrapper > textarea,
+ .ct-form > select,
+ .ct-form > .ct-validation-wrapper > select,
+ .ct-form > .bootstrap-select,
+ .ct-form > .ct-validation-wrapper > .bootstrap-select,
+ .ct-form > .ct-select,
+ .ct-form > .ct-validation-wrapper > .ct-select,
+ .ct-form > .dropdown,
+ .ct-form > .ct-validation-wrapper > .dropdown,
+ .ct-form > .combobox-container,
+ .ct-form > .ct-validation-wrapper > .combobox-container,
+ .ct-form > fieldset,
+ .ct-form > .ct-validation-wrapper > fieldset,
+ .ct-form > [role=group],
+ .ct-form > .ct-validation-wrapper > [role=group],
+ .ct-form > [data-field],
+ .ct-form > .ct-validation-wrapper > [data-field],
+ .ct-form > .form-group,
+ .ct-form > .ct-validation-wrapper > .form-group,
+ .ct-form > .btn-group,
+ .ct-form > .ct-validation-wrapper > .btn-group,
+ .ct-form > label.checkbox,
+ .ct-form > .ct-validation-wrapper > label.checkbox,
+ .ct-form > label.radio,
+ .ct-form > .ct-validation-wrapper > label.radio,
+ .ct-form > .checkbox-inline,
+ .ct-form > .ct-validation-wrapper > .checkbox-inline,
+ .ct-form > .radio-inline,
+ .ct-form > .ct-validation-wrapper > .radio-inline {
+ line-height: var(--pf-global--LineHeight--md);
+ }
+
+ .ct-form > :not(.ct-form-relax):not(.spinner) {
+ width: auto !important;
+ }
+
+ .ct-form > [role=group],
+ .ct-form > .ct-validation-wrapper > [role=group] {
+ align-self: start;
+ align-content: center;
+ display: grid;
+ grid-gap: 0.5rem;
+ min-height: 2.25rem;
+ justify-content: start;
+ grid-template-columns: repeat(2, auto);
+ }
+
+ .ct-form > [role=group].ct-form-vertical > :not(.ct-form-split),
+ .ct-form > .ct-validation-wrapper > [role=group].ct-form-vertical > :not(.ct-form-split) {
+ grid-column: 1 / -1;
+ }
+
+ .ct-form > [role=group] > .checkbox,
+ .ct-form > .ct-validation-wrapper > [role=group] > .checkbox,
+ .ct-form > [role=group] > .radio,
+ .ct-form > .ct-validation-wrapper > [role=group] > .radio {
+ margin: 0;
+ }
+
+ .ct-form > [role=group] > .checkbox:first-child,
+ .ct-form > .ct-validation-wrapper > [role=group] > .checkbox:first-child,
+ .ct-form > [role=group] > .radio:first-child,
+ .ct-form > .ct-validation-wrapper > [role=group] > .radio:first-child {
+ margin-top: 0.5rem;
+ }
+
+ .ct-form > [role=group]:not(.ct-form-relax) > .dropdown,
+ .ct-form > .ct-validation-wrapper > [role=group]:not(.ct-form-relax) > .dropdown,
+ .ct-form > .ct-validation-wrapper > [data-field]:not(.ct-form-relax) > .dropdown {
+ width: auto !important;
+ }
+
+ .ct-form > [role=group]:not(.ct-form-relax) > .ct-select,
+ .ct-form > .ct-validation-wrapper > [role=group]:not(.ct-form-relax) > .ct-select,
+ .ct-form > .ct-validation-wrapper > [data-field]:not(.ct-form-relax) > .ct-select {
+ width: 100%;
+ }
+
+ .ct-form label.checkbox,
+ .ct-form label.radio,
+ .ct-form .checkbox > label,
+ .ct-form .radio > label,
+ .ct-form .checkbox-inline,
+ .ct-form .radio-inline {
+ display: inline-flex;
+ padding-left: 0;
+ padding-right: 1.5rem;
+ align-items: center;
+ }
+
+ .ct-form label.checkbox > input[type="checkbox"],
+ .ct-form label.radio > input[type="checkbox"],
+ .ct-form .checkbox > label > input[type="checkbox"],
+ .ct-form .radio > label > input[type="checkbox"],
+ .ct-form .checkbox-inline > input[type="checkbox"],
+ .ct-form .radio-inline > input[type="checkbox"],
+ .ct-form label.checkbox > input[type="radio"],
+ .ct-form label.radio > input[type="radio"],
+ .ct-form .checkbox > label > input[type="radio"],
+ .ct-form .radio > label > input[type="radio"],
+ .ct-form .checkbox-inline > input[type="radio"],
+ .ct-form .radio-inline > input[type="radio"] {
+ margin: 0 0.5em 0 0;
+ position: static;
+ }
+
+ .ct-form fieldset > .checkbox:first-child,
+ .ct-form fieldset > .radio:first-child {
+ margin-top: 0;
+ }
+
+ .ct-form fieldset > .checkbox:last-child,
+ .ct-form fieldset > .radio:last-child {
+ margin-bottom: 0;
+ }
+
+ .ct-form .list-group {
+ margin-bottom: 0.5rem;
+ }
+
+ .ct-form > .ct-form-split {
+ grid-column: auto / auto;
+ }
+
+ .ct-form > .ct-form-full {
+ grid-column: 1 / -1;
+ }
+
+ .ct-form > .help-block {
+ position: relative;
+ margin-top: -0.5rem;
+ }
+
+ .ct-form .help-block {
+ --help-line-height: calc(var(--pf-global--LineHeight--md) * 1rem);
+ line-height: var(--help-line-height);
+ }
+
+ .ct-form .help-block:empty {
+ display: none;
+ }
+
+ .ct-form .help-block .spinner {
+ position: relative;
+ top: calc((var(--help-line-height) - 16px - 2px) / 2);
+ }
+
+ .ct-form .ct-form-box {
+ background: var(--color-gray-1);
+ border-width: 1px;
+ border-style: solid;
+ border-color: var(--color-gray-5);
+ padding: 0.5rem;
+ padding-top: 1rem;
+ width: 100%;
+ }
+
+.ct-form-stretch {
+ justify-content: stretch !important;
+}
+
+.ct-form-relax {
+ justify-self: start;
+}
+
+.modal-dialog.modal-sm .ct-form > .ct-form-split {
+ grid-column: 2 / -1;
+}
+
+@media (max-width: 640px) {
+ .listing-ct-body,
+ .modal {
+ --ct-form-columns: 1;
+ }
+}
+
+.ct-form-minmax {
+ grid-template-columns: max-content min-content max-content 1fr;
+}
+
+.ct-form-maxmin {
+ grid-template-columns: max-content 1fr max-content min-content;
+}
+
+@media (max-width: 480px) {
+ .listing-ct-body .ct-form,
+ .modal .ct-form {
+ grid-template-columns: initial;
+ }
+
+ .listing-ct-body .ct-form > *,
+ .modal .ct-form > * {
+ grid-column: auto;
+ max-width: 100%;
+ }
+
+ .listing-ct-body .ct-form > .control-label,
+ .modal .ct-form > .control-label {
+ padding: 0;
+ text-align: left;
+ }
+
+ .listing-ct-body .ct-form > .control-label:not(:first-child),
+ .modal .ct-form > .control-label:not(:first-child) {
+ margin: 6px 0 0;
+ }
+
+ .listing-ct-body .ct-form > hr,
+ .modal .ct-form > hr {
+ height: 12px;
+ }
+}
+
+/* Listing pattern */
+.ct-listing {
+ font-size: var(--font-size-s);
+ min-width: 65%;
+ clear: both;
+}
+
+ .ct-listing > header {
+ display: flex;
+ align-items: center;
+ justify-content: start;
+ flex-flow: wrap;
+ }
+
+ .ct-listing > header > :only-child {
+ flex: auto;
+ }
+
+ .ct-listing + .ct-listing {
+ margin-top: 1rem;
+ }
+
+.listing-ct-heading,
+.listing-ct-actions {
+ margin: 0.5rem 0;
+}
+
+.listing-ct-heading {
+ flex: auto;
+ padding: 0.25rem 1em 0.25rem 0;
+}
+
+.ct-listing > table > thead h3 {
+ font-size: var(--pf-global--FontSize--2xl);
+ padding: 1rem 0;
+ font-weight: 400;
+ margin-top: 0;
+ position: relative;
+}
+
+ .ct-listing > table > thead h3 > .pull-right {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ right: 0;
+ }
+
+.ct-listing > table > thead td {
+ padding-top: 1rem;
+}
+
+.ct-listing > table > thead:first-child td {
+ padding-top: 0;
+}
+
+.ct-listing > table > thead td > a {
+ line-height: 30px;
+ padding: 0.5rem 0 0.5rem;
+}
+
+.ct-listing > table > thead th {
+ font-weight: normal;
+ padding: 0.5rem 1rem;
+ color: var(--color-subtle-copy);
+}
+
+ .ct-listing > table > thead th:first-child {
+ padding-left: 1rem;
+ }
+
+ .ct-listing > table > thead th:last-child {
+ text-align: right;
+ }
+
+/* A listing item is a row in the table */
+tbody > tr.listing-ct-item {
+ border: 1px solid transparent;
+ border-top: 1px solid var(--color-ct-list-border);
+ border-bottom: 1px solid var(--color-ct-list-border);
+ cursor: pointer;
+}
+
+.ct-listing > table > tbody:last-child {
+ border-bottom: 1px solid var(--color-ct-list-border);
+}
+
+.ct-listing > table > tbody + thead {
+ border-top: 1px solid var(--color-ct-list-border);
+}
+
+.ct-listing > table > tbody.open:last-child {
+ border-bottom: none;
+}
+
+.ct-listing > table > tbody.open + thead {
+ border-top: none;
+}
+
+tbody > tr.listing-ct-item.listing-ct-warning {
+ background-color: var(--color-ct-light-red-1);
+}
+
+tbody.open > tr.listing-ct-item,
+tbody.open > tr.listing-ct-panel {
+ background-color: var(--color-ct-list-active-bg);
+ border-bottom: none;
+ border-top: none;
+ border-left: 1px solid var(--color-light-gray);
+ border-right: 1px solid var(--color-light-gray);
+ transition: all 200ms;
+}
+
+ tbody.open > tr.listing-ct-item td,
+ tbody.open > tr.listing-ct-item th {
+ border-top: 1px solid var(--color-light-gray);
+ }
+
+tbody.open td div.listing-ct-head {
+ background-color: #fff;
+}
+
+tbody.open > .listing-ct-panel > td > .listing-ct-body {
+ border: none;
+ /* Modified for Cockpit ZFS Manager - Original: overflow: auto; */
+ /* Do not display scrollbars when actions menu is open */
+ overflow: inherit;
+ /* Modified for Cockpit ZFS Manager - New */
+ overflow-y: visible;
+}
+
+tbody.open > tr.listing-ct-panel + tr.listing-ct-body {
+ border-top: none;
+}
+
+tbody.open > tr.listing-ct-panel td div.listing-ct-head {
+ border: none;
+ border-bottom: 1px solid var(--color-light-gray);
+}
+
+/* only highlight the row if navigation is available */
+tbody:not(.open) > tr.listing-ct-item:not(.listing-ct-nonavigate):hover {
+ background-color: var(--color-ct-list-hover-bg);
+}
+
+/* if we can't navigate to a row but expand is available, highlight the caret */
+tbody:not(.open) > tr.listing-ct-item.listing-ct-nonavigate:hover td.listing-ct-toggle {
+ color: var(--color-ct-list-hover-icon);
+}
+
+/* use hover color expanded rows even if navigation isn't available */
+tbody.open > tr.listing-ct-item:hover,
+/* Modified for Cockpit ZFS Manager - Original: tr.listing-ct-item.listing-ct-nonavigate:hover */
+tr.listing-ct-item.listing-ct-nonavigate:not(.listing-ct-storagepoolsnotfound):hover {
+ background-color: var(--color-ct-list-hover-bg);
+}
+
+tr.listing-ct-item .listing-ct-toggle:not(:empty) {
+ width: 35px;
+ color: #393f44;
+}
+
+/* Highlight toggle color when hovered or if the row is open */
+.listing-ct-toggle:hover,
+tbody.open .listing-ct-toggle {
+ color: var(--color-ct-list-active-bg);
+}
+
+.listing-ct > thead > tr > .listing-ct-toggle + th,
+.listing-ct-item > .listing-ct-toggle + td,
+.listing-ct-item > .listing-ct-toggle + th {
+ padding-left: 0.25rem;
+ position: relative;
+}
+
+td.listing-ct-toggle i {
+ font-size: 17px;
+}
+
+ td.listing-ct-toggle i:before {
+ position: relative;
+ content: "\F105";
+ display: block;
+ }
+
+/* Modified for Cockpit ZFS Manager - Original: tbody.open > td.listing-ct-toggle i:before */
+tbody.open > tr.listing-ct-item td.listing-ct-toggle i:before,
+/* Modified for Cockpit ZFS Manager - New */
+tbody.open > tr.listing-ct-item-snapshots .listing-ct-toggle-snapshots i:before {
+ content: "\F107";
+ animation: listingCtToggleOpen 100ms ease-in-out;
+ top: 1px;
+}
+
+@keyframes listingCtToggleOpen {
+ 0% {
+ transform-origin: 50% 50%;
+ transform: translate(0, -1px) rotate(-90deg);
+ }
+
+ 100% {
+ transform: translate(0, 0) rotate(0);
+ }
+}
+
+/* Listing items have decent padding ... */
+.listing-ct > thead > tr > th,
+tr.listing-ct-item > th,
+tr.listing-ct-item > td {
+ padding: 0.75rem;
+ vertical-align: text-top;
+ /* baseline doesn't support wrapped lines */
+}
+
+ tr.listing-ct-item > td > .btn {
+ /* .btn has padding of 6px and 1px border */
+ margin-top: -7px;
+ margin-bottom: -7px;
+ }
+
+ tr.listing-ct-item > td > .btn-control-ct {
+ /* Adapt for Cockpit's modified button, which is larger by 8px */
+ margin-top: -3px;
+ margin-bottom: -3px;
+ }
+
+/* Listing actions can be used directly as a cell */
+tr.listing-ct-item td.listing-ct-actions,
+td.listing-ct-actions {
+ padding: 0.25rem 0.5rem;
+ text-align: right;
+ float: none;
+}
+/* if the entire row is selected, highlight */
+tr.listing-ct-item.listing-ct-selected {
+ background-color: #0088ce;
+ color: #fff;
+ border-color: #007ebf;
+}
+
+ tr.listing-ct-item.listing-ct-selected:hover {
+ background-color: #007ebf;
+ border-color: #007ebf;
+ }
+
+ tr.listing-ct-item.listing-ct-selected .badge {
+ background-color: #00537e;
+ }
+
+ tr.listing-ct-item.listing-ct-selected .badge:hover {
+ background-color: #003e5f;
+ }
+
+.listing-ct-head .listing-ct-actions {
+ margin-top: -7px;
+ order: -1;
+}
+
+/* Modified for Cockpit ZFS Manager - Original: tr.listing-ct-item td:last-child */
+.ct-listing > table > tbody > tr > td:last-child:not(:first-child) {
+ text-align: right;
+}
+
+div.listing-ct-panel {
+ box-shadow: 1px 1px 1px 1px #f5f5f5;
+ margin-bottom: 1rem;
+}
+
+div.listing-ct-maybe {
+ border: 1px dashed var(--color-light-gray-3);
+ box-shadow: none;
+}
+
+div.listing-ct-head {
+ padding: 0.5rem 0.5rem 0 0.5rem;
+ background-color: #f5f5f5;
+ border-color: var(--color-light-gray);
+ border-style: solid;
+ border-width: 1px 1px 0 1px;
+ overflow: hidden;
+ display: flex;
+ flex-flow: row-reverse wrap;
+ align-items: center;
+}
+
+ div.listing-ct-head:last-child {
+ padding-bottom: 0.5rem;
+ }
+
+div.listing-ct-maybe div.listing-ct-head,
+div.listing-ct-maybe div.listing-ct-body {
+ background-color: #fff;
+ border: none;
+}
+
+tbody.active .listing-ct-head {
+ border-top: 3px solid var(--color-link);
+}
+
+.listing-ct-head h3 {
+ font-weight: normal;
+ font-size: 18px;
+ margin-top: 0px;
+ margin-left: 0.25rem;
+ margin-bottom: 0.5rem;
+}
+
+ .listing-ct-head h3 i {
+ float: left;
+ padding-right: 7px;
+ }
+
+.listing-ct-head .nav li a {
+ font-size: 13px;
+ /* Counteract listing-ct-head padding */
+ margin-top: -0.5rem;
+ margin: 0;
+}
+
+.listing-ct-head .nav-tabs {
+ border-bottom: none;
+}
+
+.listing-ct-head .nav-tabs-pf {
+ /* Counteract listing-ct-head padding */
+ margin: -0.5rem 0 0 -0.5rem;
+ flex: auto;
+}
+
+/* To display info instead of tabs */
+.listing-ct-head dl {
+ display: inline-block;
+ height: 1.6em;
+ margin-bottom: 5px;
+ white-space: nowrap;
+ margin-right: 45px;
+ margin-left: 5px;
+}
+
+.listing-ct-head dt {
+ font-weight: normal;
+ display: inline;
+ margin-right: 0.5em;
+ color: var(--color-subtle-copy);
+}
+
+.listing-ct-head dd {
+ display: inline;
+ color: black;
+}
+
+.listing-ct-body {
+ /* Modified for Cockpit ZFS Manager - Original: padding: 1rem 1.5rem; */
+ padding: 0px;
+ border: 1px solid var(--color-light-gray);
+ background-color: #fff;
+}
+
+.listing-ct-inline > td > .listing-ct-body {
+ border: none;
+ padding-top: 0px;
+ padding-left: 1rem;
+ padding-bottom: 0px;
+}
+
+.listing-ct-inline > h3 {
+ border-top: 1px solid var(--color-light-gray);
+ padding-top: 20px;
+ margin-top: 30px;
+}
+
+ .listing-ct-inline > h3:first-child {
+ border-top: none;
+ padding-top: 0px;
+ margin-top: 20px;
+ }
+
+.listing-ct-actions {
+ float: right;
+ min-height: 26px;
+}
+
+.listing-ct-status {
+ float: right;
+ clear: right;
+}
+
+.listing-ct-error {
+ border-top: 1px solid var(--color-light-gray);
+ border-left: 1px solid var(--color-light-gray);
+ border-right: 1px solid var(--color-light-gray);
+}
+
+ .listing-ct-error.alert {
+ margin-bottom: 0;
+ }
+
+.listing-ct-body tt {
+ font-size: 12px;
+}
+
+.listing-ct-body dl {
+ margin: 0;
+}
+
+ .listing-ct-body dl dd dl.inline-dl dt,
+ .listing-ct-body dt {
+ clear: left;
+ float: left;
+ width: 100px;
+ min-height: 26px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ color: var(--color-subtle-copy);
+ font-weight: normal;
+ }
+
+.listing-ct-body dt {
+ text-align: right;
+}
+
+.listing-ct-body dl dd dl dt {
+ text-align: left;
+}
+
+.listing-ct-body dd {
+ margin-left: 110px;
+ min-height: 26px;
+ max-width: 1000px;
+ text-overflow: ellipsis;
+}
+
+.listing-ct-body dl.full-width dt {
+ text-align: left;
+ min-width: none;
+ max-width: none;
+ float: none;
+ width: auto;
+}
+
+.listing-ct-body dl.full-width dd {
+ margin-left: 0px;
+}
+
+.ct-listing > table > tbody > tr > td:first-child {
+ position: relative;
+ transition: all 100ms ease-out;
+}
+
+ .ct-listing > table > tbody > tr > td:first-child::before,
+ .ct-listing > table > tbody > tr > td:first-child::after {
+ content: "";
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ opacity: 0;
+ pointer-events: none;
+ transition: all 300ms;
+ }
+
+ .ct-listing > table > tbody > tr > td:first-child::after {
+ right: auto;
+ width: 0;
+ background-color: var(--pf-global--active-color--100);
+ }
+
+.ct-listing > table > tbody > tr:not(:first-child) > td:first-child::after {
+ top: -1px;
+}
+
+.ct-listing > table > tbody.open > tr > td:first-child {
+ transition: all 100ms ease-in;
+}
+
+ .ct-listing > table > tbody.open > tr > td:first-child::before,
+ .ct-listing > table > tbody.open > tr > td:first-child::after {
+ opacity: 1;
+ }
+
+ .ct-listing > table > tbody.open > tr > td:first-child::after {
+ width: 3px;
+ }
+
+.ct-listing > table > tbody.open {
+ transition: all 100ms ease-in;
+ box-shadow: 0 0.3125rem 0.625rem -0.25rem rgba(3, 3, 3, 0.25);
+}
+
+/* By default these are hidden */
+/* (HACK: Special-case the user auth dialog) */
+tbody:not(.ssh-key-body) > tr.listing-ct-head,
+tbody > tr.listing-ct-panel,
+tbody > tr.listing-ct-body {
+ display: none;
+}
+
+ tbody:not(.ssh-key-body) > tr.listing-ct-head > td,
+ tbody > tr.listing-ct-panel > td,
+ tbody > tr.listing-ct-body > td {
+ /* Compensate for the left-side blue highlight */
+ padding-left: 3px;
+ }
+
+/* ... unless they are in the right state */
+tbody.open > tr.listing-ct-head,
+tbody.open > tr.listing-ct-panel,
+tbody.open > tr.listing-ct-body {
+ display: table-row;
+}
+
+/* Animate the listing head & the last visible body */
+/* (Switching tabs will adds new listing-ct-bodys & toggle visibility) */
+tbody.open div.listing-ct-head,
+tbody.open div.listing-ct-head + div.listing-ct-body:not([hidden]):last-child {
+ animation: listingCtShow 100ms ease-in-out;
+}
+
+@keyframes listingCtShow {
+ 0% {
+ margin-bottom: 0;
+ margin-top: 0;
+ max-height: 0;
+ opacity: 0;
+ padding-bottom: 0;
+ padding-top: 0;
+ line-height: 0;
+ }
+
+ 50% {
+ opacity: 0;
+ line-height: 1;
+ }
+
+ 100% {
+ max-height: 100vh;
+ opacity: 1;
+ }
+}
+
+/* Turn off animation if requested by the browser/OS (where supported) */
+@media (prefers-reduced-motion: reduce) {
+ tbody.open td.listing-ct-toggle i:before,
+ tbody.open div.listing-ct-head,
+ tbody.open div.listing-ct-body {
+ animation: none;
+ }
+}
+
+tbody.open tr.listing-ct-head {
+ border-color: var(--color-light-gray);
+ border-style: solid;
+ border-width: 1px 1px 0 1px;
+ border-top: 3px solid var(--color-link);
+ background-color: #f5f5f5;
+}
+
+tr.listing-ct-head + tr.listing-ct-head {
+ border-top: none;
+}
+
+ tr.listing-ct-head + tr.listing-ct-head td {
+ padding: 0px 0.5rem 0px 0.5rem;
+ }
+
+tr.listing-ct-body td {
+ padding: 1rem 1.5rem;
+ font-size: var(--font-size-s);
+}
+
+.listing-ct-empty {
+ color: var(--color-subtle-copy);
+ text-align: center;
+ border-top: 1px solid var(--color-gray-2);
+ border-bottom: 1px solid var(--color-gray-2);
+}
+
+/* Used at the end of a group of tbody to show an 'empty' message */
+thead.listing-ct-empty td,
+.ct-listing > table > thead.listing-ct-empty td {
+ padding: 0.5rem;
+}
+
+tbody + thead.listing-ct-empty {
+ display: none;
+}
+
+/* Listing pattern defaults to using full width of parent */
+.listing-ct-wide {
+ width: 100%;
+}
+
+/* Listing pattern mod to redce the padding */
+.listing-ct-compact > thead > tr > th,
+.listing-ct-compact > tbody > tr > th,
+.listing-ct-compact > tbody > tr > td {
+ padding: 0.25rem;
+}
+
+.listing-ct-compact > tbody > tr > .listing-ct-toggle:not(:empty) + th,
+.listing-ct-compact > tbody > tr > .listing-ct-toggle:not(:empty) + td {
+ padding-left: 0.25rem;
+}
+
+ .listing-ct-compact > tbody > tr > .listing-ct-toggle:not(:empty) + th::before,
+ .listing-ct-compact > tbody > tr > .listing-ct-toggle:not(:empty) + td::before {
+ top: 0.25rem;
+ }
+
+div.listing-ct-head {
+ overflow: visible;
+}
+
+.listing-ct-head .btn-group,
+.listing-ct-head button:not(.dropdown-toggle) {
+ margin-left: 0.3em;
+}
+
+tbody tr.listing-ct-noexpand {
+ cursor: default;
+}
+
+/* Fix up nav-tabs-pf to work properly */
+.nav-tabs-pf > li:first-child a {
+ margin-left: 0px !important;
+ padding-left: 1rem !important;
+}
+
+.nav-tabs-pf > li a:before {
+ right: 0px !important;
+}
+
+.nav-tabs-pf > li > a:active:before,
+.nav-tabs-pf > li > a:focus:before,
+.nav-tabs-pf > li > a:hover:before,
+.nav-tabs-pf > li.active a:before {
+ height: 3px;
+ left: 0px;
+}
+
+/* Force word-wraps when words are too long */
+.listing-ct-item td,
+.listing-ct-item th,
+.listing-ct-body {
+ overflow-wrap: break-word;
+ hyphens: auto;
+}
+
+.listing-ct-item td,
+.listing-ct-item th {
+ max-width: calc(100vw - 18rem);
+}
+
+.listing-ct-body {
+ /* 42 = (20px padding + 1px border) * 2 */
+ max-width: calc(100vw - 42px);
+}
+
+
+
+/*
+ * This file is part of Cockpit.
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * Cockpit is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * Cockpit is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Cockpit; If not, see .
+ */
+
+
pf-c-empty-state .pf-c-button.pf-m-primary.slim {
margin: 0
}
@@ -3336,113 +3341,113 @@ pf-c-empty-state .pf-c-button.pf-m-primary.slim {
.pf-u-hidden-on-2xl {
display: none !important
}
-}
-
-.pf-c-alert-group {
- --pf-c-alert-group__item--MarginTop: var(--pf-global--spacer--sm);
- /* Modified for Cockpit ZFS Manager - Original: var(--pf-global--spacer--2xl); */
- --pf-c-alert-group--m-toast--Top: var(--pf-global--spacer--xl);
- --pf-c-alert-group--m-toast--Right: var(--pf-global--spacer--xl);
- --pf-c-alert-group--m-toast--MaxWidth: 37.5rem;
- /* Modified for Cockpit ZFS Manager - Original: var(--pf-global--ZIndex--2xl); */
- --pf-c-alert-group--m-toast--ZIndex: 1055;
-}
-
- .pf-c-alert-group > * + * {
- margin-top: var(--pf-c-alert-group__item--MarginTop)
- }
-
- .pf-c-alert-group.pf-m-toast {
- position: fixed;
- top: var(--pf-c-alert-group--m-toast--Top);
- right: var(--pf-c-alert-group--m-toast--Right);
- z-index: var(--pf-c-alert-group--m-toast--ZIndex);
- width: calc(100% - var(--pf-c-alert-group--m-toast--Right)*2);
- max-width: var(--pf-c-alert-group--m-toast--MaxWidth)
- }
-
-.modal-content .pf-c-alert {
- text-align: left;
- margin-bottom: 24px;
-}
-
-.pf-c-alert {
- --pf-global--Color--100: var(--pf-global--Color--dark-100);
- --pf-global--Color--200: var(--pf-global--Color--dark-200);
- --pf-global--BorderColor--100: var(--pf-global--BorderColor--dark-100);
- --pf-global--primary-color--100: var(--pf-global--primary-color--dark-100);
- --pf-global--link--Color: var(--pf-global--link--Color--dark);
- --pf-global--link--Color--hover: var(--pf-global--link--Color--dark--hover);
- --pf-global--BackgroundColor--100: var(--pf-global--BackgroundColor--light-100);
- --pf-c-alert--BoxShadow: var(--pf-global--BoxShadow--lg);
- --pf-c-alert--BackgroundColor: var(--pf-global--BackgroundColor--100);
- --pf-c-alert--grid-template-columns: max-content 1fr max-content;
- --pf-c-alert--grid-template-rows: 1fr auto;
- --pf-c-alert__icon--Padding: var(--pf-global--spacer--md);
- --pf-c-alert__icon--Color: var(--pf-global--default-color--300);
- --pf-c-alert__icon--BackgroundColor: var(--pf-global--default-color--100);
- --pf-c-alert__icon--FontSize: var(--pf-global--icon--FontSize--lg);
- --pf-c-alert__title--FontSize: var(--pf-global--FontSize--md);
- --pf-c-alert__title--Color: var(--pf-global--default-color--300);
- --pf-c-alert__title--PaddingTop: var(--pf-global--spacer--md);
- --pf-c-alert__title--PaddingRight: var(--pf-global--spacer--md);
- --pf-c-alert__title--PaddingBottom: var(--pf-global--spacer--md);
- --pf-c-alert__title--PaddingLeft: var(--pf-global--spacer--md);
- --pf-c-alert__description--PaddingRight: var(--pf-global--spacer--md);
- --pf-c-alert__description--PaddingBottom: var(--pf-global--spacer--md);
- --pf-c-alert__description--PaddingLeft: var(--pf-global--spacer--md);
- --pf-c-alert__description--MarginTop: calc(-1*var(--pf-global--spacer--sm));
- /* Modified for Cockpit ZFS Manager - Original: 0.6875rem; */
- --pf-c-alert__action--PaddingTop: 0.375rem;
- --pf-c-alert__action--PaddingRight: var(--pf-global--spacer--xs);
- --pf-c-alert--m-success__icon--Color: var(--pf-global--success-color--200);
- --pf-c-alert--m-success__icon--BackgroundColor: var(--pf-global--success-color--100);
- --pf-c-alert--m-success__title--Color: var(--pf-global--success-color--200);
- --pf-c-alert--m-danger__icon--Color: var(--pf-global--danger-color--300);
- --pf-c-alert--m-danger__icon--BackgroundColor: var(--pf-global--danger-color--100);
- --pf-c-alert--m-danger__title--Color: var(--pf-global--danger-color--200);
- --pf-c-alert--m-warning__icon--Color: var(--pf-global--warning-color--200);
- --pf-c-alert--m-warning__icon--BackgroundColor: var(--pf-global--warning-color--100);
- --pf-c-alert--m-warning__icon--FontSize: var(--pf-global--FontSize--xl);
- --pf-c-alert--m-warning__title--Color: var(--pf-global--warning-color--200);
- --pf-c-alert--m-info__icon--Color: var(--pf-global--info-color--200);
- --pf-c-alert--m-info__icon--BackgroundColor: var(--pf-global--info-color--100);
- --pf-c-alert--m-info__title--Color: var(--pf-global--info-color--200);
- --pf-c-alert--m-inline--BoxShadow: none;
- --pf-c-alert--m-inline--BorderColor: var(--pf-global--BorderColor--300);
- --pf-c-alert--m-inline--BorderStyle: solid;
- --pf-c-alert--m-inline--BorderTopWidth: var(--pf-global--BorderWidth--sm);
- --pf-c-alert--m-inline--BorderRightWidth: var(--pf-global--BorderWidth--sm);
- --pf-c-alert--m-inline--BorderBottomWidth: var(--pf-global--BorderWidth--sm);
- --pf-c-alert--m-inline--BorderLeftWidth: 0;
- --pf-c-alert--m-inline--before--Width: var(--pf-global--BorderWidth--lg);
- --pf-c-alert--m-inline--before--Top: calc(-1*var(--pf-c-alert--m-inline--BorderTopWidth));
- --pf-c-alert--m-inline--before--Bottom: calc(-1*var(--pf-c-alert--m-inline--BorderBottomWidth));
- --pf-c-alert--m-inline--before--BackgroundColor: var(--pf-global--default-color--200);
- --pf-c-alert--m-inline__icon--FontSize: var(--pf-global--icon--FontSize--md);
- --pf-c-alert--m-inline__icon--Color: var(--pf-global--default-color--200);
- --pf-c-alert--m-inline__icon--BackgroundColor: transparent;
- --pf-c-alert--m-inline__icon--PaddingTop: calc(var(--pf-c-alert__icon--Padding) + (var(--pf-c-alert__icon--FontSize) - var(--pf-c-alert--m-inline__icon--FontSize))/2);
- --pf-c-alert--m-inline__icon--PaddingRight: 0;
- --pf-c-alert--m-inline__icon--PaddingBottom: var(--pf-global--spacer--md);
- --pf-c-alert--m-inline__icon--PaddingLeft: var(--pf-global--spacer--md);
- --pf-c-alert--m-inline--m-warning__icon--FontSize: 1.0625rem;
- --pf-c-alert--m-inline--m-success__icon--Color: var(--pf-global--success-color--100);
- --pf-c-alert--m-inline--m-success--before--BackgroundColor: var(--pf-global--success-color--100);
- --pf-c-alert--m-inline--m-danger__icon--Color: var(--pf-global--danger-color--100);
- --pf-c-alert--m-inline--m-danger--before--BackgroundColor: var(--pf-global--danger-color--100);
- --pf-c-alert--m-inline--m-warning__icon--Color: var(--pf-global--warning-color--100);
- --pf-c-alert--m-inline--m-warning--before--BackgroundColor: var(--pf-global--warning-color--100);
- --pf-c-alert--m-inline--m-info__icon--Color: var(--pf-global--info-color--100);
- --pf-c-alert--m-inline--m-info--before--BackgroundColor: var(--pf-global--info-color--100);
- color: var(--pf-global--Color--100);
- position: relative;
- display: grid;
- grid-template-columns: var(--pf-c-alert--grid-template-columns);
- grid-template-rows: var(--pf-c-alert--grid-template-rows);
- grid-template-areas: "icon title action" "icon content content";
- background-color: var(--pf-c-alert--BackgroundColor);
- box-shadow: var(--pf-c-alert--BoxShadow)
+}
+
+.pf-c-alert-group {
+ --pf-c-alert-group__item--MarginTop: var(--pf-global--spacer--sm);
+ /* Modified for Cockpit ZFS Manager - Original: var(--pf-global--spacer--2xl); */
+ --pf-c-alert-group--m-toast--Top: var(--pf-global--spacer--xl);
+ --pf-c-alert-group--m-toast--Right: var(--pf-global--spacer--xl);
+ --pf-c-alert-group--m-toast--MaxWidth: 37.5rem;
+ /* Modified for Cockpit ZFS Manager - Original: var(--pf-global--ZIndex--2xl); */
+ --pf-c-alert-group--m-toast--ZIndex: 1055;
+}
+
+ .pf-c-alert-group > * + * {
+ margin-top: var(--pf-c-alert-group__item--MarginTop)
+ }
+
+ .pf-c-alert-group.pf-m-toast {
+ position: fixed;
+ top: var(--pf-c-alert-group--m-toast--Top);
+ right: var(--pf-c-alert-group--m-toast--Right);
+ z-index: var(--pf-c-alert-group--m-toast--ZIndex);
+ width: calc(100% - var(--pf-c-alert-group--m-toast--Right)*2);
+ max-width: var(--pf-c-alert-group--m-toast--MaxWidth)
+ }
+
+.modal-content .pf-c-alert {
+ text-align: left;
+ margin-bottom: 24px;
+}
+
+.pf-c-alert {
+ --pf-global--Color--100: var(--pf-global--Color--dark-100);
+ --pf-global--Color--200: var(--pf-global--Color--dark-200);
+ --pf-global--BorderColor--100: var(--pf-global--BorderColor--dark-100);
+ --pf-global--primary-color--100: var(--pf-global--primary-color--dark-100);
+ --pf-global--link--Color: var(--pf-global--link--Color--dark);
+ --pf-global--link--Color--hover: var(--pf-global--link--Color--dark--hover);
+ --pf-global--BackgroundColor--100: var(--pf-global--BackgroundColor--light-100);
+ --pf-c-alert--BoxShadow: var(--pf-global--BoxShadow--lg);
+ --pf-c-alert--BackgroundColor: var(--pf-global--BackgroundColor--100);
+ --pf-c-alert--grid-template-columns: max-content 1fr max-content;
+ --pf-c-alert--grid-template-rows: 1fr auto;
+ --pf-c-alert__icon--Padding: var(--pf-global--spacer--md);
+ --pf-c-alert__icon--Color: var(--pf-global--default-color--300);
+ --pf-c-alert__icon--BackgroundColor: var(--pf-global--default-color--100);
+ --pf-c-alert__icon--FontSize: var(--pf-global--icon--FontSize--lg);
+ --pf-c-alert__title--FontSize: var(--pf-global--FontSize--md);
+ --pf-c-alert__title--Color: var(--pf-global--default-color--300);
+ --pf-c-alert__title--PaddingTop: var(--pf-global--spacer--md);
+ --pf-c-alert__title--PaddingRight: var(--pf-global--spacer--md);
+ --pf-c-alert__title--PaddingBottom: var(--pf-global--spacer--md);
+ --pf-c-alert__title--PaddingLeft: var(--pf-global--spacer--md);
+ --pf-c-alert__description--PaddingRight: var(--pf-global--spacer--md);
+ --pf-c-alert__description--PaddingBottom: var(--pf-global--spacer--md);
+ --pf-c-alert__description--PaddingLeft: var(--pf-global--spacer--md);
+ --pf-c-alert__description--MarginTop: calc(-1*var(--pf-global--spacer--sm));
+ /* Modified for Cockpit ZFS Manager - Original: 0.6875rem; */
+ --pf-c-alert__action--PaddingTop: 0.375rem;
+ --pf-c-alert__action--PaddingRight: var(--pf-global--spacer--xs);
+ --pf-c-alert--m-success__icon--Color: var(--pf-global--success-color--200);
+ --pf-c-alert--m-success__icon--BackgroundColor: var(--pf-global--success-color--100);
+ --pf-c-alert--m-success__title--Color: var(--pf-global--success-color--200);
+ --pf-c-alert--m-danger__icon--Color: var(--pf-global--danger-color--300);
+ --pf-c-alert--m-danger__icon--BackgroundColor: var(--pf-global--danger-color--100);
+ --pf-c-alert--m-danger__title--Color: var(--pf-global--danger-color--200);
+ --pf-c-alert--m-warning__icon--Color: var(--pf-global--warning-color--200);
+ --pf-c-alert--m-warning__icon--BackgroundColor: var(--pf-global--warning-color--100);
+ --pf-c-alert--m-warning__icon--FontSize: var(--pf-global--FontSize--xl);
+ --pf-c-alert--m-warning__title--Color: var(--pf-global--warning-color--200);
+ --pf-c-alert--m-info__icon--Color: var(--pf-global--info-color--200);
+ --pf-c-alert--m-info__icon--BackgroundColor: var(--pf-global--info-color--100);
+ --pf-c-alert--m-info__title--Color: var(--pf-global--info-color--200);
+ --pf-c-alert--m-inline--BoxShadow: none;
+ --pf-c-alert--m-inline--BorderColor: var(--pf-global--BorderColor--300);
+ --pf-c-alert--m-inline--BorderStyle: solid;
+ --pf-c-alert--m-inline--BorderTopWidth: var(--pf-global--BorderWidth--sm);
+ --pf-c-alert--m-inline--BorderRightWidth: var(--pf-global--BorderWidth--sm);
+ --pf-c-alert--m-inline--BorderBottomWidth: var(--pf-global--BorderWidth--sm);
+ --pf-c-alert--m-inline--BorderLeftWidth: 0;
+ --pf-c-alert--m-inline--before--Width: var(--pf-global--BorderWidth--lg);
+ --pf-c-alert--m-inline--before--Top: calc(-1*var(--pf-c-alert--m-inline--BorderTopWidth));
+ --pf-c-alert--m-inline--before--Bottom: calc(-1*var(--pf-c-alert--m-inline--BorderBottomWidth));
+ --pf-c-alert--m-inline--before--BackgroundColor: var(--pf-global--default-color--200);
+ --pf-c-alert--m-inline__icon--FontSize: var(--pf-global--icon--FontSize--md);
+ --pf-c-alert--m-inline__icon--Color: var(--pf-global--default-color--200);
+ --pf-c-alert--m-inline__icon--BackgroundColor: transparent;
+ --pf-c-alert--m-inline__icon--PaddingTop: calc(var(--pf-c-alert__icon--Padding) + (var(--pf-c-alert__icon--FontSize) - var(--pf-c-alert--m-inline__icon--FontSize))/2);
+ --pf-c-alert--m-inline__icon--PaddingRight: 0;
+ --pf-c-alert--m-inline__icon--PaddingBottom: var(--pf-global--spacer--md);
+ --pf-c-alert--m-inline__icon--PaddingLeft: var(--pf-global--spacer--md);
+ --pf-c-alert--m-inline--m-warning__icon--FontSize: 1.0625rem;
+ --pf-c-alert--m-inline--m-success__icon--Color: var(--pf-global--success-color--100);
+ --pf-c-alert--m-inline--m-success--before--BackgroundColor: var(--pf-global--success-color--100);
+ --pf-c-alert--m-inline--m-danger__icon--Color: var(--pf-global--danger-color--100);
+ --pf-c-alert--m-inline--m-danger--before--BackgroundColor: var(--pf-global--danger-color--100);
+ --pf-c-alert--m-inline--m-warning__icon--Color: var(--pf-global--warning-color--100);
+ --pf-c-alert--m-inline--m-warning--before--BackgroundColor: var(--pf-global--warning-color--100);
+ --pf-c-alert--m-inline--m-info__icon--Color: var(--pf-global--info-color--100);
+ --pf-c-alert--m-inline--m-info--before--BackgroundColor: var(--pf-global--info-color--100);
+ color: var(--pf-global--Color--100);
+ position: relative;
+ display: grid;
+ grid-template-columns: var(--pf-c-alert--grid-template-columns);
+ grid-template-rows: var(--pf-c-alert--grid-template-rows);
+ grid-template-areas: "icon title action" "icon content content";
+ background-color: var(--pf-c-alert--BackgroundColor);
+ box-shadow: var(--pf-c-alert--BoxShadow)
}
.pf-c-alert.pf-m-success {
@@ -7115,48 +7120,48 @@ pf-c-empty-state .pf-c-button.pf-m-primary.slim {
.pf-c-inline-edit__label.pf-m-bold {
font-weight: var(--pf-c-inline-edit__label--m-bold--FontWeight)
-}
-
-.pf-c-badge {
- --pf-c-badge--BorderRadius: var(--pf-global--BorderRadius--lg);
- --pf-c-badge--FontSize: var(--pf-global--FontSize--xs);
- --pf-c-badge--FontWeight: var(--pf-global--FontWeight--bold);
- --pf-c-badge--PaddingRight: var(--pf-global--spacer--sm);
- --pf-c-badge--PaddingLeft: var(--pf-global--spacer--sm);
- --pf-c-badge--Color: var(--pf-global--Color--dark-100);
- --pf-c-badge--MinWidth: var(--pf-global--spacer--xl);
- --pf-c-badge--m-read--BackgroundColor: var(--pf-global--BackgroundColor--300);
- --pf-c-badge--m-read--Color: var(--pf-global--Color--dark-100);
- --pf-c-badge--m-unread--BackgroundColor: var(--pf-global--primary-color--100);
- --pf-c-badge--m-unread--Color: var(--pf-global--Color--light-100);
- display: inline-block;
- min-width: var(--pf-c-badge--MinWidth);
- padding-right: var(--pf-c-badge--PaddingRight);
- padding-left: var(--pf-c-badge--PaddingLeft);
- font-size: var(--pf-c-badge--FontSize);
- font-weight: var(--pf-c-badge--FontWeight);
- color: var(--pf-c-badge--Color);
- text-align: center;
- background-color: var(--pf-c-badge--BackgroundColor);
- border-radius: var(--pf-c-badge--BorderRadius)
-}
-
-.pf-c-badge.pf-m-read {
- --pf-c-badge--Color: var(--pf-c-badge--m-read--Color);
- --pf-c-badge--BackgroundColor: var(--pf-c-badge--m-read--BackgroundColor)
-}
-
-.pf-c-badge.pf-m-unread {
- --pf-c-badge--Color: var(--pf-c-badge--m-unread--Color);
- --pf-c-badge--BackgroundColor: var(--pf-c-badge--m-unread--BackgroundColor)
-}
-
-.pf-l-bullseye {
- --pf-l-bullseye--Padding: 0;
- display: flex;
- align-items: center;
- justify-content: center;
- height: 100%;
- padding: var(--pf-l-bullseye--Padding);
- margin: 0
+}
+
+.pf-c-badge {
+ --pf-c-badge--BorderRadius: var(--pf-global--BorderRadius--lg);
+ --pf-c-badge--FontSize: var(--pf-global--FontSize--xs);
+ --pf-c-badge--FontWeight: var(--pf-global--FontWeight--bold);
+ --pf-c-badge--PaddingRight: var(--pf-global--spacer--sm);
+ --pf-c-badge--PaddingLeft: var(--pf-global--spacer--sm);
+ --pf-c-badge--Color: var(--pf-global--Color--dark-100);
+ --pf-c-badge--MinWidth: var(--pf-global--spacer--xl);
+ --pf-c-badge--m-read--BackgroundColor: var(--pf-global--BackgroundColor--300);
+ --pf-c-badge--m-read--Color: var(--pf-global--Color--dark-100);
+ --pf-c-badge--m-unread--BackgroundColor: var(--pf-global--primary-color--100);
+ --pf-c-badge--m-unread--Color: var(--pf-global--Color--light-100);
+ display: inline-block;
+ min-width: var(--pf-c-badge--MinWidth);
+ padding-right: var(--pf-c-badge--PaddingRight);
+ padding-left: var(--pf-c-badge--PaddingLeft);
+ font-size: var(--pf-c-badge--FontSize);
+ font-weight: var(--pf-c-badge--FontWeight);
+ color: var(--pf-c-badge--Color);
+ text-align: center;
+ background-color: var(--pf-c-badge--BackgroundColor);
+ border-radius: var(--pf-c-badge--BorderRadius)
+}
+
+.pf-c-badge.pf-m-read {
+ --pf-c-badge--Color: var(--pf-c-badge--m-read--Color);
+ --pf-c-badge--BackgroundColor: var(--pf-c-badge--m-read--BackgroundColor)
+}
+
+.pf-c-badge.pf-m-unread {
+ --pf-c-badge--Color: var(--pf-c-badge--m-unread--Color);
+ --pf-c-badge--BackgroundColor: var(--pf-c-badge--m-unread--BackgroundColor)
+}
+
+.pf-l-bullseye {
+ --pf-l-bullseye--Padding: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ padding: var(--pf-l-bullseye--Padding);
+ margin: 0
}
\ No newline at end of file
diff --git a/zfs/zfs.js b/zfs/zfs.js
index bb8a773..68f3d4c 100644
--- a/zfs/zfs.js
+++ b/zfs/zfs.js
@@ -1,20910 +1,20910 @@
-/*
- * This file is part of Cockpit ZFS Manager.
- *
- * Copyright (C) 2019-2020 OPTIMANS Pty Ltd.
- *
- * Cockpit ZFS Manager is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 3 of the License, or (at your option)
- * any later version.
- *
- * Cockpit ZFS Manager is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License along
- * with Cockpit ZFS Manager; If not, see .
- */
-
-
-//#region Configuration - Edit With Configure ZFS Manager Modal
-
-let zfsmanager = {
- cockpit: {
- datelocale: (navigator.languages && navigator.languages.length ? navigator.languages[0] : (navigator.userLanguage || navigator.language || navigator.browserLanguage || cockpit.language)),
- legacy: false,
- permission: null
- },
- configuration: {
- cockpit: {
- manage: false //Remove packages that cause problems for ZFS
- },
- disks: {
- base2: false //Use Base-2 calculation for disk sizes
- },
- loglevel: 2, //Console logging. 1=Minimal Logging, 2=Enhanced Logging, 3=Enhanced Logging and Process Commands, 4=Verbose
- samba: {
- manage: false, //Manage Samba shares
- windowscompatibility: true //Disable special characters in share name that don't work with Microsoft Windows
- },
- updates: {
- check: true //Check for updates on launch
- },
- zfs: {
- filesystem: {
- cloneorigin: false, //Display clone origin in tooltip
- quotarestrict: true, //Restrict quota maximum to size of storage pool
- readonlylockdown: false, //Prevent changes to read only file systems and clone file systems
- snapshotactions: true, //Display snapshot actions in file system actions menu
- },
- snapshot: {
+/*
+ * This file is part of Cockpit ZFS Manager.
+ *
+ * Copyright (C) 2019-2020 OPTIMANS Pty Ltd.
+ *
+ * Cockpit ZFS Manager is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Cockpit ZFS Manager is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with Cockpit ZFS Manager; If not, see .
+ */
+
+
+//#region Configuration - Edit With Configure ZFS Manager Modal
+
+let zfsmanager = {
+ cockpit: {
+ datelocale: (navigator.languages && navigator.languages.length ? navigator.languages[0] : (navigator.userLanguage || navigator.language || navigator.browserLanguage || cockpit.language)),
+ legacy: false,
+ permission: null
+ },
+ configuration: {
+ cockpit: {
+ manage: false //Remove packages that cause problems for ZFS
+ },
+ disks: {
+ base2: false //Use Base-2 calculation for disk sizes
+ },
+ loglevel: 2, //Console logging. 1=Minimal Logging, 2=Enhanced Logging, 3=Enhanced Logging and Process Commands, 4=Verbose
+ samba: {
+ manage: false, //Manage Samba shares
+ windowscompatibility: true //Disable special characters in share name that don't work with Microsoft Windows
+ },
+ updates: {
+ check: true //Check for updates on launch
+ },
+ zfs: {
+ filesystem: {
+ cloneorigin: false, //Display clone origin in tooltip
+ quotarestrict: true, //Restrict quota maximum to size of storage pool
+ readonlylockdown: false, //Prevent changes to read only file systems and clone file systems
+ snapshotactions: true, //Display snapshot actions in file system actions menu
+ },
+ snapshot: {
filesystemlist: true //Display snapshots in lists by file system
- },
- status: {
- errorcolors: true, //Display warning and danger colors for error counts
- trimunsupported: false //Display TRIM unsupported message
- },
- storagepool: {
- activetab: 1, //Default active tab for storage pool. 1=File Systems, 2=Snapshots, 3=Status
- boot: true, //Display boot storage pool
- bootlockdown: true, //Prevent changes to boot storage pool. Changes may cause an unbootable system
- count: true, //Display file systems and snapshots count
- refreshall: false, //Refresh all components
- root: true //Display root storage pool
- }
- }
- },
- system: {
- operatingsystem: ""
- },
- user: {
- admin: true,
- configuration: false,
- name: ""
- },
- version: "0.3.0.299",
- zfs: {
- storagepool: {
- boot: "",
- root: "",
- refreshid: []
- },
- warnings: {
+ },
+ status: {
+ errorcolors: true, //Display warning and danger colors for error counts
+ trimunsupported: false //Display TRIM unsupported message
+ },
+ storagepool: {
+ activetab: 1, //Default active tab for storage pool. 1=File Systems, 2=Snapshots, 3=Status
+ boot: true, //Display boot storage pool
+ bootlockdown: true, //Prevent changes to boot storage pool. Changes may cause an unbootable system
+ count: true, //Display file systems and snapshots count
+ refreshall: false, //Refresh all components
+ root: true //Display root storage pool
+ }
+ }
+ },
+ system: {
+ operatingsystem: ""
+ },
+ user: {
+ admin: true,
+ configuration: false,
+ name: ""
+ },
+ version: "0.3.1.301",
+ zfs: {
+ storagepool: {
+ boot: "",
+ root: "",
+ refreshid: []
+ },
+ warnings: {
nvmevdev: false
- },
- version: null
- }
-};
-
-//#endregion
-
-//#region Document Ready
-
-$(document).ready(function () {
- FnConsoleInitialize();
-
- FnConsole.log[1]("Cockpit ZFS Manager, Version: " + zfsmanager.version);
-
- FnConfigurationGet()
- .always(function () {
- Requirements({ zfs: false });
- });
-
- $("body").tooltip({
- html: "true",
- selector: `[data-toggle="tooltip"]`
- });
-
- $(cockpit.info).on("changed", function () {
- zfsmanager.cockpit.legacy = (cockpit.info["version"] < 207 ? true : false);
- });
-});
-
-//#endregion
-
-//#region Requirements
-
-function Requirements(skip = { zfs: false }) {
- if (!skip.zfs) {
- FnZfsVersionGet()
- .done(function () {
- if ($("#alerts-requirements").hasClass("hidden")) {
- if (zfsmanager.configuration.samba.manage) {
- FnSambaVersionGet()
- .done(function () {
- FnFirstSteps();
- });
- } else {
- FnFirstSteps();
- }
- }
- });
- } else {
- if (zfsmanager.configuration.samba.manage) {
- FnSambaVersionGet()
- .done(function () {
- FnFirstSteps();
- });
- } else {
- FnFirstSteps();
- }
- }
-}
-
-//#endregion
-
-//#region First Steps
-
-function FnFirstSteps() {
- FnSystemOperatingSystemGet();
- FnCockpitPermissionsGet();
-
- FnModalsRegister();
- FnStoragePoolsGet();
-
- FnVersionWarning();
- FnZfsVersionWarnings()
-}
-
-function FnFirstStepsPrivileged() {
- //Execute functions when user is an administrator
-
- FnConfigurationDirectoryCreate();
- FnConfigurationDirectoryRuntimeCreate();
-
- if (!zfsmanager.user.configuration) {
- FnConfigurationLegacyGet();
- } else {
- if (zfsmanager.configuration.cockpit.manage) {
- FnCockpitManage();
- }
- if (zfsmanager.configuration.samba.manage) {
- FnSambaManage();
- }
- FnSambaUsersharesDirectoryCreate();
- if (zfsmanager.configuration.updates.check) {
- FnUpdatesCheck({ alert: true });
- }
- }
-}
-
-//#endregion
-
-//#region Fixed Content Click Actions
-
-$(document).on("click", "#btn-alerts-requirements-samba-refresh", function () {
- Requirements({ zfs: true });
-});
-
-$(document).on("click", "#btn-alerts-requirements-zfs-refresh", function () {
- Requirements({ zfs: false });
-});
-
-$(document).on("click", "#btn-storagepools-refresh", function () {
- FnStoragePoolsGet();
-});
-
-$(document).on("click", "#table-storagepools > tbody > tr.listing-ct-item", function (element) {
- if (!$(this).hasClass("listing-ct-storagepoolsnotfound") && !$(element.target).is("a, button, .fa.fa-ellipsis-v, input")) {
- if (!$(this).parent().hasClass("open")) {
- $(this).parent().addClass("open");
-
- $(this).attr("data-pool-refresh-filesystems", "false");
- $(this).attr("data-pool-refresh-snapshots", "false");
- $(this).attr("data-pool-refresh-status", "false");
-
- FnStoragePoolRefresh({ name: $(this).attr("data-pool-name"), id: $(this).attr("data-pool-id") }, { storagepool: true, filesystems: true, snapshots: true, status: true });
- } else {
- if (!$("#spinner-storagepool-" + $(this).attr("data-pool-id")).hasClass("hidden")) {
- //Disable click action while information is still loading
- } else {
- $(this).parent().removeClass("open");
-
- $(this).attr("data-pool-refresh-filesystems", "false");
- $(this).attr("data-pool-refresh-snapshots", "false");
- $(this).attr("data-pool-refresh-status", "false");
-
- $("#spinner-storagepool-" + $(this).attr("data-pool-id")).removeClass("hidden");
- $("#listingcthead-storagepool-" + $(this).attr("data-pool-id")).addClass("hidden");
- $("#listingctbody-storagepool-" + $(this).attr("data-pool-id")).addClass("hidden");
-
- FnStoragePoolRefreshAutoDisable({ name: $(this).attr("data-pool-name"), id: $(this).attr("data-pool-id") });
- }
- }
- }
-});
-
-//#endregion
-
-//#region Helper Functions
-
-String.prototype.format = function () {
- let args = arguments;
-
- return this.replace(/\{(\d+)\}/g, function (m, n) {
- return args[n];
- });
-}
-
-function FnAppendLeadingZeroes(data = { value }) {
- if (data.value < 10) {
- return "0" + data.value;
- }
-
- return data.value;
-}
-
-function FnFormatBytes(data = { base2: true, decimals: 0, value }) {
- if (data.value == 0) {
- return "0 B";
- }
-
- data.bytes = (data.base2 ? 1024 : 1000);
- data.sizes = (data.base2 ? ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"] : ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]);
- data.integer = Math.floor(Math.log(data.value) / Math.log(data.bytes));
- data.decimals = (data.decimals <= 0 ? 0 : data.decimals);
-
- data.sizefriendly = parseFloat((data.value / Math.pow(data.bytes, data.integer)).toFixed(data.decimals)).toString() + " " + data.sizes[data.integer];
-
- if (data.sizefriendly == "NaN undefined") {
- data.sizefriendly = "-";
- }
-
- return data.sizefriendly;
-}
-
-function FnGenerateId(character = { at: false, colon: false, forwardslash: false, period: false, underscore: false, whitespace: false }, data = { name, attribute: true }) {
- let replacement = {
- character: (data.attribute ? "\u22C5" : "_"),
- regexp: []
- };
-
- if (character.underscore) {
- replacement.regexp.push({ pattern: /[_]/g, replacement: (data.attribute ? replacement.character + "u" + replacement.character : replacement.character) })
- }
- if (character.at) {
- replacement.regexp.push({ pattern: /[@]/g, replacement: (data.attribute ? replacement.character + "a" + replacement.character : replacement.character) })
- }
- if (character.colon) {
- replacement.regexp.push({ pattern: /[:]/g, replacement: (data.attribute ? replacement.character + "c" + replacement.character : replacement.character) })
- }
- if (character.forwardslash) {
- replacement.regexp.push({ pattern: /[/]/g, replacement: (data.attribute ? replacement.character + "f" + replacement.character : replacement.character) })
- }
- if (character.period) {
- replacement.regexp.push({ pattern: /[.]/g, replacement: (data.attribute ? replacement.character + "p" + replacement.character : replacement.character) })
- }
- if (character.whitespace) {
- replacement.regexp.push({ pattern: /[ ]/g, replacement: (data.attribute ? replacement.character + "w" + replacement.character : replacement.character) })
- }
-
- return replacement.regexp.reduce((n, r) => n.replace(r.pattern, r.replacement), data.name);
-}
-
-function FnGenerateShareFileName(data = { name }) {
- replacement = {
- character: "_",
- regexp: []
- };
-
- replacement.regexp.push({ pattern: /[/]/g, replacement: replacement.character });
-
- return replacement.regexp.reduce((n, r) => n.replace(r.pattern, r.replacement), data.name);
-}
-
-function FnGenerateShareName(character = { at: false, colon: false, period: false, whitespace: false }, data = { name }) {
- let replacement = {
- character: "_",
- regexp: []
- };
-
- replacement.regexp.push({ pattern: /[/]/g, replacement: replacement.character });
-
- if (character.at) {
- replacement.regexp.push({ pattern: /[@]/g, replacement: replacement.character })
- }
- if (character.colon || zfsmanager.configuration.samba.windowscompatibility) {
- replacement.regexp.push({ pattern: /[:]/g, replacement: replacement.character })
- }
- if (character.period) {
- replacement.regexp.push({ pattern: /[.]/g, replacement: replacement.character })
- } else if (zfsmanager.configuration.samba.windowscompatibility) {
- replacement.regexp.push({ pattern: /[.]$/g, replacement: replacement.character })
- }
- if (character.whitespace) {
- replacement.regexp.push({ pattern: /[ ]/g, replacement: replacement.character })
- }
-
- return replacement.regexp.reduce((n, r) => n.replace(r.pattern, r.replacement), data.name);
-}
-
-function FnRound(data = { decimals: 0, value }) {
- data.multiplier = Math.pow(10, data.decimals);
-
- return Math.round(data.value * data.multiplier) / data.multiplier;
-}
-
-//#endregion
-
-//#region Date/Time
-
-function FnDateTime() {
- return (new Date).toLocaleString(zfsmanager.cockpit.datelocale, { day: "numeric", month: "numeric", year: "numeric", hour: "numeric", minute: "numeric", second: "numeric", hour12: true });
-}
-
-function FnDateTimeEpoch(data = { date }) {
- return (new Date(data.date * 1000)).toLocaleString(zfsmanager.cockpit.datelocale, { hour12: true });
-}
-
-function FnDateTimeSnapshot(data = { date }) {
- if (!data.date) {
- data.date = new Date();
- }
-
- return data.date.getFullYear() + "." + FnAppendLeadingZeroes({ value: data.date.getMonth() + 1 }) + "." + FnAppendLeadingZeroes({ value: data.date.getDate() }) + "-" + FnAppendLeadingZeroes({ value: data.date.getHours() }) + "." + FnAppendLeadingZeroes({ value: data.date.getMinutes() }) + "." + FnAppendLeadingZeroes({ value: data.date.getSeconds() });
-}
-
-//#endregion
-
-//#region Display Alert
-
-function FnDisplayAlert(notification = { status, title, description, breakword: false }, toast = { name, id, timeout: 4 }) {
- if (zfsmanager.cockpit.legacy) { //Dirty way of handling alerts for PF3 and PF4
- FnDisplayAlertLegacy({ status: notification.status, title: notification.title, description: notification.description, breakword: notification.breakword }, { name: toast.name, id: toast.id, timeout: toast.timeout });
-
- return;
- }
-
- toast.timeout = ($.isNumeric(toast.timeout) ? toast.timeout : 4);
- toast.uniqueid = (new Date).getTime() + "-" + Math.round(Math.random() * 20);
-
- switch (notification.status) {
- case "danger":
- toast.icon = "fa fa-exclamation-circle";
- toast.statusaria = "Danger";
- break;
- case "info":
- toast.icon = "fa fa-info-circle";
- toast.statusaria = "Information";
- break;
- case "success":
- toast.icon = "fa fa-check-circle";
- toast.statusaria = "Success";
- break;
- case "warning":
- toast.icon = "fa fa-exclamation-triangle";
- toast.statusaria = "Warning";
- break;
- default:
- notification.status = "";
- toast.icon = "fa fa-bell";
- toast.statusaria = "Default";
- break;
- }
-
- notification.output = `
-
-
-
-
-
-
` + toast.statusaria + ` alert: ` + notification.title + `
- ` + (notification.description ? `
` + notification.description + `
` : ``) + `
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#alert-` + toast.name + (toast.id ? `-` + toast.id : ``) + `-` + toast.uniqueid + ` .pf-c-alert__action").on("click",".pf-c-button",function(){
- $("#alert-` + toast.name + (toast.id ? `-` + toast.id : ``) + `-` + toast.uniqueid + `").fadeTo(150, 0).slideUp(150, function () {
- $(this).remove();
- });
- });
-
- setTimeout(function () {
- $("#alert-` + toast.name + (toast.id ? `-` + toast.id : ``) + `-` + toast.uniqueid + `").fadeTo(500, 0).slideUp(500, function () {
- $(this).remove();
- });
- }, ` + toast.timeout + `000);
- \x3C/script>
-
- `;
-
- $("#alerts-notifications").append(notification.output);
-}
-
-function FnDisplayAlertLegacy(notification = { status, title, description, breakword: false }, toast = { name, id, timeout: 4 }) {
- toast.timeout = ($.isNumeric(toast.timeout) ? toast.timeout : 4);
- toast.uniqueid = (new Date).getTime() + "-" + Math.round(Math.random() * 20);
-
- switch (notification.status) {
- case "danger":
- toast.icon = "pficon pficon-error-circle-o";
- break;
- case "success":
- toast.icon = "pficon pficon-ok";
- break;
- case "warning":
- toast.icon = "pficon pficon-warning-triangle-o";
- break;
- default:
- notification.status = "info";
- toast.icon = "pficon pficon-info";
- break;
- }
-
- notification.output = `
-
-
-
-
-
- ` + notification.title + (notification.description ? `:` : ``) + ` ` + (notification.description ? notification.description : ``) + `
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- setTimeout(function () {
- $("#toast-` + toast.name + (toast.id ? `-` + toast.id : ``) + `-` + toast.uniqueid + `").fadeTo(500, 0).slideUp(500, function () {
- $(this).remove();
- });
- }, ` + toast.timeout + `000);
- \x3C/script>
-
- `;
-
- $("#alerts-notifications-legacy").append(notification.output);
-}
-
-function FnDisplayInlineAlert(notification = { status, title, description }, inline = { name, id, hidden: false }) {
- if (zfsmanager.cockpit.legacy) { //Dirty way of handling alerts for PF3 and PF4
- return FnDisplayInlineAlertLegacy({ status: notification.status, title: notification.title, description: notification.description }, { name: inline.name, id: inline.id, hidden: inline.hidden });
- }
-
- switch (notification.status) {
- case "danger":
- inline.icon = "fa fa-exclamation-circle";
- inline.statusaria = "Danger";
- break;
- case "info":
- inline.icon = "fa fa-info-circle";
- inline.statusaria = "Information";
- break;
- case "success":
- inline.icon = "fa fa-check-circle";
- inline.statusaria = "Success";
- break;
- case "warning":
- inline.icon = "fa fa-exclamation-triangle";
- inline.statusaria = "Warning";
- break;
- default:
- notification.status = "";
- inline.icon = "fa fa-bell";
- inline.statusaria = "Default";
- break;
- }
-
- notification.output = `
-
-
-
-
-
` + inline.statusaria + ` inline alert: ` + notification.title + `
- ` + (notification.description ? `
` + notification.description + `
` : ``) + `
-
- `;
-
- return notification.output;
-}
-
-function FnDisplayInlineAlertLegacy(notification = { status, title, description }, inline = { name, id, hidden: false }) {
- switch (notification.status) {
- case "danger":
- inline.icon = "pficon pficon-error-circle-o";
- break;
- case "success":
- inline.icon = "pficon pficon-ok";
- break;
- case "warning":
- inline.icon = "pficon pficon-warning-triangle-o";
- break;
- default:
- notification.status = "info";
- inline.icon = "pficon pficon-info";
- break;
- }
-
- notification.output = `
- ` + notification.title + (notification.description ? `: ` + notification.description : ``) + `
- `;
-
- return notification.output;
-}
-
-//#endregion
-
-//#region Console Logging
-
-let FnConsole = () => { };
-
-function FnConsoleCommand(process = { command: [] }) {
- return JSON.stringify(process.command.join(" "));
-}
-
-function FnConsoleInitialize() {
- FnConsole = (() => {
- let time = () => { };
-
- time.toString = () => {
- return (new Date).toLocaleString(zfsmanager.cockpit.datelocale, { hour: "numeric", minute: "numeric", second: "numeric", hour12: true }) + ":";
- };
-
- return {
- error: console.error.bind(console, "%s", time),
- log: {
- 1: (zfsmanager.configuration.loglevel >= 1 ? console.log.bind(console, "%s", time) : FnConsoleNull),
- 2: (zfsmanager.configuration.loglevel >= 2 ? console.log.bind(console, "%s", time) : FnConsoleNull),
- 3: (zfsmanager.configuration.loglevel >= 3 ? console.log.bind(console, "%c%s Command: %s", "color: #0066CC", time) : FnConsoleNull),
- 4: (zfsmanager.configuration.loglevel == 4 ? console.log.bind(console, "%c%s %s", "color: #486B00", time) : FnConsoleNull)
- },
- warn: console.warn.bind(console, "%s", time)
- }
- })();
-}
-
-function FnConsoleNull() {
- //Do not display console message
-}
-
-function FnConsoleVerbose(process = { data, message }) {
- return process.message + " Verbose\n" + process.data;
-}
-
-//#endregion
-
-//#region Cockpit ZFS Manager
-
-function FnConfigurationGet() {
- FnConsole.log[2]("Cockpit ZFS Manager, Configuration, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: [`cockpit.file("/etc/cockpit/zfs/config.json").read()`] }));
-
- return cockpit.file("/etc/cockpit/zfs/config.json").read()
- .done(function (user) {
- FnConsole.log[4](FnConsoleVerbose({ data: user, message: "Cockpit ZFS Manager, Configuration, Get:" }));
-
- try {
- user = JSON.parse(user, (key, value) => {
- if (/^#[0-9]/.test(key) == false) {
- return value;
- }
- });
-
- user.cockpit = (user.cockpit === undefined ? zfsmanager.configuration.cockpit : user.cockpit);
- user.cockpit.manage = (user.cockpit.manage === undefined ? zfsmanager.configuration.cockpit.manage : user.cockpit.manage);
-
- user.disks = (user.disks === undefined ? zfsmanager.configuration.disks : user.disks);
- user.disks.base2 = (user.disks.base2 === undefined ? zfsmanager.configuration.disks.base2 : user.disks.base2);
-
- user.loglevel = (user.loglevel === undefined ? zfsmanager.configuration.loglevel : user.loglevel);
-
- user.samba = (user.samba === undefined ? zfsmanager.configuration.samba : user.samba);
- user.samba.manage = (user.samba.manage === undefined ? zfsmanager.configuration.samba.manage : user.samba.manage);
- user.samba.windowscompatibility = (user.samba.windowscompatibility === undefined ? zfsmanager.configuration.samba.windowscompatibility : user.samba.windowscompatibility);
-
- user.updates = (user.updates === undefined ? zfsmanager.configuration.updates : user.updates);
- user.updates.check = (user.updates.check === undefined ? zfsmanager.configuration.updates.check : user.updates.check);
-
- user.zfs = (user.zfs === undefined ? zfsmanager.configuration.zfs : user.zfs);
- user.zfs.filesystem = (user.zfs.filesystem === undefined ? zfsmanager.configuration.zfs.filesystem : user.zfs.filesystem);
- user.zfs.filesystem.snapshotactions = (user.zfs.filesystem.snapshotactions === undefined ? zfsmanager.configuration.zfs.filesystem.snapshotactions : user.zfs.filesystem.snapshotactions);
- user.zfs.filesystem.cloneorigin = (user.zfs.filesystem.cloneorigin === undefined ? zfsmanager.configuration.zfs.filesystem.cloneorigin : user.zfs.filesystem.cloneorigin);
- user.zfs.filesystem.quotarestrict = (user.zfs.filesystem.quotarestrict === undefined ? zfsmanager.configuration.zfs.filesystem.quotarestrict : user.zfs.filesystem.quotarestrict);
- user.zfs.filesystem.readonlylockdown = (user.zfs.filesystem.readonlylockdown === undefined ? zfsmanager.configuration.zfs.filesystem.readonlylockdown : user.zfs.filesystem.readonlylockdown);
- user.zfs.snapshot = (user.zfs.snapshot === undefined ? zfsmanager.configuration.zfs.snapshot : user.zfs.snapshot);
- user.zfs.snapshot.filesystemlist = (user.zfs.snapshot.filesystemlist === undefined ? zfsmanager.configuration.zfs.snapshot.filesystemlist : user.zfs.snapshot.filesystemlist);
- user.zfs.status = (user.zfs.status === undefined ? zfsmanager.configuration.zfs.status : user.zfs.status);
- user.zfs.status.errorcolors = (user.zfs.status.errorcolors === undefined ? zfsmanager.configuration.zfs.status.errorcolors : user.zfs.status.errorcolors);
- user.zfs.status.trimunsupported = (user.zfs.status.trimunsupported === undefined ? zfsmanager.configuration.zfs.status.trimunsupported : user.zfs.status.trimunsupported);
- user.zfs.storagepool = (user.zfs.storagepool === undefined ? zfsmanager.configuration.zfs.storagepool : user.zfs.storagepool);
- user.zfs.storagepool.activetab = (user.zfs.storagepool.activetab === undefined ? zfsmanager.configuration.zfs.storagepool.activetab : user.zfs.storagepool.activetab);
- user.zfs.storagepool.count = (user.zfs.storagepool.count === undefined ? zfsmanager.configuration.zfs.storagepool.count : user.zfs.storagepool.count);
- user.zfs.storagepool.boot = (user.zfs.storagepool.boot === undefined ? zfsmanager.configuration.zfs.storagepool.boot : user.zfs.storagepool.boot);
- user.zfs.storagepool.bootlockdown = (user.zfs.storagepool.bootlockdown === undefined ? zfsmanager.configuration.zfs.storagepool.bootlockdown : user.zfs.storagepool.bootlockdown);
- user.zfs.storagepool.root = (user.zfs.storagepool.root === undefined ? zfsmanager.configuration.zfs.storagepool.root : user.zfs.storagepool.root);
- user.zfs.storagepool.refreshall = (user.zfs.storagepool.refreshall === undefined ? zfsmanager.configuration.zfs.storagepool.refreshall : user.zfs.storagepool.refreshall);
-
- zfsmanager.configuration = user;
- zfsmanager.user.configuration = true;
-
- FnConsole.log[1]("Cockpit ZFS Manager, Configuration, Get: Success");
-
- FnConsoleInitialize();
- }
- catch (error) {
- FnConsole.warn("Cockpit ZFS Manager, Configuration, Get: Failed, Message: Configuration does not exist. Using defaults.");
- };
- })
- .fail(function (message) {
- FnConsole.warn("Cockpit ZFS Manager, Configuration, Get: Failed, Message: Configuration does not exist. Using defaults.");
- });
-};
-
-function FnConfigure(user = { cockpit: { manage: true }, disks: { base2: false }, loglevel: 1, samba: { manage: true, windowscompatibility: true }, updates: { check: true }, zfs: { filesystem: { cloneorigin: false, quotarestrict: true, readonlylockdown: true, snapshotactions: true }, snapshot: { filesystemlist: true }, status: { errorcolors: true, trimunsupported: false }, storagepool: { activetab: 1, boot: true, bootlockdown: true, count: true, refreshall: false, root: true } } }, modal = { name, welcome: false }) {
- let process = {
- command: ["/bin/sh", "-c", "echo '" + JSON.stringify(user, null, " ").replace(/^\{\n/, `{\n "#1": "COCKPIT ZFS MANAGER",\n "#2": "WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION",\n`) + "' > /etc/cockpit/zfs/config.json"]
- };
-
- FnConsole.log[2]("Cockpit ZFS Manager, Configure: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + " span").text("Saving configuration...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (data) {
- FnDisplayAlert({ status: "success", title: "Configuration successfully updated", description: null, breakword: false }, { name: modal.name, id: null, timeout: 4 });
-
- FnConsole.log[1]("Cockpit ZFS Manager, Configure: Success");
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Configuration could not be updated", description: null, breakword: false }, { name: modal.name, id: null, timeout: 4 });
-
- FnConsole.warn("Cockpit ZFS Manager, Configure: Failed, Message: " + (data ? data : message));
- })
- .finally(function () {
- if ((modal.welcome || !modal.welcome && zfsmanager.configuration.samba.manage) && !user.samba.manage) {
- FnSambaSharesDestroyAll({ restart: false }, { silent: true }, { name: modal.name })
- .finally(function () {
- FnConfigureFinally({ name: modal.name, welcome: modal.welcome });
- });
- } else if ((modal.welcome || !modal.welcome && !zfsmanager.configuration.samba.manage) && user.samba.manage) {
- FnSambaSharesEnableAll({ restart: false }, { silent: false }, { name: modal.name })
- .finally(function () {
- FnConfigureFinally({ name: modal.name, welcome: modal.welcome });
- });
- } else {
- FnConfigureFinally({ name: modal.name, welcome: modal.welcome });
- }
- });
-}
-
-function FnConfigureFinally(modal = { name, welcome: false }) {
- $("#spinner-" + modal.name + " span").text("Reloading Cockpit ZFS Manager...");
-
- setTimeout(function () {
- location.reload(true);
- }, 2000);
-}
-
-function FnConfigurationDirectoryCreate() {
- let process = {
- command: ["/bin/sh", "-c", `[ ! -d /etc/cockpit/zfs ] || [ ! -d /etc/cockpit/zfs/shares ] || [ ! -d /etc/cockpit/zfs/snapshots ] && /bin/mkdir -p /etc/cockpit/zfs/shares /etc/cockpit/zfs/snapshots || printf "Skipped"`]
- };
-
- FnConsole.log[2]("Cockpit ZFS Manager, Configuration Directory, Create: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Cockpit ZFS Manager, Configuration Directory, Create:" }));
-
- if (data == "Skipped") {
- FnConsole.log[2]("Cockpit ZFS Manager, Configuration Directory, Create: Skipped");
- } else {
- FnConsole.log[1]("Cockpit ZFS Manager, Configuration Directory, Create: Success");
- }
- })
- .fail(function (message, data) {
- FnConsole.warn("Cockpit ZFS Manager, Configuration Directory, Create: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnConfigurationDirectoryRuntimeCreate() {
- let process = {
- command: ["/bin/sh", "-c", `[ ! -d /run/cockpit/zfs/shares ] && /bin/mkdir -p /run/cockpit/zfs/shares || printf "Skipped"`]
- };
-
- FnConsole.log[2]("Cockpit ZFS Manager, Runtime Configuration Directory, Create: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Cockpit ZFS Manager, Runtime Configuration Directory, Create:" }));
-
- if (data == "Skipped") {
- FnConsole.log[2]("Cockpit ZFS Manager, Runtime Configuration Directory, Create: Skipped");
- } else {
- FnConsole.log[1]("Cockpit ZFS Manager, Runtime Configuration Directory, Create: Success");
- }
- })
- .fail(function (message, data) {
- FnConsole.warn("Cockpit ZFS Manager, Runtime Configuration Directory, Create: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnConfigurationLegacyGet() {
- let process = {
- command: ["/bin/sh", "-c"]
- };
-
- FnCockpitPackagePathGet({ sosreport: false })
- .done(function (data) {
- let path = data.replace(/\s +/g, "\u22C5").replace(/\/$/, "").replace(/\n/, "").split("\u22C5")[2];
-
- if (!path || /\/cockpit\/zfs/.test(path) == false) {
- path = "/usr/share/cockpit/zfs"
- }
-
- process.command.push(`[ -e '` + path + `/config.json' ] && printf "true" || printf "false"`);
-
- FnConsole.log[2]("Cockpit ZFS Manager, Configuration, Legacy, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- cockpit.spawn(process.command, { err: "out" })
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Cockpit ZFS Manager, Configuration, Legacy, Get:" }));
-
- if (_data == "true") {
- FnConsole.log[1]("Cockpit ZFS Manager, Configuration, Legacy, Get: Success");
-
- FnModalUpdateContent({ id: $("#modal-update") });
-
- $("#modal-update").modal("show");
- $("#spinner-update span").text("Relocating configuration file...");
-
- FnConfigurationLegacyRelocate({ path: path })
- .done(function () {
- $("#spinner-update span").text("Reloading Cockpit ZFS Manager...");
-
- setTimeout(function () {
- location.reload(true);
- }, 2000);
- })
- .fail(function () {
- FnModalWelcomeContent({ id: $("#modal-welcome") });
-
- $("#modal-update").modal("hide");
- $("#modal-welcome").modal("show");
- });
- } else {
- FnConsole.log[2]("Cockpit ZFS Manager, Configuration, Legacy, Get: " + (_data == "false" ? "Skipped" : "Failed"));
-
- FnModalWelcomeContent({ id: $("#modal-welcome") });
-
- $("#modal-welcome").modal("show");
- }
- })
- .fail(function (_message, _data) {
- FnConsole.warn("Cockpit ZFS Manager, Configuration, Legacy, Get: Failed, Message: " + (_data ? _data : _message));
-
- FnModalWelcomeContent({ id: $("#modal-welcome") });
-
- $("#modal-welcome").modal("show");
- });
- })
- .fail(function () {
- FnModalWelcomeContent({ id: $("#modal-welcome") });
-
- $("#modal-welcome").modal("show");
- });
-}
-
-function FnConfigurationLegacyRelocate(legacy = { path }) {
- let process = {
- command: ["/bin/sh", "-c", `/bin/mv -f ` + legacy.path + `/config.json /etc/cockpit/zfs/config.json`]
- };
-
- FnConsole.log[2]("Cockpit ZFS Manager, Configuration, Legacy, Relocate: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Cockpit ZFS Manager, Configuration, Legacy, Relocate:" }));
-
- FnConsole.log[1]("Cockpit ZFS Manager, Configuration, Legacy, Relocate: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Cockpit ZFS Manager, Configuration, Legacy, Relocate: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnUpdatesCheck(display = { alert: true }) {
- FnConsole.log[2]("Cockpit ZFS Manager, Updates, Check: In Progress");
-
- $.ajax({ url: "https://api.github.com/repos/optimans/cockpit-zfs-manager/releases", dataType: "json", cache: false })
- .done(function (data) {
- if (data[0].name) {
- if (FnUpdatesVersionCompare({ installed: zfsmanager.version, latest: data[0].name }) < 0) {
- setTimeout(function () {
- $("#alert-about-update").removeClass("hidden");
- $("#span-about-update-version").html(`` + data[0].name + ` ` + (data[0].prerelease === true ? `(Pre-release)` : `(Release)`) + ` `);
-
- if (display.alert) {
- FnDisplayAlert({ status: "info", title: "A new version of Cockpit ZFS Manager is now available", description: ` ` + data[0].name + ` ` + (data[0].prerelease === true ? `(Pre-release)` : `(Release)`) + ` `, breakword: true }, { name: "update", id: null, timeout: 30 });
- }
- }, 500);
- }
-
- FnConsole.log[2]("Cockpit ZFS Manager, Updates, Check: Success");
- } else {
- FnConsole.warn("Cockpit ZFS Manager, Updates, Check: Failed, Message: Unable to retrieve release information.");
- }
- })
- .fail(function (message) {
- FnConsole.warn("Cockpit ZFS Manager, Updates, Check: Failed, Message: " + message);
- });
-}
-
-function FnUpdatesVersionCompare(version = { installed, latest }) {
- version.installed = version.installed.replace(/[^0-9.-]/g, "").replace(/\s+/g, "").replace(/-/g, ".").split(".");
- version.latest = version.latest.replace(/[^0-9.-]/g, "").replace(/\s+/g, "").replace(/-/g, ".").split(".");
-
- let min = Math.min(version.installed.length, version.latest.length);
-
- for (let i = 0; i < min; ++i) {
- version.installed[i] = parseInt(version.installed[i], 10);
- version.latest[i] = parseInt(version.latest[i], 10);
-
- if (version.installed[i] > version.latest[i]) {
- return 1;
- }
- if (version.installed[i] < version.latest[i]) {
- return -1;
- }
- }
-
- return version.installed.length == (version.latest.length ? 0 : (version.installed.length < version.latest.length ? -1 : 1));
-}
-
-function FnVersionWarning() {
- if (/alpha|beta|dev|internal|pre|rc/gi.test(zfsmanager.version)) {
- FnDisplayAlert({ status: "warning", title: "Pre-release version of Cockpit ZFS Manager is installed", description: zfsmanager.version + ` is an unstable build and features may not work as intended`, breakword: true }, { name: "version-warning", id: null, timeout: 60 });
+ },
+ version: null
}
-}
-
-//#endregion
-
-//#region Cockpit
-
-function FnCockpitElementsDisable() {
- let message = `The user ` + zfsmanager.user.name + ` is not permitted to`;
-
- //Disable buttons
- $("#btn-configure").addClass("disabled");
- $("#btn-storagepools-filesystems-unlock").addClass("disabled");
- $("#btn-storagepools-create").prop("title", message + " create a storage pool").attr("data-placement", "auto bottom").attr("data-toggle", "tooltip").addClass("disabled");
- $("#btn-storagepools-import").prop("title", message + " import a storage pool").attr("data-placement", "auto bottom").attr("data-toggle", "tooltip").addClass("disabled");
- $("[id^=btn-storagepool-filesystems-create-]").prop("title", message + " create a file system").attr("data-placement", "auto top").attr("data-toggle", "tooltip").addClass("disabled");
- $("[id^=btn-storagepool-snapshots-create-]").prop("title", message + " create a snapshot").attr("data-placement", "auto top").attr("data-toggle", "tooltip").addClass("disabled");
- $("[id^=btn-storagepool-snapshot-dropdown-]").prop("title", message + " manage this snapshot").attr("data-placement", "auto left").attr("data-toggle", "tooltip").addClass("disabled");
- $("[id^=btn-storagepool-status-dropdown-]").prop("title", message + " manage this storage pool").attr("data-placement", "auto left").attr("data-toggle", "tooltip").addClass("disabled");
-
- //Disable privileged items
- $(".privileged").addClass("disabled");
-
- //Disable privileged modal items
- $(".privileged-modal").prop("disabled", true);
- $(".privileged-modal button").prop("disabled", true);
- $(".privileged-modal input").prop("disabled", true);
-
- //Disable sliders
- $("#validationwrapper-storagepools-create-refreservation .slider-pf .slider *").addClass("disabled");
- $("#slider-storagepools-create-refreservation").slider("disable");
- $("[id^=validationwrapper-storagepool-filesystems-create-quota-] .slider-pf .slider *").addClass("disabled");
- $("[id^=slider-storagepool-filesystems-create-quota-]").slider("disable");
- $("[id^=validationwrapper-storagepool-filesystem-configure-quota-] .slider-pf .slider *").addClass("disabled");
- $("[id^=slider-storagepool-filesystem-configure-quota-]").slider("disable");
- $("[id^=validationwrapper-storagepool-filesystem-configure-refreservation-] .slider-pf .slider *").addClass("disabled");
- $("[id^=slider-storagepool-filesystem-configure-refreservation-]").slider("disable");
-
- //Remove primary color from unlock file system menu item
- $("[id^=btn-storagepool-filesystem-unlock-] > strong").removeClass("text-ct-locked");
- $("[id^=btn-storagepool-filesystem-unlock-icon-]").removeClass("pficon-ct-locked");
-}
-
-function FnCockpitElementsUpdate() {
- if (!zfsmanager.user.admin) {
- FnCockpitElementsDisable();
- }
-}
-
-function FnCockpitManage() {
- if (zfsmanager.user.admin) {
- FnCockpitPackageSosReportDelete(); //SOS Report package will cause ZFS storage drives to appear offline when performing a diagnostic report
- }
-}
-
-function FnCockpitPackagePathGet(package = { sosreport: false }) {
- let process = {
- command: ["/bin/sh", "-c", `cockpit-bridge --packages | /bin/grep -m1 '/cockpit/` + (package.sosreport ? `sosreport` : `zfs`) + `$' || printf "false"`] //printf fix for Debian
- };
-
- FnConsole.log[2]("Cockpit, " + (package.sosreport ? "SOS Report" : "Cockpit ZFS Manager") + " Package Path, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Cockpit, " + (package.sosreport ? "SOS Report" : "Cockpit ZFS Manager") + " Package Path, Get:" }));
-
- let path = data.replace(/\s +/g, "\u22C5").replace(/\/$/, "").replace(/\n/, "").split("\u22C5")[2];
-
- FnConsole.log[1]("Cockpit, " + (package.sosreport ? "SOS Report" : "Cockpit ZFS Manager") + " Package Path, Get: " + (path ? "Success" : "Failed"));
- })
- .fail(function (message, data) {
- FnConsole.warn("Cockpit, " + (package.sosreport ? "SOS Report" : "Cockpit ZFS Manager") + " Package Path, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnCockpitPackageSosReportDelete() {
- let process = {
- command: ["/bin/sh", "-c"]
- };
-
- FnCockpitPackagePathGet({ sosreport: true })
- .done(function (data) {
- let path = data.replace(/\s +/g, "\u22C5").replace(/\/$/, "").replace(/\n/, "").split("\u22C5")[2];
-
- if (!path || /\/cockpit\/sosreport$/.test(path) == false) {
- path = "/usr/share/cockpit/sosreport"
- }
-
- process.command.push(`[ -e '` + path + `' ] && /bin/rm -rf ` + path + ` || printf "Skipped"`);
-
- FnConsole.log[2]("Cockpit, Package, SOS Report, Delete: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Cockpit, Package, SOS Report, Delete:" }));
-
- if (_data == "Skipped") {
- FnConsole.log[2]("Cockpit, Package, SOS Report, Delete: Skipped");
- } else {
- FnConsole.log[1]("Cockpit, Package, SOS Report, Delete: Success");
- }
- })
- .fail(function (_message, _data) {
- FnConsole.warn("Cockpit, Package, SOS Report, Delete: Failed, Message: " + (_data ? _data : _message));
- });
- });
-}
-
-function FnCockpitPermissionsGet() {
- FnConsole.log[2]("Cockpit, Permissions, Get: In Progress");
-
- zfsmanager.cockpit.permission = cockpit.permission({ admin: true });
-
- $(zfsmanager.cockpit.permission).on("changed", function () {
- zfsmanager.user.admin = zfsmanager.cockpit.permission.allowed;
- zfsmanager.user.name = (zfsmanager.cockpit.permission.user ? zfsmanager.cockpit.permission.user.name : "");
-
- if (zfsmanager.user.admin) {
- FnConsole.log[2]("Cockpit, Permissions, Get: Success");
-
- FnFirstStepsPrivileged();
- } else {
- FnConsole.warn("Cockpit, Permissions, Get: Warning, Message: " + zfsmanager.user.name + " does not have administrator permissions");
-
- FnCockpitElementsDisable();
- }
- });
-}
-
-//#endregion
-
-//#region ZFS
-
-function FnZfsVersionCompare(version = { installed, threshold }) {
- version.installed = version.installed.replace(/[^0-9.-]/g, "").replace(/\s+/g, "").replace(/-/g, ".").split(".");
- version.threshold = version.threshold.replace(/\s+/g, "").replace(/-/g, ".").split(".");
-
- if (!version.installed[0]) {
- return -1;
- }
-
- let min = Math.min(version.installed.length, version.threshold.length);
-
- for (let i = 0; i < min; ++i) {
- version.installed[i] = parseInt(version.installed[i], 10);
- version.threshold[i] = parseInt(version.threshold[i], 10);
-
- if (version.installed[i] > version.threshold[i]) {
- return 1;
- }
- if (version.installed[i] < version.threshold[i]) {
- return -1;
- }
- }
-
- return version.installed.length == (version.threshold.length ? 0 : (version.installed.length < version.threshold.length ? -1 : 1));
-}
-
-function FnZfsVersionGet() {
- let process = {
- command: ["/bin/cat", "/sys/module/zfs/version"]
- };
- let zfs = {
- success: false,
- threshold: "0.8"
- };
-
- FnConsole.log[2]("ZFS, Version, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "ZFS, Version, Get:" }));
-
- if (data) {
- zfsmanager.zfs.version = data.replace(/\s+/g, "");
- }
-
- if (!data || FnZfsVersionCompare({ installed: zfsmanager.zfs.version, threshold: zfs.threshold }) < 0) {
- FnConsole.error("ZFS, Version, Get: Failed, Message: Version " + (zfsmanager.zfs.version ? zfsmanager.zfs.version : "0") + " < " + zfs.threshold);
- } else {
- zfs.success = true;
-
- FnConsole.log[1]("ZFS, Version, Get: Success, Version: " + (data ? data : message));
- }
- })
- .fail(function (message, data) {
- FnConsole.error("ZFS, Version, Get: Failed, Message: " + (data ? data : message));
- })
- .finally(function () {
- if (!zfs.success) {
- zfs.message = `
-
-
-
- This package requires ZFS version ` + zfs.threshold + ` or later
- If ZFS is installed, check the module is loaded into the kernel.
-
- Refresh
-
- `;
-
- $("#alerts-requirements").removeClass("hidden").html(zfs.message);
- $("#container").addClass("hidden");
- } else {
- if (!zfsmanager.configuration.samba.manage) {
- $("#alerts-requirements").empty().addClass("hidden");
- $("#container").removeClass("hidden");
- }
- }
- });
-}
-
-function FnZfsVersionWarnings() {
- zfsmanager.zfs.warnings.nvmevdev = (FnZfsVersionCompare({ installed: zfsmanager.zfs.version, threshold: "0.8.3" }) < 0 ? true : false); //GitHub Issue #9730
-}
-
-//#endregion
-
-//#region Storage Pools
-
-function FnStoragePoolsGet() {
- let process = {
- command: ["/sbin/zpool", "list", "-H", "-o", "name,guid,health,size,alloc,free,fragmentation,readonly,altroot,autotrim,version,feature@allocation_classes,feature@async_destroy,feature@bookmark_v2,feature@bookmarks,feature@device_removal,feature@edonr,feature@embedded_data,feature@empty_bpobj,feature@enabled_txg,feature@encryption,feature@extensible_dataset,feature@filesystem_limits,feature@hole_birth,feature@large_blocks,feature@large_dnode,feature@lz4_compress,feature@multi_vdev_crash_dump,feature@obsolete_counts,feature@project_quota,feature@resilver_defer,feature@sha512,feature@skein,feature@spacemap_histogram,feature@spacemap_v2,feature@userobj_accounting,feature@zpool_checkpoint", "-p"]
- };
- let pools = {
- empty: true
- };
-
- //Disable storage pool status auto refresh
- zfsmanager.zfs.storagepool.refreshid.forEach((_value, _index) => {
- clearInterval(_value);
- });
- zfsmanager.zfs.storagepool.refreshid = [];
-
- $("#btn-storagepools-refresh").prop("disabled", true);
- $("#table-storagepools > tbody").remove();
- $("[id^=modals-storagepool-]").remove();
- $("[id^=dynamics-storagepool-]").remove();
- $("#spinner-storagepools").removeClass("hidden");
-
- FnConsole.log[2]("Storage Pools, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- FnStoragePoolsSystemReservedGet()
- .finally(function () {
- cockpit.spawn(process.command, { err: "out" })
- .done((data, message) => {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Get:" }));
-
- if (data) {
- pools.empty = false;
-
- FnStoragePoolsGetCommand({ data: data, message: message });
- }
-
- FnConsole.log[1]("Storage Pools, Get: Success");
- })
- .fail((message, data) => {
- FnConsole.warn("Storage Pools, Get: Failed, Message: " + (data ? data : message));
- })
- .finally(function () {
- if ($("#table-storagepools > tbody").length == 0) {
- pools.empty = true;
- }
-
- if (pools.empty) {
- $("#table-storagepools").append(`No storage pools found. `);
- }
-
- setTimeout(function () {
- $("#spinner-storagepools").addClass("hidden");
- $("#table-storagepools > tbody").removeClass("hidden");
- }, 200);
-
- $("#btn-storagepools-refresh").prop("disabled", false);
-
- FnCockpitElementsUpdate();
- });
- });
-}
-
-function FnStoragePoolsGetCommand(process = { data, message }) {
- let pools = {
- id: []
- };
-
- pools.id = process.data.split(/\n/g).filter(v => {
- if (!zfsmanager.configuration.zfs.storagepool.boot && zfsmanager.zfs.storagepool.boot && new RegExp("^" + zfsmanager.zfs.storagepool.boot + "\t").test(v)) {
- //Do not display boot
- } else if (!zfsmanager.configuration.zfs.storagepool.root && zfsmanager.zfs.storagepool.root && new RegExp("^" + zfsmanager.zfs.storagepool.root + "\t").test(v)) {
- //Do not display root
- } else {
- return v;
- }
- });
-
- pools.id.forEach((_value, _index) => {
- let pool = {
- properties: _value.split(/\t/g).filter(v => v),
- actionsmenu: {
- register: {}
- }
- };
-
- //0=name, 1=guid, 2=health, 3=size, 4=alloc, 5=free, 6=fragmentation, 7=readonly, 8=altroot, 9=autotrim, 10=version, 11=feature@allocation_classes, 12=feature@async_destroy, 13=feature@bookmark_v2, 14=feature@bookmarks, 15=feature@device_removal, 16=feature@edonr, 17=feature@embedded_data, 18=feature@empty_bpobj, 19=feature@enabled_txg, 20=feature@encryption, 21=feature@extensible_dataset, 22=feature@filesystem_limits, 23=feature@hole_birth, 24=feature@large_blocks, 25=feature@large_dnode, 26=feature@lz4_compress, 27=feature@multi_vdev_crash_dump, 28=feature@obsolete_counts, 29=feature@project_quota, 30=feature@resilver_defer, 31=feature@sha512, 32=feature@skein, 33=feature@spacemap_histogram, 34=feature@spacemap_v2, 35=feature@userobj_accounting, 36=feature@zpool_checkpoint
-
- pool.activetab = "filesystems";
- pool.allocated = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[4] });
- pool.allocatedpercent = FnRound({ decimals: 2, value: (pool.properties[4] / pool.properties[3]) * 100 });
- pool.altroot = (pool.properties[8] && pool.properties[8] != "-" ? true : false);
- pool.autotrim = (pool.properties[9].toLowerCase() == "on" ? true : false);
- pool.boot = (zfsmanager.zfs.storagepool.boot && pool.properties[0] == zfsmanager.zfs.storagepool.boot ? true : false);
- pool.feature = {
- allocation_classes: (/active|enabled/gi.test(pool.properties[11]) ? true : false),
- async_destroy: (/active|enabled/gi.test(pool.properties[12]) ? true : false),
- bookmark_v2: (/active|enabled/gi.test(pool.properties[13]) ? true : false),
- bookmarks: (/active|enabled/gi.test(pool.properties[14]) ? true : false),
- device_removal: (/active|enabled/gi.test(pool.properties[15]) ? true : false),
- edonr: (/active|enabled/gi.test(pool.properties[16]) ? true : false),
- embedded_data: (/active|enabled/gi.test(pool.properties[17]) ? true : false),
- empty_bpobj: (/active|enabled/gi.test(pool.properties[18]) ? true : false),
- enabled_txg: (/active|enabled/gi.test(pool.properties[19]) ? true : false),
- encryption: (/active|enabled/gi.test(pool.properties[20]) ? true : false),
- extensible_dataset: (/active|enabled/gi.test(pool.properties[21]) ? true : false),
- filesystem_limits: (/active|enabled/gi.test(pool.properties[22]) ? true : false),
- hole_birth: (/active|enabled/gi.test(pool.properties[23]) ? true : false),
- large_blocks: (/active|enabled/gi.test(pool.properties[24]) ? true : false),
- large_dnode: (/active|enabled/gi.test(pool.properties[25]) ? true : false),
- lz4_compress: (/active|enabled/gi.test(pool.properties[26]) ? true : false),
- multi_vdev_crash_dump: (/active|enabled/gi.test(pool.properties[27]) ? true : false),
- obsolete_counts: (/active|enabled/gi.test(pool.properties[28]) ? true : false),
- project_quota: (/active|enabled/gi.test(pool.properties[29]) ? true : false),
- resilver_defer: (/active|enabled/gi.test(pool.properties[30]) ? true : false),
- sha512: (/active|enabled/gi.test(pool.properties[31]) ? true : false),
- skein: (/active|enabled/gi.test(pool.properties[32]) ? true : false),
- spacemap_histogram: (/active|enabled/gi.test(pool.properties[33]) ? true : false),
- spacemap_v2: (/active|enabled/gi.test(pool.properties[34]) ? true : false),
- userobj_accounting: (/active|enabled/gi.test(pool.properties[35]) ? true : false),
- zpool_checkpoint: (/active|enabled/gi.test(pool.properties[36]) ? true : false)
- };
- pool.fragmentation = (pool.properties[6] == "-" ? 0 : pool.properties[6]);
- pool.free = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[5] });
- pool.freepercent = FnRound({ decimals: 2, value: (pool.properties[5] / pool.properties[3]) * 100 });
- pool.guid = pool.properties[1];
- pool.health = pool.properties[2];
- pool.healthicon = FnStoragePoolHealthIcon({ health: pool.properties[2] });
- pool.id = FnGenerateId({ at: false, colon: true, forwardslash: false, period: true, underscore: true, whitespace: true }, { name: pool.properties[0], attribute: true });
- pool.name = pool.properties[0];
- pool.readonly = ((pool.properties[7].toLowerCase() == "on" || pool.boot && zfsmanager.configuration.zfs.storagepool.bootlockdown) ? true : false);
- pool.size = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[3] });
- pool.root = (zfsmanager.zfs.storagepool.root && pool.properties[0] == zfsmanager.zfs.storagepool.root ? true : false);
- pool.upgrade = ($.isNumeric(pool.properties[8] && !pool.boot) ? true : false);
- pool.version = pool.properties[10];
-
- //Upgrade available if a requested feature flag returns false
- if (!pool.boot) {
- for (var x in pool.feature) {
- if (!pool.feature[x] && !pool.upgrade) {
- pool.upgrade = true;
- }
- }
- }
-
- $("#modals-storagepool-" + pool.id).remove();
- $("#modals").append(`
`);
-
- pool.output = `
-
-
-
- Name: ` + pool.name + (pool.readonly ? ` ` : (pool.altroot ? ` ` : ``)) + `
-
- Health: ` + pool.health + `
-
-
- Size: ` + pool.size + `
-
-
- Allocated: ` + pool.allocated + `
-
-
- Free: ` + pool.free + `
-
-
- Fragmentation: ` + pool.fragmentation + ` %
-
-
- Usage:
-
-
- ` + pool.allocatedpercent + `% Allocated
-
-
- ` + pool.freepercent + `% Free
-
-
-
-
- Upgrade Available:
- ` + (pool.upgrade ? `Yes` : `No`) + `
-
-
- `;
-
- //Actions menu
- pool.actionsmenu.items = {
- itemconfigure: [],
- itemconfiguredivider: function () {
- if (this.itemconfigure.length > 0 && (this.itemconfigurefeatures.length > 0 || this.item.length > 0)) {
- this.itemconfigure.push(this.divider);
- }
- },
- itemconfigurefeatures: [],
- itemconfigurefeaturesdivider: function () {
- if (this.itemconfigurefeatures.length > 0 && this.item.length > 0) {
- this.itemconfigurefeatures.push(this.divider);
- }
- },
- item: [],
- divider: ` `
- };
- pool.actionsmenu.display = function () {
- if ((this.items.itemconfigure.length + this.items.itemconfigurefeatures.length + this.items.item.length) > 0) {
- this.items.itemconfiguredivider();
- this.items.itemconfigurefeaturesdivider();
-
- return this.header + this.items.itemconfigure.join("\n") + this.items.itemconfigurefeatures.join("\n") + this.items.item.join("\n") + this.footer;
- } else {
- return "";
- }
- };
- pool.actionsmenu.header = `
-
-
-
-
-
-
- `;
-
- //Configure Storage Pool
- pool.actionsmenu.items.itemconfigure.push(`Configure Storage Pool `);
-
- //Configure Storage Pool Features
- pool.actionsmenu.items.itemconfigurefeatures.push(`Configure Storage Pool Features `);
-
- //Export Storage Pool
- if (!pool.boot && !pool.root) {
- pool.actionsmenu.items.item.push(`Export Storage Pool `);
-
- pool.actionsmenu.register.export = true;
- }
-
- //Destroy Storage Pool
- if (!pool.readonly && !pool.boot && !pool.root) {
- pool.actionsmenu.items.item.push(`Destroy Storage Pool `);
-
- pool.actionsmenu.register.destroy = true;
- }
-
- pool.output += ``;
-
- if (zfsmanager.configuration.zfs.storagepool.activetab == 2) {
- pool.activetab = "snapshots";
- } else if (zfsmanager.configuration.zfs.storagepool.activetab == 3) {
- pool.activetab = "status";
- }
-
- pool.output += `
-
-
-
-
-
-
-
-
-
-
-
- Create File System
- Refresh
-
-
-
-
-
- Name
- Available
- Used
- Snapshots
- Refreservation
- Record Size
- Compression
- Deduplication
- Share
- Mounted
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Create Snapshot
- Refresh
-
-
-
- ` + (zfsmanager.configuration.zfs.snapshot.filesystemlist ? `
` : ``) + `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- //Set active tab
- $("#tab-storagepool-` + pool.activetab + `-` + pool.id + `").tab("show");
-
- $("#btn-storagepool-filesystems-refresh-` + pool.id + `").on("click", function () {
- $("#btn-storagepool-filesystems-create-` + pool.id + `").prop("disabled", true);
- $("#btn-storagepool-filesystems-refresh-` + pool.id + `").prop("disabled", true);
-
- $("[id^=btn-storagepool-filesystem-dropdown-` + pool.id + `]").addClass("disabled");
- $("#paneltitle-storagepool-filesystems-` + pool.id + `").addClass("hidden");
- $("#spinner-storagepool-filesystems-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolRefresh({ name: "` + pool.name + `", id: "` + pool.id + `" }, { storagepool: true, filesystems: true, snapshots: false, status: false });
- });
-
- $("#btn-storagepool-snapshots-refresh-` + pool.id + `").on("click", function () {
- $("#btn-storagepool-snapshots-create-` + pool.id + `").prop("disabled", true);
- $("#btn-storagepool-snapshots-refresh-` + pool.id + `").prop("disabled", true);
-
- $("[id^=btn-storagepool-snapshot-dropdown-` + pool.id + `]").addClass("disabled");
- $("#paneltitle-storagepool-snapshots-` + pool.id + `").addClass("hidden");
- $("#spinner-storagepool-snapshots-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolRefresh({ name: "` + pool.name + `", id: "` + pool.id + `" }, { storagepool: true, filesystems: false, snapshots: true, status: false });
- });
-
- $("#btn-storagepool-status-refresh-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
-
- $(this).text("Refresh").prop("disabled", true);
- $("#btn-storagepool-status-refresh-auto-` + pool.id + `").prop("disabled", true).parent().removeClass("open");;
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#paneltitle-storagepool-status-` + pool.id + `").addClass("hidden");
- $("#spinner-storagepool-status-` + pool.id + `").removeClass("hidden");
- $("#spinner-storagepool-status-0-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolRefresh({ name: "` + pool.name + `", id: "` + pool.id + `" }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- });
-
- $("#dropdown-storagepool-status-refresh-` + pool.id + `").on("click", "li a", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- $("#btn-storagepool-status-refresh-` + pool.id + `").click();
-
- if ($(this).attr("data-pool-refresh-interval") > 0) {
- let statusrefreshtimer` + _index + ` = setInterval(function () {
- $("#btn-storagepool-status-refresh-` + pool.id + `").prop("disabled", true);
- $("#btn-storagepool-status-refresh-auto-` + pool.id + `").prop("disabled", true).parent().removeClass("open");
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#paneltitle-storagepool-status-` + pool.id + `").addClass("hidden");
- $("#spinner-storagepool-status-` + pool.id + `").removeClass("hidden");
- $("#spinner-storagepool-status-0-` + pool.id + `").removeClass("hidden");
-
- setTimeout(function() {
- FnStoragePoolRefresh({ name: "` + pool.name + `", id: "` + pool.id + `" }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- }, ($(this).attr("data-pool-refresh-interval") + "000"));
-
- zfsmanager.zfs.storagepool.refreshid.push(statusrefreshtimer` + _index + `);
-
- $("#tr-storagepool-` + pool.id + `").attr("data-pool-refresh-id", statusrefreshtimer` + _index + `);
- $("#btn-storagepool-status-refresh-` + pool.id + `").text("Refresh: " + $(this).attr("data-pool-refresh-interval") + "s");
-
- FnConsole.log[2]("Storage Pools, Refresh, Auto: Enabled, Pool: ` + pool.name + `");
- }
- });
- \x3C/script>
-
- `;
-
- $("#table-storagepools").append(pool.output);
-
- $("#progressbar-storagepool-allocated-" + pool.id).css("width", pool.allocatedpercent + "%");
- $("#progressbar-storagepool-free-" + pool.id).css("width", pool.freepercent + "%");
-
- //Register storage pool modals
- FnModalStoragePoolConfigure({ name: pool.name, id: pool.id, boot: pool.boot, guid: pool.guid, readonly: false, root: pool.root });
- FnModalStoragePoolConfigureFeatures({ name: pool.name, id: pool.id, boot: pool.boot, readonly: false });
- if (pool.actionsmenu.register.destroy) {
- FnModalStoragePoolDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot });
- }
- if (pool.actionsmenu.register.export) {
- FnModalStoragePoolExport({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly });
- }
- });
-
- $("#btn-storagepools-refresh").prop("disabled", false);
-
- FnCockpitElementsUpdate();
-}
-
-function FnStoragePoolsImportableBlockDeviceGet(pools = { destroyed: false }) {
- let process = {
- command: ["/bin/sh", "-c", "/sbin/zpool import -d /dev" + (pools.destroyed ? " -D" : "") + " 2> /dev/null | /bin/grep -E 'pool:\| id:\|state:' | tr '\\\n' ','"]
- };
-
- FnConsole.log[2]("Storage Pools, Importable, Block Device, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Storage Pools, Importable, Block Device, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Importable, Block Device, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolsImportableDiskGet(pools = { destroyed: false }) {
- let process = {
- command: ["/bin/sh", "-c", "/sbin/zpool import -d /dev/disk/by-id" + (pools.destroyed ? " -D" : "") + " 2> /dev/null | /bin/grep -E 'pool:\| id:\|state:' | tr '\\\n' ','"]
- };
-
- FnConsole.log[2]("Storage Pools, Importable, Disk / WWN, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Storage Pools, Importable, Disk / WWN, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Importable, Disk / WWN, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolsImportableGet(pools = { destroyed: false }) {
- let replacement = {
- regexp: [
- { pattern: /^(?: )+pool\:/gi, replacement: "pool\:" },
- { pattern: /,(?: )+pool\:/gi, replacement: "\npool\:" },
- { pattern: /,$/g, replacement: "" },
- { pattern: /pool\: /gi, replacement: "" },
- { pattern: /id\: /gi, replacement: "" },
- { pattern: /state\: /gi, replacement: "" },
- { pattern: /,(?: )+/g, replacement: "," }
- ]
- };
-
- pools.importable = {
- blockdevice: [],
- disk: [],
- path: [],
- vdev: []
- };
-
- $("#listgroup-storagepools-import-storagepools").empty().append(`
`);
-
- FnConsole.log[2]("Storage Pools, Importable, Get: In Progress");
-
- FnStoragePoolsImportableDiskGet({ destroyed: pools.destroyed })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Importable, Disk / WWN, Get:" }));
-
- if (/no pools available to import/gi.test(data) == false) {
- pools.importable.disk = replacement.regexp.reduce((d, r) => d.replace(r.pattern, r.replacement), data).split(/\n/g).filter(v => v);
- }
-
- FnStoragePoolsImportableHardwarePathGet({ destroyed: pools.destroyed })
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Storage Pools, Importable, Hardware Path, Get:" }));
-
- if (/no pools available to import/gi.test(_data) == false) {
- pools.importable.path = replacement.regexp.reduce((d, r) => d.replace(r.pattern, r.replacement), _data).split(/\n/g).filter(v => v);
- }
-
- FnStoragePoolsImportableVirtualDeviceMappingGet({ destroyed: pools.destroyed })
- .done(function (__data) {
- FnConsole.log[4](FnConsoleVerbose({ data: __data, message: "Storage Pools, Importable, Virtual Device Mapping, Get:" }));
-
- if (/no pools available to import/gi.test(__data) == false) {
- pools.importable.vdev = replacement.regexp.reduce((d, r) => d.replace(r.pattern, r.replacement), __data).split(/\n/g).filter(v => v);
- }
-
- FnStoragePoolsImportableBlockDeviceGet({ destroyed: pools.destroyed })
- .done(function (___data) {
- FnConsole.log[4](FnConsoleVerbose({ data: ___data, message: "Storage Pools, Importable, Block Device, Get:" }));
-
- if (/no pools available to import/gi.test(___data) == false) {
- pools.importable.blockdevice = replacement.regexp.reduce((d, r) => d.replace(r.pattern, r.replacement), ___data).split(/\n/g).filter(v => v);
-
- pools.importable.blockdevice.sort().forEach((_value, _index) => {
- let pool = {
- healthstatus: "",
- properties: [],
- id: {
- blockdevice: true,
- disk: false,
- path: false,
- vdev: false,
- },
- idtext: ["Block Device"]
- };
-
- pool.properties = _value.split(/,/g).filter(v => v);
- pool.name = pool.properties[0].trim();
- pool.guid = pool.properties[1].trim();
- pool.health = pool.properties[2].trim();
-
- pools.importable.disk.filter(v => { if (v.match(pool.name) && !pool.id.disk) { pool.id.disk = true; pool.idtext.push("Disk / WWN"); } });
- pools.importable.path.filter(v => { if (v.match(pool.name) && !pool.id.path) { pool.id.path = true; pool.idtext.push("Hardware Path"); } });
- pools.importable.vdev.filter(v => { if (v.match(pool.name) && !pool.id.vdev) { pool.id.vdev = true; pool.idtext.push("Virtual Device Mapping"); } });
-
-
- if (/ONLINE/g.test(pool.health) == false) {
- pool.healthstatus = ` `;
-
- $("#helpblock-storagepools-import-storagepools-warning").html("One or more storage pools are in an unhealthy state." + pool.healthstatus);
- }
-
- pool.output = `
-
-
-
-
- ` + pool.name + `
- GUID: ` + pool.guid + `
- Disk Identifiers: ` + pool.idtext.join(", ") + `
-
- ` + pool.health.replace(/\(DESTROYED\)/i, "") + ` ` + pool.healthstatus + `
-
-
- `;
-
- $("#listgroup-storagepools-import-storagepools").append(pool.output);
- });
- }
-
- setTimeout(function () {
- $("#spinner-storagepools-import-storagepools").remove();
- $("#listgroup-storagepools-import-storagepools > li").removeClass("hidden");
- if ($("#helpblock-storagepools-import-storagepools-warning").text()) {
- $("#helpblock-storagepools-import-storagepools-warning").removeClass("hidden");
- }
-
- if ($("#listgroup-storagepools-import-storagepools > li").length == 0) {
- pools.output = `
-
-
- No ` + (pools.destroyed ? "destroyed" : "importable") + ` storage pools found.
-
-
- `;
-
- $("#listgroup-storagepools-import-storagepools").append(pools.output);
- }
- }, 200);
-
- FnConsole.log[1]("Storage Pools, Importable, Get: Success");
- })
- .fail(function (___message, ___data) {
- if (/no pools available to import/gi.test(___data) == false) {
- FnConsole.warn("Storage Pools, Importable, Get: Failed, Message: " + (___data ? ___data : ___message));
- }
-
- FnStoragePoolsImportableGetFail({ destroyed: pools.destroyed });
- });
- })
- .fail(function (__message, __data) {
- if (/no pools available to import/gi.test(__data) == false) {
- FnConsole.warn("Storage Pools, Importable, Get: Failed, Message: " + (__data ? __data : __message));
- }
-
- FnStoragePoolsImportableGetFail({ destroyed: pools.destroyed });
- });
- })
- .fail(function (_message, _data) {
- if (/no pools available to import/gi.test(_data) == false) {
- FnConsole.warn("Storage Pools, Importable, Get: Failed, Message: " + (_data ? _data : _message));
- }
-
- FnStoragePoolsImportableGetFail({ destroyed: pools.destroyed });
- });
- })
- .fail(function (message, data) {
- if (/no pools available to import/gi.test(data) == false) {
- FnConsole.warn("Storage Pools, Importable, Get: Failed, Message: " + (data ? data : message));
- }
-
- FnStoragePoolsImportableGetFail({ destroyed: pools.destroyed });
- });
-}
-
-function FnStoragePoolsImportableGetFail(pools = { destroyed: false }) {
- setTimeout(function () {
- $("#spinner-storagepools-import-storagepools").remove();
- $("#listgroup-storagepools-import-storagepools > li").removeClass("hidden");
-
- if ($("#listgroup-storagepools-import-storagepools > li").length == 0) {
- pools.output = `
-
-
- No ` + (pools.destroyed ? "destroyed" : "importable") + ` storage pools found.
-
-
- `;
-
- $("#listgroup-storagepools-import-storagepools").append(pools.output);
- }
- }, 200);
-}
-
-function FnStoragePoolsImportableHardwarePathGet(pools = { destroyed: false }) {
- let process = {
- command: ["/bin/sh", "-c", "/sbin/zpool import -d /dev/disk/by-path" + (pools.destroyed ? " -D" : "") + " 2> /dev/null | /bin/grep -E 'pool:\| id:\|state:' | tr '\\\n' ','"]
- };
-
- FnConsole.log[2]("Storage Pools, Importable, Hardware Path, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Storage Pools, Importable, Hardware Path, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Importable, Hardware Path, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolsImportableVirtualDeviceMappingGet(pools = { destroyed: false }) {
- let process = {
- command: ["/bin/sh", "-c", "/sbin/zpool import -d /dev/disk/by-vdev" + (pools.destroyed ? " -D" : "") + " 2> /dev/null | /bin/grep -E 'pool:\| id:\|state:' | tr '\\\n' ','"]
- };
-
- FnConsole.log[2]("Storage Pools, Importable, Virtual Device Mapping, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Storage Pools, Importable, Virtual Device Mapping, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Importable, Virtual Device Mapping, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolsSystemReservedGet() {
- let filesystems = {
- id: []
- };
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name,mountpoint", "-d", "3"]
- };
-
- FnConsole.log[2]("Storage Pools, System Reserved, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done((data) => {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, System Reserved, Get:" }));
-
- filesystems.id = data.split(/\n/g).filter(v => v);
-
- filesystems.id.forEach((_value, _index) => {
- let filesystem = {
- properties: _value.split(/\t/g).filter(v => v)
- };
-
- filesystem.name = filesystem.properties[0];
- filesystem.mountpoint = filesystem.properties[1].trim();
-
- if (filesystem.mountpoint == "/boot" && !zfsmanager.zfs.storagepool.boot) {
- zfsmanager.zfs.storagepool.boot = filesystem.name.split("/")[0];
- } else if (filesystem.mountpoint == "/" && !zfsmanager.zfs.storagepool.root) {
- zfsmanager.zfs.storagepool.root = filesystem.name.split("/")[0];
- }
- });
-
- FnConsole.log[1]("Storage Pools, System Reserved, Get: Success");
- })
- .fail((message, data) => {
- FnConsole.warn("Storage Pools, System Reserved, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolsTemporaryGet() {
- let process = {
- command: ["/sbin/zpool", "list", "-H", "-o", "name,readonly,altroot"]
- };
-
- FnConsole.log[2]("Storage Pools, Temporary, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function () {
- FnConsole.log[1]("Storage Pools, Temporary, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Temporary, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-//#endregion
-
-//#region Storage Pool
-
-function FnStoragePoolAlternativeRootGet(pool = { name, id }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "list", "-H", "-o", "altroot", pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Alternative Root, Get: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Alternative Root, Get:" }));
-
- data = data.replace(/\n+/g, "");
-
- $("#input-" + modal.name + "-mountpoint-" + modal.id).attr("data-field-altroot", data);
-
- FnConsole.log[1]("Storage Pools, Alternative Root, Get: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Alternative Root, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolClear(pool = { name, id }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "clear", pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Clear Errors: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Clearing storage pool errors...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Storage Pool errors successfully cleared", description: pool.name, breakword: false }, { name: "storagepool-clear", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Clear Errors: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Storage Pool errors could not be cleared", description: pool.name, breakword: false }, { name: "storagepool-clear", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Clear Errors: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });
-}
-
-function FnStoragePoolConfigurationFeaturesDisabledGet(pool = { name, id }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "get", "feature@allocation_classes,feature@async_destroy,feature@bookmark_v2,feature@bookmarks,feature@device_removal,feature@edonr,feature@embedded_data,feature@empty_bpobj,feature@enabled_txg,feature@encryption,feature@extensible_dataset,feature@filesystem_limits,feature@hole_birth,feature@large_blocks,feature@large_dnode,feature@lz4_compress,feature@multi_vdev_crash_dump,feature@obsolete_counts,feature@project_quota,feature@resilver_defer,feature@sha512,feature@skein,feature@spacemap_histogram,feature@spacemap_v2,feature@userobj_accounting,feature@zpool_checkpoint", "-H", "-o", "property,value", pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Configuration, Features, Disabled, Get: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Configuration, Features, Disabled, Get:" }));
-
- pool.configuration = data.replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v);
- pool.disabled = [];
-
- pool.configuration.forEach((_value, _index) => {
- _value = _value.split("\u22C5");
-
- pool.properties = {
- property: _value[0].toLowerCase(),
- value: _value[1].toLowerCase()
- };
-
- switch (pool.properties.property) {
- case "feature@allocation_classes":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Allocation Classes");
- }
- break;
- case "feature@async_destroy":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Asynchronous Destroy");
- }
- break;
- case "feature@bookmark_v2":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Bookmarks Version 2");
- }
- break;
- case "feature@bookmarks":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Bookmarks");
- }
- break;
- case "feature@device_removal":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Device Removal");
- }
- break;
- case "feature@edonr":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Edon-R");
- }
- break;
- case "feature@embedded_data":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Embedded Data");
- }
- break;
- case "feature@empty_bpobj":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Empty Block Pointer Objects");
- }
- break;
- case "feature@enabled_txg":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Transaction Group Accounting");
- }
- break;
- case "feature@encryption":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Encryption");
- }
- break;
- case "feature@extensible_dataset":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Extensible Dataset");
- }
- break;
- case "feature@filesystem_limits":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("File System Limits");
- }
- break;
- case "feature@hole_birth":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Hole Birth");
- }
- break;
- case "feature@large_blocks":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Large Blocks");
- }
- break;
- case "feature@large_dnode":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Large DNode");
- }
- break;
- case "feature@lz4_compress":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("LZ4 Compression");
- }
- break;
- case "feature@multi_vdev_crash_dump":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Multi Virtual Device Crash Dump");
- }
- break;
- case "feature@obsolete_counts":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Obsolete Counts");
- }
- break;
- case "feature@project_quota":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Project Quota");
- }
- break;
- case "feature@resilver_defer":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Resilver Defer");
- }
- break;
- case "feature@sha512":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("SHA-512");
- }
- break;
- case "feature@skein":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Skein");
- }
- break;
- case "feature@spacemap_histogram":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Space Map Histogram");
- }
- break;
- case "feature@spacemap_v2":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Space Map Version 2");
- }
- break;
- case "feature@userobj_accounting":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("User Object Accounting");
- }
- break;
- case "feature@zpool_checkpoint":
- if (/disabled/gi.test(pool.properties.value)) {
- pool.disabled.push("Checkpoint");
- }
- break;
- }
- });
-
- $("#ul-" + modal.name + "-features-" + modal.id).append(`` + pool.disabled.sort().join(` \n`) + ` `);
-
- FnConsole.log[1]("Storage Pools, Configuration, Features, Disabled, Get: Success, Pool: " + pool.name);
-
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Configuration, Features, Disabled, Get: In Progress, Pool: " + pool.name + " , Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolConfigurationFeaturesGet(pool = { name, id, boot: false }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "get", "readonly,feature@allocation_classes,feature@async_destroy,feature@bookmark_v2,feature@bookmarks,feature@device_removal,feature@edonr,feature@embedded_data,feature@empty_bpobj,feature@enabled_txg,feature@encryption,feature@extensible_dataset,feature@filesystem_limits,feature@hole_birth,feature@large_blocks,feature@large_dnode,feature@lz4_compress,feature@multi_vdev_crash_dump,feature@obsolete_counts,feature@project_quota,feature@resilver_defer,feature@sha512,feature@skein,feature@spacemap_histogram,feature@spacemap_v2,feature@userobj_accounting,feature@zpool_checkpoint", "-H", "-o", "property,value", pool.name]
- };
-
- pool.readonly = false;
-
- FnConsole.log[2]("Storage Pools, Configuration, Features, Get: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Configuration, Features, Get:" }));
-
- pool.configuration = data.replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v);
-
- pool.configuration.forEach((_value, _index) => {
- _value = _value.split("\u22C5");
-
- pool.properties = {
- property: _value[0].toLowerCase(),
- value: _value[1].toLowerCase()
- };
-
- switch (pool.properties.property) {
- case "feature@allocation_classes":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-allocation_classes-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-allocation_classes-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-allocation_classes-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-allocation_classes-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@async_destroy":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-async_destroy-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-async_destroy-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-async_destroy-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-async_destroy-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@bookmark_v2":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-bookmark_v2-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-bookmark_v2-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-bookmark_v2-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-bookmark_v2-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@bookmarks":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-bookmarks-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-bookmarks-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-bookmarks-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-bookmarks-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@device_removal":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-device_removal-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-device_removal-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-device_removal-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-device_removal-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@edonr":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-edonr-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-edonr-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-edonr-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-edonr-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@embedded_data":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-embedded_data-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-embedded_data-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-embedded_data-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-embedded_data-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@empty_bpobj":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-empty_bpobj-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-empty_bpobj-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-empty_bpobj-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-empty_bpobj-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@enabled_txg":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-enabled_txg-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-enabled_txg-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-enabled_txg-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-enabled_txg-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@encryption":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-encryption-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-encryption-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@extensible_dataset":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-extensible_dataset-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-extensible_dataset-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-extensible_dataset-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-extensible_dataset-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@filesystem_limits":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-filesystem_limits-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-filesystem_limits-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-filesystem_limits-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-filesystem_limits-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@hole_birth":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-hole_birth-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-hole_birth-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-hole_birth-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-hole_birth-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@large_blocks":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-large_blocks-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-large_blocks-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-large_blocks-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-large_blocks-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@large_dnode":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-large_dnode-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-large_dnode-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-large_dnode-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-large_dnode-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@lz4_compress":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-lz4_compress-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-lz4_compress-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-lz4_compress-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-lz4_compress-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@multi_vdev_crash_dump":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-multi_vdev_crash_dump-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-multi_vdev_crash_dump-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-multi_vdev_crash_dump-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-multi_vdev_crash_dump-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@obsolete_counts":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-obsolete_counts-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-obsolete_counts-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-obsolete_counts-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-obsolete_counts-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@project_quota":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-project_quota-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-project_quota-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-project_quota-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-project_quota-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@resilver_defer":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-resilver_defer-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-resilver_defer-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-resilver_defer-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-resilver_defer-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@sha512":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-sha512-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-sha512-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-sha512-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-sha512-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@skein":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-skein-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-skein-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-skein-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-skein-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@spacemap_histogram":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-spacemap_histogram-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-spacemap_histogram-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-spacemap_histogram-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-spacemap_histogram-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@spacemap_v2":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-spacemap_v2-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-spacemap_v2-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-spacemap_v2-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-spacemap_v2-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@userobj_accounting":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-userobj_accounting-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-userobj_accounting-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-userobj_accounting-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-userobj_accounting-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "feature@zpool_checkpoint":
- if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-zpool_checkpoint-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-zpool_checkpoint-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-zpool_checkpoint-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
- $("#switch-" + modal.name + "-zpool_checkpoint-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "readonly": //Default is off
- if (pool.properties.value == "on" || pool.boot && zfsmanager.configuration.zfs.storagepool.bootlockdown || !zfsmanager.user.admin) {
- pool.readonly = true;
- }
- break;
- }
- });
-
- if (pool.readonly) {
- $("#btn-" + modal.name + "-apply-" + modal.id).prop("disabled", true);
- }
-
- FnConsole.log[1]("Storage Pools, Configuration, Features, Get: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Configuration, Features, Get: Failed, Pool: " + pool.name + " , Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolConfigurationGet(pool = { name, id, boot: false, root: false }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "get", "readonly,altroot,ashift,autoexpand,autoreplace,autotrim,bootfs,cachefile,comment,delegation,failmode,guid,listsnapshots,multihost,version", "-H", "-o", "property,value", pool.name]
- };
-
- pool.readonly = false;
-
- FnConsole.log[2]("Storage Pools, Configuration, Get: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Configuration, Get:" }));
-
- pool.configuration = data.replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v);
-
- pool.configuration.forEach((_value, _index) => {
- _value = _value.split("\u22C5");
-
- pool.properties = {
- property: _value[0].toLowerCase(),
- value: _value[1].toLowerCase(),
- valueraw: _value[1],
- };
-
- switch (pool.properties.property) {
- case "altroot": //Default is empty (-)
- if (pool.properties.valueraw && pool.properties.valueraw == "-") {
- pool.properties.valueraw = "";
- }
-
- if (pool.properties.valueraw) {
- $("#controllabel-" + modal.name + "-altroot-" + modal.id).removeClass("hidden");
- $("#div-" + modal.name + "-altroot-" + modal.id).removeClass("hidden").text(pool.properties.valueraw);
- }
- break;
- case "ashift": //Default is 0
- pool.property = {
- value: "Auto Detect",
- };
-
- switch (pool.properties.value) {
- case "0":
- pool.property.value = "Auto Detect";
- break;
- case "9":
- pool.property.value = "512 B";
- break;
- case "12":
- pool.property.value = "4 KiB";
- break;
- case "13":
- pool.property.value = "8 KiB";
- break;
- case "14":
- pool.property.value = "16 KiB";
- break;
- case "15":
- pool.property.value = "32 KiB";
- break;
- case "16":
- pool.property.value = "64 KiB";
- break;
- default:
- pool.property.value = "Auto Detect";
- break;
- }
-
- $("#btnspan-" + modal.name + "-ashift-" + modal.id).text(pool.property.value).attr("data-field-value", pool.properties.value);
- $("#dropdown-" + modal.name + "-ashift-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-ashift-" + modal.id + " li[value='" + pool.properties.valueraw + "']").addClass("active");
-
- if (pool.readonly) {
- $("#div-" + modal.name + "-ashift-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- case "autoexpand": //Default is off
- if (pool.properties.value == "on" && !$("#switch-" + modal.name + "-autoexpand-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-autoexpand-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-autoexpand-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly) {
- $("#switch-" + modal.name + "-autoexpand-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "autoreplace": //Default is off
- if (pool.properties.value == "on" && !$("#switch-" + modal.name + "-autoreplace-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-autoreplace-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-autoreplace-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly) {
- $("#switch-" + modal.name + "-autoreplace-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "autotrim": //Default is off
- if (pool.properties.value == "on" && !$("#switch-" + modal.name + "-autotrim-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-autotrim-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-autotrim-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly) {
- $("#switch-" + modal.name + "-autotrim-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "comment": //Default is empty (-)
- if (pool.properties.valueraw && pool.properties.valueraw == "-") {
- pool.properties.valueraw = "";
- }
-
- $("#input-" + modal.name + "-comment-" + modal.id).val(pool.properties.valueraw);
- $("#input-" + modal.name + "-comment-" + modal.id).attr("data-field-value", pool.properties.valueraw);
-
- if (pool.readonly) {
- $("#input-" + modal.name + "-comment-" + modal.id).prop("disabled", true);
- }
-
- break;
- case "delegation": //Default is on
- if (pool.properties.value == "off" && $("#switch-" + modal.name + "-delegation-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-delegation-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-delegation-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly) {
- $("#switch-" + modal.name + "-delegation-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "failmode": //Default is wait
- pool.property = {
- value: pool.properties.value.charAt(0).toUpperCase() + pool.properties.value.slice(1),
- };
-
- $("#btnspan-" + modal.name + "-failmode-" + modal.id).text(pool.property.value).attr("data-field-value", pool.properties.value);
- $("#dropdown-" + modal.name + "-failmode-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-failmode-" + modal.id + " li[value='" + pool.properties.valueraw + "']").addClass("active");
-
- if (pool.readonly) {
- $("#div-" + modal.name + "-failmode-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- case "guid":
- $("#div-" + modal.name + "-guid-" + modal.id).html(pool.properties.value);
- break;
- case "listsnapshots": //Default is off
- if (pool.properties.value == "on" && !$("#switch-" + modal.name + "-listsnapshots-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-listsnapshots-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-listsnapshots-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly) {
- $("#switch-" + modal.name + "-listsnapshots-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "multihost": //Default is off
- if (pool.properties.value == "on" && !$("#switch-" + modal.name + "-multihost-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-multihost-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-multihost-" + modal.id).attr("data-field-value", pool.properties.value);
-
- if (pool.readonly || pool.boot || pool.root) {
- $("#switch-" + modal.name + "-multihost-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "readonly": //Default is off
- if (pool.properties.value == "on" || pool.boot && zfsmanager.configuration.zfs.storagepool.bootlockdown || !zfsmanager.user.admin) {
- pool.readonly = true;
- }
-
- $("#div-" + modal.name + "-readonly-" + modal.id).html((pool.properties.value == "on" ? "Yes" : "No"));
- break;
- }
- });
-
- if (pool.readonly) {
- $("#btn-" + modal.name + "-apply-" + modal.id).prop("disabled", true);
- }
-
- FnConsole.log[1]("Storage Pools, Configuration, Get: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Configuration, Get: Failed, Pool: " + pool.name + " , Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolConfigure(pool = { name, id, ashift, autoexpand, autoreplace, autotrim, comment, delegation, failmode, listsnapshots, multihost, readonly: false }, system = { hostid }, modal = { id }) {
- pool.properties = {
- new: []
- };
-
- if (pool.ashift) {
- pool.properties.new.push("ashift=" + pool.ashift);
- }
- if (pool.autoexpand) {
- pool.properties.new.push("autoexpand=" + pool.autoexpand);
- }
- if (pool.autoreplace) {
- pool.properties.new.push("autoreplace=" + pool.autoreplace);
- }
- if (pool.autotrim) {
- pool.properties.new.push("autotrim=" + pool.autotrim);
- }
- if (pool.comment) {
- if (pool.comment == "$empty") {
- pool.comment = "";
- }
-
- pool.properties.new.push("comment=" + pool.comment);
- }
- if (pool.delegation) {
- pool.properties.new.push("delegation=" + pool.delegation);
- }
- if (pool.failmode) {
- pool.properties.new.push("failmode=" + pool.failmode);
- }
- if (pool.listsnapshots) {
- pool.properties.new.push("listsnapshots=" + pool.listsnapshots);
- }
- if (pool.multihost) {
- pool.properties.new.push("multihost=" + pool.multihost);
- }
-
- if (system.hostid) {
- FnSystemHostIdSet({ hostid: (system.hostid == "random" ? null : "\$\(hostid\)") })
- .finally(function () {
- if (pool.properties.new.length > 0 && !pool.readonly) {
- FnConsole.log[2]("Storage Pools, Configure: In Progress, Pool: " + pool.name);
-
- $("#spinner-storagepool-configure-" + pool.id + " span").text("Configuring storage pool...");
-
- FnStoragePoolConfigureCommand({ name: pool.name, id: pool.id, properties: { new: pool.properties.new } }, { id: modal.id });
- } else {
- modal.id.modal("hide");
- }
- });
- } else {
- if (pool.properties.new.length > 0 && !pool.readonly) {
- FnConsole.log[2]("Storage Pools, Configure: In Progress, Pool: " + pool.name);
-
- $("#spinner-storagepool-configure-" + pool.id + " span").text("Configuring storage pool...");
-
- FnStoragePoolConfigureCommand({ name: pool.name, id: pool.id, properties: { new: pool.properties.new } }, { id: modal.id });
- } else {
- modal.id.modal("hide");
- }
- }
-}
-
-function FnStoragePoolConfigureCommand(pool = { name, id, properties: { new: [] } }, modal = { id }) {
- let promise = Promise.resolve();
-
- pool.properties.errorcount = 0;
-
- pool.properties.new.forEach((_value, _index) => {
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- let process = {
- command: ["/sbin/zpool", "set", _value, pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Configure: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- if (_index == (pool.properties.new.length - 1)) {
- if (pool.properties.errorcount == 0) {
- FnDisplayAlert({ status: "success", title: "Storge Pool successfully configured", description: pool.name, breakword: false }, { name: "storagepool-configure", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Configure: Success, Pool: " + pool.name);
- } else {
- FnStoragePoolConfigureFail({ name: pool.name, id: pool.id });
- }
-
- modal.id.modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
- }, 200);
- }
- })
- .fail(function (message, data) {
- pool.properties.errorcount++;
-
- FnConsole.warn("Storage Pools, Property, Set: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
-
- if (_index == (pool.properties.new.length - 1)) {
- FnStoragePoolConfigureFail({ name: pool.name, id: pool.id });
-
- modal.id.modal("hide");
- }
- });
-
- resolve();
- }, 500)
- ));
- });
-}
-
-function FnStoragePoolConfigureFail(pool = { name, id }) {
- FnDisplayAlert({ status: "danger", title: "Storge Pool could not be configured", description: pool.name, breakword: false }, { name: "storagepool-configure", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Configure: Failed, Pool: " + pool.name);
-}
-
-function FnStoragePoolConfigureFeatures(pool = { name, id, feature: { allocation_classes, async_destroy, bookmark_v2, bookmarks, device_removal, edonr, embedded_data, empty_bpobj, enabled_txg, encryption, extensible_dataset, filesystem_limits, hole_birth, large_blocks, large_dnode, lz4_compress, multi_vdev_crash_dump, obsolete_counts, project_quota, resilver_defer, sha512, skein, spacemap_histogram, spacemap_v2, userobj_accounting, zpool_checkpoint }, readonly: false }, modal = { id }) {
- pool.features = {
- new: []
- };
-
- if (pool.feature.allocation_classes) {
- pool.features.new.push("feature@allocation_classes=" + pool.feature.allocation_classes);
- }
- if (pool.feature.async_destroy) {
- pool.features.new.push("feature@async_destroy=" + pool.feature.async_destroy);
- }
- if (pool.feature.bookmark_v2) {
- pool.features.new.push("feature@bookmark_v2=" + pool.feature.bookmark_v2);
- }
- if (pool.feature.bookmarks) {
- pool.features.new.push("feature@bookmarks=" + pool.feature.bookmarks);
- }
- if (pool.feature.device_removal) {
- pool.features.new.push("feature@device_removal=" + pool.feature.device_removal);
- }
- if (pool.feature.edonr) {
- pool.features.new.push("feature@edonr=" + pool.feature.edonr);
- }
- if (pool.feature.embedded_data) {
- pool.features.new.push("feature@embedded_data=" + pool.feature.embedded_data);
- }
- if (pool.feature.empty_bpobj) {
- pool.features.new.push("feature@empty_bpobj=" + pool.feature.empty_bpobj);
- }
- if (pool.feature.enabled_txg) {
- pool.features.new.push("feature@enabled_txg=" + pool.feature.enabled_txg);
- }
- if (pool.feature.encryption) {
- pool.features.new.push("feature@encryption=" + pool.feature.encryption);
- }
- if (pool.feature.extensible_dataset) {
- pool.features.new.push("feature@extensible_dataset=" + pool.feature.extensible_dataset);
- }
- if (pool.feature.filesystem_limits) {
- pool.features.new.push("feature@filesystem_limits=" + pool.feature.filesystem_limits);
- }
- if (pool.feature.hole_birth) {
- pool.features.new.push("feature@hole_birth=" + pool.feature.hole_birth);
- }
- if (pool.feature.large_blocks) {
- pool.features.new.push("feature@large_blocks=" + pool.feature.large_blocks);
- }
- if (pool.feature.large_dnode) {
- pool.features.new.push("feature@large_dnode=" + pool.feature.large_dnode);
- }
- if (pool.feature.lz4_compress) {
- pool.features.new.push("feature@lz4_compress=" + pool.feature.lz4_compress);
- }
- if (pool.feature.multi_vdev_crash_dump) {
- pool.features.new.push("feature@multi_vdev_crash_dump=" + pool.feature.multi_vdev_crash_dump);
- }
- if (pool.feature.obsolete_counts) {
- pool.features.new.push("feature@obsolete_counts=" + pool.feature.obsolete_counts);
- }
- if (pool.feature.project_quota) {
- pool.features.new.push("feature@project_quota=" + pool.feature.project_quota);
- }
- if (pool.feature.resilver_defer) {
- pool.features.new.push("feature@resilver_defer=" + pool.feature.resilver_defer);
- }
- if (pool.feature.sha512) {
- pool.features.new.push("feature@sha512=" + pool.feature.sha512);
- }
- if (pool.feature.skein) {
- pool.features.new.push("feature@skein=" + pool.feature.skein);
- }
- if (pool.feature.spacemap_histogram) {
- pool.features.new.push("feature@spacemap_histogram=" + pool.feature.spacemap_histogram);
- }
- if (pool.feature.spacemap_v2) {
- pool.features.new.push("feature@spacemap_v2=" + pool.feature.spacemap_v2);
- }
- if (pool.feature.userobj_accounting) {
- pool.features.new.push("feature@userobj_accounting=" + pool.feature.userobj_accounting);
- }
- if (pool.feature.zpool_checkpoint) {
- pool.features.new.push("feature@zpool_checkpoint=" + pool.feature.zpool_checkpoint);
- }
-
- if (pool.features.new.length > 0 && !pool.readonly) {
- FnConsole.log[2]("Storage Pools, Configure, Features: In Progress, Pool: " + pool.name);
-
- $("#spinner-storagepool-configure-features-" + pool.id + " span").text("Configuring storage pool features...");
-
- FnStoragePoolConfigureFeaturesCommand({ name: pool.name, id: pool.id, features: { new: pool.features.new } }, { id: modal.id });
- } else {
- modal.id.modal("hide");
- }
-}
-
-function FnStoragePoolConfigureFeaturesCommand(pool = { name, id, features: { new: [] } }, modal = { id }) {
- let promise = Promise.resolve();
-
- pool.features.errorcount = 0;
-
- pool.features.new.forEach((_value, _index) => {
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- let process = {
- command: ["/sbin/zpool", "set", _value, pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Configure, Features: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- if (_index == (pool.features.new.length - 1)) {
- if (pool.features.errorcount == 0) {
- FnDisplayAlert({ status: "success", title: "Storge Pool features successfully configured", description: pool.name, breakword: false }, { name: "storagepool-configure-features", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Configure, Features: Success, Pool: " + pool.name);
- } else {
- FnStoragePoolConfigureFeaturesFail({ name: pool.name, id: pool.id });
- }
-
- modal.id.modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: true });
- }, 200);
- }
- })
- .fail(function (message, data) {
- pool.features.errorcount++;
-
- FnConsole.warn("Storage Pools, Feature, Set: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
-
- if (_index == (pool.features.new.length - 1)) {
- FnStoragePoolConfigureFeaturesFail({ name: pool.name, id: pool.id });
-
- modal.id.modal("hide");
- }
- });
-
- resolve();
- }, 500)
- ));
- });
-}
-
-function FnStoragePoolConfigureFeaturesFail(pool = { name, id }) {
- FnDisplayAlert({ status: "danger", title: "Storge Pool features could not be configured", description: pool.name, breakword: false }, { name: "storagepool-configure-features", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Configure, Features: Failed, Pool: " + pool.name);
-}
-
-function FnStoragePoolCreate(pool = { name, ashift, autoexpand, autoreplace, autotrim, force, virtualdevice }, filesystem = { compression, dedup, recordsize, refreservationpercent, selinux }, disks = { id: [] }) {
- let process = {
- command: ["/sbin/zpool", "create", "-o", "ashift=" + pool.ashift, "-o", "autoexpand=" + pool.autoexpand, "-o", "autoreplace=" + pool.autoreplace, "-o", "autotrim=" + pool.autotrim, "-O", "aclinherit=passthrough", "-O", "acltype=posixacl", "-O", "casesensitivity=sensitive", "-O", "compression=" + filesystem.compression, "-O", "normalization=formD", "-O", "recordsize=" + filesystem.recordsize, "-O", "sharenfs=off", "-O", "sharesmb=off", "-O", "utf8only=on", "-O", "xattr=sa", pool.name]
- };
- let modal = {
- hide: true
- };
-
- if (filesystem.selinux) {
- process.command.splice((process.command.length - 1), 0, "-O");
- process.command.splice((process.command.length - 1), 0, "context=system_u:object_r:samba_share_t:s0");
- process.command.splice((process.command.length - 1), 0, "-O");
- process.command.splice((process.command.length - 1), 0, "fscontext=system_u:object_r:samba_share_t:s0");
- process.command.splice((process.command.length - 1), 0, "-O");
- process.command.splice((process.command.length - 1), 0, "defcontext=system_u:object_r:samba_share_t:s0");
- process.command.splice((process.command.length - 1), 0, "-O");
- process.command.splice((process.command.length - 1), 0, "rootcontext=system_u:object_r:samba_share_t:s0");
- }
- if (filesystem.dedup) {
- process.command.splice((process.command.length - 1), 0, "-O");
- process.command.splice((process.command.length - 1), 0, "dedup=" + filesystem.dedup);
- }
- if (pool.force) {
- process.command.splice(2, 0, "-f");
- }
- if (pool.virtualdevice) {
- process.command.push(pool.virtualdevice);
- }
-
- disks.id.forEach(_value => _value && process.command.push(_value));
-
- pool.id = FnGenerateId({ at: false, colon: true, forwardslash: false, period: true, underscore: true, whitespace: true }, { name: pool.name, attribute: true });
-
- FnConsole.log[1]("Storage Pools, Create: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-storagepools-create span").text("Creating storage pool...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Storage Pool successfully created", description: pool.name, breakword: false }, { name: "storagepool-create", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Create: Success, Pool: " + pool.name);
-
- if (filesystem.refreservationpercent > 0) {
- FnStoragePoolSizeGet({ name: pool.name, id: null })
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Storage Pools, Size, Get:" }));
-
- if (_data) {
- _data = _data.replace(/\n+/g, "");
-
- filesystem.refreservation = ((_data / 100) * filesystem.refreservationpercent);
-
- FnStoragePoolRefreservationSet({ name: pool.name, id: null }, { refreservation: filesystem.refreservation });
- }
- });
- }
- })
- .fail(function (message, data) {
- if (/pool already exists/gi.test(data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepools-create-name").addClass("has-error");
- $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name already exists.");
- $("#input-storagepools-create-name").focus();
- } else if (/contains devices of different sizes/gi.test(data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepools-create-disks").addClass("has-error");
- $("#helpblock-storagepools-create-disks").addClass("has-error").removeClass("hidden").text("Disks are of different sizes. Forcefully create storage pool to override.");
- } else {
- FnDisplayAlert({ status: "danger", title: "Storage Pool could not be created", description: pool.name, breakword: false }, { name: "storagepool-create", id: pool.id, timeout: 4 });
- }
-
- FnConsole.warn("Storage Pools, Create: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
-
- if (!modal.hide) {
- $("#spinner-storagepools-create").addClass("hidden");
- $("#spinner-storagepools-create span").text("");
- $("#btn-storagepools-create-apply").prop("disabled", false);
- }
- })
- .finally(function () {
- if (modal.hide) {
- $("#modal-storagepools-create").modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- });
-}
-
-function FnStoragePoolDestroy(pool = { name, id, altroot: false, force: false, labelclear: false }, samba = { restart: false }) {
- let disks = {
- attached: []
- };
-
- pool.attached = [];
- pool.attachedconfig = [];
-
- if (pool.labelclear) {
- FnDisksStoragePoolsAttachedGet({ name: pool.name, id: pool.id }, { id: { blockdevice: true } })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Disks, Storage Pools, Attached, Get:" }));
-
- pool.attached = data.replace(/\n\t+/g, "[TAB1]").split(/\n/g).filter(v => v);
-
- pool.attached.forEach((_value, _index) => {
- if (/\[TAB1\]NAME/g.test(_value)) { //Config header row
- _value = _value.split("upath").slice(1).join("."); //Remove config header row (and any previous text if exists)
+};
- if (new RegExp("^\\[TAB1\\]" + pool.name).test(_value)) { //Confirm config rows
- _value.split("[TAB1]").filter(v => v && pool.attachedconfig.push(v));
- }
- }
- });
-
- pool.attachedconfig.forEach((_value, _index) => {
- let config = {
- disk: {
- upath: ""
- },
- tier: {
- level: (_value.match(/^\s*/g)[0].length / 2)
- }
- };
+//#endregion
- _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
+//#region Document Ready
- if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[5])) { //upath
- config.disk.upath = _value[5];
- } else if (!$.isNumeric(_value[0]) && _value[5] != "was") { //upath appears after error messages and before trim messages
- for (let i = 5; i < _value.length; i++) {
- if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[i])) {
- config.disk.upath = _value[i];
- }
- }
- }
+$(document).ready(function () {
+ FnConsoleInitialize();
- if (config.tier.level > 0) {
- if (/^\/dev\/nvme|^\/dev\/sd/gi.test(config.disk.upath)) { //Block Device via upath
- disks.attached.push(config.disk.upath.replace(/^\/dev\//gi, ""));
- } else if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[0])) { //Block Device
- if (/^\/dev\/nvme\d+n\d+p\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/p\d+$/, ""));
- } else if (/^\/dev\/sd.*\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/\d+$/, ""));
- } else {
- disks.attached.push(_value[0]);
- }
- } else if (/^nvme-nvme/gi.test(_value[0]) || /^wwn-/gi.test(_value[0])) { //WWN
- if (/^nvme-nvme.*-part\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/-part\d+$/, ""));
- } else if (/^wwn-.*-part\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/-part\d+$/, ""));
- } else {
- disks.attached.push(_value[0]);
- }
- }
- }
- });
+ FnConsole.log[1]("Cockpit ZFS Manager, Version: " + zfsmanager.version);
- disks.attached.sort();
- });
- }
-
- if (samba.restart) {
- FnSambaStop()
- .finally(function () {
- if (zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: [] })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Destroying storage pool...");
-
- if (filesystems.id.length > 0) {
- FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
- .done(function () {
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Destroying Samba shares...");
-
- FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
- .finally(function () {
- if (pool.labelclear) {
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
-
- FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
- .finally(function () {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- });
- } else {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- })
- });
- } else {
- FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
- .done(function () {
- if (pool.labelclear) {
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
-
- FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
- .finally(function () {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- });
- } else {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- })
- .finally(function () {
- FnSambaStart();
- });
- }
- })
- .fail(function (message, data) {
- FnStoragePoolDestroyFail({ name: pool.name, id: pool.id }, { data: data, message: message });
- FnSambaStart();
- });
- } else {
- FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
- .done(function () {
- if (pool.labelclear) {
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
-
- FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
- .finally(function () {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- });
- } else {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- })
- .finally(function () {
- FnSambaStart();
- });
- }
- });
- } else {
- if (zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: [] })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Destroying storage pool...");
-
- if (filesystems.id.length > 0) {
- FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
- .done(function () {
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Destroying Samba shares...");
-
- FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
- .finally(function () {
- if (pool.labelclear) {
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
-
- FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
- .finally(function () {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- });
- } else {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- })
- });
- } else {
- FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
- .done(function () {
- if (pool.labelclear) {
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
-
- FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
- .finally(function () {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- });
- } else {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- });
- }
- })
- .fail(function (message, data) {
- FnStoragePoolDestroyFail({ name: pool.name, id: pool.id }, { data: data, message: message });
- });
- } else {
- FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
- .done(function () {
- if (pool.labelclear) {
- $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
-
- FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
- .finally(function () {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- });
- } else {
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- });
- }
- }
-}
-
-function FnStoragePoolDestroyCommand(pool = { name, id, force: false }) {
- let process = {
- command: ["/sbin/zpool", "destroy", pool.name]
- };
-
- if (pool.force) {
- process.command.splice(2, 0, "-f");
- }
-
- FnConsole.log[1]("Storage Pools, Destroy: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Storage Pool successfully destroyed", description: pool.name, breakword: false }, { name: "storagepool-destroy", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Destroy: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnStoragePoolDestroyFail({ name: pool.name, id: pool.id }, { data: data, message: message });
- });
-}
-
-function FnStoragePoolDestroyFail(pool = { name, id }, process = { data, message }) {
- FnDisplayAlert({ status: "danger", title: "Storage Pool could not be destroyed", description: pool.name, breakword: false }, { name: "storagepool-destroy", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Destroy: Failed, Pool: " + pool.name + ", Message: " + (process.data ? process.data : process.message));
-
- $("#modal-storagepool-destroy-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
-}
-
-function FnStoragePoolDestroyLabelClear(pool = { name, id }, disks = { id: [] }) {
- let process = {
- promise: cockpit.defer()
- };
- let promise = Promise.resolve();
-
- disks.clear = {
- error: 0
- };
-
- FnConsole.log[2]("Storage Pools, Disk Labels, Clear: In Progress");
-
- if (disks.id.length > 0) {
- disks.id.forEach((_value, _index) => {
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- FnStoragePoolDiskLabelClear({ name: pool.name, id: pool.id }, { id: _value, inactive: true }, { silent: true })
- .fail(function () {
- disks.clear.error++;
- });
-
- if (_index == (disks.id.length - 1)) {
- setTimeout(function () {
- if (disks.clear.error == 0) {
- FnDisplayAlert({ status: "success", title: "Storage Pool disk labels successfully cleared", description: pool.name, breakword: false }, { name: "storagepool-destroy-labelclear", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Disk Labels, Clear: Success");
- } else {
- FnDisplayAlert({ status: "danger", title: "Storage Pool disk labels could not be cleared", description: pool.name, breakword: false }, { name: "storagepool-destroy-labelclear", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Disk Labels, Clear: Failed");
- }
-
- process.promise.resolve();
- }, 2000);
- }
-
- resolve();
- }, 2000)
- ));
- });
- } else {
- process.promise.resolve();
- }
-
- return process.promise.promise();
-}
-
-function FnStoragePoolDiskAttach(pool = { name, id, force: false }, virtualdevice = { id, disk: true }, disk = { idnew: [] }, modal = { name, id }) {
- virtualdevice.mirror = {
- start: null,
- end: null
- };
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Attaching disk...");
-
- if (!virtualdevice.disk && /^mirror-/.test(virtualdevice.id)) {
- disk.id = "";
-
- FnDisksStoragePoolsAttachedGet({ name: pool.name, id: pool.id }, { id: { blockdevice: false } })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Disks, Storage Pools, Attached, Get:" }));
-
- pool.attached = data.replace(/\n\t+/g, "[TAB1]").split(/\n/g).filter(v => v);
- pool.attachedconfig = [];
-
- pool.attached.forEach((_value, _index) => {
- if (/\[TAB1\]NAME/g.test(_value)) { //Config header row
- _value = _value.split("upath").slice(1).join("."); //Remove config header row (and any previous text if exists)
+ FnConfigurationGet()
+ .always(function () {
+ Requirements({ zfs: false });
+ });
- if (new RegExp("^\\[TAB1\\]" + pool.name).test(_value)) { //Confirm config rows
- _value.split("[TAB1]").filter(v => v && pool.attachedconfig.push(v));
- }
- }
- });
-
- pool.attachedconfig.forEach((_value, _index) => { //Find disks in Mirror virtual device and get hierarchy information
- let config = {
- tier: {
- level: (_value.match(/^\s*/g)[0].length / 2)
- }
- };
+ $("body").tooltip({
+ html: "true",
+ selector: `[data-toggle="tooltip"]`
+ });
- _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
+ $(cockpit.info).on("changed", function () {
+ zfsmanager.cockpit.legacy = (cockpit.info["version"] < 207 ? true : false);
+ });
+});
- virtualdevice.mirror.regexp = new RegExp(virtualdevice.id, "g");
-
- if (config.tier.level == 1 && virtualdevice.mirror.regexp.test(_value[0])) {
- if (!virtualdevice.mirror.start) {
- virtualdevice.mirror.start = _index;
- }
- }
-
- if (virtualdevice.mirror.start && _index > virtualdevice.mirror.start) {
- if (config.tier.level == 1) {
- if (!virtualdevice.mirror.end) {
- virtualdevice.mirror.end = _index;
- }
- }
- }
- });
+//#endregion
- if (!virtualdevice.mirror.end) {
- virtualdevice.mirror.end = pool.attachedconfig.length;
+//#region Requirements
+
+function Requirements(skip = { zfs: false }) {
+ if (!skip.zfs) {
+ FnZfsVersionGet()
+ .done(function () {
+ if ($("#alerts-requirements").hasClass("hidden")) {
+ if (zfsmanager.configuration.samba.manage) {
+ FnSambaVersionGet()
+ .done(function () {
+ FnFirstSteps();
+ });
+ } else {
+ FnFirstSteps();
+ }
}
+ });
+ } else {
+ if (zfsmanager.configuration.samba.manage) {
+ FnSambaVersionGet()
+ .done(function () {
+ FnFirstSteps();
+ });
+ } else {
+ FnFirstSteps();
+ }
+ }
+}
- pool.attachedconfig.forEach((_value, _index) => { //Find first healthy disk in the mirror virtual device
- let config = {
- disk: {
- upath: ""
- },
- tier: {
- level: (_value.match(/^\s*/g)[0].length / 2)
- }
- };
+//#endregion
- _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
+//#region First Steps
- if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[5])) { //upath
- config.disk.upath = _value[5];
- } else if (!$.isNumeric(_value[0]) && _value[5] != "was") { //upath appears after error messages and before trim messages
- for (let i = 5; i < _value.length; i++) {
- if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[i])) {
- config.disk.upath = _value[i];
- }
- }
- }
+function FnFirstSteps() {
+ FnSystemOperatingSystemGet();
+ FnCockpitPermissionsGet();
- if (config.tier.level == 2 && _index > virtualdevice.mirror.start && _index < virtualdevice.mirror.end && _value[1] == "ONLINE") {
- if (/^\/dev\/nvme|^\/dev\/sd/gi.test(config.disk.upath) || /^\/dev\/nvme|^\/dev\/sd/gi.test(_value[0])) { //Block Device
- if (/^\/dev\/nvme\d+n\d+p\d+$/gi.test(_value[0])) {
- if (!disk.id) {
- disk.id = _value[0].replace(/p\d+$/, "");
- }
- } else if (/^\/dev\/sd.*\d+$/gi.test(_value[0])) {
- if (!disk.id) {
- disk.id = _value[0].replace(/\d+$/, "");
- }
- } else {
- if (!disk.id) {
- disk.id = _value[0].replace(/-part\d+$/, "");
- }
- }
- } else if (/^nvme-nvme/gi.test(_value[0]) || /^wwn-/gi.test(_value[0])) { //WWN
- if (!disk.id) {
- disk.id = _value[0].replace(/-part\d+$/, "");
- }
- }
- }
- });
-
- if (!disk.id || /^mirror-/g.test(disk.id)) {
- FnStoragePoolDiskAttachFail({ name: pool.name, id: pool.id }, { id: virtualdevice.id, disk: virtualdevice.disk }, { idnew: disk.idnew }, { name: modal.name, id: modal.id }, { data: null, message: "There are no healthy disks to attach to." });
- } else {
- FnStoragePoolDiskAttachCommand({ name: pool.name, id: pool.id, force: pool.force }, { id: virtualdevice.id, disk: virtualdevice.disk }, { id: disk.id, idnew: disk.idnew }, { name: modal.name, id: modal.id });
- }
- })
- .fail(function (message, data) {
- FnStoragePoolDiskAttachFail({ name: pool.name, id: pool.id }, { id: virtualdevice.id, disk: virtualdevice.disk }, { idnew: disk.idnew }, { name: modal.name, id: modal.id }, { data: data, message: message });
- });
- } else {
- FnStoragePoolDiskAttachCommand({ name: pool.name, id: pool.id, force: pool.force }, { id: virtualdevice.id, disk: virtualdevice.disk }, { id: virtualdevice.id, idnew: disk.idnew }, { name: modal.name, id: modal.id });
- }
-}
-
-function FnStoragePoolDiskAttachCommand(pool = { name, id, force: false }, virtualdevice = { id, disk: true }, disk = { id, idnew }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "attach", pool.name, disk.id, disk.idnew]
- };
-
- if (pool.force) {
- process.command.splice(2, 0, "-f");
- }
-
- FnConsole.log[1]("Storage Pools, Disk, Attach: In Progress, Pool: " + pool.name + ", " + (!virtualdevice.disk ? "Virtual Device: " + virtualdevice.id + ", " : "") + "Disk: " + disk.idnew);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Disk attached successfully to Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-attach", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Disk, Attach: Success, Pool: " + pool.name + ", " + (!virtualdevice.disk ? "Virtual Device: " + virtualdevice.id + ", " : "") + "Disk: " + disk.idnew);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Disk could not be attached to Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-attach", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Disk, Attach: Failed, Pool: " + pool.name + ", " + (!virtualdevice.disk ? "Virtual Device: " + virtualdevice.id + ", " : "") + "Disk: " + disk.idnew + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });;
-}
-
-function FnStoragePoolDiskAttachFail(pool = { name, id }, virtualdevice = { id, disk: true }, disk = { idnew }, modal = { name, id }, process = { data, message }) {
- FnDisplayAlert({ status: "danger", title: "Disk could not be attached to Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-attach", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Disk, Attach: Failed, Pool: " + pool.name + ", " + (!virtualdevice.disk ? "Virtual Device: " + virtualdevice.id + ", " : "") + "Disk: " + disk.idnew + ", Message: " + (process.data ? process.data : process.message));
-
- if (modal.id) {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- }
-}
-
-function FnStoragePoolDiskClear(pool = { name, id }, disk = { id }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "clear", pool.name, disk.id]
- };
-
- FnConsole.log[2]("Storage Pools, Disk, Clear Errors: In Progress, Pool: " + pool.name + ", Disk: " + disk.id);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Clearing disk errors...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Disk errors successfully cleared", description: disk.id, breakword: false }, { name: "storagepool-disk-clear", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Disk, Clear Errors: Success, Pool: " + pool.name + ", Disk: " + disk.id);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Disk errors could not be cleared", description: disk.id, breakword: false }, { name: "storagepool-disk-clear", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Disk, Clear Errors: Failed, Pool: " + pool.name + ", Disk: " + disk.id + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });
-}
-
-function FnStoragePoolDiskDetach(pool = { name, id }, disk = { id, labelclear: false }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "detach", pool.name, disk.id]
- };
-
- modal.hide = true;
-
- FnConsole.log[1]("Storage Pools, Disk, Detach: In Progress, Pool: " + pool.name + ", Disk: " + disk.id);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Detaching disk...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Disk detached successfully from Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-detach", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Disk, Detach: Success, Pool: " + pool.name + ", Disk: " + disk.id);
-
- if (disk.labelclear) {
- modal.hide = false;
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Clearing disk label...");
-
- setTimeout(function () {
- FnStoragePoolDiskLabelClear({ name: pool.name, id: pool.id }, { id: disk.id, inactive: false }, { silent: false })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- })
- }, 2000);
- }
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Disk could not be detached from Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-detach", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Disk, Detach: Failed, Pool: " + pool.name + ", Disk: " + disk.id + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- if (modal.hide) {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- }
- });;
-}
-
-function FnStoragePoolDiskLabelClear(pool = { name, id }, disk = { id, inactive: false }, display = { silent: false }) {
- let process = {
- command: ["/sbin/zpool", "labelclear", disk.id]
- };
-
- if (disk.inactive) {
- process.command.splice(2, 0, "-f");
- }
-
- FnConsole.log[2]("Storage Pools, Disk Label, Clear: In Progress, Disk: " + disk.id);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Disk label successfully cleared", description: disk.id, breakword: false }, { name: "storagepool-disk-labelclear", id: pool.id, timeout: 4 });
- }
-
- FnConsole.log[1]("Storage Pools, Disk Label, Clear: Success, Disk: " + disk.id);
-
- setTimeout(function () {
- FnDisksBlkidGet();
- }, 200);
- })
- .fail(function (message, data) {
- if (!display.silent) {
- FnDisplayAlert({ status: "danger", title: "Disk label could not be cleared", description: disk.id, breakword: false }, { name: "storagepool-disk-labelclear", id: pool.id, timeout: 4 });
- }
-
- FnConsole.warn("Storage Pools, Disk Label, Clear: Failed, Disk: " + disk.id + ", Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolDiskOffline(pool = { name, id }, disk = { id, force: false, temporary: false }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "offline", pool.name, disk.id]
- };
-
- if (disk.force) {
- process.command.splice(2, 0, "-f");
- }
- if (disk.temporary) {
- process.command.splice(2, 0, "-t");
- }
-
- FnConsole.log[1]("Storage Pools, Disk, Offline: In Progress, Pool: " + pool.name + ", Disk: " + disk.id);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Setting disk offline...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Disk successfully set offline", description: disk.id, breakword: false }, { name: "storagepool-disk-offline", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Disk, Offline: Success, Pool: " + pool.name + ", Disk: " + disk.id);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Disk could not be set offline", description: disk.id, breakword: false }, { name: "storagepool-disk-offline", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Disk, Offline: Failed, Pool: " + pool.name + ", Disk: " + disk.id + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });;
-}
-
-function FnStoragePoolDiskOnline(pool = { name, id, scrub: false }, disk = { id, expand: false }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "online", pool.name, disk.id]
- };
-
- if (disk.expand) {
- process.command.splice(2, 0, "-e");
- }
-
- FnConsole.log[1]("Storage Pools, Disk, Online: In Progress, Pool: " + pool.name + ", Disk: " + disk.id);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Setting disk online...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Disk, Online:" }));
-
- if (/^warning:/gi.test(data)) {
- FnDisplayAlert({ status: "warning", title: "Disk set online but remains in faulted state", description: disk.id, breakword: false }, { name: "storagepool-disk-online", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Disk, Online: Warning, Pool: " + pool.name + ", Message: " + (data ? data.replace(/^warning: /gi, "") : message));
- } else {
- FnDisplayAlert({ status: "success", title: "Disk successfully set online", description: disk.id, breakword: false }, { name: "storagepool-disk-online", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Disk, Online: Success, Pool: " + pool.name + ", Disk: " + disk.id);
- }
-
- if (pool.scrub) {
- FnStoragePoolScrubStart({ name: pool.name, id: pool.id }, { resume: false }, { refresh: false });
- }
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Disk could not be set online", description: disk.id, breakword: false }, { name: "storagepool-disk-online", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Disk, Online: Failed, Pool: " + pool.name + ", Disk: " + disk.id + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });;
-}
-
-function FnStoragePoolDiskReplace(pool = { name, id, force: false }, disk = { id, idnew }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "replace", pool.name, disk.id, disk.idnew]
- };
-
- if (pool.force) {
- process.command.splice(2, 0, "-f");
- }
-
- FnConsole.log[1]("Storage Pools, Disk, Replace: In Progress, Pool: " + pool.name + ", Disk: " + disk.id);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Replacing disk...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Disk replaced successfully on Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-replace", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Disk, Replace: Success, Pool: " + pool.name + ", Disk: " + disk.id);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Disk could not be replaced on Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-replace", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Disk, Replace: Failed, Pool: " + pool.name + ", Disk: " + disk.id + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });;
-}
-
-function FnStoragePoolExport(pool = { name, id, altroot: false, force: false, readonly: false }, samba = { restart: false }) {
- if (samba.restart) {
- FnSambaStop()
- .finally(function () {
- if (zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-export-" + pool.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: [] })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-export-" + pool.id + " span").text("Exporting storage pool...");
-
- if (filesystems.id.length > 0) {
- FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: false })
- .done(function () {
- $("#spinner-storagepool-export-" + pool.id + " span").text("Destroying Samba shares...");
-
- FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
- .finally(function () {
- $("#modal-storagepool-export-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- });
- });
- } else {
- FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: true })
- .finally(function () {
- FnSambaStart();
- });
- }
- })
- .fail(function (message, data) {
- FnStoragePoolExportFail({ name: pool.name, id: pool.id }, { data: data, message: message }, { refresh: true });
- FnSambaStart();
- });
- } else {
- FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: true })
- .finally(function () {
- FnSambaStart();
- });
- }
- });
- } else {
- if (zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-export-" + pool.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: [] })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-export-" + pool.id + " span").text("Exporting storage pool...");
-
- if (filesystems.id.length > 0) {
- FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: false })
- .done(function () {
- $("#spinner-storagepool-export-" + pool.id + " span").text("Destroying Samba shares...");
-
- FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
- .finally(function () {
- $("#modal-storagepool-export-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- });
- });
- } else {
- FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: true });
- }
- })
- .fail(function (message, data) {
- FnStoragePoolExportFail({ name: pool.name, id: pool.id }, { data: data, message: message }, { refresh: true });
- });
- } else {
- FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: true });
- }
- }
-}
-
-function FnStoragePoolExportCommand(pool = { name, id, force: false }, display = { refresh: true }) {
- let process = {
- command: ["/sbin/zpool", "export", pool.name]
- };
-
- if (pool.force) {
- process.command.splice(2, 0, "-f");
- }
-
- FnConsole.log[1]("Storage Pools, Export: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Storage Pool successfully exported", description: pool.name, breakword: false }, { name: "storagepool-export", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Export: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnStoragePoolExportFail({ name: pool.name, id: pool.id }, { data: data, message: message }, { refresh: false });
-
- display.refresh = true;
- })
- .finally(function () {
- if (display.refresh) {
- $("#modal-storagepool-export-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- });
-}
-
-function FnStoragePoolExportFail(pool = { name, id }, process = { data, message }, display = { refresh: true }) {
- FnDisplayAlert({ status: "danger", title: "Storage Pool could not be exported", description: pool.name, breakword: false }, { name: "storagepool-export", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Export: Failed, Pool: " + pool.name + ", Message: " + (process.data ? process.data : process.message));
+ FnModalsRegister();
+ FnStoragePoolsGet();
+
+ FnVersionWarning();
+ FnZfsVersionWarnings()
+}
- if (display.refresh) {
- $("#modal-storagepool-export-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
+function FnFirstStepsPrivileged() {
+ //Execute functions when user is an administrator
+
+ FnConfigurationDirectoryCreate();
+ FnConfigurationDirectoryRuntimeCreate();
+
+ if (!zfsmanager.user.configuration) {
+ FnConfigurationLegacyGet();
+ } else {
+ if (zfsmanager.configuration.cockpit.manage) {
+ FnCockpitManage();
+ }
+ if (zfsmanager.configuration.samba.manage) {
+ FnSambaManage();
+ }
+ FnSambaUsersharesDirectoryCreate();
+ if (zfsmanager.configuration.updates.check) {
+ FnUpdatesCheck({ alert: true });
+ }
}
-}
-
-function FnStoragePoolHealthIcon(pool = { health }) {
- switch (pool.health.toLowerCase()) {
- case "online":
- pool.healthicon = "pficon pficon-ok list-view-pf-icon-sm";
- break;
- case "offline":
- pool.healthicon = "fa pficon-info list-view-pf-icon-sm";
- break;
- case "split":
- pool.healthicon = "fa pficon-info list-view-pf-icon-sm";
- break;
- case "degraded":
- pool.healthicon = "pficon pficon-warning-triangle-o list-view-pf-icon-sm";
- break;
- case "unknown":
- pool.healthicon = "pficon pficon-warning-triangle-o list-view-pf-icon-sm";
- break;
- case "removed":
- pool.healthicon = "pficon pficon-error-circle-o list-view-pf-icon-sm";
- break;
- case "faulted":
- pool.healthicon = "pficon pficon-error-circle-o list-view-pf-icon-sm";
- break;
- case "unavail":
- pool.healthicon = "pficon pficon-error-circle-o list-view-pf-icon-sm";
- break;
- case "avail":
- pool.healthicon = "pficon pficon-ok list-view-pf-icon-sm";
- break;
- case "inuse":
- pool.healthicon = "pficon pficon-ok list-view-pf-icon-sm";
- break;
- case "fail":
- pool.healthicon = "pficon pficon-error-circle-o list-view-pf-icon-sm";
- break;
- case "destroyed":
- pool.healthicon = "pficon pficon-error-circle-o list-view-pf-icon-sm";
- break;
- default:
- pool.healthicon = "fa pficon-info list-view-pf-icon-sm";
- break;
- }
-
- return pool.healthicon;
-}
-
-function FnStoragePoolImport(pool = { name, altroot, destroyed: false, force: false, guid, ignoremissinglog: false, namenew, readonly: false, recoverymode: false }, filesystem = { mount: true, selinux: true }, disks = { id: { blockdevice: true, disk: false, path: false, vdev: false }, identifier }) {
- let process = {
- command: ["/sbin/zpool", "import", pool.guid]
- };
- let modal = {
- hide: true
- };
-
- disks.devpath = "/dev";
- disks.fallback = false;
- disks.identifiertext = "Block Device";
-
- if (pool.namenew) {
- pool.name = pool.namenew;
- }
-
- process.command.push(pool.name);
-
- pool.id = FnGenerateId({ at: false, colon: true, forwardslash: false, period: true, underscore: true, whitespace: true }, { name: pool.name, attribute: true });
- pool.imported = false;
-
- if (!filesystem.mount) {
- process.command.splice(2, 0, "-N");
- }
-
- if (pool.altroot) {
- process.command.splice(2, 0, "-o");
- process.command.splice(3, 0, "altroot=" + pool.altroot);
- }
- if (pool.destroyed) {
- process.command.splice(2, 0, "-D");
- }
- if (pool.force) {
- process.command.splice(2, 0, "-f");
- }
- if (pool.recoverymode) {
- process.command.splice(2, 0, "-F");
- }
- if (pool.ignoremissinglog) {
- process.command.splice(2, 0, "-m");
- }
- if (pool.readonly) {
- process.command.splice(2, 0, "-o");
- process.command.splice(3, 0, "readonly=on");
- }
-
- process.command.splice(2, 0, "-d");
-
- switch (disks.identifier) { //Fallback to block device to prevent import error when selected identifier is not available
- case "disk":
- if (disks.id.disk) {
- disks.devpath = "/dev/disk/by-id";
- } else {
- disks.fallback = true;
- }
- disks.identifiertext = "Disk / WWN";
- break;
- case "path":
- if (disks.id.path) {
- disks.devpath = "/dev/disk/by-path";
- } else {
- disks.fallback = true;
- }
- disks.identifiertext = "Hardware Path";
- break;
- case "vdev":
- if (disks.id.vdev) {
- disks.devpath = "/dev/disk/by-vdev";
+}
+
+//#endregion
+
+//#region Fixed Content Click Actions
+
+$(document).on("click", "#btn-alerts-requirements-samba-refresh", function () {
+ Requirements({ zfs: true });
+});
+
+$(document).on("click", "#btn-alerts-requirements-zfs-refresh", function () {
+ Requirements({ zfs: false });
+});
+
+$(document).on("click", "#btn-storagepools-refresh", function () {
+ FnStoragePoolsGet();
+});
+
+$(document).on("click", "#table-storagepools > tbody > tr.listing-ct-item", function (element) {
+ if (!$(this).hasClass("listing-ct-storagepoolsnotfound") && !$(element.target).is("a, button, .fa.fa-ellipsis-v, input")) {
+ if (!$(this).parent().hasClass("open")) {
+ $(this).parent().addClass("open");
+
+ $(this).attr("data-pool-refresh-filesystems", "false");
+ $(this).attr("data-pool-refresh-snapshots", "false");
+ $(this).attr("data-pool-refresh-status", "false");
+
+ FnStoragePoolRefresh({ name: $(this).attr("data-pool-name"), id: $(this).attr("data-pool-id") }, { storagepool: true, filesystems: true, snapshots: true, status: true });
+ } else {
+ if (!$("#spinner-storagepool-" + $(this).attr("data-pool-id")).hasClass("hidden")) {
+ //Disable click action while information is still loading
} else {
- disks.fallback = true;
+ $(this).parent().removeClass("open");
+
+ $(this).attr("data-pool-refresh-filesystems", "false");
+ $(this).attr("data-pool-refresh-snapshots", "false");
+ $(this).attr("data-pool-refresh-status", "false");
+
+ $("#spinner-storagepool-" + $(this).attr("data-pool-id")).removeClass("hidden");
+ $("#listingcthead-storagepool-" + $(this).attr("data-pool-id")).addClass("hidden");
+ $("#listingctbody-storagepool-" + $(this).attr("data-pool-id")).addClass("hidden");
+
+ FnStoragePoolRefreshAutoDisable({ name: $(this).attr("data-pool-name"), id: $(this).attr("data-pool-id") });
}
- disks.identifiertext = "Virtual Device Mapping";
- break;
- }
-
- process.command.splice(3, 0, disks.devpath);
-
- FnConsole.log[1]("Storage Pools, Import: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-storagepools-import span").text("Importing storage pool...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- pool.imported = true;
-
- if (disks.fallback) {
- FnDisplayAlert({ status: "warning", title: "Storage Pool imported with errors", description: pool.name, breakword: false }, { name: "storagepools-import", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Import: Warning, Pool: " + pool.name + ", Message: " + disks.identifiertext + " disks identifier was not available during import. Block Device disks identifier was used.");
- } else {
- FnDisplayAlert({ status: "success", title: "Storage Pool successfully imported", description: pool.name, breakword: false }, { name: "storagepools-import", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Import: Success, Pool: " + pool.name);
- }
- })
- .fail(function (message, data) {
- if (/cannot mount.*directory is not empty|smb add share failed|cannot share/gi.test(data)) { //Storage pool has successfully imported, however a file system error is generated
- pool.imported = true;
-
- FnDisplayAlert({ status: "warning", title: "Storage Pool imported with errors", description: pool.name, breakword: false }, { name: "storagepools-import", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Import: Warning, Pool: " + pool.name + ", Message: " + (data ? data : message));
- } else if (/cannot import.*pool already exists/gi.test(data)) {
- modal.hide = false;
-
- if (!$("#switch-storagepools-import-rename input").prop("checked")) {
- $("#switch-storagepools-import-rename input").click();
- }
- $("#validationwrapper-storagepools-import-storagepools").addClass("has-error");
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name already exists. New name is needed.");
- $("#input-storagepools-import-namenew").focus();
- } else {
- FnDisplayAlert({ status: "danger", title: "Storage Pool could not be imported", description: pool.name, breakword: false }, { name: "storagepools-import", id: pool.id, timeout: 4 });
- }
-
- if (!modal.hide) {
- $("#spinner-storagepools-import").addClass("hidden");
- $("#spinner-storagepools-import span").text("");
- $("#btn-storagepools-import-apply").prop("disabled", false);
- }
-
- if (!pool.imported) {
- FnConsole.warn("Storage Pools, Import: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- }
- })
- .finally(function () {
- if (pool.imported) {
- if (filesystem.selinux && !pool.readonly) {
- $("#spinner-storagepools-import span").text("Configuring SELinux contexts for Samba...");
-
- FnStoragePoolSelinuxContextsSambaSet({ name: pool.name, id: pool.id })
- .finally(function () {
- if (zfsmanager.configuration.samba.manage) {
- if (!pool.readonly) {
- $("#spinner-storagepools-import span").text("Disabling Samba share inheritance...");
-
- FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false) }, { name: null }, { disable: false })
- .finally(function () {
- $("#spinner-storagepools-import span").text("Creating Samba shares...");
-
- FnSambaSharesEnable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false), readonly: pool.readonly }, { name: null, force: true }, { restart: false }, { refresh: false, silent: false })
- .finally(function () {
- if (modal.hide) {
- $("#modal-storagepools-import").modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- });
- });
- } else {
- $("#spinner-storagepools-import span").text("Creating Samba shares...");
-
- FnSambaSharesEnable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false), readonly: pool.readonly }, { name: null, force: true }, { restart: false }, { refresh: false, silent: false })
- .finally(function () {
- if (modal.hide) {
- $("#modal-storagepools-import").modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- });
- }
- } else {
- if (modal.hide) {
- $("#modal-storagepools-import").modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- }
- });
- } else {
- if (zfsmanager.configuration.samba.manage) {
- if (!pool.readonly) {
- $("#spinner-storagepools-import span").text("Disabling Samba share inheritance...");
-
- FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false) }, { name: null }, { disable: false })
- .finally(function () {
- $("#spinner-storagepools-import span").text("Creating Samba shares...");
-
- FnSambaSharesEnable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false), readonly: pool.readonly }, { name: null, force: true }, { restart: false }, { refresh: false, silent: false })
- .finally(function () {
- if (modal.hide) {
- $("#modal-storagepools-import").modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- });
- });
- } else {
- $("#spinner-storagepools-import span").text("Creating Samba shares...");
-
- FnSambaSharesEnable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false), readonly: pool.readonly }, { name: null, force: true }, { restart: false }, { refresh: false, silent: false })
- .finally(function () {
- if (modal.hide) {
- $("#modal-storagepools-import").modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- });
- }
- } else {
- if (modal.hide) {
- $("#modal-storagepools-import").modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- }
- }
- } else {
- if (modal.hide) {
- $("#modal-storagepools-import").modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 200);
- }
- }
- });
-}
-
-function FnStoragePoolRefreservationSet(pool = { name, id }, filesystem = { refreservation }) {
- let process = {
- command: ["/sbin/zfs", "set", "refreservation=" + filesystem.refreservation, pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Refreservation, Set: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[2]("Storage Pools, Refreservation, Set: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Refreservation, Set: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolRefresh(pool = { name, id }, refresh = { storagepool: true, filesystems: false, snapshots: false, status: false }) {
- if (zfsmanager.configuration.zfs.storagepool.refreshall || refresh.storagepool) {
- FnStoragePoolRefreshCommand({ name: pool.name, id: pool.id });
- }
-
- setTimeout(function () {
- if (zfsmanager.configuration.zfs.storagepool.refreshall) {
- FnStoragePoolRefreshAutoDisable({ name: pool.name, id: pool.id });
- }
-
- if (zfsmanager.configuration.zfs.storagepool.refreshall || refresh.filesystems) {
- $("#btn-storagepool-filesystems-create-" + pool.id).prop("disabled", true);
- $("#btn-storagepool-filesystems-refresh-" + pool.id).prop("disabled", true);
- $("[id^=btn-storagepool-filesystem-dropdown-" + pool.id + "]").addClass("disabled");
- $("#paneltitle-storagepool-filesystems-" + pool.id).addClass("hidden");
- $("#spinner-storagepool-filesystems-" + pool.id).removeClass("hidden");
-
- FnFileSystemsGet({ name: pool.name, id: pool.id });
- }
-
- if (zfsmanager.configuration.zfs.storagepool.refreshall || refresh.snapshots) {
- $("#btn-storagepool-snapshots-create-" + pool.id).prop("disabled", true);
- $("#btn-storagepool-snapshots-refresh-" + pool.id).prop("disabled", true);
- $("[id^=btn-storagepool-snapshot-dropdown-" + pool.id + "]").addClass("disabled");
- $("#paneltitle-storagepool-snapshots-" + pool.id).addClass("hidden");
- $("#spinner-storagepool-snapshots-" + pool.id).removeClass("hidden");
-
- FnSnapshotsGet({ name: pool.name, id: pool.id });
- }
-
- if (zfsmanager.configuration.zfs.storagepool.refreshall || refresh.status) {
- $("#btn-storagepool-status-refresh-" + pool.id).prop("disabled", true);
- $("[id^=btn-storagepool-status-dropdown-][id$=" + pool.id + "]").addClass("disabled");
- $("#paneltitle-storagepool-status-" + pool.id).addClass("hidden");
- $("#spinner-storagepool-status-" + pool.id).removeClass("hidden");
- $("#spinner-storagepool-status-0-" + pool.id).removeClass("hidden");
-
- FnStatusGet({ name: pool.name, id: pool.id });
- }
- }, 200);
-}
-
-function FnStoragePoolRefreshAutoDisable(pool = { name, id }) {
- if ($("#tr-storagepool-" + pool.id).attr("data-pool-refresh-id") != "") {
- FnConsole.log[2]("Storage Pools, Refresh, Auto: Disabled, Pool: " + pool.name);
- }
-
- clearInterval($("#tr-storagepool-" + pool.id).attr("data-pool-refresh-id"));
-
- $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-id", "");
- $("#btn-storagepool-status-refresh-" + pool.id).text("Refresh");
-}
-
-function FnStoragePoolRefreshCommand(pool = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "list", "-H", "-o", "guid,health,size,alloc,free,fragmentation,autotrim,version,feature@allocation_classes,feature@async_destroy,feature@bookmark_v2,feature@bookmarks,feature@device_removal,feature@edonr,feature@embedded_data,feature@empty_bpobj,feature@enabled_txg,feature@encryption,feature@extensible_dataset,feature@filesystem_limits,feature@hole_birth,feature@large_blocks,feature@large_dnode,feature@lz4_compress,feature@multi_vdev_crash_dump,feature@obsolete_counts,feature@project_quota,feature@resilver_defer,feature@sha512,feature@skein,feature@spacemap_histogram,feature@spacemap_v2,feature@userobj_accounting,feature@zpool_checkpoint", "-p", pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Refresh: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Refresh:" }));
-
- pool.properties = data.trim().split(/\t/g).filter(v => v);
-
- //0=guid, 1=health, 2=size, 3=alloc, 4=free, 5=fragmentation, 6=autotrim, 7=version, 8=feature@allocation_classes, 9=feature@async_destroy, 10=feature@bookmark_v2, 11=feature@bookmarks, 12=feature@device_removal, 13=feature@edonr, 14=feature@embedded_data, 15=feature@empty_bpobj, 16=feature@enabled_txg, 17=feature@encryption, 18=feature@extensible_dataset, 19=feature@filesystem_limits, 20=feature@hole_birth, 21=feature@large_blocks, 22=feature@large_dnode, 23=feature@lz4_compress, 24=feature@multi_vdev_crash_dump, 25=feature@obsolete_counts, 26=feature@project_quota, 27=feature@resilver_defer, 28=feature@sha512, 29=feature@skein, 30=feature@spacemap_histogram, 31=feature@spacemap_v2, 32=feature@userobj_accounting, 33=feature@zpool_checkpoint
-
- pool.allocated = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[3] });
- pool.allocatedpercent = FnRound({ decimals: 2, value: (pool.properties[3] / pool.properties[2]) * 100 });
- pool.autotrim = (pool.properties[6].toLowerCase() == "on" ? true : false);
- pool.boot = (zfsmanager.zfs.storagepool.boot && pool.name == zfsmanager.zfs.storagepool.boot ? true : false);
- pool.feature = {
- allocation_classes: (/active|enabled/gi.test(pool.properties[8]) ? true : false),
- async_destroy: (/active|enabled/gi.test(pool.properties[9]) ? true : false),
- bookmark_v2: (/active|enabled/gi.test(pool.properties[10]) ? true : false),
- bookmarks: (/active|enabled/gi.test(pool.properties[11]) ? true : false),
- device_removal: (/active|enabled/gi.test(pool.properties[12]) ? true : false),
- edonr: (/active|enabled/gi.test(pool.properties[13]) ? true : false),
- embedded_data: (/active|enabled/gi.test(pool.properties[14]) ? true : false),
- empty_bpobj: (/active|enabled/gi.test(pool.properties[15]) ? true : false),
- enabled_txg: (/active|enabled/gi.test(pool.properties[16]) ? true : false),
- encryption: (/active|enabled/gi.test(pool.properties[17]) ? true : false),
- extensible_dataset: (/active|enabled/gi.test(pool.properties[18]) ? true : false),
- filesystem_limits: (/active|enabled/gi.test(pool.properties[19]) ? true : false),
- hole_birth: (/active|enabled/gi.test(pool.properties[20]) ? true : false),
- large_blocks: (/active|enabled/gi.test(pool.properties[21]) ? true : false),
- large_dnode: (/active|enabled/gi.test(pool.properties[22]) ? true : false),
- lz4_compress: (/active|enabled/gi.test(pool.properties[23]) ? true : false),
- multi_vdev_crash_dump: (/active|enabled/gi.test(pool.properties[24]) ? true : false),
- obsolete_counts: (/active|enabled/gi.test(pool.properties[25]) ? true : false),
- project_quota: (/active|enabled/gi.test(pool.properties[26]) ? true : false),
- resilver_defer: (/active|enabled/gi.test(pool.properties[27]) ? true : false),
- sha512: (/active|enabled/gi.test(pool.properties[28]) ? true : false),
- skein: (/active|enabled/gi.test(pool.properties[29]) ? true : false),
- spacemap_histogram: (/active|enabled/gi.test(pool.properties[30]) ? true : false),
- spacemap_v2: (/active|enabled/gi.test(pool.properties[31]) ? true : false),
- userobj_accounting: (/active|enabled/gi.test(pool.properties[32]) ? true : false),
- zpool_checkpoint: (/active|enabled/gi.test(pool.properties[33]) ? true : false)
- };
- pool.fragmentation = (pool.properties[5] == "-" ? 0 : pool.properties[5]);
- pool.free = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[4] });
- pool.freepercent = FnRound({ decimals: 2, value: (pool.properties[4] / pool.properties[2]) * 100 });
- pool.guid = pool.properties[0];
- pool.health = pool.properties[1];
- pool.healthicon = FnStoragePoolHealthIcon({ health: pool.health });
- pool.root = (zfsmanager.zfs.storagepool.root && pool.name == zfsmanager.zfs.storagepool.root ? true : false);
- pool.size = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[2] });
- pool.upgrade = ($.isNumeric(pool.properties[6] && !pool.boot) ? true : false);
- pool.version = pool.properties[7];
-
- //Upgrade available if a requested feature flag returns false
- if (!pool.boot) {
- for (var x in pool.feature) {
- if (!pool.feature[x] && !pool.upgrade) {
- pool.upgrade = true;
- }
- }
- }
-
- if (pool.upgrade) {
- $("#span-storagepool-upgrade-" + pool.id).removeClass("hidden");
- } else {
- $("#span-storagepool-upgrade-" + pool.id).addClass("hidden");
- }
-
- $("#div-storagepool-health-" + pool.id).empty().html(` ` + pool.health);
- $("#div-storagepool-size-" + pool.id).text(pool.size);
- $("#div-storagepool-allocated-" + pool.id).text(pool.allocated);
- $("#div-storagepool-free-" + pool.id).text(pool.free);
- $("#div-storagepool-fragmentation-" + pool.id).text(pool.fragmentation + " %");
-
- $("#progressbar-storagepool-allocated-" + pool.id).attr("aria-valuenow", pool.allocatedpercent);
- $("#progressbar-storagepool-allocated-" + pool.id).attr("title", pool.allocatedpercent + "% Allocated");
- $("#progressbar-storagepool-allocated-" + pool.id).attr("data-original-title", pool.allocatedpercent + "% Allocated");
- $("#progressbar-storagepool-allocated-" + pool.id).css("width", pool.allocatedpercent + "%");
- $("#progressbar-storagepool-allocated-" + pool.id + " .sr-only").text(pool.allocatedpercent + "% Allocated");
-
- $("#progressbar-storagepool-free-" + pool.id).attr("aria-valuenow", pool.freepercent);
- $("#progressbar-storagepool-free-" + pool.id).attr("title", pool.freepercent + "% Free");
- $("#progressbar-storagepool-free-" + pool.id).attr("data-original-title", pool.freepercent + "% Free");
- $("#progressbar-storagepool-free-" + pool.id).css("width", pool.freepercent + "%");
- $("#progressbar-storagepool-free-" + pool.id + " .sr-only").text(pool.freepercent + "% Free");
-
- $("#tr-storagepool-" + pool.id).attr("data-pool-autotrim", pool.autotrim);
- $("#tr-storagepool-" + pool.id).attr("data-pool-feature-allocation_classes", pool.feature.allocation_classes);
- $("#tr-storagepool-" + pool.id).attr("data-pool-feature-device_removal", pool.feature.device_removal);
- $("#tr-storagepool-" + pool.id).attr("data-pool-feature-edonr", pool.feature.edonr);
- $("#tr-storagepool-" + pool.id).attr("data-pool-feature-encryption", pool.feature.encryption);
- $("#tr-storagepool-" + pool.id).attr("data-pool-feature-large_blocks", pool.feature.large_blocks);
- $("#tr-storagepool-" + pool.id).attr("data-pool-feature-lz4_compress", pool.feature.lz4_compress);
- $("#tr-storagepool-" + pool.id).attr("data-pool-feature-resilver_defer", pool.feature.resilver_defer);
- $("#tr-storagepool-" + pool.id).attr("data-pool-feature-sha512", pool.feature.sha512);
- $("#tr-storagepool-" + pool.id).attr("data-pool-feature-skein", pool.feature.skein);
- $("#tr-storagepool-" + pool.id).attr("data-pool-guid", pool.guid);
- $("#tr-storagepool-" + pool.id).attr("data-pool-version", pool.version);
-
- FnConsole.log[1]("Storage Pools, Refresh: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Refresh: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolRegenerateGuid(pool = { name, id }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "reguid", pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Regenerate GUID: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Regenerating storage pool GUID...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Storage Pool GUID successfully regenerated", description: pool.name, breakword: false }, { name: "storagepool-regenerateguid", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Regenerate GUID: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Storage Pool GUID could not be regenerated", description: pool.name, breakword: false }, { name: "storagepool-regenerateguid", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Regenerate GUID: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });;
-}
-
-function FnStoragePoolResilver(pool = { name, id }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "resilver", pool.name]
- };
-
- FnConsole.log[1]("Storage Pools, Resilver, Start: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Starting storage pool resilver...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Storage Pool resilver successfully started", description: pool.name, breakword: false }, { name: "storagepool-resilver", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Resilver, Start: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Storage Pool resilver could not be started", description: pool.name, breakword: false }, { name: "storagepool-resilver", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Resilver, Start: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });
-}
-
-function FnStoragePoolScrubPause(pool = { name, id }, display = { refresh: true }) {
- let process = {
- command: ["/sbin/zpool", "scrub", "-p", pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Scrub, Pause: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Storage Pool scrub successfully paused", description: pool.name, breakword: false }, { name: "storagepool-scrub-pause", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Scrub, Pause: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Storage Pool scrub could not be paused", description: pool.name, breakword: false }, { name: "storagepool-scrub-pause", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Scrub, Pause: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- }
- });;
-}
-
-function FnStoragePoolScrubStart(pool = { name, id }, scrub = { resume: false }, display = { refresh: true }) {
- let process = {
- command: ["/sbin/zpool", "scrub", pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Scrub, " + (scrub.resume ? "Resume" : "Start") + ": In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Storage Pool scrub successfully " + (scrub.resume ? "resumed" : "started"), description: pool.name, breakword: false }, { name: "storagepool-scrub-start", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Scrub, " + (scrub.resume ? "Resume" : "Start") + ": Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- if (/currently scrubbing/gi.test(data)) { //Start scrub will fail if the storage pool has already initiated scrub
- FnDisplayAlert({ status: "success", title: "Storage Pool scrub successfully " + (scrub.resume ? "resumed" : "started"), description: pool.name, breakword: false }, { name: "storagepool-scrub-start", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Scrub, " + (scrub.resume ? "Resume" : "Start") + ": Success, Pool: " + pool.name);
- } else {
- if (/currently resilvering/gi.test(data)) { //Start scrub will fail if the storage pool has initiated resilver
- FnDisplayAlert({ status: "warning", title: "Storage Pool scrub could not be " + (scrub.resume ? "resumed" : "started") + ". Resilver in progress", description: pool.name, breakword: false }, { name: "storagepool-scrub-start", id: pool.id, timeout: 4 });
- } else {
- FnDisplayAlert({ status: "danger", title: "Storage Pool scrub could not be " + (scrub.resume ? "resumed" : "started"), description: pool.name, breakword: false }, { name: "storagepool-scrub-start", id: pool.id, timeout: 4 });
- }
-
- FnConsole.warn("Storage Pools, Scrub, " + (scrub.resume ? "Resume" : "Start") + ": Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- }
- })
- .finally(function () {
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- }
- });
-}
-
-function FnStoragePoolScrubStop(pool = { name, id }, display = { refresh: true }) {
- let process = {
- command: ["/sbin/zpool", "scrub", "-s", pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Scrub, Stop: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Storage Pool scrub successfully stopped", description: pool.name, breakword: false }, { name: "storagepool-scrub-stop", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Scrub, Stop: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Storage Pool scrub could not be stopped", description: pool.name, breakword: false }, { name: "storagepool-scrub-stop", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Scrub, Stop: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- }
- });;
-}
-
-function FnStoragePoolSelinuxContextsSambaSet(pool = { name, id }, display = { silent: false }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name", "-r", "-t", "filesystem", pool.name],
- promise: cockpit.defer()
- };
-
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, SELinux Contexts, Samba, Set:" }));
-
- let filesystems = data.split(/\n/g).filter(v => v);
- let promise = Promise.resolve();
-
- if (filesystems.length > 0) {
- filesystems.forEach((_value, _index) => {
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- FnFileSystemSelinuxContextsSambaSet({ name: pool.name, id: pool.id }, { name: _value })
- .finally(function () {
- if (_index == (filesystems.length - 1)) {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "SELinux contexts for Samba successfully configured", description: pool.name, breakword: false }, { name: "selinux-enable", id: pool.id, timeout: 4 });
- }
-
- process.promise.resolve();
- }
- });
-
- resolve();
- }, 500)
- ));
- });
- } else {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "SELinux contexts for Samba successfully configured", description: pool.name, breakword: false }, { name: "selinux-enable", id: pool.id, timeout: 4 });
- }
-
- process.promise.resolve();
- }
- })
- .fail(function (message, data) {
- if (!display.silent) {
- FnDisplayAlert({ status: "danger", title: "SELinux contexts for Samba could not be configured", description: pool.name, breakword: false }, { name: "selinux-enable", id: pool.id, timeout: 4 });
- }
-
- FnConsole.warn("Storage Pools, SELinux Contexts, Samba, Set: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
-
- process.promise.resolve();
- });
-
- return process.promise.promise();
-}
-
-function FnStoragePoolSizeGet(pool = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "get", "size", "-H", "-o", "value", "-p", pool.name]
- };
-
- FnConsole.log[2]("Storage Pools, Size, Get: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function () {
- FnConsole.log[2]("Storage Pools, Size, Get: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Storage Pools, Size. Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnStoragePoolSpinnerHide(pool = { name, id }) {
- if ($("#tr-storagepool-" + pool.id).attr("data-pool-refresh-filesystems") == "true" && $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-snapshots") == "true" && $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-status") == "true") {
- setTimeout(function () {
- $("#spinner-storagepool-" + pool.id).addClass("hidden");
- $("#listingcthead-storagepool-" + pool.id).removeClass("hidden");
- $("#listingctbody-storagepool-" + pool.id).removeClass("hidden");
- }, 200);
- }
-}
-
-function FnStoragePoolTrimCancel(pool = { name, id }, disk = { id }) {
- let process = {
- command: ["/sbin/zpool", "trim", "-c", pool.name]
- };
-
- if (disk.id) {
- process.command.push(disk.id);
- }
-
- FnConsole.log[2]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Cancel: In Progress, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM successfully cancelled", description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-cancel", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Cancel: Success, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM could not be cancelled", description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-cancel", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Cancel: Failed, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : "") + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });
-}
-
-function FnStoragePoolTrimStart(pool = { name, id }, disk = { id }, trim = { resume: false, secure: false }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "trim", pool.name]
- };
-
- if (trim.secure) {
- process.command.splice(2, 0, "-d");
- }
- if (disk.id) {
- process.command.push(disk.id);
- }
-
- FnConsole.log[2]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, " + (trim.resume ? "Resume" : "Start") + ": In Progress, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- if (!trim.resume) {
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Starting " + (disk.id ? "disk" : "storage pool") + " TRIM...");
- }
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM successfully " + (trim.resume ? "resumed" : "started"), description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-start", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, " + (trim.resume ? "Resume" : "Start") + ": Success, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM could not be " + (trim.resume ? "resumed" : "started"), description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-start", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, " + (trim.resume ? "Resume" : "Start") + ": Failed, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : "") + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- if (modal.name && modal.id) {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
- }
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });
-}
-
-function FnStoragePoolTrimSuspend(pool = { name, id }, disk = { id }) {
- let process = {
- command: ["/sbin/zpool", "trim", "-s", pool.name]
- };
-
- if (disk.id) {
- process.command.push(disk.id);
- }
-
- FnConsole.log[2]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Suspend: In Progress, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM successfully suspended", description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-suspend", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Suspend: Success, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM could not be suspended", description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-suspend", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Suspend: Failed, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : "") + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });
-}
-
-function FnStoragePoolUpgrade(pool = { name, id }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "upgrade", pool.name]
- };
-
- FnConsole.log[1]("Storage Pools, Upgrade: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Upgrading storage pool...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Upgrade:" }));
-
- if (/Successfully upgraded|Enabled the following features/gi.test(data)) {
- FnDisplayAlert({ status: "success", title: "Storage Pool successfully upgraded", description: pool.name, breakword: false }, { name: "storagepool-upgrade", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Upgrade: Success, Pool: " + pool.name);
- } else {
- FnStoragePoolUpgradeFail({ name: pool.name, id: pool.id }, { data: data, message: message });
- }
- })
- .fail(function (message, data) {
- FnStoragePoolUpgradeFail({ name: pool.name, id: pool.id }, { data: data, message: message });
- })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true , snapshots: true, status: true });
- }, 200);
- });;
-}
-
-function FnStoragePoolUpgradeFail(pool = { name, id }, process = { data, message }) {
- FnDisplayAlert({ status: "danger", title: "Storage Pool could not be upgraded", description: pool.name, breakword: false }, { name: "storagepool-upgrade", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Upgrade: Failed, Pool: " + pool.name + ", Message: " + (process.data ? process.data : process.message));
-}
-
-function FnStoragePoolVirtualDeviceAdd(pool = { name, id, force: false, virtualdevice }, disks = { id: [] }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "add", pool.name]
- };
-
- modal.hide = true;
-
- if (pool.force) {
- process.command.splice(2, 0, "-f");
- }
- if (pool.virtualdevice) {
- if (pool.virtualdevice == "dedup mirror") {
- process.command.push("dedup");
- process.command.push("mirror");
- } else if (pool.virtualdevice == "log mirror") {
- process.command.push("log");
- process.command.push("mirror");
- } else if (pool.virtualdevice == "special mirror") {
- process.command.push("special");
- process.command.push("mirror");
- } else {
- process.command.push(pool.virtualdevice);
- }
- }
-
- disks.id.forEach(_value => _value && process.command.push(_value));
-
- FnConsole.log[1]("Storage Pools, Virtual Device, Add: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Adding virtual device...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Virtual Device successfully added to Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-virtualdevice-add", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Virtual Device, Add: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- if (/contains devices of different sizes/gi.test(data)) {
- modal.hide = false;
-
- $("#validationwrapper-" + modal.name + "-disks-" + modal.id).addClass("has-error");
- $("#helpblock-" + modal.name + "-disks-" + modal.id).addClass("has-error").removeClass("hidden").text("Disks are of different sizes. Forcefully add virtual device to override.");
- } else if (/mismatched replication level/gi.test(data)) {
- modal.hide = false;
-
- $("#validationwrapper-" + modal.name + "-disks-" + modal.id).addClass("has-error");
- $("#helpblock-" + modal.name + "-disks-" + modal.id).addClass("has-error").removeClass("hidden").text("Mismatched replication level. Forcefully add virtual device to override.");
- }
-
- if (!modal.hide) {
- $("#spinner-" + modal.name + "-" + modal.id).addClass("hidden");
- $("#btn-" + modal.name + "-apply-" + modal.id).prop("disabled", false);
-
- $("[id^=btn-storagepool-status-dropdown-][id$=" + pool.id + "]").removeClass("disabled");
- $("#spinner-storagepool-status-" + modal.id).addClass("hidden");
- }
-
- if (modal.hide) {
- FnDisplayAlert({ status: "danger", title: "Virtual Device could not be added to Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-virtualdevice-add", id: pool.id, timeout: 4 });
- }
-
- FnConsole.warn("Storage Pools, Virtual Device, Add: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- if (modal.hide) {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: true });
- }, 200);
- }
- });
-}
-
-function FnStoragePoolVirtualDeviceClear(pool = { name, id }, virtualdevice = { id }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "clear", pool.name, virtualdevice.id]
- };
-
- FnConsole.log[2]("Storage Pools, Virtual Device, Clear Errors: In Progress, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Clearing virtual device errors...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Virtual Device errors successfully cleared", description: virtualdevice.id, breakword: false }, { name: "storagepool-virtualdevice-clear", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Virtual Device, Clear Errors: Success, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Virtual Device errors could not be cleared", description: virtualdevice.id, breakword: false }, { name: "storagepool-virtualdevice-clear", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Virtual Device, Clear Errors: Failed, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
- }, 200);
- });
-}
-
-function FnStoragePoolVirtualDeviceRemove(pool = { name, id }, virtualdevice = { id, labelclear: false }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zpool", "remove", pool.name, virtualdevice.id]
- };
-
- modal.hide = true;
-
- FnConsole.log[1]("Storage Pools, Virtual Device, Remove: In Progress, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Removing virtual device...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Virtual Device successfully removed from Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-virtualdevice-remove", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Storage Pools, Virtual Device, Remove: Success, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id);
-
- if (virtualdevice.labelclear) {
- modal.hide = false;
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Clearing disk label...");
-
- setTimeout(function () {
- FnStoragePoolDiskLabelClear({ name: pool.name, id: pool.id }, { id: virtualdevice.id, inactive: true }, { silent: false })
- .finally(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: true });
- }, 200);
- });
- }, 2000);
- }
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Virtual Device could not be removed from Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-virtualdevice-remove", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Storage Pools, Virtual Device, Remove: Failed, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- if (modal.hide) {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: true });
- }, 200);
- }
- });
-}
-
-//#endregion
-
-//#region File Systems
-
-function FnFileSystemsGet(pool = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "readonly,name,avail,used,usedsnap,usedrefreserv,recordsize,compression,dedup,sharenfs,sharesmb,mountpoint,mounted,origin,encryption,encryptionroot,keyformat,keystatus", "-r", "-p", pool.name]
- };
- let filesystems = {
- empty: true
- };
-
- pool.altroot = (($("#tr-storagepool-" + pool.id).attr("data-pool-altroot") == "true") ? true : false);
- pool.boot = (($("#tr-storagepool-" + pool.id).attr("data-pool-boot") == "true") ? true : false);
- pool.readonly = (($("#tr-storagepool-" + pool.id).attr("data-pool-readonly") == "true") ? true : false);
- pool.feature = {
- allocation_classes: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-allocation_classes") == "true") ? true : false),
- edonr: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-edonr") == "true") ? true : false),
- encryption: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-encryption") == "true") ? true : false),
- large_blocks: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-large_blocks") == "true") ? true : false),
- large_dnode: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-large_dnode") == "true") ? true : false),
- lz4_compress: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-lz4_compress") == "true") ? true : false),
- sha512: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-sha512") == "true") ? true : false),
- skein: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-skein") == "true") ? true : false)
- };
-
- FnConsole.log[2]("File Systems, Get: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Get:" }));
-
- if (data) {
- filesystems.empty = false;
-
- FnStoragePoolSizeGet({ name: pool.name, id: pool.id })
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Storage Pools, Size, Get:" }));
-
- if (_data) {
- pool.sizeraw = _data.replace(/\n+/g, "");
-
- FnFileSystemsGetCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, boot: pool.boot, feature: { allocation_classes: pool.feature.allocation_classes, edonr: pool.feature.edonr, encryption: pool.feature.encryption, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, sha512: pool.feature.sha512, skein: pool.feature.skein }, readonly: pool.readonly, sizeraw: pool.sizeraw }, { data: data, message: message });
- }
- })
- .fail(function () {
- FnFileSystemsGetCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, boot: pool.boot, feature: { allocation_classes: pool.feature.allocation_classes, edonr: pool.feature.edonr, encryption: pool.feature.encryption, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, sha512: pool.feature.sha512, skein: pool.feature.skein }, readonly: pool.readonly, sizeraw: null }, { data: data, message: message });
- });
- }
-
- FnConsole.log[1]("File Systems, Get: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- if (filesystems.empty) {
- $("#tbody-storagepool-filesystems-" + pool.id).empty();
- $("#tbody-storagepool-filesystems-" + pool.id).append(`No file systems found. `);
- $("#modals-storagepool-filesystems-" + pool.id).remove();
- $("#modals-storagepool-filesystem-" + pool.id).remove();
- $("#modals").append(`
`);
-
- //Register file systems modals
- if (!pool.readonly) {
- FnModalFileSystemsCreate({ name: pool.name, id: pool.id, altroot: pool.altroot, feature: { allocation_classes: pool.feature.allocation_classes, edonr: pool.feature.edonr, encryption: pool.feature.encryption, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, sha512: pool.feature.sha512, skein: pool.feature.skein } });
- }
-
- $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-filesystems", "true");
-
- $("#spinner-storagepool-filesystems-" + pool.id).addClass("hidden");
- $("#paneltitle-storagepool-filesystems-" + pool.id).removeClass("hidden").text(FnDateTime());
- $("#btn-storagepool-filesystems-create-" + pool.id).prop("disabled", false);
- $("#btn-storagepool-filesystems-refresh-" + pool.id).prop("disabled", false);
- }
-
- FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
- FnCockpitElementsUpdate();
- });
-}
-
-function FnFileSystemsGetCommand(pool = { name, id, altroot: false, boot: false, feature: { allocation_classes: true, edonr: true, encryption: true, large_blocks: true, large_dnode: true, lz4_compress: true, sha512: true, skein: true }, readonly: false, sizeraw: 0 }, process = { data, message }) {
- let filesystems = process.data.split(/\n/g).filter(v => v);
-
- $("#tbody-storagepool-filesystems-" + pool.id).empty();
- $("#modals-storagepool-filesystems-" + pool.id).remove();
- $("#modals-storagepool-filesystem-" + pool.id).remove();
- $("#modals").append(`
`);
- $("#modals").append(`
`);
-
- filesystems.forEach((_value, _index) => {
- let filesystem = {
- properties: _value.split(/\t/g).filter(v => v),
- clone: false,
- compression: "",
- dedup: "",
- encryption: false,
- encryptionroot: "",
- id: "",
- keyformat: "",
- keystatus: "",
- mounted: false,
- mountpoint: "",
- name: "",
- origin: "",
- readonly: false,
- recordsize: "",
- shares: [],
- sharenfs: false,
- sharesmb: false,
- type: "File System",
- actionsmenu: {
- register: {
- samba: {},
- snapshot: {}
- }
- }
- };
-
- filesystem.output = ``;
-
- filesystem.properties.forEach((__value, __index) => {
- //0=readonly, 1=name, 2=avail, 3=used, 4=usedsnap, 5=usedrefreserv, 6=recordsize, 7=compression, 8=dedup, 9=sharenfs, 10=sharesmb, 11=mountpoint, 12=mounted, 13=origin, 14=encryption, 15=encryptionroot, 16=keyformat, 17=keystatus
-
- switch (__index) {
- case 0: //0=readonly
- if (__value.toLowerCase() == "on" || pool.boot && zfsmanager.configuration.zfs.storagepool.bootlockdown) {
- filesystem.readonly = true;
- }
-
- break;
- case 1: //1=name
- filesystem.name = __value;
- filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.name, attribute: true });
-
- filesystem.output += `Name: ` + __value + (filesystem.readonly ? ` ` : ``) + ` `;
-
- break;
- case 2: //2=avail
- filesystem.output += `Available: ` + FnFormatBytes({ base2: true, decimals: 2, value: __value }) + ` `;
-
- break;
- case 3: //3=used
- filesystem.output += `Used: ` + FnFormatBytes({ base2: true, decimals: 2, value: __value }) + ` `;
-
- break;
- case 4: //4=usedsnap
- filesystem.output += `Snapshots: ` + FnFormatBytes({ base2: true, decimals: 2, value: __value }) + ` `;
-
- break;
- case 5: //5=usedrefreserv
- if (pool.sizeraw) {
- filesystem.usedrefreservpercent = FnRound({ decimals: 1, value: (__value / pool.sizeraw) * 100 });
-
- __value = FnFormatBytes({ base2: true, decimals: 2, value: __value });
-
- if ($.isNumeric(filesystem.usedrefreservpercent) && filesystem.usedrefreservpercent > 0) {
- __value += " (" + filesystem.usedrefreservpercent + " %)";
- }
- } else {
- __value = FnFormatBytes({ base2: true, decimals: 2, value: __value });
- }
-
- filesystem.output += `Refreservation: ` + __value + ` `;
-
- break;
- case 6: //6=recordsize
- filesystem.recordsize = __value;
-
- filesystem.output += `Record Size: ` + FnFormatBytes({ base2: true, decimals: 0, value: __value }) + ` `;
-
- break;
- case 7: //7=compression
- filesystem.compression = __value;
-
- if (/off|on/gi.test(__value)) {
- __value = __value.charAt(0).toUpperCase() + __value.slice(1);
- } else {
- __value = __value.toUpperCase();
- }
-
- filesystem.output += `Compression: ` + __value + ` `;
-
- break;
- case 8: //8=dedup
- filesystem.dedup = __value;
-
- if (/sha256|sha512/gi.test(__value)) {
- __value = __value.replace(/sha/gi, "SHA-");
- }
- if (/off|on|verify|skein/gi.test(__value)) {
- __value = __value.charAt(0).toUpperCase() + __value.slice(1);
- }
- if (/edonr/gi.test(__value)) {
- __value = __value.replace(/edonr/gi, "Edon-R");
- }
-
- filesystem.output += `Deduplication: ` + __value.replace(/,verify/g, " + Verify") + ` `;
-
- break;
- case 9: //9=sharenfs
- filesystem.sharenfs = __value;
-
- if (__value.toLowerCase() != "off" && __value.toLowerCase() != "-") {
- filesystem.sharenfs = true;
- filesystem.shares.push("NFS");
- } else {
- filesystem.sharenfs = false;
- }
-
- break;
- case 10: //10=sharesmb
- filesystem.sharesmb = __value;
-
- if (__value.toLowerCase() == "on") {
- filesystem.sharesmb = true;
- filesystem.shares.push("SMB");
- } else {
- filesystem.sharesmb = false;
- }
-
- if (/off|on/gi.test(__value)) {
- __value = __value.charAt(0).toUpperCase() + __value.slice(1);
- } else {
- __value = __value.toUpperCase();
- }
-
- filesystem.output += `Share: ` + (filesystem.shares.length > 0 ? filesystem.shares.join(" + ") : "Off") + ` `;
-
- break;
- case 11: //11=mountpoint
- filesystem.mountpoint = __value;
- break;
- case 12: //12=mounted
- if (__value.toLowerCase() == "yes") {
- filesystem.mounted = true;
- } else {
- filesystem.mounted = false;
- }
-
- if (/yes|no/gi.test(__value)) {
- __value = __value.charAt(0).toUpperCase() + __value.slice(1);
- }
-
- filesystem.output += `Mounted: ` + __value + ` `;
-
- break;
- case 13: //13=origin
- if (__value != "-") {
- filesystem.origin = __value;
- filesystem.clone = true;
- filesystem.type = "Clone File System";
- } else {
- filesystem.clone = false;
- filesystem.type = "File System";
- }
-
- break;
- case 14: //14=encryption
- if (__value.toLowerCase() != "off") {
- filesystem.encryption = true;
- } else {
- filesystem.encryption = false;
- }
-
- break;
- case 15: //15=encryptionroot
- filesystem.encryptionroot = __value;
-
- break;
- case 16: //16=keyformat
- if (filesystem.encryption && __value.toLowerCase() == "passphrase") {
- filesystem.keyformat = "passphrase";
- }
-
- break;
- case 17: //17=keystatus
- if (__value != "-") {
- filesystem.keystatus = __value;
- } else {
- filesystem.keystatus = "";
- }
-
- break;
- }
-
- //Add icons and actions menu at end of array
- if (__index >= (filesystem.properties.length - 1)) {
- filesystem.icons = {
- clone: ` `,
- keystatus: {
- locked: ` `,
- unlocked: ` `
- }
- };
-
- filesystem.output += `Clone: ` + (filesystem.clone ? `Yes ` + filesystem.icons.clone : `No`) + ` `;
- filesystem.output += `Encrypted: ` + (/available|unavailable/.test(filesystem.keystatus) ? `Yes` : `No`) + ` `;
-
- if (filesystem.keystatus == "unavailable") {
- filesystem.output += filesystem.icons.keystatus.locked;
- } else if (filesystem.keystatus == "available") {
- filesystem.output += filesystem.icons.keystatus.unlocked;
- }
-
- filesystem.output += ` `;
-
- //Actions menu
- filesystem.actionsmenu.items = {
- itemconfigure: [],
- itemconfiguredivider: function () {
- if (this.itemconfigure.length > 0 && this.item.length > 0) {
- this.itemconfigure.push(this.divider);
- }
- },
- item: [],
- itemdivider: function () {
- if (this.item.length > 0 && this.itemencrypted.length > 0) {
- this.item.push(this.divider);
- }
- },
- itemencrypted: [],
- itemencrypteddivider: function () {
- if ((this.item.length > 0 || this.itemencrypted.length > 0) && (this.itemsamba.length > 0 || this.itemsnapshot.length > 0)) {
- this.itemencrypted.push(this.divider);
- }
- },
- itemsamba: [],
- itemsambadivider: function () {
- if ((this.item.length > 0 || this.itemencrypted.length > 0) && this.itemsamba.length > 0 && this.itemsnapshot.length > 0) {
- this.itemsamba.push(this.divider);
- }
- },
- itemsnapshot: [],
- divider: ` `
- };
- filesystem.actionsmenu.display = function () {
- if (/@/g.test(filesystem.name) == false && (this.items.itemconfigure.length + this.items.item.length + this.items.itemencrypted.length + this.items.itemsamba.length + this.items.itemsnapshot.length) > 0) {
- this.items.itemconfiguredivider();
- this.items.itemdivider();
- this.items.itemencrypteddivider();
- this.items.itemsambadivider();
-
- return this.header + this.items.itemconfigure.join("\n") + this.items.item.join("\n") + this.items.itemencrypted.join("\n") + this.items.itemsamba.join("\n") + this.items.itemsnapshot.join("\n") + this.footer;
- } else {
- return "";
- }
- };
- filesystem.actionsmenu.header = `
-
-
-
-
-
-
- `;
-
- //Configure File System
- filesystem.actionsmenu.items.itemconfigure.push(`Configure ` + filesystem.type + ` `);
-
- //Rename File System
- if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && filesystem.name != pool.name) {
- filesystem.actionsmenu.items.item.push(`Rename ` + filesystem.type + ` `);
-
- filesystem.actionsmenu.register.rename = true;
- }
-
- //Promote Clone File System
- if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && filesystem.clone && filesystem.origin.replace(/^(.*)\@.*$/, "$1") != pool.name) {
- filesystem.actionsmenu.items.item.push(`Promote ` + filesystem.type + ` `);
-
- filesystem.actionsmenu.register.promote = true;
- }
-
- //Mount File System / Unmount File System
- if (!pool.boot || pool.boot && !zfsmanager.configuration.zfs.storagepool.bootlockdown) {
- if (!filesystem.mounted && filesystem.keystatus != "unavailable") {
- filesystem.actionsmenu.items.item.push(`Mount ` + filesystem.type + ` `);
-
- filesystem.actionsmenu.register.mount = true;
- } else if (filesystem.mounted) {
- filesystem.actionsmenu.items.item.push(`Unmount ` + filesystem.type + ` `);
-
- filesystem.actionsmenu.register.unmount = true;
- }
- }
-
- //Unlock File System / Lock File System
- if (filesystem.keystatus == "unavailable" && !filesystem.clone && filesystem.encryptionroot == filesystem.name) {
- filesystem.actionsmenu.items.item.push(`Unlock File System `);
-
- filesystem.actionsmenu.register.unlock = true;
- } else if (filesystem.keystatus == "available" && !filesystem.mounted && !filesystem.clone && filesystem.encryptionroot == filesystem.name) {
- filesystem.actionsmenu.items.item.push(`Lock File System `);
-
- filesystem.actionsmenu.register.lock = true;
- }
-
- //Change Passphrase
- if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && filesystem.keystatus == "available" && !filesystem.clone && filesystem.encryptionroot == filesystem.name) {
- filesystem.actionsmenu.items.itemencrypted.push(`Change Passphrase `);
-
- filesystem.actionsmenu.register.changepassphrase = true;
- }
-
- //Destroy File System
- if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && filesystem.name != pool.name) {
- if (!filesystem.clone || filesystem.clone && new RegExp("^" + filesystem.name + "/").test(filesystem.origin.replace(/^(.*)\@.*$/, "$1")) == false) { //Do not display if clone origin is a child file system - will generate recursive dependency error
- filesystem.actionsmenu.items.item.push(`Destroy ` + filesystem.type + ` `);
-
- filesystem.actionsmenu.register.destroy = true;
- }
- }
-
- //Enable Samba Share
- if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && !filesystem.sharesmb && zfsmanager.configuration.samba.manage) {
- filesystem.actionsmenu.items.itemsamba.push(`Enable Samba Share `);
-
- filesystem.actionsmenu.register.samba.enable = true;
- }
-
- //Configure Samba Share
- if (filesystem.sharesmb && zfsmanager.configuration.samba.manage) {
- filesystem.actionsmenu.items.itemsamba.push(`Configure Samba Share `);
-
- filesystem.actionsmenu.register.samba.configure = true;
- }
-
- //Disable Samba Share
- if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && filesystem.sharesmb && zfsmanager.configuration.samba.manage) {
- filesystem.actionsmenu.items.itemsamba.push(`Disable Samba Share `);
-
- filesystem.actionsmenu.register.samba.disable = true;
- }
-
- //Create Snapshot
- if (!pool.readonly && zfsmanager.configuration.zfs.filesystem.snapshotactions) {
- filesystem.actionsmenu.items.itemsnapshot.push(`Create Snapshot `);
-
- filesystem.actionsmenu.register.snapshot.create = true;
- }
-
- filesystem.output += ``;
- }
- });
-
- filesystem.output += ` `;
-
- $("#tbody-storagepool-filesystems-" + pool.id).append(filesystem.output);
-
- //Register file system modals
- FnModalFileSystemConfigure({ name: pool.name, id: pool.id, altroot: pool.altroot, feature: { allocation_classes: pool.feature.allocation_classes, edonr: pool.feature.edonr, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, sha512: pool.feature.sha512, skein: pool.feature.skein }, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, origin: filesystem.origin, type: filesystem.type });
- if (filesystem.actionsmenu.register.changepassphrase) {
- FnModalFileSystemChangePassphrase({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- }
- if (filesystem.actionsmenu.register.destroy) {
- FnModalFileSystemDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, sharesmb: filesystem.sharesmb, type: filesystem.type });
- }
- if (filesystem.actionsmenu.register.lock) {
- FnModalFileSystemLock({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, type: filesystem.type });
- }
- if (filesystem.actionsmenu.register.mount) {
- FnModalFileSystemMount({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, sharesmb: filesystem.sharesmb, type: filesystem.type });
- }
- if (filesystem.actionsmenu.register.promote) {
- FnModalFileSystemPromote({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, origin: filesystem.origin, type: filesystem.type });
- }
- if (filesystem.actionsmenu.register.rename) {
- FnModalFileSystemRename({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, id: filesystem.id, clone: filesystem.clone, encryption: filesystem.encryption, encryptionroot: filesystem.encryptionroot, origin: filesystem.origin, sharesmb: filesystem.sharesmb, type: filesystem.type });
- }
- if (filesystem.actionsmenu.register.samba.configure) {
- FnModalFileSystemSambaConfigure({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint });
- }
- if (filesystem.actionsmenu.register.samba.disable) {
- FnModalFileSystemSambaDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, type: filesystem.type });
- }
- if (filesystem.actionsmenu.register.samba.enable) {
- FnModalFileSystemSambaEnable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint });
- }
- if (filesystem.actionsmenu.register.snapshot.create) {
- FnModalFileSystemSnapshotCreate({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- }
- if (filesystem.actionsmenu.register.unlock) {
- FnModalFileSystemUnlock({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, sharesmb: filesystem.sharesmb, type: filesystem.type });
- }
- if (filesystem.actionsmenu.register.unmount) {
- FnModalFileSystemUnmount({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, encryptionroot: filesystem.encryptionroot, keystatus: filesystem.keystatus, sharesmb: filesystem.sharesmb, type: filesystem.type });
- }
- });
-
- //Register file systems modals
- if (!pool.readonly) {
- FnModalFileSystemsCreate({ name: pool.name, id: pool.id, altroot: pool.altroot, feature: { allocation_classes: pool.feature.allocation_classes, edonr: pool.feature.edonr, encryption: pool.feature.encryption, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, sha512: pool.feature.sha512, skein: pool.feature.skein } });
- }
-
- $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-filesystems", "true");
-
- $("#spinner-storagepool-filesystems-" + pool.id).addClass("hidden");
- $("#paneltitle-storagepool-filesystems-" + pool.id).removeClass("hidden").html(FnDateTime() + (zfsmanager.configuration.zfs.storagepool.count ? ` ` + filesystems.length + ` ` : ``));
- $("#btn-storagepool-filesystems-create-" + pool.id).prop("disabled", false);
- $("#btn-storagepool-filesystems-refresh-" + pool.id).prop("disabled", false);
-
- FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
- FnCockpitElementsUpdate();
-}
-
-function FnFileSystemsLockedGet() {
- let filesystems = {
- id: []
- };
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name,encryption,encryptionroot,keyformat,keystatus", "-r", "-t", "filesystem"]
- };
-
- $("#listgroup-storagepools-filesystems-unlock-filesystems").empty().append(`
`);
-
- FnConsole.log[2]("File Systems, Locked, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Locked, Get:" }));
-
- filesystems.id = data.split(/\n/g).filter(v => {
- if (!zfsmanager.configuration.zfs.storagepool.boot && zfsmanager.zfs.storagepool.boot && new RegExp("^" + zfsmanager.zfs.storagepool.boot + "\t|^" + zfsmanager.zfs.storagepool.boot + "/").test(v)) {
- //Do not display boot
- } else if (!zfsmanager.configuration.zfs.storagepool.root && zfsmanager.zfs.storagepool.root && new RegExp("^" + zfsmanager.zfs.storagepool.root + "\t|^" + zfsmanager.zfs.storagepool.root + "/").test(v)) {
- //Do not display root
- } else {
- return v;
- }
- });
-
- filesystems.id.forEach((_value, _index) => {
- let filesystem = {
- properties: _value.split(/\t/g).filter(v => v)
- };
-
- filesystem.name = filesystem.properties[0];
- filesystem.encryption = filesystem.properties[1];
- filesystem.encryptionroot = filesystem.properties[2];
- filesystem.keyformat = filesystem.properties[3];
- filesystem.keystatus = filesystem.properties[4];
-
- if (filesystem.encryptionroot == filesystem.name && filesystem.keyformat == "passphrase" && filesystem.keystatus == "unavailable") {
- filesystems.output = `
-
-
-
- ` + filesystem.name + `
-
-
-
- `;
-
- $("#listgroup-storagepools-filesystems-unlock-filesystems").append(filesystems.output);
- }
- });
-
- setTimeout(function () {
- $("#spinner-storagepools-filesystems-unlock-filesystems").remove();
- $("#listgroup-storagepools-filesystems-unlock-filesystems > li").removeClass("hidden");
- if ($("#helpblock-storagepools-filesystems-unlock-filesystems-warning").text()) {
- $("#helpblock-storagepools-filesystems-unlock-filesystems-warning").removeClass("hidden");
- }
-
- if ($("#listgroup-storagepools-filesystems-unlock-filesystems > li").length == 0) {
- filesystems.output = `
-
-
- No locked file systems found.
-
-
- `;
-
- $("#listgroup-storagepools-filesystems-unlock-filesystems").append(filesystems.output);
- }
- }, 200);
-
- FnConsole.log[1]("File Systems, Locked, Get: Success");
- })
- .fail(function (message, data) {
- $("#spinner-storagepools-filesystems-unlock-filesystems").remove();
- $("#listgroup-storagepools-filesystems-unlock-filesystems > li").removeClass("hidden");
-
- if ($("#listgroup-storagepools-filesystems-unlock-filesystems > li").length == 0) {
- filesystems.output = `
-
-
- No locked file systems found.
-
-
- `;
-
- $("#listgroup-storagepools-filesystems-unlock-filesystems").append(filesystems.output);
- }
-
- FnConsole.warn("File Systems, Locked, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnFileSystemsMountedGet(pool = { name, id }, filesystem = { name, id }, modal = { alert: { id, mount: true } }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name,mounted", "-r", "-t", "filesystem", filesystem.name]
- };
-
- filesystem.children = {
- mounted: false
- }
-
- FnConsole.log[2]("File Systems, Mounted, Get: In Progress: Success, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Mounted, Get:" }));
-
- let filesystems = data.split(/\n/g).filter((v, i) => v && i > 0);
-
- filesystems.forEach((_value, _index) => {
- filesystem.properties = _value.split(/\t/g).filter(v => v);
-
- if (filesystem.properties[1] == "yes" && !filesystem.children.mount) {
- filesystem.children.mounted = true;
- }
- });
-
- if (filesystem.children.mounted) {
- modal.alert.id.html(FnDisplayInlineAlert({ status: "warning", title: "There are child file systems currently mounted. " + (modal.alert.mount ? "Mounting" : "Unmounting") + " this file system may adversely affect the child file systems.", description: null }, { name: null, id: null, hidden: false }));
- }
-
- FnConsole.log[1]("File Systems, Mounted, Get: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, Mounted, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnFileSystemsNamesGet(pool = { name, id }, filesystem = { existing: { name, clone: false, encryption: false, encryptionroot, origin }, override: false }, modal = { dropdown: { id, selected } }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name,encryption,encryptionroot,keystatus", "-r", "-t", "filesystem", pool.name]
- };
-
- FnConsole.log[2]("File Systems, Names, Get: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Names, Get:" }));
-
- let filesystems = data.split(/\n/g).filter(v => v);
-
- modal.dropdown.items = [];
-
- modal.dropdown.id.empty();
-
- filesystems.forEach((_value, _index) => {
- filesystem.properties = _value.split(/\t/g).filter(v => v);
- filesystem.name = filesystem.properties[0];
- filesystem.encryption = (filesystem.properties[1].toLowerCase() != "off" ? true : false);
- filesystem.encryptionroot = (filesystem.properties[2] && filesystem.properties[2] != "-" ? filesystem.properties[2] : "");
- filesystem.encryptionstatus = "";
- filesystem.existing.regexp = {
- name: new RegExp("^" + filesystem.existing.name + "/", "g")
- };
- filesystem.keystatus = filesystem.properties[3].toLowerCase();
-
- if (filesystem.encryption && /^available$|^unavailable$/.test(filesystem.keystatus)) {
- filesystem.encryptionstatus = ` `
- }
-
- modal.dropdown.add = false;
- modal.dropdown.item = `` + filesystem.name + filesystem.encryptionstatus + ` `;
-
- if ((filesystem.override || filesystem.existing.encryption) && filesystem.existing.clone) { //Encrypted clone file systems can only move within origin and child file systems
- filesystem.existing.regexp.origin = new RegExp("^" + filesystem.existing.origin.replace(/^(.*)\@.*$/, "$1\/"), "g");
-
- if (filesystem.name == filesystem.existing.origin.replace(/^(.*)\@.*$/, "$1")) { //Origin file system
- modal.dropdown.add = true;
- } else if (filesystem.name == filesystem.existing.name.replace(/\/[^\/]+$/, "")) { //File System parent
- modal.dropdown.add = true;
- } else if (filesystem.name != filesystem.existing.name && filesystem.existing.regexp.origin.test(filesystem.name) && !filesystem.existing.regexp.name.test(filesystem.name)) { //Origin child file systems
- modal.dropdown.add = true;
- }
- } else if (filesystem.override || filesystem.existing.encryption) { //Encrypted file systems that are their own encryption root can move anywhere, child file system of the encryption root can only move within encryption root and its child file systems
- if (filesystem.name != filesystem.existing.name && !filesystem.existing.regexp.name.test(filesystem.name)) {
- if (filesystem.existing.name == filesystem.existing.encryptionroot) { //File system is its own encryption root
- modal.dropdown.add = true;
- } else if (filesystem.encryptionroot == filesystem.existing.encryptionroot) { //File system is a child of the encryption root
- modal.dropdown.add = true;
- }
- }
- } else { //Unencrypted file systems can only move to unencrypted file systems
- if (!filesystem.encryption && filesystem.name != filesystem.existing.name && !filesystem.existing.regexp.name.test(filesystem.name)) {
- modal.dropdown.add = true;
- }
- }
-
- if (modal.dropdown.add) {
- modal.dropdown.items.push(modal.dropdown.item);
- }
- });
-
- modal.dropdown.id.append(modal.dropdown.items.join("\n"));
-
- FnConsole.log[1]("File Systems, Names, Get: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, Names, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnFileSystemsUnlock(filesystems = { id: [] }, filesystem = { mount: true, overlay: true, passphrase }, modal = { name, id }) {
- let promise = Promise.resolve();
-
- filesystems.count = {
- available: 0,
- error: 0,
- success: 0
- };
-
- $("#listgroup-" + modal.name + modal.id + "-filesystems > li.list-group-item > label > span.pficon").removeClass("list-group-ct-warning");
-
- if (filesystems.id.length > 0) {
- FnConsole.log[2]("File Systems, Unlock: In Progress");
-
- $("#spinner-" + modal.name + modal.id + " span").text("Unlocking file system" + (filesystems.id.length > 1 ? "s" : "") + "...");
-
- filesystems.id.forEach((_value, _index) => {
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- let pool = {
- name: _value.replace(/\/.*$/, ""),
- id: FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: _value.replace(/\/.*$/, ""), attribute: true })
- };
-
- filesystem.name = _value;
- filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: _value, attribute: true });
-
- FnFileSystemUnlock({ name: pool.name, id: pool.id, altroot: false, readonly: false }, { name: filesystem.name, id: filesystem.id, mount: filesystem.mount, overlay: filesystem.overlay, passphrase: filesystem.passphrase, type: "File System" }, { enable: false }, { name: modal.name, id: modal.id }, { refresh: false })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Unlock:" }));
-
- if (/error|Incorrect key/i.test(data)) {
- filesystems.count.error++;
-
- $("#listgroup-" + modal.name + modal.id + "-filesystems > li.list-group-item[data-filesystem-name='" + filesystem.name + "'] > label > span.pficon").addClass("list-group-ct-warning");
- } else {
- filesystems.count.success++;
-
- $("#listgroup-" + modal.name + modal.id + "-filesystems > li.list-group-item[data-filesystem-name='" + filesystem.name + "']").remove();
- }
- })
- .fail(function (message, data) {
- if (/Key already loaded/i.test(data)) {
- filesystems.count.success++;
-
- $("#listgroup-" + modal.name + modal.id + "-filesystems > li.list-group-item[data-filesystem-name='" + filesystem.name + "']").remove();
- } else {
- filesystems.count.error++;
-
- $("#listgroup-" + modal.name + modal.id + "-filesystems > li.list-group-item[data-filesystem-name='" + filesystem.name + "'] > label > span.pficon").addClass("list-group-ct-warning");
- }
- })
- .finally(function () {
- if (_index == (filesystems.id.length - 1)) {
- $("#listgroup-storagepools-filesystems-unlock-filesystems input[name='checkbox-storagepools-filesystems-unlock-filesystems']").map(function () {
- filesystems.count.available++;
- });
-
- if (filesystems.count.error == 0) {
- FnConsole.log[1]("File Systems, Unlock: Success");
- } else {
- FnConsole.warn("File Systems, Unlock: Failed");
- }
-
- if (filesystems.count.available == 0) {
- $("#modal-" + modal.name + modal.id).modal("hide");
- } else {
- $("#spinner-" + modal.name + modal.id).addClass("hidden");
- $("#spinner-" + modal.name + modal.id + " span").text("");
- $("#btn-" + modal.name + "-apply" + modal.id).prop("disabled", false);
- }
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 1000);
- }
- });
-
- resolve();
- }, 1000)
- ));
- });
- } else {
- $("#modal-" + modal.name + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolsGet();
- }, 1000);
- }
-}
-
-//#endregion
-
-//#region File System
-
-function FnFileSystemChangePassphrase(pool = { name, id }, filesystem = { name, id, passphrase }) {
- let process = {
- command: []
- };
-
- if (!filesystem.passphrase || filesystem.passphrase.length < 8) {
- FnFileSystemChangePassphraseFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: "Passphrase requires a minimum of 8 characters.", message: null });
- return;
- }
-
- //Escape percentage and single quote special character for printf
- if (/\%/g.test(filesystem.passphrase)) {
- filesystem.passphrase = filesystem.passphrase.replace(/\%/g, "\%\%");
- }
- if (/\'/g.test(filesystem.passphrase)) {
- filesystem.passphrase = filesystem.passphrase.replace(/\'/g, "\'\"\'\"\'");
- }
-
- process.command = ["/bin/sh", "-c", "printf '" + filesystem.passphrase + "' | /sbin/zfs change-key \"" + filesystem.name + "\""];
-
- FnConsole.log[2]("File Systems, Change Passphrase: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-storagepool-filesystem-changepassphrase-" + filesystem.id + " span").text("Changing passphrase...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Change Passphrase:" }));
-
- if (/error|Key must be loaded/i.test(data)) {
- FnFileSystemChangePassphraseFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: data, message: message });
- return;
- }
-
- FnDisplayAlert({ status: "success", title: "File System passphrase successfully changed", description: filesystem.name, breakword: false }, { name: "filesystem-changepassphrase", id: filesystem.id, timeout: 4 });
-
- FnConsole.log[1]("File Systems, Change Passphrase: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- $("#modal-storagepool-filesystem-changepassphrase-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- })
- .fail(function (message, data) {
- FnFileSystemChangePassphraseFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: data, message: message });
- });
-}
-
-function FnFileSystemChangePassphraseFail(pool = { name, id }, filesystem = { name, id }, process = { data, message }) {
- let modal = {
- hide: true
- };
-
- if (/Passphrase requires a minimum of 8 characters./i.test(process.data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).addClass("has-error");
- $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
- $("#input-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).focus();
- } else if (/Key must be loaded/i.test(process.data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-filesystem-changepassphrase-filesystem-" + filesystem.id).addClass("has-error");
- $("#helpblock-storagepool-filesystem-changepassphrase-filesystem-" + filesystem.id).addClass("has-error").removeClass("hidden").text("File System is locked.");
- $("#input-storagepool-filesystem-changepassphrase-filesystem-" + filesystem.id).focus();
- } else if (/encryption failure/i.test(process.data)) { //Error message when pool is read only
- modal.hide = true;
- } else if (/error/i.test(process.data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).addClass("has-error");
- $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Passphrase is incorrect.");
- $("#input-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).focus();
- }
-
- if (!modal.hide) {
- $("#spinner-storagepool-filesystem-changepassphrase-" + filesystem.id).addClass("hidden");
- $("#spinner-storagepool-filesystem-changepassphrase-" + filesystem.id + " span").text("");
- $("#btn-storagepool-filesystem-changepassphrase-apply-" + filesystem.id).prop("disabled", false);
- }
-
- FnConsole.warn("File Systems, Change Passphrase: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
-
- if (modal.hide) {
- FnDisplayAlert({ status: "danger", title: "File System passphrase could not be changed", description: filesystem.name, breakword: false }, { name: "filesystem-changepassphrase", id: filesystem.id, timeout: 4 });
-
- $("#modal-storagepool-filesystem-changepassphrase-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
-}
-
-function FnFileSystemChildDatasetsGet(pool = { name, id }, filesystem = { name, id, clones: true }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name,clones", "-r", "-t", "filesystem,snapshot", filesystem.name]
- };
-
- FnConsole.log[2]("File Systems, Child, Datasets, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Child, Datasets, Get:" }));
-
- data = data.split(/\n/g).filter(v => v);
-
- let filesystems = {
- id: []
- };
- let snapshots = {
- id: []
- };
-
- if (data.length > 0) {
- data.forEach((_value, _index) => {
- let dataset = {
- properties: _value.split(/\t/g).filter(v => v)
- };
-
- dataset.name = dataset.properties[0];
- dataset.clones = (dataset.properties[1] ? dataset.properties[1] : "");
-
- if (new RegExp("^" + filesystem.name + ".*@").test(dataset.name)) {
- snapshots.id.push(dataset.name);
-
- if (dataset.clones && filesystem.clones) {
- dataset.clones = dataset.clones.split(",").filter(v => v);
-
- dataset.clones.forEach((_value, _index) => {
- filesystems.id.push(_value);
- });
- }
-
- } else if (new RegExp("^" + filesystem.name + ".*@").test(dataset.name) == false) {
- filesystems.id.push(dataset.name);
- }
- });
- }
-
- filesystems.id.sort();
- snapshots.id.sort();
-
- FnConsole.log[1]("File Systems, Child, Datasets, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- FnFileSystemChildFileSystemsGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { id: filesystems.id }, { name: modal.name, id: modal.id });
- FnFileSystemChildSnapshotsGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { id: filesystems.id }, { name: modal.name, id: modal.id });
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, Child, Datasets, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnFileSystemChildFileSystemsGet(pool = { name, id }, filesystem = { name, id }, filesystems = { id: [] }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name", "-r", "-t", "filesystem"]
- };
-
- filesystems.id.forEach(_value => _value && process.command.push(_value));
-
- FnConsole.log[2]("File Systems, Child, File Systems, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Child, File Systems, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v),
- count: {
- filesystems: 0,
- filesystemswithclones: 0
- }
- };
-
- if (filesystems.id.length > 0) {
- filesystems.id.forEach((_value, _index) => {
- if (new RegExp("^" + filesystem.name + "/").test(_value)) {
- filesystems.count.filesystems++;
-
- $("#ul-" + modal.name + "-child-filesystems-" + modal.id).append("" + _value + " \n");
- }
-
- if (_value != filesystem.name) {
- filesystems.count.filesystemswithclones++;
-
- $("#ul-" + modal.name + "-child-filesystemswithclones-" + modal.id).append("" + _value + " \n");
- }
- });
-
- $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-filesystem-child-filesystems", filesystems.count.filesystems);
- $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-filesystem-child-filesystemswithclones", filesystems.count.filesystemswithclones);
- }
-
- FnConsole.log[1]("File Systems, Child, File Systems, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, Child, File Systems, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnFileSystemChildSnapshotsGet(pool = { name, id }, filesystem = { name, id }, snapshots = { id: [] }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name", "-r", "-t", "snapshot"]
- };
-
- snapshots.id.forEach(_value => _value && process.command.push(_value));
-
- FnConsole.log[2]("File Systems, Child, Snapshots, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Child, Snapshots, Get:" }));
-
- let snapshots = {
- id: data.split(/\n/g).filter(v => v),
- count: {
- snapshots: 0,
- snapshotswithclones: 0
- }
- };
-
- if (snapshots.id.length > 0) {
- snapshots.id.forEach((_value, _index) => {
- if (new RegExp("^" + filesystem.name + ".*@").test(_value)) {
- snapshots.count.snapshots++;
-
- $("#ul-" + modal.name + "-child-snapshots-" + modal.id).append("" + _value + " \n");
- }
-
- snapshots.count.snapshotswithclones++;
-
- $("#ul-" + modal.name + "-child-snapshotswithclones-" + modal.id).append("" + _value + " \n");
- });
-
- $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-filesystem-child-snapshots", snapshots.count.snapshots);
- $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-filesystem-child-snapshotswithclones", snapshots.count.snapshotswithclones);
- }
-
- FnConsole.log[1]("File Systems, Child, Snapshots, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, Child, Snapshots, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnFileSystemConfigurationGet(pool = { name, id, readonly: false }, filesystem = { name, id }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "get", "readonly,aclinherit,acltype,atime,available,canmount,casesensitivity,checksum,compression,context,dedup,dnodesize,defcontext,encryption,encryptionroot,fscontext,guid,mountpoint,quota,recordsize,refreservation,rootcontext,sharenfs,sharesmb,special_small_blocks,used,xattr", "-H", "-o", "property,value,source", "-p", filesystem.name]
- };
-
- if (!zfsmanager.user.admin) {
- pool.readonly = true;
- }
-
- filesystem.available = "";
- filesystem.context = false;
- filesystem.fscontext = false;
- filesystem.defcontext = false;
- filesystem.readonly = false;
- filesystem.rootcontext = false;
-
- FnConsole.log[2]("File Systems, Configuration, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Configuration, Get:" }));
-
- process.data = data.replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v);
-
- process.data.forEach((_value, _index) => {
- _value = _value.split("\u22C5");
-
- filesystem.properties = {
- property: _value[0].toLowerCase(),
- value: _value[1].toLowerCase(),
- valueraw: _value[1],
- source: _value[2]
- };
-
- let size = {};
-
- switch (filesystem.properties.property) {
- case "aclinherit": //Default is restricted
- filesystem.property = {
- value: "Restricted",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "discard":
- filesystem.property.value = "Discard";
- break;
- case "noallow":
- filesystem.property.value = "No Allow";
- break;
- case "restricted":
- filesystem.property.value = "Restricted";
- break;
- case "passthrough":
- filesystem.property.value = "Passthrough";
- break;
- case "passthrough-x":
- filesystem.property.value = "Passthrough-X";
- break;
- default:
- filesystem.property.value = "Restricted";
- break;
- }
-
- if (/^inherited/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "inherited";
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- } else if (/^default|^local/gi.test(filesystem.properties.source)) {
- $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
-
- if (/^default/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "default";
- filesystem.property.valueinherited = "Default (Restricted)";
-
- $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
- filesystem.property.source = "local";
-
- $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='InheritedReset'] a").text("Default (Restricted)");
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
- filesystem.property.source = "local";
-
- FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "aclinherit" }, { name: modal.name, id: modal.id });
- }
- }
-
- $("#btnspan-" + modal.name + "-aclinherit-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
- $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#div-" + modal.name + "-aclinherit-dropdown-" + modal.id + " button").prop("disabled", true);
- }
-
- break;
- case "acltype": //Default is off
- filesystem.property = {
- value: "Off",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "off":
- filesystem.property.value = "Off";
- break;
- case "noacl":
- filesystem.property.value = "No ACL";
- break;
- case "posixacl":
- filesystem.property.value = "POSIX ACL";
- break;
- default:
- filesystem.property.value = "Off";
- break;
- }
-
- if (/^inherited/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "inherited";
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- } else if (/^default|^local/gi.test(filesystem.properties.source)) {
- $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
-
- if (/^default/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "default";
- filesystem.property.valueinherited = "Default (Off)";
-
- $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
- filesystem.property.source = "local";
-
- $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='InheritedReset'] a").text("Default (Off)");
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
- filesystem.property.source = "local";
-
- FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "acltype" }, { name: modal.name, id: modal.id });
- }
- }
-
- $("#btnspan-" + modal.name + "-acltype-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
- $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#div-" + modal.name + "-acltype-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- case "atime": //Default is on
- filesystem.property = {
- source: "",
- value: "On",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "off":
- filesystem.property.value = "Off";
- break;
- case "on":
- filesystem.property.value = "On";
- break;
- default:
- filesystem.property.value = "On";
- break;
- }
-
- if (/^inherited/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "inherited";
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- } else if (/^default|^local/gi.test(filesystem.properties.source)) {
- $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
-
- if (/^default/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "default";
- filesystem.property.valueinherited = "Default (On)";
-
- $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
- filesystem.property.source = "local";
-
- $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='InheritedReset'] a").text("Default (On)");
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
- filesystem.property.source = "local";
-
- FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "atime" }, { name: modal.name, id: modal.id });
- }
- }
-
- $("#btnspan-" + modal.name + "-atime-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
- $("#dropdown-" + modal.name + "-atime-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#div-" + modal.name + "-atime-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- case "available":
- filesystem.available = filesystem.properties.value;
-
- filesystem.property = {
- value: "0 B"
- };
-
- if (filesystem.properties.value == "none" || filesystem.properties.value == "0" || filesystem.properties.value == "0b") {
- filesystem.property.value = "0 B";
- } else {
- filesystem.property.value = FnFormatBytes({ base2: true, decimals: 2, value: filesystem.properties.value });
- }
-
- $("#helpblock-" + modal.name + "-available-" + modal.id).text("Available size: " + filesystem.property.value);
- break;
- case "canmount": //Default is on
- filesystem.property = {
- value: "On"
- };
-
- switch (filesystem.properties.value) {
- case "on":
- filesystem.property.value = "On";
- break;
- case "off":
- filesystem.property.value = "Off";
- break;
- case "noauto":
- filesystem.property.value = "No Auto";
- break;
- default:
- filesystem.property.value = "On";
- break;
- }
-
- $("#btnspan-" + modal.name + "-canmount-" + modal.id).text(filesystem.property.value).attr("data-field-value", filesystem.properties.value);
- $("#dropdown-" + modal.name + "-canmount-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-canmount-" + modal.id + " li[value='" + filesystem.properties.valueraw + "']").addClass("active");
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#div-" + modal.name + "-canmount-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- case "casesensitivity": //Default is sensitive
- $("#div-" + modal.name + "-casesensitivity-" + modal.id).text(filesystem.properties.value.charAt(0).toUpperCase() + filesystem.properties.value.slice(1));
- break;
- case "checksum": //Default is on
- filesystem.property = {
- value: "On",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "on":
- filesystem.property.value = "On";
- break;
- case "off":
- filesystem.property.value = "Off";
- break;
- case "edonr":
- filesystem.property.value = "Edon-R";
- break;
- case "fletcher2":
- filesystem.property.value = "Fletcher2";
- break;
- case "fletcher4":
- filesystem.property.value = "Fletcher4";
- break;
- case "noparity":
- filesystem.property.value = "No Parity";
- break;
- case "sha256":
- filesystem.property.value = "SHA-256";
- break;
- case "sha512":
- filesystem.property.value = "SHA-512";
- break;
- case "skein":
- filesystem.property.value = "Skein";
- break;
- default:
- filesystem.property.value = "On";
- break;
- }
-
- if (/^inherited/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "inherited";
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- } else if (/^default|^local/gi.test(filesystem.properties.source)) {
- $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
-
- if (/^default/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "default";
- filesystem.property.valueinherited = "Default (On)";
-
- $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
- filesystem.property.source = "local";
-
- $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='InheritedReset'] a").text("Default (On)");
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
- filesystem.property.source = "local";
-
- FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "checksum" }, { name: modal.name, id: modal.id });
- }
- }
-
- $("#btnspan-" + modal.name + "-checksum-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
- $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#div-" + modal.name + "-checksum-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- case "compression": //Default is off
- filesystem.property = {
- value: "Off",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "on":
- filesystem.property.value = "On";
- break;
- case "gzip":
- filesystem.property.value = "GZIP";
- break;
- case "lz4":
- filesystem.property.value = "LZ4";
- break;
- case "lzjb":
- filesystem.property.value = "LZJB";
- break;
- case "zle":
- filesystem.property.value = "ZLE";
- break;
- default:
- filesystem.property.value = "Off";
- break;
- }
-
- if (/^inherited/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "inherited";
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- } else if (/^default|^local/gi.test(filesystem.properties.source)) {
- $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
-
- if (/^default/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "default";
- filesystem.property.valueinherited = "Default (Off)";
-
- $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
- filesystem.property.source = "local";
-
- $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='InheritedReset'] a").text("Default (Off)");
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
- filesystem.property.source = "local";
-
- FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "compression" }, { name: modal.name, id: modal.id });
- }
- }
-
- $("#btnspan-" + modal.name + "-compression-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
- $("#dropdown-" + modal.name + "-compression-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#div-" + modal.name + "-compression-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- case "context": //Default is empty
- if (filesystem.properties.value == "system_u:object_r:samba_share_t:s0") {
- filesystem.context = true;
- }
- break;
- case "dedup": //Default is off
- filesystem.property = {
- value: "Off",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "on":
- filesystem.property.value = "On";
- break;
- case "off":
- filesystem.property.value = "Off";
- break;
- case "edonr,verify":
- filesystem.property.value = "Edon-R + Verify";
- break;
- case "sha256":
- filesystem.property.value = "SHA-256";
- break;
- case "sha256,verify":
- filesystem.property.value = "SHA-256 + Verify";
- break;
- case "sha512":
- filesystem.property.value = "SHA-512";
- break;
- case "sha512,verify":
- filesystem.property.value = "SHA-512 + Verify";
- break;
- case "skein":
- filesystem.property.value = "Skein";
- break;
- case "skein,verify":
- filesystem.property.value = "Skein + Verify";
- break;
- case "verify":
- filesystem.property.value = "Verify";
- break;
- default:
- filesystem.property.value = "Off";
- break;
- }
-
- if (/^inherited/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "inherited";
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- } else if (/^default|^local/gi.test(filesystem.properties.source)) {
- $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
-
- if (/^default/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "default";
- filesystem.property.valueinherited = "Default (Off)";
-
- $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
- filesystem.property.source = "local";
-
- $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='InheritedReset'] a").text("Default (Off)");
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
- filesystem.property.source = "local";
-
- FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "dedup" }, { name: modal.name, id: modal.id });
- }
- }
-
- $("#btnspan-" + modal.name + "-dedup-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
- $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#div-" + modal.name + "-dedup-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- case "dnodesize": //Default is legacy
- filesystem.property = {
- value: "Off",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "1k":
- filesystem.property.value = "1 KiB";
- break;
- case "2k":
- filesystem.property.value = "2 KiB";
- break;
- case "4k":
- filesystem.property.value = "4 KiB";
- break;
- case "8k":
- filesystem.property.value = "8 KiB";
- break;
- case "16k":
- filesystem.property.value = "16 KiB";
- break;
- case "auto":
- filesystem.property.value = "Auto";
- break;
- case "legacy":
- filesystem.property.value = "Legacy";
- break;
- default:
- filesystem.property.value = "Legacy";
- break;
- }
-
- if (/^inherited/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "inherited";
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- } else if (/^default|^local/gi.test(filesystem.properties.source)) {
- $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
-
- if (/^default/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "default";
- filesystem.property.valueinherited = "Default (Legacy)";
-
- $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
- filesystem.property.source = "local";
-
- $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='InheritedReset'] a").text("Default (Legacy)");
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
- filesystem.property.source = "local";
-
- FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "dnodesize" }, { name: modal.name, id: modal.id });
- }
- }
-
- $("#btnspan-" + modal.name + "-dnodesize-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
- $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#div-" + modal.name + "-dnodesize-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- case "defcontext": //Default is empty
- if (filesystem.properties.value == "system_u:object_r:samba_share_t:s0") {
- filesystem.defcontext = true;
- }
- break;
- case "encryption": //Default is off
- filesystem.property = {
- value: "Off"
- };
-
- switch (filesystem.properties.value) {
- case "on":
- filesystem.property.value = "On";
- break;
- case "off":
- filesystem.property.value = "Off";
- break;
- case "aes-128-ccm":
- filesystem.property.value = "AES-128-CCM";
- break;
- case "aes-192-ccm":
- filesystem.property.value = "AES-192-CCM";
- break;
- case "aes-256-ccm":
- filesystem.property.value = "AES-256-CCM";
- break;
- case "aes-128-gcm":
- filesystem.property.value = "AES-128-GCM";
- break;
- case "aes-192-gcm":
- filesystem.property.value = "AES-192-GCM";
- break;
- case "aes-256-gcm":
- filesystem.property.value = "AES-256-GCM";
- break;
- default:
- filesystem.property.value = "Off";
- break;
- }
-
- $("#div-" + modal.name + "-encryption-" + modal.id).text(filesystem.property.value);
-
- if (filesystem.property.value != "Off") {
- $("#controllabel-" + modal.name + "-encryption-" + modal.id).removeClass("hidden");
- $("#div-" + modal.name + "-encryption-" + modal.id).removeClass("hidden");
- }
- break;
- case "encryptionroot":
- if (filesystem.properties.valueraw && filesystem.properties.valueraw == "-") {
- filesystem.properties.valueraw = "";
- }
-
- if (filesystem.properties.valueraw && filesystem.properties.valueraw != filesystem.name) {
- $("#controllabel-" + modal.name + "-encryptionroot-" + modal.id).removeClass("hidden");
- $("#div-" + modal.name + "-encryptionroot-" + modal.id).text(filesystem.properties.valueraw).removeClass("hidden");
- }
- break;
- case "fscontext": //Default is empty
- if (filesystem.properties.value == "system_u:object_r:samba_share_t:s0") {
- filesystem.fscontext = true;
- }
- break;
- case "guid":
- $("#div-" + modal.name + "-guid-" + modal.id).text(filesystem.properties.value);
- break;
- case "mountpoint":
- $("#input-" + modal.name + "-mountpoint-" + modal.id).val(filesystem.properties.valueraw).attr("data-field-value", filesystem.properties.valueraw);
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#input-" + modal.name + "-mountpoint-" + modal.id).prop("disabled", true);
- }
- break;
- case "quota": //Default is none
- filesystem.property = {
- value: "0 B",
- valueraw: "0",
- valueunit: "KiB"
- };
-
- if (filesystem.properties.value == "none" || filesystem.properties.value == "0" || filesystem.properties.value == "0b") {
- filesystem.property.value = "0 B";
- } else {
- filesystem.property.value = FnFormatBytes({ base2: true, decimals: 1, value: filesystem.properties.value });
-
- if (/KiB/g.test(filesystem.property.value)) {
- filesystem.property.valueunit = "KiB";
- } else if (/MiB/g.test(filesystem.property.value)) {
- filesystem.property.valueunit = "MiB";
- } else if (/GiB/g.test(filesystem.property.value)) {
- filesystem.property.valueunit = "GiB";
- } else if (/TiB/g.test(filesystem.property.value)) {
- filesystem.property.valueunit = "TiB";
- }
-
- filesystem.property.valueraw = filesystem.property.value.toString().replace(" " + filesystem.property.valueunit, "");
- }
-
- $("#input-" + modal.name + "-quota-" + modal.id).val(filesystem.property.valueraw);
-
- size.quota = {
- quota: parseInt(filesystem.properties.value),
- max: {
- raw: 1099511627776000,
- unit: "",
- unitnumber: 0
- },
- slider: {
- valuemax: 1000
- },
- property: filesystem.property
- };
-
- FnStoragePoolSizeGet({ name: pool.name, id: null })
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Storage Pools, Size, Get:" }));
-
- if (_data && zfsmanager.configuration.zfs.filesystem.quotarestrict) {
- size.quota.max.raw = parseInt(_data.replace(/\n+/g, ""));
- }
- })
- .finally(function () {
- size.quota.max.raw = (size.quota.max.raw > size.quota.quota ? size.quota.max.raw : size.quota.quota);
- size.quota.max.unitnumber = FnFormatBytes({ base2: true, decimals: 2, value: size.quota.max.raw }).replace(/ .*$/g, "");
- size.quota.max.unit = FnFormatBytes({ base2: true, decimals: 2, value: size.quota.max.raw }).replace(/ /g, "").replace(/^[0-9.]/, "");
-
- if (size.quota.max.raw <= 1024000) {
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.max.unitnumber);
- }
- if (size.quota.max.raw > 1024000) {
- $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='MiB']").removeClass("hidden");
-
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.max.unitnumber);
- }
- if (size.quota.max.raw > 1048576000) {
- $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='GiB']").removeClass("hidden");
-
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib", size.quota.max.unitnumber);
- }
- if (size.quota.max.raw > 1073741824000) {
- $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='TiB']").removeClass("hidden");
-
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-tib", size.quota.max.unitnumber);
- }
-
- if (size.quota.property.valueunit == "KiB") {
- size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib");
- }
- if (size.quota.property.valueunit == "MiB") {
- size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib");
- }
- if (size.quota.property.valueunit == "GiB") {
- size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib");
- }
- if (size.quota.property.valueunit == "TiB") {
- size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-tib");
- }
-
- $("#slider-" + modal.name + "-quota-" + modal.id).data("slider").options.max = size.quota.slider.valuemax;
- $("#slider-" + modal.name + "-quota-" + modal.id).data("slider").options.step = (size.quota.slider.valuemax < 10 ? "0.1" : "1");
- $("#slider-" + modal.name + "-quota-" + modal.id).slider("setValue", size.quota.property.valueraw);
-
- $("#btnspan-" + modal.name + "-quota-" + modal.id).text(size.quota.property.valueunit).attr("data-field-value", size.quota.property.valueunit);
- $("#dropdown-" + modal.name + "-quota-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='" + size.quota.property.valueunit + "']").addClass("active");
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-field-value", size.quota.property.value.toString().replace(/ /g, "").replace(/iB$/g, ""));
- });
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#input-" + modal.name + "-quota-" + modal.id).prop("disabled", true);
- $("#div-" + modal.name + "-quota-dropdown-" + modal.id + " button").prop("disabled", true);
- $("#validationwrapper-" + modal.name + "-quota-" + modal.id + " .slider-pf .slider *").addClass("disabled");
- $("#slider-" + modal.name + "-quota-" + modal.id).slider("disable");
- }
- break;
- case "readonly": //Default is off
- if (filesystem.properties.value == "on") {
- filesystem.readonly = true;
- }
-
- if (filesystem.properties.value == "on" && !$("#switch-" + modal.name + "-readonly-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-readonly-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-readonly-" + modal.id).attr("data-field-value", filesystem.properties.value);
-
- if (pool.readonly) {
- $("#switch-" + modal.name + "-readonly-" + modal.id + " input").prop("disabled", true);
- }
- break;
- case "recordsize": //Default is 128K
- filesystem.property = {
- value: FnFormatBytes({ base2: true, decimals: 0, value: filesystem.properties.value }),
- valueinherited: ""
- };
-
- if (/^inherited/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "inherited";
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- } else if (/^default|^local/gi.test(filesystem.properties.source)) {
- $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
-
- if (/^default/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "default";
- filesystem.property.valueinherited = "Default (128 KiB)";
-
- $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
- filesystem.property.source = "local";
-
- $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='InheritedReset'] a").text("Default (128 KiB)");
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
- filesystem.property.source = "local";
-
- FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "recordsize" }, { name: modal.name, id: modal.id });
- }
- }
-
- $("#btnspan-" + modal.name + "-recordsize-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
- $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#div-" + modal.name + "-recordsize-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- case "refreservation": //Default is none / 0
- filesystem.property = {
- value: "0 B",
- valueraw: "0",
- valueunit: "KiB"
- };
-
- if (filesystem.properties.value == "none" || filesystem.properties.value == "0" || filesystem.properties.value == "0b") {
- filesystem.property.value = "0 B";
- } else {
- filesystem.property.value = FnFormatBytes({ base2: true, decimals: 1, value: filesystem.properties.value });
-
- if (/KiB/g.test(filesystem.property.value)) {
- filesystem.property.valueunit = "KiB";
- } else if (/MiB/g.test(filesystem.property.value)) {
- filesystem.property.valueunit = "MiB";
- } else if (/GiB/g.test(filesystem.property.value)) {
- filesystem.property.valueunit = "GiB";
- } else if (/TiB/g.test(filesystem.property.value)) {
- filesystem.property.valueunit = "TiB";
- }
-
- filesystem.property.valueraw = filesystem.property.value.toString().replace(" " + filesystem.property.valueunit, "");
- }
-
- $("#input-" + modal.name + "-refreservation-" + modal.id).val(filesystem.property.valueraw);
-
- size.refreservation = {
- available: parseInt(filesystem.available),
- refreservation: parseInt(filesystem.properties.value),
- max: {
- raw: 0,
- unit: "",
- unitnumber: 0
- },
- slider: {
- valuemax: 1000
- }
- };
-
- size.refreservation.max.raw = (size.refreservation.available > size.refreservation.refreservation ? size.refreservation.available : size.refreservation.refreservation);
- size.refreservation.max.unitnumber = FnFormatBytes({ base2: true, decimals: 2, value: size.refreservation.max.raw }).replace(/ .*$/g, "");
- size.refreservation.max.unit = FnFormatBytes({ base2: true, decimals: 2, value: size.refreservation.max.raw }).replace(/ /g, "").replace(/^[0-9.]/, "");
-
- if (size.refreservation.max.raw <= 1024000) {
- $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-kib", size.refreservation.max.unitnumber);
- }
- if (size.refreservation.max.raw > 1024000) {
- $("#dropdown-" + modal.name + "-refreservation-" + modal.id + " li[value='MiB']").removeClass("hidden");
-
- $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-kib", size.refreservation.slider.valuemax);
- $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-mib", size.refreservation.max.unitnumber);
- }
- if (size.refreservation.max.raw > 1048576000) {
- $("#dropdown-" + modal.name + "-refreservation-" + modal.id + " li[value='GiB']").removeClass("hidden");
-
- $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-kib", size.refreservation.slider.valuemax);
- $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-mib", size.refreservation.slider.valuemax);
- $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-gib", size.refreservation.max.unitnumber);
- }
- if (size.refreservation.max.raw > 1073741824000) {
- $("#dropdown-" + modal.name + "-refreservation-" + modal.id + " li[value='TiB']").removeClass("hidden");
-
- $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-kib", size.refreservation.slider.valuemax);
- $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-mib", size.refreservation.slider.valuemax);
- $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-gib", size.refreservation.slider.valuemax);
- $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-tib", size.refreservation.max.unitnumber);
- }
-
- if (filesystem.property.valueunit == "KiB") {
- size.refreservation.slider.valuemax = $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-kib");
- }
- if (filesystem.property.valueunit == "MiB") {
- size.refreservation.slider.valuemax = $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-mib");
- }
- if (filesystem.property.valueunit == "GiB") {
- size.refreservation.slider.valuemax = $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-gib");
- }
- if (filesystem.property.valueunit == "TiB") {
- size.refreservation.slider.valuemax = $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-tib");
- }
-
- $("#slider-" + modal.name + "-refreservation-" + modal.id).data("slider").options.max = size.refreservation.slider.valuemax;
- $("#slider-" + modal.name + "-refreservation-" + modal.id).data("slider").options.step = (size.refreservation.slider.valuemax < 10 ? "0.1" : "1");
- $("#slider-" + modal.name + "-refreservation-" + modal.id).slider("setValue", filesystem.property.valueraw);
-
- $("#btnspan-" + modal.name + "-refreservation-" + modal.id).text(filesystem.property.valueunit).attr("data-field-value", filesystem.property.valueunit);
- $("#dropdown-" + modal.name + "-refreservation-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-refreservation-" + modal.id + " li[value='" + filesystem.property.valueunit + "']").addClass("active");
- $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-field-value", filesystem.property.value.toString().replace(/ /g, "").replace(/iB$/g, ""));
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#input-" + modal.name + "-refreservation-" + modal.id).prop("disabled", true);
- $("#div-" + modal.name + "-refreservation-dropdown-" + modal.id + " button").prop("disabled", true);
- $("#validationwrapper-" + modal.name + "-refreservation-" + modal.id + " .slider-pf .slider *").addClass("disabled");
- $("#slider-" + modal.name + "-refreservation-" + modal.id).slider("disable");
- }
- break;
- case "rootcontext": //Default is empty
- if (filesystem.properties.value == "system_u:object_r:samba_share_t:s0") {
- filesystem.rootcontext = true;
- }
- break;
- case "sharenfs": //Default is off
- if (filesystem.properties.value != "off") {
- if (!$("#switch-" + modal.name + "-sharenfs-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-sharenfs-" + modal.id + " input").click();
- }
-
- $("#controllabel-" + modal.name + "-sharenfs-options-" + modal.id).removeClass("hidden");
- $("#validationwrapper-" + modal.name + "-sharenfs-options-" + modal.id).removeClass("hidden");
- $("#input-" + modal.name + "-sharenfs-options-" + modal.id).val((filesystem.properties.value == "on" ? "sec=sys,rw,crossmnt,no_subtree_check,no_root_squash" : filesystem.properties.value));
-
- FnSystemNfsVersionGet({ alert: { id: $("#alert-" + modal.name + "-sharenfs-options-" + modal.id) } });
- }
-
- $("#input-" + modal.name + "-sharenfs-options-" + modal.id).attr("data-field-value", filesystem.properties.value);
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#switch-" + modal.name + "-sharenfs-" + modal.id + " input").prop("disabled", true);
- $("#input-" + modal.name + "-sharenfs-options-" + modal.id).prop("disabled", true);
- }
- break;
- case "sharesmb":
- if (filesystem.properties.value == "on" && !$("#switch-" + modal.name + "-sharesmb-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-sharesmb-" + modal.id + " input").click();
- }
-
- if (pool.readonly || zfsmanager.configuration.samba.manage) {
- $("#switch-" + modal.name + "-sharesmb-" + modal.id + " input").prop("disabled", true);
- }
-
- $("#switch-" + modal.name + "-sharesmb-" + modal.id).attr("data-field-value", filesystem.properties.value);
- break;
- case "special_small_blocks": //Default is 0
- filesystem.property = {
- value: FnFormatBytes({ base2: true, decimals: 0, value: filesystem.properties.value }),
- valueinherited: ""
- };
-
- if (/^inherited/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "inherited";
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- } else if (/^default|^local/gi.test(filesystem.properties.source)) {
- $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
-
- if (/^default/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "default";
- filesystem.property.valueinherited = "Default (0 B)";
-
- $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
- filesystem.property.source = "local";
-
- $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='InheritedReset'] a").text("Default (0 B)");
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
- filesystem.property.source = "local";
-
- FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "special_small_blocks" }, { name: modal.name, id: modal.id });
- }
- }
-
- $("#btnspan-" + modal.name + "-special_small_blocks-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
- $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#div-" + modal.name + "-special_small_blocks-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- case "used":
- filesystem.used = filesystem.properties.value;
-
- filesystem.property = {
- value: "0 B"
- };
-
- if (filesystem.properties.value == "none" || filesystem.properties.value == "0" || filesystem.properties.value == "0b") {
- filesystem.property.value = "0 B";
- } else {
- filesystem.property.value = FnFormatBytes({ base2: true, decimals: 2, value: filesystem.properties.value });
- }
-
- $("#helpblock-" + modal.name + "-used-" + modal.id).text("Used size: " + filesystem.property.value);
- break;
- case "xattr": //Default is on
- filesystem.property = {
- value: "On",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "off":
- filesystem.property.value = "Off";
- break;
- case "sa":
- filesystem.property.value = "System Attribute";
- break;
- default:
- filesystem.property.value = "On";
- break;
- }
-
- if (/^inherited/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "inherited";
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- } else if (/^default|^local/gi.test(filesystem.properties.source)) {
- $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
-
- if (/^default/gi.test(filesystem.properties.source)) {
- filesystem.property.source = "default";
- filesystem.property.valueinherited = "Default (On)";
-
- $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
- filesystem.property.source = "local";
-
- $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='InheritedReset'] a").text("Default (On)");
- } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
- filesystem.property.source = "local";
-
- FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "xattr" }, { name: modal.name, id: modal.id });
- }
- }
-
- $("#btnspan-" + modal.name + "-xattr-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
- $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#div-" + modal.name + "-xattr-dropdown-" + modal.id + " button").prop("disabled", true);
- }
- break;
- }
- });
-
- if (filesystem.context && filesystem.fscontext && filesystem.defcontext && filesystem.rootcontext) {
- if (!$("#switch-" + modal.name + "-selinux-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-selinux-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-selinux-" + modal.id).attr("data-field-value", "true");
- } else {
- $("#switch-" + modal.name + "-selinux-" + modal.id).attr("data-field-value", "false");
- }
-
- if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
- $("#switch-" + modal.name + "-selinux-" + modal.id + " input").prop("disabled", true);
- }
- if (pool.readonly) {
- $("#btn-" + modal.name + "-apply-" + modal.id).prop("disabled", true);
- }
-
- FnConsole.log[1]("File Systems, Configuration, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, Configuration, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + " , Message: " + (data ? data : message));
- });
-}
-
-function FnFileSystemConfigurationInheritedGet(pool = { name, id }, filesystem = { name }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "get", "atime,casesensitivity,compression,dedup,dnodesize,encryption,recordsize,special_small_blocks,xattr", "-H", "-o", "property,value,source", "-p", filesystem.name]
- };
-
- FnConsole.log[2]("File Systems, Configuration, Inherited, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Configuration, Inherited, Get:" }));
-
- process.data = data.replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v);
-
- process.data.forEach((_value, _index) => {
- _value = _value.split("\u22C5");
-
- filesystem.properties = {
- property: _value[0].toLowerCase(),
- value: _value[1].toLowerCase(),
- valueraw: _value[1],
- source: _value[2]
- };
-
- switch (filesystem.properties.property) {
- case "atime": //Default is on
- filesystem.property = {
- value: "On",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "on":
- filesystem.property.value = "On";
- break;
- case "gzip":
- filesystem.property.value = "GZIP";
- break;
- case "lz4":
- filesystem.property.value = "LZ4";
- break;
- case "lzjb":
- filesystem.property.value = "LZJB";
- break;
- case "zle":
- filesystem.property.value = "ZLE";
- break;
- default:
- filesystem.property.value = "Off";
- break;
- }
-
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#btnspan-" + modal.name + "-atime-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
- $("#dropdown-" + modal.name + "-atime-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='Inherited']").addClass("active");
- break; case "casesensitivity": //Default is sensitive
- filesystem.property = {
- value: "Sensitive",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "insensitive":
- filesystem.property.value = "Insensitive";
- break;
- case "mixed":
- filesystem.property.value = "Mixed";
- break;
- case "sensitive":
- filesystem.property.value = "Sensitive";
- break;
- default:
- filesystem.property.value = "Sensitive";
- break;
- }
-
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#btnspan-" + modal.name + "-casesensitivity-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
- $("#dropdown-" + modal.name + "-casesensitivity-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-casesensitivity-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-casesensitivity-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- $("#dropdown-" + modal.name + "-casesensitivity-" + modal.id + " li[value='Inherited']").addClass("active");
- break;
- case "compression": //Default is off
- filesystem.property = {
- value: "Off",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "on":
- filesystem.property.value = "On";
- break;
- case "gzip":
- filesystem.property.value = "GZIP";
- break;
- case "lz4":
- filesystem.property.value = "LZ4";
- break;
- case "lzjb":
- filesystem.property.value = "LZJB";
- break;
- case "zle":
- filesystem.property.value = "ZLE";
- break;
- default:
- filesystem.property.value = "Off";
- break;
- }
-
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#btnspan-" + modal.name + "-compression-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
- $("#dropdown-" + modal.name + "-compression-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='Inherited']").addClass("active");
- break;
- case "dedup": //Default is off
- filesystem.property = {
- value: "Off",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "on":
- filesystem.property.value = "On";
- break;
- case "off":
- filesystem.property.value = "Off";
- break;
- case "verify":
- filesystem.property.value = "Verify";
- break;
- case "sha256":
- filesystem.property.value = "SHA-256";
- break;
- case "sha256,verify":
- filesystem.property.value = "SHA-256 + Verify";
- break;
- case "sha512":
- filesystem.property.value = "SHA-512";
- break;
- case "sha512,verify":
- filesystem.property.value = "SHA-512 + Verify";
- break;
- case "skein":
- filesystem.property.value = "Skein";
- break;
- case "skein,verify":
- filesystem.property.value = "Skein + Verify";
- break;
- case "edonr,verify":
- filesystem.property.value = "Edon-R + Verify";
- break;
- default:
- filesystem.property.value = "Off";
- break;
- }
-
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#btnspan-" + modal.name + "-dedup-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
- $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='Inherited']").addClass("active");
- break;
- case "dnodesize": //Default is legacy
- filesystem.property = {
- value: "Off",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "1k":
- filesystem.property.value = "1 KiB";
- break;
- case "2k":
- filesystem.property.value = "2 KiB";
- break;
- case "4k":
- filesystem.property.value = "4 KiB";
- break;
- case "8k":
- filesystem.property.value = "8 KiB";
- break;
- case "16k":
- filesystem.property.value = "16 KiB";
- break;
- case "auto":
- filesystem.property.value = "Auto";
- break;
- case "legacy":
- filesystem.property.value = "Legacy";
- break;
- default:
- filesystem.property.value = "Legacy";
- break;
- }
-
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#btnspan-" + modal.name + "-dnodesize-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
- $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='Inherited']").addClass("active");
- break;
- case "encryption": //Default is off
- filesystem.property = {
- value: "Off",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "on":
- filesystem.property.value = "On";
- break;
- case "off":
- filesystem.property.value = "Off";
- break;
- case "aes-128-ccm":
- filesystem.property.value = "AES-128-CCM";
- break;
- case "aes-192-ccm":
- filesystem.property.value = "AES-192-CCM";
- break;
- case "aes-256-ccm":
- filesystem.property.value = "AES-256-CCM";
- break;
- case "aes-128-gcm":
- filesystem.property.value = "AES-128-GCM";
- break;
- case "aes-192-gcm":
- filesystem.property.value = "AES-192-GCM";
- break;
- case "aes-256-gcm":
- filesystem.property.value = "AES-256-GCM";
- break;
- }
-
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- if (filesystem.properties.value != "off") {
- if (!$("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-encryption-" + modal.id + " input").click();
- }
-
- $("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("disabled", true);
- $("#btnspan-" + modal.name + "-encryption-cipher-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
- $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='Inherited']").addClass("active");
- $("#helpblock-" + modal.name + "-encryption-passphrase-" + modal.id).removeClass("has-error").removeClass("hidden").text("Passphrase is not required.");
- } else if (filesystem.properties.value == "off") {
- $("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("disabled", false);
-
- if ($("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-encryption-" + modal.id + " input").click();
- }
-
- $("#btnspan-" + modal.name + "-encryption-cipher-" + modal.id).text("AES-256-GCM").attr("data-field-value", "aes-256-gcm");
- $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='aes-256-gcm']").addClass("active");
- $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='Inherited']").addClass("hidden");
- $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='Inherited'] a").text("Inherited");
-
- if ($("#input-" + modal.name + "-encryption-passphrase-" + modal.id).val().length == 0) {
- $("#validationwrapper-" + modal.name + "-encryption-passphrase-" + modal.id).removeClass("has-error");
- $("#helpblock-" + modal.name + "-encryption-passphrase-" + modal.id).removeClass("has-error").addClass("hidden").text("");
- $("#validationwrapper-" + modal.name + "-encryption-passphrase-confirm-" + modal.id).removeClass("has-error");
- $("#helpblock-" + modal.name + "-encryption-passphrase-" + modal.id).removeClass("has-error").addClass("hidden").text("");
- }
- }
- break;
- case "recordsize": //Default is 128K
- filesystem.property = {
- value: FnFormatBytes({ base2: true, decimals: 0, value: filesystem.properties.value }),
- valueinherited: ""
- };
-
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#btnspan-" + modal.name + "-recordsize-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
- $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='Inherited']").addClass("active");
- break;
- case "special_small_blocks": //Default is 0
- filesystem.property = {
- value: FnFormatBytes({ base2: true, decimals: 0, value: filesystem.properties.value }),
- valueinherited: ""
- };
-
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#btnspan-" + modal.name + "-special_small_blocks-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
- $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='Inherited']").addClass("active");
- break;
- case "xattr": //Default is on
- filesystem.property = {
- value: "On",
- valueinherited: ""
- };
-
- switch (filesystem.properties.value) {
- case "on":
- filesystem.property.value = "On";
- break;
- case "off":
- filesystem.property.value = "Off";
- break;
- case "sa":
- filesystem.property.value = "System Attribute";
- break;
- default:
- filesystem.property.value = "On";
- break;
- }
-
- filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
-
- $("#btnspan-" + modal.name + "-xattr-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
- $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='Inherited']").removeClass("hidden");
- $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
- $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='Inherited']").addClass("active");
- break;
- }
- });
-
- //Quota
- let size = {
- quota: {
- max: {
- raw: 1099511627776000,
- unit: "",
- unitnumber: 0
- },
- slider: {
- valuemax: 1000
- },
- property: {
- value: "0 B",
- valueraw: "0",
- valueunit: "KiB"
- }
- }
- };
-
- FnStoragePoolSizeGet({ name: pool.name, id: null })
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Storage Pools, Size, Get:" }));
-
- if (_data && zfsmanager.configuration.zfs.filesystem.quotarestrict) {
- size.quota.max.raw = parseInt(_data.replace(/\n+/g, ""));
- }
- })
- .finally(function () {
- size.quota.max.unitnumber = FnFormatBytes({ base2: true, decimals: 2, value: size.quota.max.raw }).replace(/ .*$/g, "");
- size.quota.max.unit = FnFormatBytes({ base2: true, decimals: 2, value: size.quota.max.raw }).replace(/ /g, "").replace(/^[0-9.]/, "");
-
- if (size.quota.max.raw <= 1024000) {
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.max.unitnumber);
- }
- if (size.quota.max.raw > 1024000) {
- $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='MiB']").removeClass("hidden");
-
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.max.unitnumber);
- }
- if (size.quota.max.raw > 1048576000) {
- $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='GiB']").removeClass("hidden");
-
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib", size.quota.max.unitnumber);
- }
- if (size.quota.max.raw > 1073741824000) {
- $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='TiB']").removeClass("hidden");
-
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib", size.quota.slider.valuemax);
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-tib", size.quota.max.unitnumber);
- }
-
- if (size.quota.property.valueunit == "KiB") {
- size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib");
- }
- if (size.quota.property.valueunit == "MiB") {
- size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib");
- }
- if (size.quota.property.valueunit == "GiB") {
- size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib");
- }
- if (size.quota.property.valueunit == "TiB") {
- size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-tib");
- }
-
- $("#slider-" + modal.name + "-quota-" + modal.id).data("slider").options.max = size.quota.slider.valuemax;
- $("#slider-" + modal.name + "-quota-" + modal.id).data("slider").options.step = (size.quota.slider.valuemax < 10 ? "0.1" : "1");
- $("#slider-" + modal.name + "-quota-" + modal.id).slider("setValue", size.quota.property.valueraw);
-
- $("#btnspan-" + modal.name + "-quota-" + modal.id).text(size.quota.property.valueunit).attr("data-field-value", size.quota.property.valueunit);
- $("#dropdown-" + modal.name + "-quota-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='" + size.quota.property.valueunit + "']").addClass("active");
- $("#input-" + modal.name + "-quota-" + modal.id).attr("data-field-value", size.quota.property.value.toString().replace(/ /g, "").replace(/iB$/g, ""));
- });
-
- FnConsole.log[1]("File Systems, Configuration, Inherited, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, Configuration, Inherited, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + " , Message: " + (data ? data : message));
- });
-}
-
-function FnFileSystemConfigurationInheritedPropertyGet(pool = { name, id }, filesystem = { name, id, property }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "get", filesystem.property, "-H", "-o", "value", "-p", "-d", "0", filesystem.name.replace(/\/[^\/]+$/, "")]
- };
-
- FnConsole.log[2]("File Systems, Configuration, Property, Inherited, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Configuration, Property, Get:" }));
-
- filesystem.properties = {
- value: data.trim()
- };
-
- switch (filesystem.properties.value) {
- case "edonr":
- filesystem.properties.value = "Edon-R";
- break;
- case "edonr,verify":
- filesystem.properties.value = "Edon-R + Verify";
- break;
- case "gzip":
- filesystem.properties.value = "GZIP";
- break;
- case "lz4":
- filesystem.properties.value = "LZ4";
- break;
- case "lzjb":
- filesystem.properties.value = "LZJB";
- break;
- case "noacl":
- filesystem.properties.value = "No ACL";
- break;
- case "noallow":
- filesystem.properties.value = "No Allow";
- break;
- case "noparity":
- filesystem.properties.value = "No Parity";
- break;
- case "passthrough-x":
- filesystem.properties.value = "Passthrough-X";
- break;
- case "posixacl":
- filesystem.properties.value = "POSIX ACL";
- break;
- case "sa":
- filesystem.properties.value = "System Attribute";
- break;
- case "sha256":
- filesystem.properties.value = "SHA-256";
- break;
- case "sha256,verify":
- filesystem.properties.value = "SHA-256 + Verify";
- break;
- case "sha512":
- filesystem.properties.value = "SHA-512";
- break;
- case "sha512,verify":
- filesystem.properties.value = "SHA-512 + Verify";
- break;
- case "skein,verify":
- filesystem.properties.value = "Skein + Verify";
- break;
- case "zle":
- filesystem.properties.value = "ZLE";
- break;
- default:
- filesystem.properties.value = ($.isNumeric(filesystem.properties.value) ? FnFormatBytes({ base2: true, decimals: 0, value: filesystem.properties.value }) : filesystem.properties.value.charAt(0).toUpperCase() + filesystem.properties.value.slice(1));
- }
-
- $("#dropdown-" + modal.name + "-" + filesystem.property + "-" + modal.id + " li[value='InheritedReset'] a").text("Inherited" + (filesystem.properties.value ? " (" + filesystem.properties.value + ")" : ""));
-
- FnConsole.log[2]("File Systems, Configuration, Property, Inherited, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- $("#dropdown-" + modal.name + "-" + filesystem.property + "-" + modal.id + " li[value='InheritedReset'] a").text("Inherited");
-
- FnConsole.warn("File Systems, Configuration, Property, Inherited, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + " , Message: " + (data ? data : message));
- });
-}
-
-function FnFileSystemConfigure(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, aclinherit, acltype, atime, canmount, checksum, compression, context, dedup, dnodesize, defcontext, fscontext, mountpoint, quota, readonly, recordsize, refreservation, rootcontext, sharenfs, sharesmb, special_small_blocks, type, xattr }, samba = { restart: false }, modal = { id }) {
- filesystem.properties = {
- inherit: [],
- new: []
- };
-
- if (filesystem.aclinherit) {
- if (/^Default|^Inherited/g.test(filesystem.aclinherit)) {
- filesystem.properties.inherit.push("aclinherit");
- } else {
- filesystem.properties.new.push("aclinherit=" + filesystem.aclinherit);
- }
- }
- if (filesystem.acltype) {
- if (/^Default|^Inherited/g.test(filesystem.acltype)) {
- filesystem.properties.inherit.push("acltype");
- } else {
- filesystem.properties.new.push("acltype=" + filesystem.acltype);
- }
- }
- if (filesystem.atime) {
- if (/^Default|^Inherited/g.test(filesystem.atime)) {
- filesystem.properties.inherit.push("atime");
- } else {
- filesystem.properties.new.push("atime=" + filesystem.atime);
- }
- }
- if (filesystem.canmount) {
- filesystem.properties.new.push("canmount=" + filesystem.canmount);
- }
- if (filesystem.checksum) {
- if (/^Default|^Inherited/g.test(filesystem.checksum)) {
- filesystem.properties.inherit.push("checksum");
- } else {
- filesystem.properties.new.push("checksum=" + filesystem.checksum);
- }
- }
- if (filesystem.compression) {
- if (/^Default|^Inherited/g.test(filesystem.compression)) {
- filesystem.properties.inherit.push("compression");
- } else {
- filesystem.properties.new.push("compression=" + filesystem.compression);
- }
- }
- if (filesystem.context) {
- filesystem.properties.new.push("context=" + filesystem.context);
- }
- if (filesystem.dedup) {
- if (/^Default|^Inherited/g.test(filesystem.dedup)) {
- filesystem.properties.inherit.push("dedup");
- } else {
- filesystem.properties.new.push("dedup=" + filesystem.dedup);
- }
- }
- if (filesystem.dnodesize) {
- if (/^Default|^Inherited/g.test(filesystem.dnodesize)) {
- filesystem.properties.inherit.push("dnodesize");
- } else {
- filesystem.properties.new.push("dnodesize=" + filesystem.dnodesize);
- }
- }
- if (filesystem.defcontext) {
- filesystem.properties.new.push("defcontext=" + filesystem.defcontext);
- }
- if (filesystem.fscontext) {
- filesystem.properties.new.push("fscontext=" + filesystem.fscontext);
- }
- if (filesystem.mountpoint) {
- filesystem.properties.new.push(`mountpoint="` + filesystem.mountpoint + `"`);
- }
- if (filesystem.quota) {
- filesystem.properties.new.push(`quota="` + filesystem.quota + `"`);
- }
- if (filesystem.readonly) {
- filesystem.properties.new.push("readonly=" + filesystem.readonly);
- }
- if (filesystem.recordsize) {
- if (/^Default|^Inherited/g.test(filesystem.recordsize)) {
- filesystem.properties.inherit.push("recordsize");
- } else {
- filesystem.properties.new.push("recordsize=" + filesystem.recordsize);
- }
- }
- if (filesystem.refreservation) {
- filesystem.properties.new.push("refreservation=" + filesystem.refreservation);
- }
- if (filesystem.rootcontext) {
- filesystem.properties.new.push("rootcontext=" + filesystem.rootcontext);
- }
- if (filesystem.sharenfs) {
- filesystem.properties.new.push(`sharenfs="` + filesystem.sharenfs + `"`);
- }
- if (filesystem.sharesmb && !zfsmanager.configuration.samba.manage) {
- filesystem.properties.new.push("sharesmb=" + filesystem.sharesmb);
- }
- if (filesystem.special_small_blocks) {
- if (/^Default|^Inherited/g.test(filesystem.special_small_blocks)) {
- filesystem.properties.inherit.push("special_small_blocks");
- } else {
- filesystem.properties.new.push("special_small_blocks=" + filesystem.special_small_blocks);
- }
- }
- if (filesystem.xattr) {
- if (/^Default|^Inherited/g.test(filesystem.xattr)) {
- filesystem.properties.inherit.push("xattr");
- } else {
- filesystem.properties.new.push("xattr=" + filesystem.xattr);
- }
- }
-
- if (filesystem.properties.inherit.length > 0 && !pool.readonly) {
- FnFileSystemConfigureInheritance({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, properties: { inherit: filesystem.properties.inherit }, type: filesystem.type })
- .finally(function () {
- if (filesystem.properties.new.length > 0 && !pool.readonly) {
- FnFileSystemConfigureCommand({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint, properties: { new: filesystem.properties.new }, type: filesystem.type }, { restart: samba.restart }, { id: modal.id });
- } else {
- modal.id.modal("hide");
- }
- });
- } else if (filesystem.properties.new.length > 0 && !pool.readonly) {
- FnFileSystemConfigureCommand({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint, properties: { new: filesystem.properties.new }, type: filesystem.type }, { restart: samba.restart }, { id: modal.id });
- } else {
- modal.id.modal("hide");
- }
-}
-
-function FnFileSystemConfigureCommand(pool = { name, id, altroot: false }, filesystem = { name, id, mountpoint, properties: { new: [] }, type }, samba = { restart: false }, modal = { id }) {
- let process = {
- command: ["/bin/sh", "-c", "/sbin/zfs set " + filesystem.properties.new.join(" ") + " " + `"` + filesystem.name + `"`]
- };
-
- modal.hide = true;
-
- FnConsole.log[2]("File Systems, Configure: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-storagepool-filesystem-configure-" + filesystem.id + " span").text("Configuring " + filesystem.type.toLowerCase() + "...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "File System successfully configured", description: filesystem.name, breakword: false }, { name: "filesystem-configure", id: filesystem.id, timeout: 4 });
-
- FnConsole.log[1]("File Systems, Configure: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- if (zfsmanager.configuration.samba.manage) {
- if (filesystem.mountpoint) {
- modal.hide = false;
-
- $("#spinner-storagepool-filesystem-configure-" + filesystem.id + " span").text("Updating Samba shares...");
-
- FnSambaZfsShareConfigurationPathsSet({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name }, { restart: samba.restart }, display = { refresh: false, silent: true })
- .finally(function () {
- modal.id.modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
- } else if (samba.restart) {
- FnSambaRestart();
- }
- } else {
- if (samba.restart) {
- FnSambaRestart();
- }
- }
- })
- .fail(function (message, data) {
- filesystem.configured = false;
-
- if (/size is greater than available space/gi.test(data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-filesystem-configure-refreservation-" + filesystem.id).addClass("has-error");
- $("#helpblock-storagepool-filesystem-configure-refreservation-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Refreservation can not be greater than available size.");
- $("#input-storagepool-filesystem-configure-refreservation-" + filesystem.id).focus();
- } else if (/size is less than current used or reserved space/gi.test(data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-filesystem-configure-quota-" + filesystem.id).addClass("has-error");
- $("#helpblock-storagepool-filesystem-configure-quota-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Quota can not be less than used size.");
- $("#input-storagepool-filesystem-configure-quota-" + filesystem.id).focus();
- } else if (/property may be set/gi.test(data)) {
- filesystem.configured = true;
-
- FnDisplayAlert({ status: "warning", title: "File system configured with errors", description: filesystem.name, breakword: false }, { name: "filesystem-configure", id: filesystem.id, timeout: 4 });
-
- FnConsole.warn("File Systems, Configure: Warning, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- }
-
- if (!filesystem.configured) {
- if (modal.hide) {
- FnDisplayAlert({ status: "danger", title: "File System could not be configured", description: filesystem.name, breakword: false }, { name: "filesystem-configure", id: filesystem.id, timeout: 4 });
- }
-
- FnConsole.warn("File Systems, Configure: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- }
-
- if (!modal.hide) {
- $("#spinner-storagepool-filesystem-configure-" + filesystem.id).addClass("hidden");
- $("#spinner-storagepool-filesystem-configure-" + filesystem.id + " span").text("");
- $("#btn-storagepool-filesystem-configure-apply-" + filesystem.id).prop("disabled", false);
- }
- })
- .finally(function () {
- if (modal.hide) {
- modal.id.modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- });
-}
-
-function FnFileSystemConfigureInheritance(pool = { name, id }, filesystem = { name, id, properties: { inherit: [] }, type }) {
- let process = {
- promise: cockpit.defer()
- };
- let promise = Promise.resolve();
-
- filesystem.properties.errorcount = 0;
-
- $("#spinner-storagepool-filesystem-configure-" + filesystem.id + " span").text("Configuring " + filesystem.type.toLowerCase() + " inheritance...");
-
- filesystem.properties.inherit.forEach((_value, _index) => {
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- process.command = ["/sbin/zfs", "inherit", _value, filesystem.name];
-
- FnConsole.log[2]("File Systems, Configure, Inheritance: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[2]("File Systems, Configure, Inheritance: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- if (_index == (filesystem.properties.inherit.length - 1)) {
- if (filesystem.properties.errorcount == 0) {
- FnDisplayAlert({ status: "success", title: "File System inheritance successfully configured", description: filesystem.name, breakword: false }, { name: "filesystem-configure-inheritance", id: filesystem.id, timeout: 4 });
- } else {
- FnDisplayAlert({ status: "danger", title: "File System inheritance could not be configured", description: filesystem.name, breakword: false }, { name: "filesystem-configure-inheritance", id: filesystem.id, timeout: 4 });
- }
-
- process.promise.resolve();
- }
- })
- .fail(function (message, data) {
- filesystem.properties.errorcount++;
-
- FnConsole.warn("File Systems, Configure, Inheritance: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
-
- if (_index == (filesystem.properties.inherit.length - 1)) {
- FnDisplayAlert({ status: "danger", title: "File System inheritance could not be configured", description: filesystem.name, breakword: false }, { name: "filesystem-configure-inheritance", id: filesystem.id, timeout: 4 });
-
- process.promise.resolve();
- }
- });
-
- resolve();
- }, 500)
- ));
- });
-
- return process.promise.promise();
-}
-
-function FnFileSystemCreate(pool = { name, id, altroot: false }, filesystem = { name, id, atime, casesensitivity, cipher, compression, dedup, dnodesize, encryption, passphrase, quota, readonly, recordsize, selinux, sharenfs, sharesmb, special_small_blocks, xattr }) {
- let process = {
- command: [],
- options: `-o normalization=formD -o sharenfs="` + filesystem.sharenfs + `" -o sharesmb=` + filesystem.sharesmb + ` -o utf8only=on`
- };
-
- if (filesystem.quota) {
- process.options += " -o quota=" + filesystem.quota;
- }
- if (filesystem.readonly) {
- process.options += " -o readonly=" + filesystem.readonly;
- }
- if (filesystem.selinux) {
- process.options += " -o context=system_u:object_r:samba_share_t:s0 -o fscontext=system_u:object_r:samba_share_t:s0 -o defcontext=system_u:object_r:samba_share_t:s0 -o rootcontext=system_u:object_r:samba_share_t:s0";
- }
- if (/^Inherited/g.test(filesystem.atime) == false) {
- process.options += " -o atime=" + filesystem.atime;
- }
- if (/^Inherited/g.test(filesystem.casesensitivity) == false) {
- process.options += " -o casesensitivity=" + filesystem.casesensitivity;
- }
- if (/^Inherited/g.test(filesystem.dedup) == false) {
- process.options += " -o dedup=" + filesystem.dedup;
- }
- if (/^Inherited/g.test(filesystem.dnodesize) == false) {
- process.options += " -o dnodesize=" + filesystem.dnodesize;
- }
- if (/^Inherited/g.test(filesystem.compression) == false) {
- process.options += " -o compression=" + filesystem.compression;
- }
- if (/^Inherited/g.test(filesystem.recordsize) == false) {
- process.options += " -o recordsize=" + filesystem.recordsize;
- }
- if (/^Inherited/g.test(filesystem.special_small_blocks) == false) {
- process.options += " -o special_small_blocks=" + filesystem.special_small_blocks;
- }
- if (/^Inherited/g.test(filesystem.xattr) == false) {
- process.options += " -o xattr=" + filesystem.xattr;
- }
- if (/^Inherited/g.test(filesystem.cipher) == false && filesystem.encryption) {
- process.options += " -o encryption=" + filesystem.cipher;
- }
-
- if (filesystem.encryption && filesystem.passphrase) {
- process.options += " -o keyformat=passphrase -o keylocation=prompt";
-
- if (filesystem.passphrase.length < 8) {
- FnFileSystemCreateFail({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, id: filesystem.id, sharesmb: filesystem.sharesmb }, { data: "Passphrase requires a minimum of 8 characters.", message: null });
- return;
- }
-
- //Escape percentage and single quote special character for printf
- if (/\%/g.test(filesystem.passphrase)) {
- filesystem.passphrase = filesystem.passphrase.replace(/\%/g, "\%\%");
- }
- if (/\'/g.test(filesystem.passphrase)) {
- filesystem.passphrase = filesystem.passphrase.replace(/\'/g, "\'\"\'\"\'");
- }
-
- process.command = ["/bin/sh", "-c", "printf '" + filesystem.passphrase + "' | /sbin/zfs create " + process.options + ` "` + filesystem.name + `"`];
- } else {
- process.command = ["/bin/sh", "-c", "/sbin/zfs create " + process.options + ` "` + filesystem.name + `"`];
- }
-
- FnConsole.log[1]("File Systems, Create: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-storagepool-filesystems-create-" + pool.id + " span").text("Creating file system...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "File System successfully created", description: filesystem.name, breakword: false }, { name: "filesystem-create", id: filesystem.id, timeout: 4 });
-
- FnConsole.log[1]("File Systems, Create: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- if (filesystem.sharesmb == "on" && zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-filesystems-create-" + pool.id + " span").text("Enabling Samba share...");
-
- FnSambaShareEnableMountpointGet({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { name: filesystem.name, id: filesystem.id, sharesmb: true }, { silent: false });
- }
-
- setTimeout(function () {
- $("#modal-storagepool-filesystems-create-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }, (filesystem.sharesmb == "on" && zfsmanager.configuration.samba.manage ? 500 : 0));
- })
- .fail(function (message, data) {
- FnFileSystemCreateFail({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, id: filesystem.id, sharesmb: filesystem.sharesmb }, { data: data, message: message });
- });
-}
-
-function FnFileSystemCreateFail(pool = { name, id, altroot: false }, filesystem = { name, id, sharesmb }, process = { data, message }) {
- let modal = {
- hide: true
- };
-
- filesystem.created = false;
-
- if (/dataset already exists/gi.test(process.data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-filesystems-create-name-" + pool.id).addClass("has-error");
- $("#helpblock-storagepool-filesystems-create-name-" + pool.id).addClass("has-error").removeClass("hidden").text("Name already exists.");
- $("#input-storagepool-filesystems-create-name-" + pool.id).focus();
- } else if (/encryption root's key is not loaded or provided/gi.test(process.data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-" + pool.id).addClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-" + pool.id).addClass("has-error").removeClass("hidden").html("Parent file system is locked. Unlock parent file system or enter a passphrase to create an independent encryption root.");
- $("#input-storagepool-filesystems-create-encryption-passphrase-" + pool.id).focus();
- } else if (/Passphrase requires a minimum of 8 characters./i.test(process.data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-" + pool.id).addClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-" + pool.id).addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
- $("#input-storagepool-filesystems-create-encryption-passphrase-" + pool.id).focus();
- } else if (/filesystem successfully created/gi.test(process.data)) {
- filesystem.created = true;
-
- FnDisplayAlert({ status: "warning", title: "File system created with errors", description: filesystem.name, breakword: false }, { name: "filesystem-create", id: filesystem.id, timeout: 4 });
-
- FnConsole.warn("File Systems, Create: Warning, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
-
- if (filesystem.sharesmb == "on" && zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-filesystems-create-" + pool.id + " span").text("Enabling Samba share...");
-
- FnSambaShareEnableMountpointGet({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { name: filesystem.name, id: filesystem.id, sharesmb: true }, { silent: false });
- }
- }
-
- if (!modal.hide) {
- $("#spinner-storagepool-filesystems-create-" + pool.id).addClass("hidden");
- $("#spinner-storagepool-filesystems-create-" + pool.id + " span").text("");
- $("#btn-storagepool-filesystems-create-apply-" + pool.id).prop("disabled", false);
- }
-
- if (!filesystem.created) {
- FnConsole.warn("File Systems, Create: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
- }
-
- if (modal.hide) {
- if (!filesystem.created) {
- FnDisplayAlert({ status: "danger", title: "File System could not be created", description: filesystem.name, breakword: false }, { name: "filesystem-create", id: filesystem.id, timeout: 4 });
- }
-
- $("#modal-storagepool-filesystems-create-" + pool.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
-}
-
-function FnFileSystemDestroy(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, force: false, recursive: false, recursiveall: false, sharesmb: false, type }, samba = { restart: false }) {
- if (samba.restart) {
- FnSambaStop()
- .finally(function () {
- if ((filesystem.recursive || filesystem.recursiveall) && zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: filesystem.name, clones: [] })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying " + filesystem.type.toLowerCase() + "s...");
-
- if (filesystems.id.length > 0) {
- FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: false })
- .done(function () {
- $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying Samba shares...");
-
- FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: true })
- .finally(function () {
- $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
- });
- } else {
- FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: true })
- }
- })
- .fail(function (message, data) {
- FnFileSystemDestroyFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: data, message: message }, { refresh: true });
- FnSambaStart();
- });
- } else {
- $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying " + filesystem.type.toLowerCase() + "...");
-
- if (filesystem.sharesmb && zfsmanager.configuration.samba.manage) {
- FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: false })
- .done(function () {
- $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying Samba share...");
-
- FnSambaShareDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { silent: true })
- .finally(function () {
- $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
- });
- } else {
- FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: true })
- .finally(function () {
- if (!filesystem.sharesmb || !zfsmanager.configuration.samba.manage) {
- FnSambaStart();
- }
- });
- }
- }
- });
- } else {
- if ((filesystem.recursive || filesystem.recursiveall) && zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: filesystem.name, clones: [] })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying " + filesystem.type.toLowerCase() + "s...");
-
- if (filesystems.id.length > 0) {
- FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: false })
- .done(function () {
- $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying Samba shares...");
-
- FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: true })
- .finally(function () {
- $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
- });
- } else {
- FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: true })
- }
- })
- .fail(function (message, data) {
- FnFileSystemDestroyFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: data, message: message }, { refresh: true });
- });
- } else {
- $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying " + filesystem.type.toLowerCase() + "...");
-
- if (filesystem.sharesmb && zfsmanager.configuration.samba.manage) {
- FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: false })
- .done(function () {
- $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying Samba share...");
-
- FnSambaShareDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { silent: true })
- .finally(function () {
- $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
- });
- } else {
- FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: true })
- }
- }
- }
-}
-
-function FnFileSystemDestroyCommand(pool = { name, id }, filesystem = { name, id, force: false, recursive: false, recursiveall: false }, display = { refresh: true }) {
- let process = {
- command: ["/sbin/zfs", "destroy", filesystem.name]
- };
-
- if (filesystem.force) {
- process.command.splice(2, 0, "-f");
- }
- if (filesystem.recursive) {
- process.command.splice(2, 0, "-r");
- }
- if (filesystem.recursiveall) {
- process.command.splice(2, 0, "-R");
- }
-
- FnConsole.log[1]("File Systems, Destroy: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "File System successfully destroyed", description: filesystem.name, breakword: false }, { name: "filesystem-destroy", id: filesystem.id, timeout: 4 });
-
- FnConsole.log[1]("File Systems, Destroy: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnFileSystemDestroyFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: data, message: message }, { refresh: false });
-
- display.refresh = true;
- })
- .finally(function () {
- if (display.refresh) {
- $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- });
-}
-
-function FnFileSystemDestroyFail(pool = { name, id }, filesystem = { name, id }, process = { data, message }, display = { refresh: true }) {
- FnDisplayAlert({ status: "danger", title: "File System could not be destroyed", description: filesystem.name, breakword: false }, { name: "filesystem-destroy", id: filesystem.id, timeout: 4 });
-
- FnConsole.warn("File Systems, Destroy: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
-
- if (display.refresh) {
- $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
-}
-
-function FnFileSystemLock(pool = { name, id }, filesystem = { name, id, type }, display = { refresh: true }) {
- let process = {
- command: ["/sbin/zfs", "unload-key", filesystem.name]
- };
-
- FnConsole.log[2]("File Systems, Lock: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-storagepool-filesystem-lock-" + filesystem.id + " span").text("Locking " + filesystem.type.toLowerCase() + "...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "File System successfully locked", description: filesystem.name, breakword: false }, { name: "filesystem-lock", id: filesystem.id, timeout: 4 });
-
- FnConsole.log[1]("File Systems, Lock: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "File System could not be locked", description: filesystem.name, breakword: false }, { name: "filesystem-lock", id: filesystem.id, timeout: 4 });
-
- FnConsole.warn("File Systems, Lock: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- if (display.refresh) {
- $("#modal-storagepool-filesystem-lock-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- });
-}
-
-function FnFileSystemMount(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, overlay: true, type }, samba = { enable: false }, display = { refresh: true }) {
- let process = {
- command: ["/sbin/zfs", "mount", filesystem.name]
- };
-
- if (filesystem.overlay) {
- process.command.splice(2, 0, "-O");
- }
-
- FnConsole.log[2]("File Systems, Mount: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-storagepool-filesystem-mount-" + filesystem.id + " span").text("Mounting " + filesystem.type.toLowerCase() + "...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "File System successfully mounted", description: filesystem.name, breakword: false }, { name: "filesystem-mount", id: filesystem.id, timeout: 4 });
-
- FnConsole.log[1]("File Systems, Mount: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- if (samba.enable) {
- $("#spinner-storagepool-filesystem-mount-" + filesystem.id + " span").text("Enabling Samba share...");
-
- if (zfsmanager.configuration.samba.manage) {
- FnSambaShareEnableMountpointGet({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, sharesmb: false }, { silent: false });
- } else {
- FnFileSystemShareSmbEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- }
- }
- })
- .fail(function (message, data) {
- if (/filesystem already mounted/gi.test(data)) {
- FnDisplayAlert({ status: "warning", title: "File System was already mounted", description: filesystem.name, breakword: false }, { name: "filesystem-mount", id: filesystem.id, timeout: 4 });
- } else {
- FnDisplayAlert({ status: "danger", title: "File System could not be mounted", description: filesystem.name, breakword: false }, { name: "filesystem-mount", id: filesystem.id, timeout: 4 });
- }
-
- FnConsole.warn("File Systems, Mount: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- setTimeout(function () {
- $("#modal-storagepool-filesystem-mount-" + filesystem.id).modal("hide");
-
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
- }, 200);
- }
- }, (samba.enable ? 500 : 0));
- });
-}
-
-function FnFileSystemMountpointGet(pool = { name, id }, filesystem = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "get", "mountpoint", "-H", "-o", "value", filesystem.name]
- };
-
- FnConsole.log[2]("File Systems, Mountpoint, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function () {
- FnConsole.log[1]("File Systems, Mountpoint, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, Mountpoint, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnFileSystemPromote(pool = { name, id }, filesystem = { name, id, type }) {
- let process = {
- command: ["/sbin/zfs", "promote", filesystem.name]
- };
-
- FnConsole.log[2]("File Systems, Promote: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-storagepool-filesystem-promote-" + filesystem.id + " span").text("Promoting " + filesystem.type.toLowerCase() + "...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "File System successfully promoted", description: filesystem.name, breakword: false }, { name: "filesystem-promote", id: filesystem.id, timeout: 4 });
-
- FnConsole.log[1]("File Systems, Promote: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "File System could not be promoted", description: filesystem.name, breakword: false }, { name: "filesystem-promote", id: filesystem.id, timeout: 4 });
-
- FnConsole.warn("File Systems, Promote: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#modal-storagepool-filesystem-promote-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
-}
-
-function FnFileSystemRename(pool = { name, id, altroot: false }, filesystem = { name, id, createnonexistparents: false, force: false, namenew, parent, sharesmb: false, type }, samba = { restart: false }) {
- if (samba.restart) {
- FnSambaStop()
- .finally(function () {
- if (zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: filesystem.name, clones: [] })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Renaming " + filesystem.type.toLowerCase() + "...");
-
- if (filesystems.id.length > 0) {
- FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: false })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Rename:" }));
-
- if (/dataset already exists/i.test(data) == false) {
- $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Renaming Samba share" + (filesystems.id.length > 1 ? "s" : "") + "...");
-
- FnSambaSharesRename({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, filesystems = { id: filesystems.id, parent: { name: filesystem.name, namenew: filesystem.namenew } }, { restart: samba.restart }, { silent: false })
- .finally(function () {
- if (filesystem.createnonexistparents) {
- FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.parent }, { disable: true })
- .finally(function () {
- $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- });
- } else {
- $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- }
- });
-
- }
- });
- } else {
- FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: (filesystem.createnonexistparents ? false : true) })
- .done(function () {
- if (filesystem.createnonexistparents) {
- $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Disabling Samba share inheritance...");
-
- FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.parent }, { disable: true })
- .finally(function () {
- $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
-
- FnSambaStart();
- });
- } else {
- FnSambaStart();
- }
- })
- .fail(function () {
- FnSambaStart();
- });
- }
- })
- .fail(function (message, data) {
- FnFileSystemRenameFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, parent: filesystem.parent }, { data: data, message: message }, { refresh: true });
- FnSambaStart();
- });
- } else {
- FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: true })
- .finally(function () {
- FnSambaStart();
- });
- }
- });
- } else {
- if (zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: filesystem.name, clones: [] })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Renaming " + filesystem.type.toLowerCase() + "...");
-
- if (filesystems.id.length > 0) {
- FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: false })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Rename:" }));
-
- if (/dataset already exists/i.test(data) == false) {
- $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Renaming Samba share" + (filesystems.id.length > 1 ? "s" : "") + "...");
-
- FnSambaSharesRename({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, filesystems = { id: filesystems.id, parent: { name: filesystem.name, namenew: filesystem.namenew } }, { restart: samba.restart }, { silent: false })
- .finally(function () {
- if (filesystem.createnonexistparents) {
- FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.parent }, { disable: true })
- .finally(function () {
- $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- });
- } else {
- $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- }
- });
- }
- });
- } else {
- FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: (filesystem.createnonexistparents ? false : true) })
- .done(function () {
- if (filesystem.createnonexistparents) {
- $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Disabling Samba share inheritance...");
-
- FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.parent }, { disable: true })
- .finally(function () {
- $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- });
- }
- });
- }
- })
- .fail(function (message, data) {
- FnFileSystemRenameFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, parent: filesystem.parent }, { data: data, message: message }, { refresh: true });
- });
- } else {
- FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: true });
- }
- }
-}
-
-function FnFileSystemRenameCommand(pool = { name, id }, filesystem = { name, id, createnonexistparents: false, force: false, namenew, parent }, display = { refresh: true }) {
- let process = {
- command: ["/sbin/zfs", "rename", filesystem.name, filesystem.namenew]
- };
-
- if (filesystem.force) {
- process.command.splice(2, 0, "-f");
- }
- if (filesystem.createnonexistparents) {
- process.command.splice(2, 0, "-p");
- }
-
- FnConsole.log[1]("File Systems, Rename: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Rename:" }));
-
- if (/dataset already exists/i.test(data)) {
- FnFileSystemRenameFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, parent: filesystem.parent }, { data: data, message: message }, { refresh: true });
- return;
- }
-
- FnDisplayAlert({ status: "success", title: "File System successfully renamed", description: filesystem.name, breakword: false }, { name: "filesystem-rename", id: filesystem.id, timeout: 4 });
-
- FnConsole.log[1]("File Systems, Rename: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- if (display.refresh) {
- $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- }
- })
- .fail(function (message, data) {
- FnFileSystemRenameFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, parent: filesystem.parent }, { data: data, message: message }, { refresh: true });
- });
-}
-
-function FnFileSystemRenameFail(pool = { name, id }, filesystem = { name, id, createnonexistparents: false, parent }, process = { data, message }, display = { refresh: true }) {
- let modal = {
- hide: true
- };
-
- if (/dataset already exists/i.test(process.data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-filesystem-rename-name-" + filesystem.id).addClass("has-error");
- $("#helpblock-storagepool-filesystem-rename-name-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Name already exists.");
- $("#input-storagepool-filesystem-rename-name-" + filesystem.id).focus();
- } else if (/parent does not exist/i.test(process.data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-filesystem-rename-name-" + filesystem.id).addClass("has-error");
- $("#helpblock-storagepool-filesystem-rename-name-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Parent file system does not exist.");
- $("#input-storagepool-filesystem-rename-name-" + filesystem.id).focus();
- }
-
- if (!modal.hide) {
- $("#spinner-storagepool-filesystem-rename-" + filesystem.id).addClass("hidden");
- $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("");
- $("#btn-storagepool-filesystem-rename-apply-" + filesystem.id).prop("disabled", false);
- }
-
- FnConsole.warn("File Systems, Rename: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
-
- if (modal.hide) {
- FnDisplayAlert({ status: "danger", title: "File System could not be renamed", description: filesystem.name, breakword: false }, { name: "filesystem-rename", id: filesystem.id, timeout: 4 });
-
- $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
-
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- }
-}
-
-function FnFileSystemSelinuxContextsSambaSet(pool = { name, id }, filesystem = { name }) {
- let process = {
- command: ["/sbin/zfs", "set", "context=system_u:object_r:samba_share_t:s0", "defcontext=system_u:object_r:samba_share_t:s0", "fscontext=system_u:object_r:samba_share_t:s0", "rootcontext=system_u:object_r:samba_share_t:s0", filesystem.name]
- };
-
- FnConsole.log[2]("File Systems, SELinux Contexts, Samba, Set: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("File Systems, SELinux Contexts, Samba, Set: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, SELinux Contexts, Samba, Set: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- })
-}
-
-function FnFileSystemShareSmbDisable(pool = { name, id }, filesystem = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "set", "sharesmb=off", filesystem.name]
- };
-
- FnConsole.log[2]("File Systems, Share SMB, Disable: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("File Systems, Share SMB, Disable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- if (/property may be set/gi.test(data)) { //False error is generated when configuring filesystem
- FnConsole.log[1]("File Systems, Share SMB, Disable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- } else {
- FnConsole.warn("File Systems, Share SMB, Disable: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- }
- });
-}
-
-function FnFileSystemShareSmbEnable(pool = { name, id }, filesystem = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "set", "sharesmb=on", filesystem.name]
- };
-
- FnConsole.log[2]("File Systems, Share SMB, Enable: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("File Systems, Share SMB, Enable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- if (/property may be set/gi.test(data)) { //False error is generated when configuring filesystem
- FnConsole.log[1]("File Systems, Share SMB, Enable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- } else {
- FnConsole.warn("File Systems, Share SMB, Enable: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- }
- });
-}
-
-function FnFileSystemShareSmbInheritedDisable(pool = { name, id, altroot: false }, filesystem = { name }, force = { disable: false }) {
- let process = {
- command: ["/sbin/zfs", "get", "-H", "name,sharesmb", "-o", "property,value,source", "-r", "-t", "filesystem"],
- promise: cockpit.defer()
- };
-
- if (filesystem.name) {
- process.command.push(filesystem.name);
- } else if (pool.name) {
- process.command.push(pool.name);
- }
-
- FnConsole.log[2]("File Systems, Share SMB, Inherited, Disable: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Share SMB, Inherited, Disable:" }));
-
- let filesystems = data.replace(/\nsharesmb/g, "\u22C5sharesmb").replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v && /\u22C5sharesmb\u22C5on\u22C5inherited from|\u22C5sharesmb\u22C5off\u22C5inherited from/gi.test(v));
- let promise = Promise.resolve();
-
- if (filesystems.length > 0) {
- filesystems.forEach((_value, _index) => {
- _value = _value.split("\u22C5");
-
- let filesystem = {
- name: _value[1],
- id: FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: _value[1], attribute: true }),
- sharesmb: {
- enabled: (_value[4].toLowerCase() == "on" ? true : false),
- source: _value[5]
- }
- };
- let pool = {
- name: filesystem.name.replace(/\/.*$/, ""),
- id: FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.name, attribute: true })
- };
-
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- if (filesystem.sharesmb.enabled && !force.disable) {
- FnFileSystemShareSmbEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id })
- .finally(function () {
- if (_index == (filesystems.length - 1)) {
- FnConsole.log[1]("File Systems, Share SMB, Inherited, Disable: Success");
-
- process.promise.resolve();
- }
- });
- } else {
- if (force.disable) {
- FnSambaShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { name: filesystem.name, id: filesystem.id }, { restart: false }, { modal: false, silent: true });
-
- if (_index == (filesystems.length - 1)) {
- setTimeout(function () {
- FnConsole.log[1]("File Systems, Share SMB, Inherited, Disable: Success");
-
- process.promise.resolve();
- }, 1000);
- }
- } else {
- FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id })
- .finally(function () {
- if (_index == (filesystems.length - 1)) {
- FnConsole.log[1]("File Systems, Share SMB, Inherited, Disable: Success");
-
- process.promise.resolve();
- }
- });
- }
- }
-
- resolve();
- }, (force.disable ? 1000 : 500))
- ));
- });
- } else {
- FnConsole.log[1]("File Systems, Share SMB, Inherited, Disable: Success" + (pool.name ? ", Pool: " + pool.name : ""));
-
- process.promise.resolve();
- }
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, Share SMB, Inherited, Disable: Failed" + ", Message: " + (data ? data : message));
-
- process.promise.resolve();
- });
-
- return process.promise.promise();
-}
-
-function FnFileSystemUnlock(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mount: true, overlay: true, passphrase, type }, samba = { enable: false }, modal = { name, id }, display = { refresh: true }) {
- let process = {
- command: []
- };
-
- modal.id = (modal.id ? "-" + modal.id : "");
-
- //Escape percentage and single quote special character for printf
- if (/\%/g.test(filesystem.passphrase)) {
- filesystem.passphrase = filesystem.passphrase.replace(/\%/g, "\%\%");
- }
- if (/\'/g.test(filesystem.passphrase)) {
- filesystem.passphrase = filesystem.passphrase.replace(/\'/g, "\'\"\'\"\'");
- }
-
- process.command = ["/bin/sh", "-c", "printf '" + filesystem.passphrase + "' | /sbin/zfs load-key \"" + filesystem.name + "\""];
-
- FnConsole.log[2]("File Systems, Unlock: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- if (display.refresh) {
- $("#spinner-" + modal.name + modal.id + " span").text("Unlocking " + filesystem.type.toLowerCase() + "...");
- }
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Unlock:" }));
-
- if (/error|Incorrect key/i.test(data)) {
- FnFileSystemUnlockFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, type: filesystem.type }, { name: modal.name, id: modal.id }, { refresh: display.refresh }, { data: data, message: message });
- return;
- }
-
- FnDisplayAlert({ status: "success", title: "File System successfully unlocked", description: filesystem.name, breakword: false }, { name: "filesystem-unlock", id: filesystem.id, timeout: 4 });
-
- FnConsole.log[1]("File Systems, Unlock: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- if (filesystem.mount) {
- setTimeout(function () {
- FnFileSystemMount({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, overlay: filesystem.overlay, type: filesystem.type }, { enable: samba.enable }, { refresh: display.refresh })
- .finally(function () {
- if (display.refresh) {
- $("#modal-" + modal.name + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- });
- }, 200);
- } else if (display.refresh) {
- $("#modal-" + modal.name + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- })
- .fail(function (message, data) {
- if (/Key already loaded/i.test(data)) {
- FnFileSystemUnlockWarn({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, mount: filesystem.mount, overlay: filesystem.overlay, type: filesystem.type }, { enable: samba.enable }, { name: modal.name, id: modal.id }, { refresh: display.refresh }, { data: data, message: message });
- } else {
- FnFileSystemUnlockFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, type: filesystem.type }, { name: modal.name, id: modal.id }, { refresh: display.refresh }, { data: data, message: message });
- }
- });
-}
-
-function FnFileSystemUnlockFail(pool = { name, id }, filesystem = { name, id, type }, modal = { name, id }, display = { refresh: true }, process = { data, message }) {
- modal.hide = true;
-
- if (/Incorrect key provided/gi.test(process.data)) {
- modal.hide = false;
-
- $("#validationwrapper-" + modal.name + "-passphrase" + modal.id).addClass("has-error");
- $("#helpblock-" + modal.name + "-passphrase" + modal.id).addClass("has-error").removeClass("hidden").text("Passphrase is incorrect.");
- $("#input-" + modal.name + "-passphrase" + modal.id).focus();
- }
-
- if (!modal.hide && display.refresh) {
- $("#spinner-" + modal.name + modal.id).addClass("hidden");
- $("#spinner-" + modal.name + modal.id + " span").text("");
- $("#btn-" + modal.name + "-apply" + modal.id).prop("disabled", false);
- }
-
- if (modal.hide || !display.refresh) {
- FnDisplayAlert({ status: "danger", title: "File System could not be unlocked", description: filesystem.name, breakword: false }, { name: "filesystem-unlock", id: filesystem.id, timeout: 4 });
- }
-
- if (modal.hide) {
- if (display.refresh) {
- $("#modal-" + modal.name + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- }
-
- FnConsole.warn("File Systems, Unlock: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
-}
-
-function FnFileSystemUnlockWarn(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mount: true, overlay: true, type }, samba = { enable: false }, modal = { name, id }, display = { refresh: true }, process = { data, message }) {
- FnDisplayAlert({ status: "warning", title: "File System was already unlocked", description: filesystem.name, breakword: false }, { name: "filesystem-unlock", id: filesystem.id, timeout: 4 });
-
- FnConsole.warn("File Systems, Unlock: Warning, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
-
- if (filesystem.mount) {
- setTimeout(function () {
- FnFileSystemMount({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, overlay: filesystem.overlay, type: filesystem.type }, { enable: samba.enable }, { refresh: display.refresh })
- .finally(function () {
- if (display.refresh) {
- $("#modal-" + modal.name + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- });
- }, 200);
- } else if (display.refresh) {
- $("#modal-" + modal.name + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
-}
-
-function FnFileSystemUnmount(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, force: false, lock: false, type }, samba = { disable: false, restart: false }) {
- if (samba.restart) {
- FnSambaStop()
- .finally(function () {
- $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Unmounting " + filesystem.type.toLowerCase() + "...");
-
- FnFileSystemUnmountCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, lock: filesystem.lock }, { refresh: ((filesystem.lock || samba.disable) ? false : true) })
- .done(function () {
- if (filesystem.lock) {
- $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Locking " + filesystem.type.toLowerCase() + "...");
-
- FnFileSystemLock({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, type: filesystem.type }, { refresh: false })
- .finally(function () {
- if (samba.disable) {
- $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Disabling Samba share...");
-
- if (zfsmanager.configuration.samba.manage) {
- FnSambaShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: false, silent: false });
- } else {
- FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- }
- }
-
- setTimeout(function () {
- $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }, (samba.disable ? 1000 : 200));
- });
- } else {
- if (samba.disable) {
- $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Disabling Samba share...");
-
- if (zfsmanager.configuration.samba.manage) {
- FnSambaShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: false, silent: false });
- } else {
- FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- }
- }
-
- setTimeout(function () {
- $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }, (samba.disable ? 1000 : 200));
- }
- })
- .finally(function () {
- if (!samba.disable || !zfsmanager.configuration.samba.manage) {
- FnSambaStart();
- }
- });
- });
- } else {
- $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Unmounting " + filesystem.type.toLowerCase() + "...");
-
- FnFileSystemUnmountCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, lock: filesystem.lock }, { refresh: ((filesystem.lock || samba.disable) ? false : true) })
- .done(function () {
- if (filesystem.lock) {
- $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Locking " + filesystem.type.toLowerCase() + "...");
-
- FnFileSystemLock({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, type: filesystem.type }, { refresh: false })
- .finally(function () {
- if (samba.disable) {
- $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Disabling Samba share...");
-
- if (zfsmanager.configuration.samba.manage) {
- FnSambaShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: false, silent: false });
- } else {
- FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- }
- }
-
- setTimeout(function () {
- $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }, (samba.disable ? 1000 : 200));
- });
- } else {
- if (samba.disable) {
- $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Disabling Samba share...");
-
- if (zfsmanager.configuration.samba.manage) {
- FnSambaShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: false, silent: false });
- } else {
- FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- }
- }
-
- setTimeout(function () {
- $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }, (samba.disable ? 1000 : 200));
- }
- });
- }
-}
-
-function FnFileSystemUnmountCommand(pool = { name, id }, filesystem = { name, id, force: false, lock: false }, display = { refresh: true }) {
- let process = {
- command: ["/sbin/zfs", "unmount", filesystem.name]
- };
-
- if (filesystem.force) {
- process.command.splice(2, 0, "-f");
- }
-
- FnConsole.log[2]("File Systems, Unmount: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "File System successfully unmounted", description: filesystem.name, breakword: false }, { name: "filesystem-unmount", id: filesystem.id, timeout: 4 });
-
- FnConsole.log[1]("File Systems, Unmount: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- if (display.refresh) {
- $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "File System could not be unmounted", description: filesystem.name, breakword: false }, { name: "filesystem-unmount", id: filesystem.id, timeout: 4 });
-
- FnConsole.warn("File Systems, Unmount: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
-
- $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
-}
-
-//#endregion
-
-//#region Snapshots
-
-function FnSnapshotsGet(pool = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name,creation,used,refer,encryption,encryptionroot,keystatus,clones", "-r", "-p", "-t", "snapshot", pool.name]
- };
- let snapshots = {
- empty: true
- };
-
- pool.altroot = (($("#tr-storagepool-" + pool.id).attr("data-pool-altroot") == "true") ? true : false);
- pool.readonly = (($("#tr-storagepool-" + pool.id).attr("data-pool-readonly") == "true") ? true : false);
-
- FnConsole.log[2]("Snapshots, Get: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Get:" }));
-
- if (data) {
- snapshots.empty = false;
-
- FnSnapshotsGetCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { data: data, message: message });
- }
-
- FnConsole.log[1]("Snapshots, Get: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Snapshots, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- if (snapshots.empty) {
- if (zfsmanager.configuration.zfs.snapshot.filesystemlist) {
- $("#div-storagepool-snapshots-" + pool.id).empty();
- }
- $("#tbody-storagepool-snapshots-" + pool.id).empty();
- $("#" + (zfsmanager.configuration.zfs.snapshot.filesystemlist ? "div" : "tbody") + "-storagepool-snapshots-" + pool.id).append((zfsmanager.configuration.zfs.snapshot.filesystemlist ? `` : ``) + `No snapshots found. ` + (zfsmanager.configuration.zfs.snapshot.filesystemlist ? `
` : ``));
- $("#modals-storagepool-snapshots-" + pool.id).remove();
- $("#modals-storagepool-snapshot-" + pool.id).remove();
- $("#modals").append(`
`);
-
- //Register snapshots modals
- if (!pool.readonly) {
- FnModalSnaphshotsCreate({ name: pool.name, id: pool.id });
- }
-
- $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-snapshots", "true");
-
- $("#spinner-storagepool-snapshots-" + pool.id).addClass("hidden");
- $("#paneltitle-storagepool-snapshots-" + pool.id).removeClass("hidden").text(FnDateTime());
- $("#btn-storagepool-snapshots-create-" + pool.id).prop("disabled", false);
- $("#btn-storagepool-snapshots-refresh-" + pool.id).prop("disabled", false);
- }
-
- FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
- FnCockpitElementsUpdate();
- });
-}
-
-function FnSnapshotsGetCommand(pool = { name, id, altroot: false, readonly: false }, process = { data, message }) {
- let snapshots = {
- data: process.data.split(/\n/g).filter(v => v),
- filesystemlist: {
- count: 0,
- name: ""
- }
- };
-
- if (zfsmanager.configuration.zfs.snapshot.filesystemlist) {
- $("#div-storagepool-snapshots-" + pool.id).empty();
- }
- $("#tbody-storagepool-snapshots-" + pool.id).empty();
- $("#modals-storagepool-snapshots-" + pool.id).remove();
- $("#modals-storagepool-snapshot-" + pool.id).remove();
- $("#modals").append(`
`);
- $("#modals").append(`
`);
-
- snapshots.data.forEach((_value, _index) => {
- let snapshot = {
- properties: _value.split(/\t/g).filter(v => v),
- clones: [],
- creation: "",
- encryption: false,
- encryptionroot: "",
- id: "",
- keystatus: "",
- name: "",
- actionsmenu: {
- register: {}
- }
- };
-
- if (!snapshot.properties[7]) { //Append clones property if not included after split
- snapshot.properties[7] = "";
- }
-
- snapshot.filesystem = {
- id: FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: snapshot.properties[0].replace(/^(.*)\@.*$/, "$1"), attribute: true })
- };
-
- snapshot.output = "";
-
- if (zfsmanager.configuration.zfs.snapshot.filesystemlist) {
- if (_index == 0 || (snapshots.filesystemlist.name != "" && snapshots.filesystemlist.name != snapshot.properties[0].replace(/^(.*)\@.*$/, "$1"))) {
- snapshot.output += `
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#table-storagepool-snapshots-listing-` + snapshot.filesystem.id + ` > tbody > tr.listing-ct-item").on("click", function () {
- if (!$(this).parent().hasClass("open")) {
- $(this).parent().addClass("open");
- } else {
- $(this).parent().removeClass("open");
- }
- });
- \x3C/script>
-
-
-
- Name: ` + snapshot.properties[0].replace(/^(.*)\@.*$/, "$1") + (zfsmanager.configuration.zfs.storagepool.count ? ` ` : ``) + `
-
-
-
-
-
-
-
-
- `;
+ }
+ }
+});
- $("#div-storagepool-snapshots-" + pool.id).append(snapshot.output);
+//#endregion
- snapshot.output = "";
- snapshots.filesystemlist.count = 0;
- }
-
- snapshots.filesystemlist.count++;
- $("#span-storagepool-snapshots-listing-" + snapshot.filesystem.id + "-count").html(snapshots.filesystemlist.count);
- }
-
- snapshot.output += ``;
-
- snapshot.properties.forEach((__value, __index) => {
- //0=name, 1=creation, 2=used, 3=refer, 4=encryption, 5=encryptionroot, 6=keystatus, 7=clones
-
- switch (__index) {
- case 0: //0=name
- snapshot.name = __value;
- snapshot.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: snapshot.name, attribute: true });
-
- snapshot.output += `Name: ` + __value + ` `;
- break;
- case 1: //1=creation
- snapshot.creation = __value;
-
- snapshot.output += `Created: ` + FnDateTimeEpoch({ date: __value }) + ` `;
- break;
- case 2: //2=used
- snapshot.output += `Used: ` + FnFormatBytes({ base2: true, decimals: 2, value: __value }) + ` `;
- break;
- case 3: //3=refer
- snapshot.output += `Referenced: ` + FnFormatBytes({ base2: true, decimals: 2, value: __value }) + ` `;
- break;
- case 4: //4=encryption
- if (__value.toLowerCase() != "off") {
- snapshot.encryption = true;
- } else {
- snapshot.encryption = false;
- }
- break;
- case 5: //5=encryptionroot
- snapshot.encryptionroot = __value;
- break;
- case 6: //6=keystatus
- snapshot.keystatus = __value;
- break;
- case 7: //7=clones
- snapshot.clones = __value.split(",").filter(v => v).sort();
-
- snapshot.output += `Clones: ` + (snapshot.clones.length > 0 ? snapshot.clones.join(", ") : `None `) + ` `;
- break;
- }
-
- //Add action menu at end of array
- if (__index >= (snapshot.properties.length - 1)) {
- snapshot.icons = {
- keystatus: {
- locked: ` `,
- unlocked: ` `
- }
- };
-
- snapshot.output += `Encrypted: ` + (/available|unavailable/.test(snapshot.keystatus) ? `Yes` : `No`) + ` `;
-
- if (snapshot.keystatus == "unavailable") {
- snapshot.output += snapshot.icons.keystatus.locked;
- } else if (snapshot.keystatus == "available") {
- snapshot.output += snapshot.icons.keystatus.unlocked;
- }
-
- snapshot.output += ` `;
-
- //Actions menu
- snapshot.actionsmenu.items = {
- item: [],
- itemdivider: function () {
- if (this.item.length > 0 && this.itemdestroy.length > 0) {
- this.item.push(this.divider);
- }
- },
- itemdestroy: [],
- divider: ` `
- };
- snapshot.actionsmenu.display = function () {
- if ((this.items.item.length + this.items.itemdestroy.length) > 0 || pool.readonly) {
- this.items.itemdivider();
-
- return this.header + this.items.item.join("\n") + this.items.itemdestroy.join("\n") + this.footer;
- } else {
- return "";
- }
- };
- snapshot.actionsmenu.header = `
-
-
-
-
-
-
- `;
-
- //Clone Snapshot
- if (!pool.readonly) {
- snapshot.actionsmenu.items.item.push(`Clone Snapshot `);
-
- snapshot.actionsmenu.register.clone = true;
- }
-
- //Rename Snapshot
- if (!pool.readonly && snapshot.name != pool.name) {
- snapshot.actionsmenu.items.item.push(`Rename Snapshot `);
-
- snapshot.actionsmenu.register.rename = true;
- }
-
- //Roll Back Snapshot
- if (!pool.readonly) {
- snapshot.actionsmenu.items.item.push(`Roll Back Snapshot `);
-
- snapshot.actionsmenu.register.rollback = true;
- }
-
- //Destroy Snapshot
- if (!pool.readonly) {
- snapshot.actionsmenu.items.itemdestroy.push(`Destroy Snapshot `);
-
- snapshot.actionsmenu.register.destroy = true;
- }
-
- snapshot.output += ``;
- }
- });
-
- snapshot.output += ` `;
-
- if (zfsmanager.configuration.zfs.snapshot.filesystemlist) {
- $("#tbody-storagepool-snapshots-list-" + snapshot.filesystem.id).append(snapshot.output);
-
- snapshots.filesystemlist.name = snapshot.properties[0].replace(/^(.*)\@.*$/, "$1");
- } else {
- $("#tbody-storagepool-snapshots-" + pool.id).append(snapshot.output);
- }
-
-
- //Register snapshot modals
- if (snapshot.actionsmenu.register.clone) {
- FnModalSnapshotClone({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: snapshot.name, id: snapshot.id, encryption: snapshot.encryption, encryptionroot: snapshot.encryptionroot });
- }
- if (snapshot.actionsmenu.register.destroy) {
- FnModalSnapshotDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: snapshot.name, id: snapshot.id, clones: snapshot.clones });
- }
- if (snapshot.actionsmenu.register.rename) {
- FnModalSnapshotRename({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, creation: snapshot.creation });
- }
- if (snapshot.actionsmenu.register.rollback) {
- FnModalSnapshotRollBack({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: snapshot.name, id: snapshot.id, creation: snapshot.creation });
- }
- });
-
- //Register snapshots modals
- if (!pool.readonly) {
- FnModalSnaphshotsCreate({ name: pool.name, id: pool.id });
- }
-
- $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-snapshots", "true");
-
- $("#spinner-storagepool-snapshots-" + pool.id).addClass("hidden");
- $("#paneltitle-storagepool-snapshots-" + pool.id).removeClass("hidden").html(FnDateTime() + (zfsmanager.configuration.zfs.storagepool.count ? ` ` + snapshots.data.length + ` ` : ``));
- $("#btn-storagepool-snapshots-create-" + pool.id).prop("disabled", false);
- $("#btn-storagepool-snapshots-refresh-" + pool.id).prop("disabled", false);
-
- FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
- FnCockpitElementsUpdate();
-}
-
-//#endregion
-
-//#region Snapshot
-
-function FnSnapshotChildFileSystemsGet(pool = { name, id }, snapshot = { name, id }, filesystems = { id: [] }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name", "-r", "-t", "filesystem"]
- };
-
- filesystems.id.forEach(_value => _value && process.command.push(_value));
-
- FnConsole.log[2]("Snapshots, Child, File Systems, Get: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Child, File Systems, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v),
- count: {
- filesystems: 0
- }
- };
-
- if (filesystems.id.length > 0) {
- filesystems.id.forEach((_value, _index) => {
- if (_value != snapshot.name.replace(/^(.*)\@.*$/, "$1")) {
- filesystems.count.filesystems++;
-
- $("#ul-" + modal.name + "-child-filesystems-" + modal.id).append("" + _value + " \n");
- }
- });
-
- $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-child-filesystems", filesystems.count.filesystems);
- }
-
- FnConsole.log[1]("Snapshots, Child, File Systems, Get: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Snapshots, Child, File Systems, Get: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnSnapshotChildSnapshotsGet(pool = { name, id }, snapshot = { name, id, exclude: false }, filesystems = { id: [] }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name", "-r", "-t", "snapshot"]
- };
-
- if (!snapshot.exclude) {
- process.command.push(snapshot.name.replace(/^(.*)\@.*$/, "$1"));
- }
-
- filesystems.id.forEach(_value => _value && process.command.push(_value));
-
- FnConsole.log[2]("Snapshots, Child, Snapshots, Get: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Child, Snapshots, Get:" }));
-
- let snapshots = {
- id: data.split(/\n/g).filter(v => v),
- count: {
- snapshots: 0,
- snapshotswithclones: (snapshot.exclude ? $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-child-snapshotswithclones") : 0) //Exclude for Roll Back and append
- }
- };
-
- if (snapshots.id.length > 0) {
- snapshots.id.forEach((_value, _index) => {
- if (_value != snapshot.name) {
- //Recursive all will delete child file system snapshots with same name only. If clones are also found, all clone snapshots will be deleted
- if (new RegExp("^" + snapshot.name.replace(/^(.*)\@.*$/, "$1") + "/.*@" + snapshot.name.replace(/^.*\@(.*)$/, "$1") + "$").test(_value)) { //Child file system snapshots with same name
- if (!snapshot.exclude) {
- snapshots.count.snapshots++;
-
- $("#ul-" + modal.name + "-child-snapshots-" + modal.id).append("" + _value + " \n");
- }
-
- snapshots.count.snapshotswithclones++;
-
- $("#ul-" + modal.name + "-child-snapshotswithclones-" + modal.id).append("" + _value + " \n");
- } else {
- filesystems.id.forEach((__value, __index) => {
- if (new RegExp("^" + __value.replace(/^(.*)\@.*$/, "$1") + "@").test(_value) || new RegExp("^" + __value.replace(/^(.*)\@.*$/, "$1") + "/.*@").test(_value)) { //Snapshots of clone file system
- snapshots.count.snapshotswithclones++;
-
- $("#ul-" + modal.name + "-child-snapshotswithclones-" + modal.id).append("" + _value + " \n");
- }
- });
- }
- }
- });
-
- if (!snapshot.exclude) {
- $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-child-snapshots", snapshots.count.snapshots);
- }
- $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-child-snapshotswithclones", snapshots.count.snapshotswithclones);
- }
-
- FnConsole.log[1]("Snapshots, Child, Snapshots, Get: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Snapshots, Child, Snapshots, Get: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnSnapshotClone(pool = { name, id, altroot: false }, snapshot = { name, id, clone: { name, createnonexistparents: false, parent } }) {
- let process = {
- command: ["/sbin/zfs", "clone", "-o", "sharenfs=off", "-o", "sharesmb=off", snapshot.name, snapshot.clone.name]
- };
-
- if (snapshot.clone.createnonexistparents) {
- process.command.splice(2, 0, "-p");
- }
-
- FnConsole.log[2]("Snapshots, Clone: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-storagepool-snapshot-clone-" + snapshot.id + " span").text("Cloning snapshot...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Clone:" }));
-
- if (/dataset already exists/i.test(data)) {
- FnSnapshotCloneFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message });
- return;
- }
-
- FnDisplayAlert({ status: "success", title: "Snapshot successfully cloned", description: snapshot.name, breakword: false }, { name: "snapshot-clone", id: snapshot.id, timeout: 4 });
-
- FnConsole.log[1]("Snapshots, Clone: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
-
- if (snapshot.clone.createnonexistparents && zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-snapshot-clone-" + snapshot.id + " span").text("Disabling Samba share inheritance...");
-
- FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: snapshot.clone.parent }, { disable: true })
- .finally(function () {
- $("#modal-storagepool-snapshot-clone-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
- } else {
- $("#modal-storagepool-snapshot-clone-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- })
- .fail(function (message, data) {
- FnSnapshotCloneFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message });
- });
-}
-
-function FnSnapshotCloneFail(pool = { name, id }, snapshot = { name, id }, process = { data, message }) {
- let modal = {
- hide: true
- };
-
- if (/filesystem successfully created/gi.test(process.data)) {
- FnDisplayAlert({ status: "warning", title: "Snapshot cloned with errors", description: snapshot.name, breakword: false }, { name: "snapshot-clone", id: snapshot.id, timeout: 4 });
-
- FnConsole.warn("Snapshots, Clone: Warning, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (process.data ? process.data : process.message));
- } else {
- if (/dataset already exists/i.test(process.data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-snapshot-clone-name-" + snapshot.id).addClass("has-error");
- $("#helpblock-storagepool-snapshot-clone-name-" + snapshot.id).addClass("has-error").removeClass("hidden").text("Name already exists.");
- $("#input-storagepool-snapshot-clone-name-" + snapshot.id).focus();
- } else if (/parent does not exist/i.test(process.data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-snapshot-clone-name-" + snapshot.id).addClass("has-error");
- $("#helpblock-storagepool-snapshot-clone-name-" + snapshot.id).addClass("has-error").removeClass("hidden").text("Parent file system does not exist.");
- $("#input-storagepool-snapshot-clone-name-" + snapshot.id).focus();
- }
-
- if (modal.hide) {
- FnDisplayAlert({ status: "danger", title: "Snapshot could not be cloned", description: snapshot.name, breakword: false }, { name: "snapshot-clone", id: snapshot.id, timeout: 4 });
- }
-
- FnConsole.warn("Snapshots, Clone: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (process.data ? process.data : process.message));
- }
-
- if (!modal.hide) {
- $("#spinner-storagepool-snapshot-clone-" + snapshot.id).addClass("hidden");
- $("#spinner-storagepool-snapshot-clone-" + snapshot.id + " span").text("");
- $("#btn-storagepool-snapshot-clone-apply-" + snapshot.id).prop("disabled", false);
- }
-
- if (modal.hide) {
- $("#modal-storagepool-snapshot-clone-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
-}
-
-function FnSnapshotCreate(pool = { name, id }, snapshot = { name, id, recursive: false }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "snapshot", snapshot.name]
- };
-
- modal.hide = true;
-
- if (snapshot.recursive) {
- process.command.splice(2, 0, "-r");
- }
-
- FnConsole.log[2]("Snapshots, Create: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Creating snapshot" + (snapshot.recursive ? "s" : "") + "...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Snapshot successfully created", description: snapshot.name, breakword: false }, { name: "snapshot-create", id: snapshot.id, timeout: 4 });
-
- FnConsole.log[1]("Snapshots, Create: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- })
- .fail(function (message, data) {
- if (/dataset already exists/gi.test(data)) {
- modal.hide = false;
-
- $("#validationwrapper-" + modal.name + "-name-" + modal.id).addClass("has-error");
- $("#helpblock-" + modal.name + "-name-" + modal.id).addClass("has-error").removeClass("hidden").text("Name already exists.");
- $("#input-" + modal.name + "-name-" + modal.id).focus();
- }
-
- if (!modal.hide) {
- $("#spinner-" + modal.name + "-" + modal.id).addClass("hidden");
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("");
- $("#btn-" + modal.name + "-apply-" + modal.id).prop("disabled", false);
- }
-
- if (modal.hide) {
- FnDisplayAlert({ status: "danger", title: "Snapshot could not be created", description: snapshot.name, breakword: false }, { name: "snapshot-create", id: snapshot.id, timeout: 4 });
- }
-
- FnConsole.warn("Snapshots, Create: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- if (modal.hide) {
- setTimeout(function () {
- $("#modal-" + modal.name + "-" + modal.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }, 700);
- }
- });
-}
-
-function FnSnapshotCreateDateGet(pool = { name, id }, snapshot = { name, id, recursive: false }, modal = { name, id }) {
- let process = {
- command: ["/bin/date", "\+\%Y.\%m.\%d-\%H.\%M.\%S"]
- };
-
- snapshot.date = "";
-
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + "-" + modal.id + " span").text("Creating snapshot" + (snapshot.recursive ? "s" : "") + "...");
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Create, Date, Get:" }));
-
- snapshot.date = data.replace(/[ \t\n]+/g, "");
- })
- .fail(function () {
- snapshot.date = FnDateTimeSnapshot({ date: null });
- })
- .finally(function () {
- snapshot.name = snapshot.name.replace(/^(.*)\@.*$/, "$1") + "@" + snapshot.date;
- snapshot.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: snapshot.name, attribute: true });
-
- $("#input-" + modal.name + "-name-" + modal.id).val(snapshot.date);
-
- FnSnapshotCreate({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive }, { name: modal.name, id: modal.id });
- });
-}
-
-function FnSnapshotDestroy(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, clones: [], recursive: false, recursiveall: false }, samba = { restart: false }) {
- if (samba.restart) {
- FnSambaStop()
- .finally(function () {
- if (snapshot.recursiveall && snapshot.clones.length > 0 && zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: snapshot.clones })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
-
- if (filesystems.id.length > 0) {
- FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: false })
- .done(function () {
- $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying Samba shares...");
-
- FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
- .finally(function () {
- $("#modal-storagepool-snapshot-destroy-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
- });
- } else {
- $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
-
- FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true })
- .finally(function () {
- FnSambaStart();
- });
- }
- })
- .fail(function (message, data) {
- FnSnapshotDestroyFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message }, { refresh: true });
- FnSambaStart();
- });
- } else {
- $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
-
- FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true })
- .finally(function () {
- FnSambaStart();
- });
- }
- });
- } else {
- if (snapshot.recursiveall && snapshot.clones.length > 0 && zfsmanager.configuration.samba.manage) {
- $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: snapshot.clones })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
-
- if (filesystems.id.length > 0) {
- FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: false })
- .done(function () {
- $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying Samba shares...");
-
- FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
- .finally(function () {
- $("#modal-storagepool-snapshot-destroy-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
- });
- } else {
- $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
-
- FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true });
- }
- })
- .fail(function (message, data) {
- FnSnapshotDestroyFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message }, { refresh: true });
- });
- } else {
- $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
-
- FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true });
- }
- }
-}
-
-function FnSnapshotDestroyCommand(pool = { name, id }, snapshot = { name, id, recursive: false, recursiveall: false }, display = { refresh: true }) {
- let process = {
- command: ["/sbin/zfs", "destroy", snapshot.name]
- };
-
- if (snapshot.recursive) {
- process.command.splice(2, 0, "-r");
- }
- if (snapshot.recursiveall) {
- process.command.splice(2, 0, "-R");
- }
-
- FnConsole.log[1]("Snapshots, Destroy: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Snapshot successfully destroyed", description: snapshot.name, breakword: false }, { name: "snapshot-destroy", id: snapshot.id, timeout: 4 });
-
- FnConsole.log[1]("Snapshots, Destroy: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- })
- .fail(function (message, data) {
- FnSnapshotDestroyFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message }, { refresh: false });
-
- display.refresh = true;
- })
- .finally(function () {
- if (display.refresh) {
- $("#modal-storagepool-snapshot-destroy-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- });
-}
-
-function FnSnapshotDestroyFail(pool = { name, id }, snapshot = { name, id }, process = { data, message }, display = { refresh: true }) {
- FnDisplayAlert({ status: "danger", title: "Snapshot could not be destroyed", description: snapshot.name, breakword: false }, { name: "snapshot-destroy", id: snapshot.id, timeout: 4 });
-
- FnConsole.warn("Snapshots, Destroy: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (process.data ? process.data : process.message));
+//#region Helper Functions
+
+String.prototype.format = function () {
+ let args = arguments;
+
+ return this.replace(/\{(\d+)\}/g, function (m, n) {
+ return args[n];
+ });
+}
- if (display.refresh) {
- $("#modal-storagepool-snapshot-destroy-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
+function FnAppendLeadingZeroes(data = { value }) {
+ if (data.value < 10) {
+ return "0" + data.value;
}
-}
-
-function FnSnapshotRename(pool = { name, id }, snapshot = { name, id, namenew, recursive: false }) {
- let process = {
- command: ["/sbin/zfs", "rename", snapshot.name, snapshot.namenew]
- };
- let modal = {
- hide: true
- };
-
- if (snapshot.recursive) {
- process.command.splice(2, 0, "-r");
- }
-
- FnConsole.log[1]("Snapshots, Rename: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-storagepool-snapshot-rename-" + snapshot.id + " span").text("Renaming snapshot...");
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Snapshot successfully renamed", description: snapshot.name, breakword: false }, { name: "snapshot-rename", id: snapshot.id, timeout: 4 });
-
- FnConsole.log[1]("Snapshots, Rename: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- })
- .fail(function (message, data) {
- if (/dataset already exists|child dataset already has a snapshot with the new name/gi.test(data)) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-snapshot-rename-name-" + snapshot.id).addClass("has-error");
- $("#helpblock-storagepool-snapshot-rename-name-" + snapshot.id).addClass("has-error").removeClass("hidden").text("Name already exists.");
- $("#input-storagepool-snapshot-rename-name-" + snapshot.id).focus();
- }
-
- if (!modal.hide) {
- $("#spinner-storagepool-snapshot-rename-" + snapshot.id).addClass("hidden");
- $("#spinner-storagepool-snapshot-rename-" + snapshot.id + " span").text("");
- $("#btn-storagepool-snapshot-rename-apply-" + snapshot.id).prop("disabled", false);
- }
-
- FnConsole.warn("Snapshots, Rename: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (data ? data : message));
-
- if (modal.hide) {
- FnDisplayAlert({ status: "danger", title: "Snapshot could not be renamed", description: snapshot.name, breakword: false }, { name: "snapshot-rename", id: snapshot.id, timeout: 4 });
- }
- })
- .finally(function () {
- if (modal.hide) {
- $("#modal-storagepool-snapshot-rename-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- });
-}
-
-function FnSnapshotRollBack(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, creation, force: false, recursive: false, recursiveall: false }, samba = { restart: false }) {
- if (samba.restart) {
- FnSambaStop()
- .finally(function () {
- if (snapshot.recursiveall && zfsmanager.configuration.samba.manage) {
- FnSnapshotRollBackSnapshotsGet({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, creation: snapshot.creation }, { name: null, id: null })
- .done(function (data) {
- let snapshots = {
- id: data.split(/\n/g).filter(v => v),
- clones: []
- };
-
- if (snapshots.id.length > 0) {
- snapshots.id.forEach((_value, _index) => {
- _value = _value.split(/\t/g).filter(v => v);
-
- snapshots.properties = {
- clones: (_value[2] ? _value[2].split(",").filter(v => v) : []),
- creation: _value[1],
- name: _value[0]
- };
-
- if (snapshots.properties.name != snapshot.name && snapshots.properties.creation > snapshot.creation && snapshots.properties.clones.length > 0) {
- snapshots.properties.clones.forEach((_value, _index) => {
- snapshots.clones.push(_value);
- });
- }
- });
- }
-
- if (snapshots.clones.length > 0) {
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: snapshots.clones })
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: _data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
-
- if (filesystems.id.length > 0) {
- FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: false })
- .done(function () {
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Destroying Samba shares...");
-
- FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
- .finally(function () {
- $("#modal-storagepool-snapshot-rollback-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
- });
- } else {
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
-
- FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true })
- .finally(function () {
- FnSambaStart();
- });
- }
- })
- .fail(function (_message, _data) {
- FnSnapshotRollBackCommandFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: _data, message: _message }, { refresh: true });
- FnSambaStart();
- });
- } else {
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
-
- FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true })
- .finally(function () {
- FnSambaStart();
- });
- }
- });
- } else {
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
-
- FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true })
- .finally(function () {
- FnSambaStart();
- });
- }
- });
- } else {
- if (snapshot.recursiveall && zfsmanager.configuration.samba.manage) {
- FnSnapshotRollBackSnapshotsGet({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, creation: snapshot.creation }, { name: null, id: null })
- .done(function (data) {
- let snapshots = {
- id: data.split(/\n/g).filter(v => v),
- clones: []
- };
-
- if (snapshots.id.length > 0) {
- snapshots.id.forEach((_value, _index) => {
- _value = _value.split(/\t/g).filter(v => v);
-
- snapshots.properties = {
- clones: (_value[2] ? _value[2].split(",").filter(v => v) : []),
- creation: _value[1],
- name: _value[0]
- };
-
- if (snapshots.properties.name != snapshot.name && snapshots.properties.creation > snapshot.creation && snapshots.properties.clones.length > 0) {
- snapshots.properties.clones.forEach((_value, _index) => {
- snapshots.clones.push(_value);
- });
- }
- });
- }
-
- if (snapshots.clones.length > 0) {
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Retrieving Samba shares...");
-
- FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: snapshots.clones })
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Samba, Shares, Get:" }));
-
- let filesystems = {
- id: _data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
-
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
-
- if (filesystems.id.length > 0) {
- FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: false })
- .done(function () {
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Destroying Samba shares...");
-
- FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
- .finally(function () {
- $("#modal-storagepool-snapshot-rollback-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- });
- });
- } else {
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
-
- FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true });
- }
- })
- .fail(function (_message, _data) {
- FnSnapshotRollBackCommandFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: _data, message: _message }, { refresh: true });
- });
- } else {
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
-
- FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true });
- }
- });
- } else {
- $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
-
- FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true });
- }
- }
-}
-
-function FnSnapshotRollBackCommand(pool = { name, id }, snapshot = { name, id, force: false, recursive: false, recursiveall: false }, display = { refresh: true }) {
- let process = {
- command: ["/sbin/zfs", "rollback", snapshot.name]
- };
-
- if (snapshot.force) {
- process.command.splice(2, 0, "-f");
- }
- if (snapshot.recursive) {
- process.command.splice(2, 0, "-r");
- }
- if (snapshot.recursiveall) {
- process.command.splice(2, 0, "-R");
- }
-
- FnConsole.log[1]("Snapshots, Roll Back: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Snapshot successfully rolled back", description: snapshot.name, breakword: false }, { name: "snapshot-rollback", id: snapshot.id, timeout: 4 });
-
- FnConsole.log[1]("Snapshots, Roll Back: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- })
- .fail(function (message, data) {
- FnSnapshotRollBackCommandFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message }, { refresh: false });
-
- display.refresh = true;
- })
- .finally(function () {
- if (display.refresh) {
- $("#modal-storagepool-snapshot-rollback-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
- });
-}
-
-function FnSnapshotRollBackCommandFail(pool = { name, id }, snapshot = { name, id }, process = { data, message }, display = { refresh: true }) {
- FnDisplayAlert({ status: "danger", title: "Snapshot could not be rolled back", description: snapshot.name, breakword: false }, { name: "snapshot-rollback", id: snapshot.id, timeout: 4 });
-
- FnConsole.warn("Snapshots, Roll Back: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (process.data ? process.data : process.message));
-
- if (display.refresh) {
- $("#modal-storagepool-snapshot-rollback-" + snapshot.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 200);
- }
-}
-
-function FnSnapshotRollBackSnapshotsGet(pool = { name, id }, snapshot = { name, id, creation }, modal = { name, id }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name,creation,clones", "-p", "-t", "snapshot"]
- };
-
- process.command.push(snapshot.name.replace(/^(.*)\@.*$/, "$1"));
-
- FnConsole.log[2]("Snapshots, Roll Back, Snapshots, Get: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Roll Back, Snapshots, Get:" }));
-
- if (modal.name && modal.id) {
- let snapshots = {
- id: data.split(/\n/g).filter(v => v),
- clones: [],
- count: {
- snapshots: 0,
- snapshotswithclones: 0
- }
- };
-
- if (snapshots.id.length > 0) {
- snapshots.id.forEach((_value, _index) => {
- _value = _value.split(/\t/g).filter(v => v);
-
- snapshots.properties = {
- clones: (_value[2] ? _value[2].split(",").filter(v => v) : []),
- creation: _value[1],
- name: _value[0]
- };
-
- if (snapshots.properties.name != snapshot.name && snapshots.properties.creation > snapshot.creation) {
- snapshots.count.snapshots++;
- snapshots.count.snapshotswithclones++;
-
- if (snapshots.properties.clones.length > 0) {
- snapshots.properties.clones.forEach((_value, _index) => {
- snapshots.clones.push(_value);
- });
- }
-
- $("#ul-" + modal.name + "-snapshots-" + modal.id).append("" + snapshots.properties.name + " \n");
- $("#ul-" + modal.name + "-child-snapshotswithclones-" + modal.id).append("" + snapshots.properties.name + " \n");
- }
- });
-
- $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-snapshots", snapshots.count.snapshots);
- $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-child-snapshotswithclones", snapshots.count.snapshotswithclones);
- }
-
- if (snapshots.clones.length > 0) {
- FnSnapshotChildFileSystemsGet({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, filesystems = { id: snapshots.clones }, { name: modal.name, id: modal.id });
- FnSnapshotChildSnapshotsGet({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, exclude: true }, { id: snapshots.clones }, { name: modal.name, id: modal.id });
- }
- }
-
- FnConsole.log[1]("Snapshots, Roll Back, Snapshots, Get: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Snapshots, Roll Back, Snapshots, Get: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (data ? data : message));
- });
-}
-
-//#endregion
-
-//#region Status
-
-function FnStatusErrorColors(status = { count }) {
- if (!$.isNumeric(status.count)) {
- return status.count;
- }
-
- if (status.count >= 5 && status.count <= 20) {
- return (`` + status.count + ` `);
- } else if (status.count >= 21) {
- return (`` + status.count + ` `);
- } else {
- return status.count;
- }
-}
-
-function FnStatusGet(pool = { name, id }) {
- let process = {
- command: ["/bin/sh", "-c", ((zfsmanager.user.name == "root" || !zfsmanager.user.name) ? "ZPOOL_SCRIPTS_AS_ROOT=1 " : "") + `/sbin/zpool status -p -t -c upath "` + pool.name + `"`]
- };
-
- pool.autotrim = ($("#tr-storagepool-" + pool.id).attr("data-pool-autotrim") == "true" ? true : false);
- pool.boot = ($("#tr-storagepool-" + pool.id).attr("data-pool-boot") == "true" ? true : false);
- pool.feature = {
- allocation_classes: ($("#tr-storagepool-" + pool.id).attr("data-pool-feature-allocation_classes") == "true" ? true : false),
- device_removal: ($("#tr-storagepool-" + pool.id).attr("data-pool-feature-device_removal") == "true" ? true : false),
- resilver_defer: ($("#tr-storagepool-" + pool.id).attr("data-pool-feature-resilver_defer") == "true" ? true : false)
- };
- pool.guid = $("#tr-storagepool-" + pool.id).attr("data-pool-guid");
- pool.readonly = ($("#tr-storagepool-" + pool.id).attr("data-pool-readonly") == "true" ? true : false);
- pool.root = ($("#tr-storagepool-" + pool.id).attr("data-pool-root") == "true" ? true : false);
- pool.status = {
- empty: true
- };
- pool.upgrade = ($("#tr-storagepool-" + pool.id).attr("data-pool-upgrade") == "true" ? true : false);
- pool.version = $("#tr-storagepool-" + pool.id).attr("data-pool-version");
-
- FnConsole.log[2]("Status, Get: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Status, Get:" }));
-
- FnDisksLsblkGet({ sizeraw: true })
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Disks, Lsblk, Get:" }));
-
- if (data) {
- pool.status.empty = false;
-
- let disks = {
- lsblkjson: JSON.parse(_data)
- };
-
- FnStatusGetCommand({ name: pool.name, id: pool.id, autotrim: pool.autotrim, boot: pool.boot, feature: { allocation_classes: pool.feature.allocation_classes, device_removal: pool.feature.device_removal, resilver_defer: pool.feature.resilver_defer }, guid: pool.guid, readonly: pool.readonly, root: pool.root, upgrade: pool.upgrade, version: pool.version }, { lsblk: disks.lsblkjson }, { data: data, message: message });
- }
-
- FnConsole.log[1]("Status, Get: Success, Pool: " + pool.name);
-
- if (pool.status.empty) {
- $("#tbody-storagepool-status-messages-" + pool.id).empty();
- $("#tbody-storagepool-status-config-" + pool.id).empty();
- $("#tbody-storagepool-status-messages-" + pool.id).append(`Status not available `);
- $("#modals-storagepool-status-" + pool.id).remove();
- $("#dynamics-storagepool-status-" + pool.id).remove();
-
- $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-status", "true");
-
- $("#spinner-storagepool-status-" + pool.id).addClass("hidden");
- $("#paneltitle-storagepool-status-" + pool.id).removeClass("hidden").text(FnDateTime());
- $("#btn-storagepool-status-refresh-" + pool.id).prop("disabled", false);
- $("#btn-storagepool-status-refresh-auto-" + pool.id).prop("disabled", false);
- }
-
- FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
- FnCockpitElementsUpdate();
- })
- .fail(function (_message, _data) {
- FnConsole.warn("Status, Get: Failed, Pool: " + pool.name + ", Message: " + (_data ? _data : _message));
-
- FnStatusGetFail({ name: pool.name, id: pool.id, status: { empty: pool.status.empty } });
- });
- })
- .fail(function (message, data) {
- FnConsole.warn("Status, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
-
- FnStatusGetFail({ name: pool.name, id: pool.id, status: { empty: pool.status.empty } });
- });
-}
-
-function FnStatusGetCommand(pool = { name, id, autotrim: false, boot: false, feature: { allocation_classes: true, device_removal: true, resilver_defer: true }, guid, readonly: false, root: false, upgrade: false, version }, disks = { lsblk: {} }, process = { data, message }) {
- process.data = process.data.replace(/\n\t+/g, "[TAB1]").split(/\n/g).filter(v => v); //Replace new line with [TAB1] for multi line messages and config
-
- pool.status = {
- state: "",
- status: "",
- action: "",
- see: "",
- scan: "",
- remove: "",
- memory: "",
- errors: "",
- upgrade: false,
- resilver: {
- started: false
- },
- scrub: {
- started: false,
- paused: false
- },
- trim: {
- started: false,
- suspended: false
- },
- disks: {
- count: 0,
- ssd: false,
- trim: {
- unsupportedcount: 0
- }
- },
- config: {
- items: [],
- regexp: {},
- replacement: {},
- tier: {
- count: 0,
- nametier0: "",
- nametier1: "",
- nametier2: "",
- nametier3: ""
- },
- virtualdevice: {
- count: 0
- }
- }
- };
-
- $("#modals-storagepool-status-" + pool.id).remove();
- $("#modals").append(`
`);
- $("#dynamics-storagepool-status-" + pool.id).remove();
- $("#dynamics").append(`
`);
-
- pool.status.output = `Pool: ` + pool.name + ` `;
-
- process.data.forEach((_value, _index) => {
- if (/^(?: )+pool:/g.test(_value)) {
- _value = "";
- }
- if (/^(?: )+state:/g.test(_value)) {
- pool.status.state = _value.replace(/\[TAB1\]/g, " ").replace(/^(?: )+state:/g, "").trim();
- _value = "";
-
- pool.status.output += `State: ` + (pool.status.state ? ` ` + pool.status.state : ``) + ` `;
- }
- if (/^status:/g.test(_value)) {
- pool.status.status = _value.replace(/\[TAB1\]/g, " ").replace(/^status:/g, "").trim();
- _value = "";
-
- if (/currently being resilvered/gi.test(pool.status.status)) {
- pool.status.resilver.started = true;
- }
-
- pool.status.output += `Status: ` + pool.status.status + ` `;
- }
- if (/^action:/g.test(_value)) {
- pool.status.action = _value.replace(/\[TAB1\]/g, " ").replace(/^action:/g, "").trim();
- pool.status.upgrade = ((pool.upgrade || /Upgrade the pool|zpool upgrade/gi.test(pool.status.action)) && !pool.boot ? true : false);
- _value = "";
-
- if (/Upgrade the pool|zpool upgrade/gi.test(pool.status.action) && !pool.boot) { //Hide upgrade message for boot pool. Upgrading version may cause an unbootable system
- pool.status.output += `Action: ` + pool.status.action + ` `;
- }
- }
- if (/^(?: )+see:/g.test(_value)) {
- pool.status.see = _value.replace(/\[TAB1\]/g, " ").replace(/^(?: )+see:(?: )+/g, "").trim();
- _value = "";
-
- if (/http/g.test(pool.status.see)) {
- pool.status.see = `` + pool.status.see + ` `;
- }
-
- pool.status.output += `See: ` + pool.status.see + ` `;
- }
- if (/^(?: )+scan:/g.test(_value)) {
- pool.status.scan = _value.replace(/\[TAB1\]/g, " ").replace(/^(?: )+scan:/g, "").trim();
- _value = "";
-
- if (/scrub in progress/gi.test(pool.status.scan)) {
- pool.status.scrub.started = true;
- } else if (/scrub paused/gi.test(pool.status.scan)) {
- pool.status.scrub.paused = true;
- }
-
- if (/resilver in progress/gi.test(pool.status.scan)) {
- pool.status.resilver.started = true;
- }
-
- pool.status.output += `Scan: ` + pool.status.scan + ` `;
- }
- if (/^remove:/g.test(_value)) {
- pool.status.remove = _value.replace(/\[TAB1\]/g, " ").replace(/^remove:/g, "").trim();
- _value = "";
-
- pool.status.output += `Remove: ` + pool.status.remove + ` `;
- }
- if (/memory used for/g.test(_value)) {
- pool.status.memory = ". " + _value.replace(/\[TAB1\]/g, " ").trim();
- _value = "";
- }
- if (/^config:/g.test(_value)) {
- _value = "";
- }
- if (/^errors:/g.test(_value)) {
- pool.status.errors = _value.replace(/\[TAB1\]/g, " ").replace(/^errors:/g, "").trim();
- _value = "";
-
- pool.status.output += `Errors: ` + pool.status.errors + ` `;
- }
- if (/\[TAB1\]NAME/g.test(_value)) { //Config header row
- _value = _value.split("upath").slice(1).join("."); //Remove config header row (and any previous text if exists)
-
- pool.status.config.regexp.tabspace = new RegExp("^\\[TAB1\\]" + pool.name);
-
- if (pool.status.config.regexp.tabspace.test(_value)) { //Confirm config rows
- pool.status.config.items = _value.split("[TAB1]").filter(v => v);
- }
-
- if (/trimmed, started|trimmed started/i.test(pool.status.config.items.join(" "))) { //Storage pool contains a disk with TRIM started
- pool.status.trim.started = true;
- } else if (/trimmed, suspended|trimmed suspended/i.test(pool.status.config.items.join(" "))) { //Storage pool contains a disk with TRIM suspended
- pool.status.trim.suspended = true;
- }
- }
- });
-
- pool.status.output += ` `;
- pool.status.output += ` `;
-
- $("#tbody-storagepool-status-messages-" + pool.id).html(pool.status.output);
- $("#td-storagepool-status-messages-remove-" + pool.id).append(pool.status.memory);
-
- pool.status.config.output = `
-
- Name
- State
- Read
- Write
- Checksum
- Message
- Product
-
-
-
- `;
-
- $("#tbody-storagepool-status-config-" + pool.id).html(pool.status.config.output);
-
- pool.status.config.items.forEach((_value, _index) => {
- pool.status.config.disk = false;
- pool.status.config.tier.level = (_value.match(/^\s*/g)[0].length / 2);
- pool.status.config.tier.cache = false;
- pool.status.config.tier.dedup = false;
- pool.status.config.tier.logs = false;
- pool.status.config.tier.pool = false;
- pool.status.config.tier.spares = false;
- pool.status.config.tier.special = false;
- pool.status.config.tier.replacing = false;
- pool.status.config.output = "";
-
- pool.status.disks.disk = {
- ssd: false,
- trim: {
- started: false,
- suspended: false,
- unsupported: false
- },
- replacing: false,
- messages: [],
- upath: ""
- }
-
- if (_index == 0 && /[ ]/g.test(pool.name)) { //Fix for storage pool name if it contains whitespace
- pool.status.config.regexp.poolname = new RegExp("^" + pool.name, "g");
- _value = _value.replace(pool.status.config.regexp.poolname, "[POOLNAME]");
- }
-
- _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
-
- if (_index == 0 && _value[0] == "[POOLNAME]") {
- _value[0] = pool.name;
- }
-
- switch (pool.status.config.tier.level) {
- case 0: //Pool / Cache / Dedup / Log / Spares / Special tier
- pool.status.config.tier.nametier0 = _value[0].trim();
- break;
- case 1: //Virtual device tier
- pool.status.config.tier.nametier1 = _value[0];
-
- if (pool.status.config.tier.nametier0 == pool.name) {
- pool.status.config.virtualdevice.count++;
- }
- break;
- case 2: //Drive tier
- pool.status.config.tier.nametier2 = _value[0];
- break;
- case 3: //Action tier
- pool.status.config.tier.nametier3 = _value[0];
- break;
- case 4: //Action Drive tier
- break;
- }
-
- if (pool.status.config.tier.level == 0) { //1= Pool, 2+= / Cache / Dedup / Log / Spares / Special
- pool.status.config.tier.count++;
- }
-
- if (pool.status.config.tier.level > 0) {
- if (pool.status.config.tier.nametier0 == pool.name && pool.status.config.tier.count == 1) { //Virtual Device / Disk is member of pool
- pool.status.config.tier.pool = true;
- }
- if (/^cache/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) { //Virtual Device / Disk is member of cache
- pool.status.config.tier.cache = true;
- }
- if (/^dedup/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) { //Virtual Device / Disk is member of dedup
- pool.status.config.tier.dedup = true;
- }
- if (/^logs/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) { //Virtual Device / Disk is member of logs
- pool.status.config.tier.logs = true;
- }
- if (/^spares/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) { //Virtual Device / Disk is member of spares
- pool.status.config.tier.spares = true;
- }
- if (/^special/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) { //Virtual Device / Disk is member of special
- pool.status.config.tier.special = true;
- }
- }
-
- pool.status.config.tier.virtualdevice = ((pool.status.config.tier.level == 0 && /^cache|^dedup|^logs|^spares|^special/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) ? true : false);
-
- if (pool.status.config.tier.level == 0 && /^special/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) {
- $("#tr-storagepool-" + pool.id).attr("data-pool-special", true);
- }
-
- if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[5])) { //upath
- pool.status.disks.disk.upath = _value[5];
- _value[5] = "";
- } else if ($.isNumeric(_value[0]) && _value[5] == "was") { //upath appears after was device path message
- pool.status.disks.disk.upath = _value[7];
- _value[7] = "";
- } else if (!$.isNumeric(_value[0]) && _value[5] != "was") { //upath appears after error messages and before trim messages
- for (let i = 5; i < _value.length; i++) { //Collect messages
- if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[i])) {
- pool.status.disks.disk.upath = _value[i];
- _value[i] = "";
- }
- }
- }
-
- if ((/^\/dev\/nvme|^\/dev\/sd/gi.test(pool.status.disks.disk.upath) || /^nvme-nvme/gi.test(_value[0]) || /^wwn-/gi.test(_value[0]) || $.isNumeric(_value[0])) && pool.status.config.tier.level > 0) {
- pool.status.config.disk = true;
- pool.status.disks.count++;
- }
-
- if (pool.status.config.disk && (pool.status.config.tier.level == 2 && /^replacing-/g.test(pool.status.config.tier.nametier1) || pool.status.config.tier.level == 3 && /^replacing-/g.test(pool.status.config.tier.nametier2) || pool.status.config.tier.level == 4 && /^replacing-/g.test(pool.status.config.tier.nametier3))) {
- pool.status.disks.disk.replacing = true;
- }
-
- if (pool.status.config.tier.level > 0 && /^replacing-/g.test(_value[0])) {
- pool.status.config.tier.replacing = true;
- }
-
- pool.status.config.output += ``;
- pool.status.config.output += `` + (pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name ? `Pool` : (pool.status.config.disk ? `Disk` : `Virtual Device`)) + `: ` + _value[0] + ` `; //Pool / Virtual Device / Disk
- pool.status.config.output += `State: ` + (_value[1] ? ` ` + _value[1] : ``) + ` `; //State
-
- if (_value[2] && /^spares/g.test(pool.status.config.tier.nametier0)) { //Read
- pool.status.disks.disk.messages.push(_value[2]);
-
- pool.status.config.output += ` `;
- } else {
- pool.status.config.output += `` + (_value[2] ? `Read: ` + (zfsmanager.configuration.zfs.status.errorcolors ? FnStatusErrorColors({ count: _value[2] }) : _value[2]) : ``) + ` `;
- }
-
- if (_value[3] && /^spares/g.test(pool.status.config.tier.nametier0)) { //Write
- pool.status.disks.disk.messages.push(_value[3]);
-
- pool.status.config.output += ` `;
- } else {
- pool.status.config.output += `` + (_value[3] ? `Write: ` + (zfsmanager.configuration.zfs.status.errorcolors ? FnStatusErrorColors({ count: _value[3] }) : _value[3]) : ``) + ` `;
- }
-
- if (/^spares/g.test(pool.status.config.tier.nametier0)) { //Checksum
- if (_value[4]) {
- pool.status.disks.disk.messages.push(_value[4]);
- }
-
- pool.status.config.output += ` `;
- } else {
- pool.status.config.output += `` + (_value[4] ? `Checksum: ` + (zfsmanager.configuration.zfs.status.errorcolors ? FnStatusErrorColors({ count: _value[4] }) : _value[4]) : ``) + ` `;
- }
-
- for (let i = 5; i < _value.length; i++) { //Collect messages
- if (_value[i]) {
- pool.status.disks.disk.messages.push(_value[i]);
- }
- }
-
- pool.status.disks.disk.messages = pool.status.disks.disk.messages.join(" "); //Join Messages for output
-
- if (pool.status.config.disk && /\(trim unsupported\)/gi.test(pool.status.disks.disk.messages)) {
- pool.status.disks.disk.trim.unsupported = true;
- pool.status.disks.trim.unsupportedcount++;
- }
-
- if (!zfsmanager.configuration.zfs.status.trimunsupported) {
- pool.status.disks.disk.messages = pool.status.disks.disk.messages.replace(/\(trim unsupported\)/gi, "");
- }
- if (pool.status.config.tier.cache || pool.status.config.tier.spares) { //Cache and spare disks can not be trimmed
- pool.status.disks.disk.messages = pool.status.disks.disk.messages.replace(/\(untrimmed\)/gi, "");
- }
-
- pool.status.config.replacement.messages = [
- { pattern: /^\(/g, replacement: "" },
- { pattern: /\)$/g, replacement: "" },
- { pattern: / \(/g, replacement: ", " },
- { pattern: /\),/g, replacement: "," },
- { pattern: /\) /g, replacement: " " }
- ];
-
- pool.status.config.output += `Message: ` + pool.status.config.replacement.messages.reduce((m, r) => m.replace(r.pattern, r.replacement), pool.status.disks.disk.messages) + ` `; //Message
-
- if (pool.status.config.disk) {
- if (/trimmed, started|trimmed started/i.test(pool.status.disks.disk.messages)) {
- pool.status.disks.disk.trim.started = true;
-
- if (!pool.status.trim.started) { //Storage pool contains a disk with TRIM started
- pool.status.trim.started = true;
- }
- } else if (/trimmed, suspended|trimmed suspended/i.test(pool.status.disks.disk.messages)) {
- pool.status.disks.disk.trim.suspended = true;
-
- if (!pool.status.trim.suspended) { //Storage pool contains a disk with TRIM suspended
- pool.status.trim.suspended = true;
- }
- }
- }
-
- pool.status.config.output += `Product: `; //Product
-
- if (pool.status.config.disk) {
- disks.lsblk.blockdevices.forEach((__value, __index) => {
- if (__value.type == "disk") {
- if (pool.status.disks.disk.upath.replace(/^\/dev\//gi, "") == __value.name || "nvme-" + __value.wwn == _value[0] || "wwn-" + __value.wwn == _value[0]) {
- if (__value.rota == 0 || __value.rota === "false") {
- pool.status.disks.disk.ssd = true;
-
- if (!pool.status.ssd) { //Storage pool contains an SSD
- pool.status.disks.ssd = true;
- }
- }
-
- pool.status.config.output += FnFormatBytes({ base2: zfsmanager.configuration.disks.base2, decimals: 2, value: __value.size }) + " " + __value.model + (__value.serial ? " (" + __value.serial + ")" : "");
- }
- }
- });
- }
-
- pool.status.config.output += ` `;
-
- //Actions Menu
- pool.status.config.actionsmenu = {
- items: {
- storagepool: [],
- storagepooldivider: function () {
- if (this.storagepool.length > 0 && (this.virtualdevice.length > 0 || this.disk.length > 0)) {
- this.storagepool.push(this.divider);
- }
- },
- virtualdevice: [],
- virtualdevicedivider: function () {
- if (this.virtualdevice.length > 0 && this.disk.length > 0) {
- this.virtualdevice.push(this.divider);
- }
- },
- disk: [],
- divider: ` `
- },
- display: function () {
- if ((this.items.virtualdevice.length + this.items.virtualdevice.length + this.items.disk.length) > 0 || pool.readonly) {
- this.items.storagepooldivider();
- this.items.virtualdevicedivider();
- return this.header + this.items.storagepool.join("\n") + this.items.virtualdevice.join("\n") + this.items.disk.join("\n") + this.footer;
- } else {
- return "";
- }
- }
- }
- pool.status.config.actionsmenu.header = `
-
-
-
-
-
-
- `;
- pool.status.config.actionsmenu.register = {
- storagepool: {
- scrub: {},
- trim: {}
- },
- virtualdevice: {},
- disk: {
- trim: {}
- }
- };
-
- //Clear storage pool errors
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name) {
- pool.status.config.actionsmenu.items.storagepool.push(`Clear Storage Pool Errors `);
-
- pool.status.config.actionsmenu.register.storagepool.clear = true;
- }
-
- //Resilver Storage Pool
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.feature.resilver_defer) {
- pool.status.config.actionsmenu.items.storagepool.push(`Resilver Storage Pool `);
-
- pool.status.config.actionsmenu.register.storagepool.resilver = true;
- }
-
- //Start Storage Pool Scrub
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && !pool.status.scrub.started && !pool.status.scrub.paused) {
- pool.status.config.actionsmenu.items.storagepool.push(`Scrub Storage Pool `);
-
- pool.status.config.actionsmenu.register.storagepool.scrub.start = true;
- }
-
- //Resume Storage Pool Scrub
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.status.scrub.paused) {
- pool.status.config.actionsmenu.items.storagepool.push(`Resume Storage Pool Scrub `);
-
- pool.status.config.actionsmenu.register.storagepool.scrub.resume = true;
- }
-
- //Pause Storage Pool Scrub
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.status.scrub.started) {
- pool.status.config.actionsmenu.items.storagepool.push(`Pause Storage Pool Scrub `);
-
- pool.status.config.actionsmenu.register.storagepool.scrub.pause = true;
- }
-
- //Stop Storage Pool Scrub
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && (pool.status.scrub.started || pool.status.scrub.paused)) {
- pool.status.config.actionsmenu.items.storagepool.push(`Stop Storage Pool Scrub `);
-
- pool.status.config.actionsmenu.register.storagepool.scrub.stop = true;
- }
-
- //TRIM Storage Pool
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && !pool.status.trim.started && !pool.status.trim.suspended) {
- pool.status.config.actionsmenu.items.storagepool.push(`TRIM Storage Pool `);
-
- pool.status.config.actionsmenu.register.storagepool.trim.start = true;
- }
-
- //Resume Storage Pool TRIM
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.status.trim.suspended) {
- pool.status.config.actionsmenu.items.storagepool.push(`Resume Storage Pool TRIM `);
-
- pool.status.config.actionsmenu.register.storagepool.trim.resume = true;
- }
-
- //Suspend Storage Pool TRIM
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.status.trim.started) {
- pool.status.config.actionsmenu.items.storagepool.push(`Suspend Storage Pool TRIM `);
-
- pool.status.config.actionsmenu.register.storagepool.trim.suspend = true;
- }
-
- //Cancel Storage Pool TRIM
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && (pool.status.trim.started || pool.status.trim.suspended)) {
- pool.status.config.actionsmenu.items.storagepool.push(`Cancel Storage Pool TRIM `);
-
- pool.status.config.actionsmenu.register.storagepool.trim.cancel = true;
- }
-
- //Upgrade Storage Pool
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.status.upgrade) {
- pool.status.config.actionsmenu.items.storagepool.push(`Upgrade Storage Pool `);
-
- pool.status.config.actionsmenu.register.storagepool.upgrade = true;
- }
-
- //Regenerate Storage Pool GUID
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name) {
- pool.status.config.actionsmenu.items.storagepool.push(`Regenerate Storage Pool GUID `);
-
- pool.status.config.actionsmenu.register.storagepool.regenerateguid = true;
- }
-
- //Clear Virtual Device Errors
- if (!pool.readonly && pool.status.config.tier.level > 0 && !pool.status.config.disk) {
- pool.status.config.actionsmenu.items.virtualdevice.push(`Clear Virtual Device Errors `);
-
- pool.status.config.actionsmenu.register.virtualdevice.clear = true;
- }
-
- //Add Virtual Device
- if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name) {
- pool.status.config.actionsmenu.items.virtualdevice.push(`Add Virtual Device `);
-
- pool.status.config.actionsmenu.register.virtualdevice.add = true;
- }
-
- //Remove Virtual Device
- if (!pool.readonly && pool.status.config.tier.level == 1 && !pool.status.config.tier.replacing && (pool.feature.device_removal || pool.status.config.tier.spares)) {
- pool.status.config.actionsmenu.items.virtualdevice.push(`Remove Virtual Device `);
-
- pool.status.config.actionsmenu.register.virtualdevice.remove = true;
- }
-
- //Clear Disk Errors
- if (!pool.readonly && pool.status.config.tier.level > 0 && !pool.status.config.tier.spares && pool.status.config.disk) {
- pool.status.config.actionsmenu.items.disk.push(`Clear Disk Errors `);
-
- pool.status.config.actionsmenu.register.disk.clear = true;
- }
-
- //Attach Disk: Disk and Mirror virtual devices only
- if (!pool.readonly && pool.status.config.tier.level == 1 && !pool.status.config.tier.cache && !pool.status.config.tier.spares && (/^mirror-/g.test(_value[0]) || pool.status.config.disk)) {
- pool.status.config.actionsmenu.items.disk.push(`Attach Disk `);
-
- pool.status.config.actionsmenu.register.disk.attach = true;
- }
-
- //Detach Disk: Disk and Mirror virtual devices only
- if (!pool.readonly && (pool.status.config.tier.level == 2 && /^spare-/g.test(_value[0]) == false || pool.status.config.tier.level == 3) && /^mirror-/g.test(pool.status.config.tier.nametier1) && pool.status.config.disk) {
- pool.status.config.actionsmenu.items.disk.push(`Detach Disk `);
-
- pool.status.config.actionsmenu.register.disk.detach = true;
- }
-
- if (!pool.readonly && pool.status.config.tier.level > 0 && pool.status.config.disk) {
- //Online Disk / Offline Disk
- if (_value[1] == "OFFLINE" || _value[1] == "UNAVAIL" || _value[1] == "FAULTED") {
- pool.status.config.actionsmenu.items.disk.push(`Online Disk `);
-
- pool.status.config.actionsmenu.register.disk.online = true;
- } else if ((_value[1] == "ONLINE" || _value[1] == "DEGRADED") && (pool.status.config.tier.level > 1 || pool.status.config.tier.level == 1 && (pool.status.config.tier.cache || pool.status.config.tier.logs))) { //Do not show offline disk if virtual device is Disk in Pool and Dedup
- pool.status.config.actionsmenu.items.disk.push(`Offline Disk `);
-
- pool.status.config.actionsmenu.register.disk.offline = true;
- }
-
- //Replace Disk
- if (!pool.status.config.tier.spares) {
- pool.status.config.actionsmenu.items.disk.push(`Replace Disk `);
-
- pool.status.config.actionsmenu.register.disk.replace = true;
- }
-
- if (pool.status.disks.disk.ssd && !pool.status.disks.disk.trim.unsupported && !pool.status.config.tier.cache && !pool.status.config.tier.spares) {
- //TRIM Disk
- if (!pool.status.disks.disk.trim.started && !pool.status.disks.disk.trim.suspended) {
- pool.status.config.actionsmenu.items.disk.push(`TRIM Disk `);
-
- pool.status.config.actionsmenu.register.disk.trim.start = true;
- }
-
- //Resume Disk TRIM
- if (pool.status.disks.disk.trim.suspended) {
- pool.status.config.actionsmenu.items.disk.push(`Resume Disk TRIM `);
-
- pool.status.config.actionsmenu.register.disk.trim.resume = true;
- }
-
- //Suspend Disk TRIM
- if (pool.status.disks.disk.trim.started) {
- pool.status.config.actionsmenu.items.disk.push(`Suspend Disk TRIM `);
-
- pool.status.config.actionsmenu.register.disk.trim.suspend = true;
- }
-
- //Cancel Disk TRIM
- if (pool.status.disks.disk.trim.started || pool.status.disks.disk.trim.suspended) {
- pool.status.config.actionsmenu.items.disk.push(`Cancel Disk TRIM `);
-
- pool.status.config.actionsmenu.register.disk.trim.cancel = true;
- }
- }
- }
-
- pool.status.config.output += `
`;
- pool.status.config.output += ``;
- pool.status.config.output += ` `;
-
- $("#tbody-storagepool-status-config-" + pool.id).append(pool.status.config.output);
-
- //Register status modals
- if (pool.status.config.actionsmenu.register.disk.attach) {
- FnModalStatusDiskAttach({ name: pool.name, id: pool.id, status: { config: { items: { index: _index }, tier: { name: pool.status.config.tier.nametier0, dedup: pool.status.config.tier.dedup, logs: pool.status.config.tier.logs, special: pool.status.config.tier.special } } } }, { id: _value[0], disk: pool.status.config.disk });
- }
- if (pool.status.config.actionsmenu.register.disk.clear) {
- FnModalStatusDiskClear({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
- }
- if (pool.status.config.actionsmenu.register.disk.detach) {
- FnModalStatusDiskDetach({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
- }
- if (pool.status.config.actionsmenu.register.disk.offline) {
- FnModalStatusDiskOffline({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
- }
- if (pool.status.config.actionsmenu.register.disk.online) {
- FnModalStatusDiskOnline({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
- }
- if (pool.status.config.actionsmenu.register.disk.replace) {
- FnModalStatusDiskReplace({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
- }
- if (pool.status.config.actionsmenu.register.storagepool.clear) {
- FnModalStatusStoragePoolClear({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
- }
- if (pool.status.config.actionsmenu.register.storagepool.regenerateguid) {
- FnModalStatusStoragePoolRegenerateGuid({ name: pool.name, id: pool.id, guid: pool.guid, status: { config: { items: { index: _index } } } });
- }
- if (pool.status.config.actionsmenu.register.storagepool.resilver) {
- FnModalStatusStoragePoolResilver({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } }, resilver: { started: pool.status.resilver.started } } });
- }
- if (pool.status.config.actionsmenu.register.storagepool.trim.start) {
- FnModalStatusStoragePoolTrimStart({ name: pool.name, id: pool.id, autotrim: pool.autotrim, status: { config: { items: { index: _index } } } });
- }
- if (pool.status.config.actionsmenu.register.storagepool.upgrade) {
- FnModalStatusStoragePoolUpgrade({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } }, version: pool.version });
- }
- if (pool.status.config.actionsmenu.register.virtualdevice.add) {
- FnModalStatusVirtualDeviceAdd({ name: pool.name, id: pool.id, feature: { allocation_classes: pool.feature.allocation_classes }, status: { config: { items: { index: _index } } } });
- }
- if (pool.status.config.actionsmenu.register.virtualdevice.clear) {
- FnModalStatusVirtualDeviceClear({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
- }
- if (pool.status.config.actionsmenu.register.virtualdevice.remove) {
- FnModalStatusVirtualDeviceRemove({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0], disk: pool.status.config.disk });
- }
-
- //Register status dynamics
- if (pool.status.config.actionsmenu.register.disk.trim.cancel) {
- FnDynamicStatusDiskTrimCancel({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
- }
- if (pool.status.config.actionsmenu.register.disk.trim.resume) {
- FnDynamicStatusDiskTrimResume({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
- }
- if (pool.status.config.actionsmenu.register.disk.trim.start) {
- FnModalStatusDiskTrimStart({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
- }
- if (pool.status.config.actionsmenu.register.disk.trim.suspend) {
- FnDynamicStatusDiskTrimSuspend({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
- }
- if (pool.status.config.actionsmenu.register.storagepool.scrub.pause) {
- FnDynamicStatusStoragePoolScrubPause({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
- }
- if (pool.status.config.actionsmenu.register.storagepool.scrub.resume) {
- FnDynamicStatusStoragePoolScrubResume({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
- }
- if (pool.status.config.actionsmenu.register.storagepool.scrub.start) {
- FnDynamicStatusStoragePoolScrubStart({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
- }
- if (pool.status.config.actionsmenu.register.storagepool.scrub.stop) {
- FnDynamicStatusStoragePoolScrubStop({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
- }
- if (pool.status.config.actionsmenu.register.storagepool.trim.cancel) {
- FnDynamicStatusStoragePoolTrimCancel({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
- }
- if (pool.status.config.actionsmenu.register.storagepool.trim.resume) {
- FnDynamicStatusStoragePoolTrimResume({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
- }
- if (pool.status.config.actionsmenu.register.storagepool.trim.suspend) {
- FnDynamicStatusStoragePoolTrimSuspend({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
- }
- });
-
- //Hide Storage Pool TRIM actions menu items if there is no SSD in the storage pool or all disks are TRIM unsupported
- if (!pool.status.disks.ssd || pool.status.disks.trim.unsupportedcount == pool.status.disks.count) {
- $("#btn-storagepool-status-trim-start-0-" + pool.id).addClass("hidden");
- $("#btn-storagepool-status-trim-resume-0-" + pool.id).addClass("hidden");
- $("#btn-storagepool-status-trim-suspend-0-" + pool.id).addClass("hidden");
- $("#btn-storagepool-status-trim-cancel-0-" + pool.id).addClass("hidden");
- }
-
- //Hide Remove Virtual Device actions menu item is there is only one in the storage pool
- if (pool.status.config.virtualdevice.count < 2) {
- $("[id^=btn-storagepool-status-virtualdevice-remove-][id$='" + pool.id + "'].pool-virtualdevice").addClass("hidden");
- $("[id^=divider-storagepool-status-][id$=" + pool.id + "].pool-virtualdevice").addClass("hidden");
- }
-
- $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-status", "true");
-
- $("#spinner-storagepool-status-" + pool.id).addClass("hidden");
- $("#paneltitle-storagepool-status-" + pool.id).removeClass("hidden").text(FnDateTime());
- $("#btn-storagepool-status-refresh-" + pool.id).prop("disabled", false);
- $("#btn-storagepool-status-refresh-auto-" + pool.id).prop("disabled", false);
-
- FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
- FnCockpitElementsUpdate();
-}
-
-function FnStatusGetFail(pool = { name, id, status: { empty: true } }) {
- if (pool.status.empty) {
- $("#tbody-storagepool-status-messages-" + pool.id).empty();
- $("#tbody-storagepool-status-config-" + pool.id).empty();
- $("#tbody-storagepool-status-messages-" + pool.id).append(`Status not available `);
- $("#modals-storagepool-status-" + pool.id).remove();
- $("#dynamics-storagepool-status-" + pool.id).remove();
-
- $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-status", "true");
-
- $("#spinner-storagepool-status-" + pool.id).addClass("hidden");
- $("#paneltitle-storagepool-status-" + pool.id).removeClass("hidden").text(FnDateTime());
- $("#btn-storagepool-status-refresh-" + pool.id).prop("disabled", false);
- $("#btn-storagepool-status-refresh-auto-" + pool.id).prop("disabled", false);
- }
-
- FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
- FnCockpitElementsUpdate();
-}
-
-//#endregion
-
-//#region System
-
-function FnSystemHostIdGet(modal = { name, id }) {
- let process = {
- command: ["/bin/sh", "-c", "/bin/cat /etc/hostid 2> /dev/null && echo response true || echo response false"]
- };
-
- FnConsole.log[2]("System, Host ID, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "System, Host ID, Get:" }));
-
- data = data.replace(/\n+/g, "").replace(/^.+response /, "").replace("response ", "");
-
- if (data == "false") {
- if (modal.name) {
- if ($("#switch-" + modal.name + "-multihost-" + modal.id + " input").prop("checked")) {
- $("#btnspan-" + modal.name + "-hostid-" + modal.id).text("Use Lib C Generated Host ID").attr("data-field-value", "libc");
- $("#dropdown-" + modal.name + "-hostid-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-hostid-" + modal.id + " li[value='libc']").addClass("active");
-
- $("#controllabel-" + modal.name + "-hostid-" + modal.id).removeClass("hidden");
- $("#validationwrapper-" + modal.name + "-hostid-" + modal.id).removeClass("hidden");
- } else {
- $("#btnspan-" + modal.name + "-hostid-" + modal.id).text("Use Lib C Generated Host ID").attr("data-field-value", "missing");
- $("#dropdown-" + modal.name + "-hostid-" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-" + modal.name + "-hostid-" + modal.id + " li[value='libc']").addClass("active");
- }
- }
-
- FnConsole.warn("System, Host ID, Get: Warning, Message: Host ID does not exist");
- } else {
- FnConsole.log[1]("System, Host ID, Get: Success");
- }
- })
- .fail(function (message, data) {
- FnConsole.warn("System, Host ID, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnSystemHostIdSet(system = { hostid }) {
- let process = {
- command: ["/bin/sh", "-c", "[ -x /usr/" + (/Debian/.test(zfsmanager.system.operatingsystem) ? "s" : "") + "bin/zgenhostid ] && /usr/" + (/Debian/.test(zfsmanager.system.operatingsystem) ? "s" : "") + "bin/zgenhostid" + (system.hostid ? " " + system.hostid : "") + " || zgenhostid " + (system.hostid ? " " + system.hostid : "")]
- };
-
- FnConsole.log[2]("System, Host ID, Set: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "System Host ID successfully configured", description: null, breakword: false }, { name: "system-hostid-set", id: null, timeout: 4 });
-
- FnConsole.log[1]("System, Host ID, Set: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("System, Host ID, Set: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnSystemNfsVersionGet(modal = { alert: { id } }) {
- let process = {
- command: ["/usr/sbin/nfsstat", "--version"]
- };
-
- FnConsole.log[2]("System, NFS, Version, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "System, NFS, Version, Get:" }));
-
- modal.alert.id.addClass("hidden");
-
- FnConsole.log[1]("System, NFS, Version, Get: Success");
- })
- .fail(function () {
- modal.alert.id.removeClass("hidden");
-
- FnConsole.warn("System, NFS, Version, Get: Failed, Message: NFS is not installed.");
- });
-}
-
-function FnSystemOperatingSystemGet() {
- let process = {
- command: ["/bin/sh", "-c", "/usr/bin/hostnamectl status | /bin/grep 'Operating System'"]
- };
-
- FnConsole.log[2]("System, Operating System, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "System, Operating System, Get:" }));
-
- data = data.replace(/\n+/g, "").replace(/^(?: +)Operating System: /, "");
-
- if (data) {
- zfsmanager.system.operatingsystem = data;
- }
-
- FnConsole.log[2]("System, Operating System, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("System, Operating System, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-//#endregion
-
-//#region Disks
-
-function FnDisksAvailableGet(modal = { name, id, default: true }) {
- disks = {
- attached: [],
- id: {
- device: [],
- path: [],
- vdev: []
- },
- importable: [],
- importableconfig: [],
- importableconfigok: false,
- storagepools: [],
- storagepoolsconfig: []
-
- };
- modal.id = (modal.id ? "-" + modal.id : "");
-
- $("#listgroup-" + modal.name + modal.id).empty();
- $("#listgroup-" + modal.name + modal.id).append(`
`);
-
- FnDisksStoragePoolsAttachedGet({ name: null, id: null }, { id: { blockdevice: true } })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Disks, Storage Pools, Attached, Get:" }));
-
- disks.storagepools = data.replace(/\n\t+/g, "[TAB1]").split(/\n/g).filter(v => v);
-
- disks.storagepools.forEach((_value, _index) => {
- if (/\[TAB1\]NAME/g.test(_value)) { //Config header row
- _value = _value.split("upath").slice(1).join("."); //Remove config header row (and any previous text if exists)
-
- if (new RegExp("^\\[TAB1\\]").test(_value)) { //Confirm config rows
- _value.split("[TAB1]").filter(v => v && disks.storagepoolsconfig.push(v));
- }
- }
- });
-
- disks.storagepoolsconfig.forEach((_value, _index) => {
- let config = {
- disk: {
- upath: ""
- },
- tier: {
- level: (_value.match(/^\s*/g)[0].length / 2)
- }
- };
-
- _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
-
- if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[5])) { //upath
- config.disk.upath = _value[5];
- } else if (!$.isNumeric(_value[0]) && _value[5] != "was") { //upath appears after error messages and before trim messages
- for (let i = 5; i < _value.length; i++) {
- if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[i])) {
- config.disk.upath = _value[i];
- }
- }
- }
-
- if (config.tier.level > 0) {
- if (/^\/dev\/nvme|^\/dev\/sd/gi.test(config.disk.upath)) { //Block Device via upath
- disks.attached.push(config.disk.upath.replace(/^\/dev\//gi, ""));
- } else if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[0])) { //Block Device
- if (/^\/dev\/nvme\d+n\d+p\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/p\d+$/, ""));
- } else if (/^\/dev\/sd.*\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/\d+$/, ""));
- } else {
- disks.attached.push(_value[0]);
- }
- } else if (/^nvme-nvme/gi.test(_value[0]) || /^wwn-/gi.test(_value[0])) { //WWN
- if (/^nvme-nvme.*-part\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/-part\d+$/, ""));
- } else if (/^wwn-.*-part\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/-part\d+$/, ""));
- } else {
- disks.attached.push(_value[0]);
- }
- }
- }
- });
-
- disks.attached.sort();
-
- FnDisksStoragePoolsImportableAttachedGet()
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Disks, Storage Pools, Importable, Attached, Get:" }));
-
- disks.importable = _data.replace(/\n\t+/g, "[TAB1]").split(/\n/g).filter(v => v);
-
- disks.importable.forEach((_value, _index) => {
- if (/config:/g.test(_value)) { //Config header row
- disks.importableconfigok = true;
- }
-
- if (new RegExp("^\\[TAB1\\]").test(_value) && disks.importableconfigok) { //Confirm config rows
- _value.split("[TAB1]").filter(v => v && disks.importableconfig.push(v));
- }
- });
-
- disks.importableconfig.forEach((_value, _index) => {
- let config = {
- tier: {
- level: (_value.match(/^\s*/g)[0].length / 2)
- }
- };
-
- _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
-
- if (config.tier.level > 0) {
- if (/^nvme|^sd/gi.test(_value[0])) { //Block Device
- if (/^nvme\d+n\d+p\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/p\d+$/, ""));
- } else if (/^sd.*\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/\d+$/, ""));
- } else {
- disks.attached.push(_value[0]);
- }
- } else if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[0])) { //Block Device
- if (/^\/dev\/nvme\d+n\d+p\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/p\d+$/, ""));
- } else if (/^\/dev\/sd.*\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/\d+$/, ""));
- } else {
- disks.attached.push(_value[0]);
- }
- } else if (/^nvme-nvme/gi.test(_value[0]) || /^wwn-/gi.test(_value[0])) { //WWN
- if (/^nvme-nvme.*-part\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/-part\d+$/, ""));
- } else if (/^wwn-.*-part\d+$/gi.test(_value[0])) {
- disks.attached.push(_value[0].replace(/-part\d+$/, ""));
- } else {
- disks.attached.push(_value[0]);
- }
- }
- }
- });
-
- disks.attached.sort();
-
- FnDisksLsblkGet({ sizeraw: true })
- .done(function (__data) {
- FnConsole.log[4](FnConsoleVerbose({ data: __data, message: "Disks, Lsblk, Get:" }));
-
- disks.lsblkjson = __data;
-
- FnDisksBlkidGet()
- .done(function (___data) {
- FnConsole.log[4](FnConsoleVerbose({ data: ___data, message: "Disks, Blkid, Get:" }));
-
- let replacement = {
- regexp: [
- { pattern: /"/g, replacement: "" },
- { pattern: /: LABEL=/g, replacement: ",LABEL=" },
- { pattern: / UUID=/g, replacement: ",UUID=" },
- { pattern: / UUID_SUB=/g, replacement: ",UUID_SUB=" },
- { pattern: / TYPE=/g, replacement: ",TYPE=" },
- { pattern: / PARTLABEL=/g, replacement: ",PARTLABEL=" },
- { pattern: / PARTUUID=/g, replacement: ",PARTUUID=" }
- ]
- };
-
- disks.blkid = replacement.regexp.reduce((d, r) => d.replace(r.pattern, r.replacement), ___data).split(/\n/g).filter(v => v);
-
- FnDisksIdentifierDiskGet()
- .done(function (____data) {
- FnConsole.log[4](FnConsoleVerbose({ data: ____data, message: "Disks, Identifier, Disk / WWN, Get:" }));
- disks.id.device = ____data.replace(/\t+/g, "\u22C5").replace(/..\/..\//g, "").split(/\n/g).filter(v => v && v != "\u22C5");
+ return data.value;
+}
- FnDisksIdentifierHardwarePathGet()
- .done(function (_____data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _____data, message: "Disks, Identifier, Hardware Path, Get:" }));
+function FnFormatBytes(data = { base2: true, decimals: 0, value }) {
+ if (data.value == 0) {
+ return "0 B";
+ }
- disks.id.path = _____data.replace(/\t+/g, "\u22C5").replace(/..\/..\//g, "").split(/\n/g).filter(v => v && v != "\u22C5");
+ data.bytes = (data.base2 ? 1024 : 1000);
+ data.sizes = (data.base2 ? ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"] : ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]);
+ data.integer = Math.floor(Math.log(data.value) / Math.log(data.bytes));
+ data.decimals = (data.decimals <= 0 ? 0 : data.decimals);
- FnDisksIdentifierVirtualDeviceMappingGet()
- .done(function (______data) {
- FnConsole.log[4](FnConsoleVerbose({ data: ______data, message: "Disks, Identifier, Virtual Device Mapping, Get:" }));
+ data.sizefriendly = parseFloat((data.value / Math.pow(data.bytes, data.integer)).toFixed(data.decimals)).toString() + " " + data.sizes[data.integer];
- disks.id.vdev = ______data.replace(/\t+/g, "\u22C5").replace(/..\/..\//g, "").split(/\n/g).filter(v => v && v != "\u22C5");
+ if (data.sizefriendly == "NaN undefined") {
+ data.sizefriendly = "-";
+ }
- FnDisksAvailableGetCommand({ attached: disks.attached, blkid: disks.blkid, id: { device: disks.id.device, path: disks.id.path, vdev: disks.id.vdev }, lsblkjson: disks.lsblkjson }, { name: modal.name, id: modal.id, default: modal.default });
- })
- .fail(function (______message, ______data) {
- FnConsole.warn("Disks, Available, Get: Failed, Message: " + (______data ? ______data : ______message));
-
- FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: ______data, message: ______message });
- });
- })
- .fail(function (_____message, _____data) {
- FnConsole.warn("Disks, Available, Get: Failed, Message: " + (_____data ? _____data : _____message));
-
- FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: _____data, message: _____message });
- });
- })
- .fail(function (____message, ____data) {
- FnConsole.warn("Disks, Available, Get: Failed, Message: " + (____data ? ____data : ____message));
-
- FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: ____data, message: ____message });
- });
- })
- .fail(function (___message, ___data) {
- FnConsole.warn("Disks, Available, Get: Failed, Message: " + (___data ? ___data : ___message));
-
- FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: ___data, message: ___message });
- });
- })
- .fail(function (__message, __data) {
- FnConsole.warn("Disks, Available, Get: Failed, Message: " + (__data ? __data : __message));
-
- FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: __data, message: __message });
- });
- })
- .fail(function (_message, _data) {
- FnConsole.warn("Disks, Available, Get: Failed, Message: " + (_data ? _data : _message));
-
- FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: _data, message: _message });
- });
- })
- .fail(function (message, data) {
- FnConsole.warn("Disks, Available, Get: Failed, Message: " + (data ? data : message));
-
- FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: data, message: message });
- });
-}
-
-function FnDisksAvailableGetCommand(disks = { attached: [], blkid: [], id: { device: [], path: [], vdev: [] }, lsblkjson }, modal = { name, id, default: true }) {
- disks.lsblk = JSON.parse(disks.lsblkjson);
- disks.regexp = {};
-
- disks.lsblk.blockdevices.forEach((_value, _index) => {
- if (_value.type == "disk") {
- let disk = {
- id: {
- blockdevice: "",
- disk: "",
- path: "",
- vdev: "",
- wwn: ""
- },
- allow: true,
- zfsmember: false,
- warning: "",
- warningicon: "",
- };
-
- disks.attached.forEach((__value, __index) => {
- if (_value.name == __value || _value.wwn == __value || "nvme-" + _value.wwn == __value || "wwn-" + _value.wwn == __value) { //Do not allow if block device or WWN identifier match
- disk.allow = false;
- return;
- }
- });
-
- if (_value.children && disk.allow) {
- _value.children.forEach((__value, __index) => {
- if (__value.mountpoint) { //Do not allow if partition of disk is mounted
- disk.allow = false;
- return;
- }
- });
- }
-
- if (disk.allow) {
- disks.blkid.forEach((__value, __index) => {
- disks.regexp.name = new RegExp("^\/dev\/" + _value.name, "gi");
-
- if (disks.regexp.name.test(__value)) {
- if (/,TYPE=zfs_member/gi.test(__value)) {
- disk.zfsmember = true;
- return;
- }
- }
- });
-
- if (disk.zfsmember) {
- disk.warningicon = ` `;
-
- $("#helpblock-" + modal.name + "-zfsmemberwarning" + modal.id).html("One or more disks used to be a member of a Storage Pool." + disk.warningicon);
- }
-
- disk.id.blockdevice = _value.name;
-
- if (!_value.wwn) {
- disk.id.wwn = "";
- disk.warning = "One or more disks is missing a WWN identifier.";
-
- $("#helpblock-" + modal.name + "-identifierwarning" + modal.id).removeClass("hidden").text(disk.warning);
- } else {
- if (/^nvme/gi.test(_value.wwn)) {
- disk.id.wwn = "nvme-" + _value.wwn;
- } else {
- disk.id.wwn = "wwn-" + _value.wwn;
- }
- }
-
- disks.id.device.forEach((_value, _index) => {
- _value = _value.split("\u22C5");
-
- if (_value[1] == disk.id.blockdevice) {
- if (/^nvme-nvme|^wwn-/gi.test(_value[0])) {
- return;
- } else {
- disk.id.disk = _value[0];
- return;
- }
- }
- });
-
- disks.id.path.forEach((_value, _index) => {
- _value = _value.split("\u22C5");
-
- if (_value[1] == disk.id.blockdevice) {
- disk.id.path = _value[0];
-
- return;
- }
- });
-
- disks.id.vdev.forEach((_value, _index) => {
- _value = _value.split("\u22C5");
-
- if (_value[1] == disk.id.blockdevice) {
- disk.id.vdev = _value[0];
-
- return;
- }
- });
-
- disks.output = `
-
-
-
-
- ` + FnFormatBytes({ base2: zfsmanager.configuration.disks.base2, decimals: 2, value: _value.size }) + " " + _value.model + (_value.serial ? " (" + _value.serial + ")" : "") + `
- ` + (!disk.id.wwn ? "/dev/" + disk.id.blockdevice : disk.id.wwn) + `
- Physical Sector Size: ` + FnFormatBytes({ base2: true, decimals: 0, value: _value["phy-sec"] }) + `
-
- ` + disk.warningicon + `
-
-
- `;
-
- $("#listgroup-" + modal.name + modal.id).append(disks.output);
- }
- }
- });
-
- setTimeout(function () {
- $("#spinner-" + modal.name + modal.id).remove();
- $("#listgroup-" + modal.name + modal.id + " > li").removeClass("hidden");
-
- if ($("#helpblock-" + modal.name + "-identifierwarning" + modal.id).text) {
- $("#helpblock-" + modal.name + "-identifierwarning" + modal.id).removeClass("hidden");
- }
- if ($("#helpblock-" + modal.name + "-zfsmemberwarning" + modal.id).text()) {
- $("#helpblock-" + modal.name + "-zfsmemberwarning" + modal.id).removeClass("hidden");
- }
-
- if ($("#listgroup-" + modal.name + modal.id + " > li").length == 1 && modal.default) { //Change Virtual Device dropdown to Disk if there is only 1 disk available
- if (modal.name == "storagepools-create-disks") {
- $("#btnspan-storagepools-create-virtualdevice").text("Disk").attr("data-field-value", "disk");
- $("#dropdown-storagepools-create-virtualdevice li").siblings().removeClass("active");
- $("#dropdown-storagepools-create-virtualdevice li[value='disk']").addClass("active");
- } else if (modal.name == "storagepool-status-virtualdevice-add-disks") {
- $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice" + modal.id).text("Disk").attr("data-field-value", "disk");
- $("#dropdown-storagepool-status-virtualdevice-add-virtualdevice" + modal.id + " li").siblings().removeClass("active");
- $("#dropdown-storagepool-status-virtualdevice-add-virtualdevice" + modal.id + " li[value='disk']").addClass("active");
- }
- }
-
- if ($("#listgroup-" + modal.name + modal.id + " > li").length == 0) {
- disks.output = `
-
-
- No available disks found.
-
-
- `;
-
- $("#listgroup-" + modal.name + modal.id).append(disks.output);
- }
- }, 200);
-
- FnConsole.log[1]("Disks, Available, Get: Success");
-}
-
-function FnDisksAvailableGetFail(modal = { name, id }, process = { data, message }) {
- setTimeout(function () {
- $("#spinner-" + modal.name + modal.id).remove();
- $("#listgroup-" + modal.name + modal.id + " > li").removeClass("hidden");
-
- if ($("#listgroup-" + modal.name + modal.id + " > li").length == 0) {
- let disks = {
- output: ""
- };
-
- disks.output = `
-
-
- No available disks found.
-
-
- `;
-
- $("#listgroup-" + modal.name + modal.id).append(disks.output);
- }
- }, 200);
-}
-
-function FnDisksBlkidGet() {
- let process = {
- command: ["/bin/sh", "-c", "/sbin/blkid -o full | /bin/grep -E '/dev/nvme\|/dev/sd'"]
- };
-
- FnConsole.log[2]("Disks, Blkid, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[2]("Disks, Blkid, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Disks, Blkid, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnDisksIdentifierDiskGet() {
- let process = {
- command: ["/bin/sh", "-c", `ls -lF /dev/disk/by-id | awk '{ print $9"\t"$11 }'`]
- };
-
- FnConsole.log[2]("Disks, Identifier, Disk / WWN, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[2]("Disks, Identifier, Disk / WWN, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Disks, Identifier, Disk / WWN, Get: Failed, Message: " + (data ? data : message));
+ return data.sizefriendly;
+}
+
+function FnGenerateId(character = { at: false, colon: false, forwardslash: false, period: false, underscore: false, whitespace: false }, data = { name, attribute: true }) {
+ let replacement = {
+ character: (data.attribute ? "\u22C5" : "_"),
+ regexp: []
+ };
+
+ if (character.underscore) {
+ replacement.regexp.push({ pattern: /[_]/g, replacement: (data.attribute ? replacement.character + "u" + replacement.character : replacement.character) })
+ }
+ if (character.at) {
+ replacement.regexp.push({ pattern: /[@]/g, replacement: (data.attribute ? replacement.character + "a" + replacement.character : replacement.character) })
+ }
+ if (character.colon) {
+ replacement.regexp.push({ pattern: /[:]/g, replacement: (data.attribute ? replacement.character + "c" + replacement.character : replacement.character) })
+ }
+ if (character.forwardslash) {
+ replacement.regexp.push({ pattern: /[/]/g, replacement: (data.attribute ? replacement.character + "f" + replacement.character : replacement.character) })
+ }
+ if (character.period) {
+ replacement.regexp.push({ pattern: /[.]/g, replacement: (data.attribute ? replacement.character + "p" + replacement.character : replacement.character) })
+ }
+ if (character.whitespace) {
+ replacement.regexp.push({ pattern: /[ ]/g, replacement: (data.attribute ? replacement.character + "w" + replacement.character : replacement.character) })
+ }
+
+ return replacement.regexp.reduce((n, r) => n.replace(r.pattern, r.replacement), data.name);
+}
+
+function FnGenerateShareFileName(data = { name }) {
+ replacement = {
+ character: "_",
+ regexp: []
+ };
+
+ replacement.regexp.push({ pattern: /[/]/g, replacement: replacement.character });
+
+ return replacement.regexp.reduce((n, r) => n.replace(r.pattern, r.replacement), data.name);
+}
+
+function FnGenerateShareName(character = { at: false, colon: false, period: false, whitespace: false }, data = { name }) {
+ let replacement = {
+ character: "_",
+ regexp: []
+ };
+
+ replacement.regexp.push({ pattern: /[/]/g, replacement: replacement.character });
+
+ if (character.at) {
+ replacement.regexp.push({ pattern: /[@]/g, replacement: replacement.character })
+ }
+ if (character.colon || zfsmanager.configuration.samba.windowscompatibility) {
+ replacement.regexp.push({ pattern: /[:]/g, replacement: replacement.character })
+ }
+ if (character.period) {
+ replacement.regexp.push({ pattern: /[.]/g, replacement: replacement.character })
+ } else if (zfsmanager.configuration.samba.windowscompatibility) {
+ replacement.regexp.push({ pattern: /[.]$/g, replacement: replacement.character })
+ }
+ if (character.whitespace) {
+ replacement.regexp.push({ pattern: /[ ]/g, replacement: replacement.character })
+ }
+
+ return replacement.regexp.reduce((n, r) => n.replace(r.pattern, r.replacement), data.name);
+}
+
+function FnRound(data = { decimals: 0, value }) {
+ data.multiplier = Math.pow(10, data.decimals);
+
+ return Math.round(data.value * data.multiplier) / data.multiplier;
+}
+
+//#endregion
+
+//#region Date/Time
+
+function FnDateTime() {
+ return (new Date).toLocaleString(zfsmanager.cockpit.datelocale, { day: "numeric", month: "numeric", year: "numeric", hour: "numeric", minute: "numeric", second: "numeric", hour12: true });
+}
+
+function FnDateTimeEpoch(data = { date }) {
+ return (new Date(data.date * 1000)).toLocaleString(zfsmanager.cockpit.datelocale, { hour12: true });
+}
+
+function FnDateTimeSnapshot(data = { date }) {
+ if (!data.date) {
+ data.date = new Date();
+ }
+
+ return data.date.getFullYear() + "." + FnAppendLeadingZeroes({ value: data.date.getMonth() + 1 }) + "." + FnAppendLeadingZeroes({ value: data.date.getDate() }) + "-" + FnAppendLeadingZeroes({ value: data.date.getHours() }) + "." + FnAppendLeadingZeroes({ value: data.date.getMinutes() }) + "." + FnAppendLeadingZeroes({ value: data.date.getSeconds() });
+}
+
+//#endregion
+
+//#region Display Alert
+
+function FnDisplayAlert(notification = { status, title, description, breakword: false }, toast = { name, id, timeout: 4 }) {
+ if (zfsmanager.cockpit.legacy) { //Dirty way of handling alerts for PF3 and PF4
+ FnDisplayAlertLegacy({ status: notification.status, title: notification.title, description: notification.description, breakword: notification.breakword }, { name: toast.name, id: toast.id, timeout: toast.timeout });
+
+ return;
+ }
+
+ toast.timeout = ($.isNumeric(toast.timeout) ? toast.timeout : 4);
+ toast.uniqueid = (new Date).getTime() + "-" + Math.round(Math.random() * 20);
+
+ switch (notification.status) {
+ case "danger":
+ toast.icon = "fa fa-exclamation-circle";
+ toast.statusaria = "Danger";
+ break;
+ case "info":
+ toast.icon = "fa fa-info-circle";
+ toast.statusaria = "Information";
+ break;
+ case "success":
+ toast.icon = "fa fa-check-circle";
+ toast.statusaria = "Success";
+ break;
+ case "warning":
+ toast.icon = "fa fa-exclamation-triangle";
+ toast.statusaria = "Warning";
+ break;
+ default:
+ notification.status = "";
+ toast.icon = "fa fa-bell";
+ toast.statusaria = "Default";
+ break;
+ }
+
+ notification.output = `
+
+
+
+
+
+
` + toast.statusaria + ` alert: ` + notification.title + `
+ ` + (notification.description ? `
` + notification.description + `
` : ``) + `
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#alert-` + toast.name + (toast.id ? `-` + toast.id : ``) + `-` + toast.uniqueid + ` .pf-c-alert__action").on("click",".pf-c-button",function(){
+ $("#alert-` + toast.name + (toast.id ? `-` + toast.id : ``) + `-` + toast.uniqueid + `").fadeTo(150, 0).slideUp(150, function () {
+ $(this).remove();
+ });
+ });
+
+ setTimeout(function () {
+ $("#alert-` + toast.name + (toast.id ? `-` + toast.id : ``) + `-` + toast.uniqueid + `").fadeTo(500, 0).slideUp(500, function () {
+ $(this).remove();
+ });
+ }, ` + toast.timeout + `000);
+ \x3C/script>
+
+ `;
+
+ $("#alerts-notifications").append(notification.output);
+}
+
+function FnDisplayAlertLegacy(notification = { status, title, description, breakword: false }, toast = { name, id, timeout: 4 }) {
+ toast.timeout = ($.isNumeric(toast.timeout) ? toast.timeout : 4);
+ toast.uniqueid = (new Date).getTime() + "-" + Math.round(Math.random() * 20);
+
+ switch (notification.status) {
+ case "danger":
+ toast.icon = "pficon pficon-error-circle-o";
+ break;
+ case "success":
+ toast.icon = "pficon pficon-ok";
+ break;
+ case "warning":
+ toast.icon = "pficon pficon-warning-triangle-o";
+ break;
+ default:
+ notification.status = "info";
+ toast.icon = "pficon pficon-info";
+ break;
+ }
+
+ notification.output = `
+
+
+
+
+
+ ` + notification.title + (notification.description ? `:` : ``) + ` ` + (notification.description ? notification.description : ``) + `
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ setTimeout(function () {
+ $("#toast-` + toast.name + (toast.id ? `-` + toast.id : ``) + `-` + toast.uniqueid + `").fadeTo(500, 0).slideUp(500, function () {
+ $(this).remove();
+ });
+ }, ` + toast.timeout + `000);
+ \x3C/script>
+
+ `;
+
+ $("#alerts-notifications-legacy").append(notification.output);
+}
+
+function FnDisplayInlineAlert(notification = { status, title, description }, inline = { name, id, hidden: false }) {
+ if (zfsmanager.cockpit.legacy) { //Dirty way of handling alerts for PF3 and PF4
+ return FnDisplayInlineAlertLegacy({ status: notification.status, title: notification.title, description: notification.description }, { name: inline.name, id: inline.id, hidden: inline.hidden });
+ }
+
+ switch (notification.status) {
+ case "danger":
+ inline.icon = "fa fa-exclamation-circle";
+ inline.statusaria = "Danger";
+ break;
+ case "info":
+ inline.icon = "fa fa-info-circle";
+ inline.statusaria = "Information";
+ break;
+ case "success":
+ inline.icon = "fa fa-check-circle";
+ inline.statusaria = "Success";
+ break;
+ case "warning":
+ inline.icon = "fa fa-exclamation-triangle";
+ inline.statusaria = "Warning";
+ break;
+ default:
+ notification.status = "";
+ inline.icon = "fa fa-bell";
+ inline.statusaria = "Default";
+ break;
+ }
+
+ notification.output = `
+
+
+
+
+
` + inline.statusaria + ` inline alert: ` + notification.title + `
+ ` + (notification.description ? `
` + notification.description + `
` : ``) + `
+
+ `;
+
+ return notification.output;
+}
+
+function FnDisplayInlineAlertLegacy(notification = { status, title, description }, inline = { name, id, hidden: false }) {
+ switch (notification.status) {
+ case "danger":
+ inline.icon = "pficon pficon-error-circle-o";
+ break;
+ case "success":
+ inline.icon = "pficon pficon-ok";
+ break;
+ case "warning":
+ inline.icon = "pficon pficon-warning-triangle-o";
+ break;
+ default:
+ notification.status = "info";
+ inline.icon = "pficon pficon-info";
+ break;
+ }
+
+ notification.output = `
+ ` + notification.title + (notification.description ? `: ` + notification.description : ``) + `
+ `;
+
+ return notification.output;
+}
+
+//#endregion
+
+//#region Console Logging
+
+let FnConsole = () => { };
+
+function FnConsoleCommand(process = { command: [] }) {
+ return JSON.stringify(process.command.join(" "));
+}
+
+function FnConsoleInitialize() {
+ FnConsole = (() => {
+ let time = () => { };
+
+ time.toString = () => {
+ return (new Date).toLocaleString(zfsmanager.cockpit.datelocale, { hour: "numeric", minute: "numeric", second: "numeric", hour12: true }) + ":";
+ };
+
+ return {
+ error: console.error.bind(console, "%s", time),
+ log: {
+ 1: (zfsmanager.configuration.loglevel >= 1 ? console.log.bind(console, "%s", time) : FnConsoleNull),
+ 2: (zfsmanager.configuration.loglevel >= 2 ? console.log.bind(console, "%s", time) : FnConsoleNull),
+ 3: (zfsmanager.configuration.loglevel >= 3 ? console.log.bind(console, "%c%s Command: %s", "color: #0066CC", time) : FnConsoleNull),
+ 4: (zfsmanager.configuration.loglevel == 4 ? console.log.bind(console, "%c%s %s", "color: #486B00", time) : FnConsoleNull)
+ },
+ warn: console.warn.bind(console, "%s", time)
+ }
+ })();
+}
+
+function FnConsoleNull() {
+ //Do not display console message
+}
+
+function FnConsoleVerbose(process = { data, message }) {
+ return process.message + " Verbose\n" + process.data;
+}
+
+//#endregion
+
+//#region Cockpit ZFS Manager
+
+function FnConfigurationGet() {
+ FnConsole.log[2]("Cockpit ZFS Manager, Configuration, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: [`cockpit.file("/etc/cockpit/zfs/config.json").read()`] }));
+
+ return cockpit.file("/etc/cockpit/zfs/config.json").read()
+ .done(function (user) {
+ FnConsole.log[4](FnConsoleVerbose({ data: user, message: "Cockpit ZFS Manager, Configuration, Get:" }));
+
+ try {
+ user = JSON.parse(user, (key, value) => {
+ if (/^#[0-9]/.test(key) == false) {
+ return value;
+ }
+ });
+
+ user.cockpit = (user.cockpit === undefined ? zfsmanager.configuration.cockpit : user.cockpit);
+ user.cockpit.manage = (user.cockpit.manage === undefined ? zfsmanager.configuration.cockpit.manage : user.cockpit.manage);
+
+ user.disks = (user.disks === undefined ? zfsmanager.configuration.disks : user.disks);
+ user.disks.base2 = (user.disks.base2 === undefined ? zfsmanager.configuration.disks.base2 : user.disks.base2);
+
+ user.loglevel = (user.loglevel === undefined ? zfsmanager.configuration.loglevel : user.loglevel);
+
+ user.samba = (user.samba === undefined ? zfsmanager.configuration.samba : user.samba);
+ user.samba.manage = (user.samba.manage === undefined ? zfsmanager.configuration.samba.manage : user.samba.manage);
+ user.samba.windowscompatibility = (user.samba.windowscompatibility === undefined ? zfsmanager.configuration.samba.windowscompatibility : user.samba.windowscompatibility);
+
+ user.updates = (user.updates === undefined ? zfsmanager.configuration.updates : user.updates);
+ user.updates.check = (user.updates.check === undefined ? zfsmanager.configuration.updates.check : user.updates.check);
+
+ user.zfs = (user.zfs === undefined ? zfsmanager.configuration.zfs : user.zfs);
+ user.zfs.filesystem = (user.zfs.filesystem === undefined ? zfsmanager.configuration.zfs.filesystem : user.zfs.filesystem);
+ user.zfs.filesystem.snapshotactions = (user.zfs.filesystem.snapshotactions === undefined ? zfsmanager.configuration.zfs.filesystem.snapshotactions : user.zfs.filesystem.snapshotactions);
+ user.zfs.filesystem.cloneorigin = (user.zfs.filesystem.cloneorigin === undefined ? zfsmanager.configuration.zfs.filesystem.cloneorigin : user.zfs.filesystem.cloneorigin);
+ user.zfs.filesystem.quotarestrict = (user.zfs.filesystem.quotarestrict === undefined ? zfsmanager.configuration.zfs.filesystem.quotarestrict : user.zfs.filesystem.quotarestrict);
+ user.zfs.filesystem.readonlylockdown = (user.zfs.filesystem.readonlylockdown === undefined ? zfsmanager.configuration.zfs.filesystem.readonlylockdown : user.zfs.filesystem.readonlylockdown);
+ user.zfs.snapshot = (user.zfs.snapshot === undefined ? zfsmanager.configuration.zfs.snapshot : user.zfs.snapshot);
+ user.zfs.snapshot.filesystemlist = (user.zfs.snapshot.filesystemlist === undefined ? zfsmanager.configuration.zfs.snapshot.filesystemlist : user.zfs.snapshot.filesystemlist);
+ user.zfs.status = (user.zfs.status === undefined ? zfsmanager.configuration.zfs.status : user.zfs.status);
+ user.zfs.status.errorcolors = (user.zfs.status.errorcolors === undefined ? zfsmanager.configuration.zfs.status.errorcolors : user.zfs.status.errorcolors);
+ user.zfs.status.trimunsupported = (user.zfs.status.trimunsupported === undefined ? zfsmanager.configuration.zfs.status.trimunsupported : user.zfs.status.trimunsupported);
+ user.zfs.storagepool = (user.zfs.storagepool === undefined ? zfsmanager.configuration.zfs.storagepool : user.zfs.storagepool);
+ user.zfs.storagepool.activetab = (user.zfs.storagepool.activetab === undefined ? zfsmanager.configuration.zfs.storagepool.activetab : user.zfs.storagepool.activetab);
+ user.zfs.storagepool.count = (user.zfs.storagepool.count === undefined ? zfsmanager.configuration.zfs.storagepool.count : user.zfs.storagepool.count);
+ user.zfs.storagepool.boot = (user.zfs.storagepool.boot === undefined ? zfsmanager.configuration.zfs.storagepool.boot : user.zfs.storagepool.boot);
+ user.zfs.storagepool.bootlockdown = (user.zfs.storagepool.bootlockdown === undefined ? zfsmanager.configuration.zfs.storagepool.bootlockdown : user.zfs.storagepool.bootlockdown);
+ user.zfs.storagepool.root = (user.zfs.storagepool.root === undefined ? zfsmanager.configuration.zfs.storagepool.root : user.zfs.storagepool.root);
+ user.zfs.storagepool.refreshall = (user.zfs.storagepool.refreshall === undefined ? zfsmanager.configuration.zfs.storagepool.refreshall : user.zfs.storagepool.refreshall);
+
+ zfsmanager.configuration = user;
+ zfsmanager.user.configuration = true;
+
+ FnConsole.log[1]("Cockpit ZFS Manager, Configuration, Get: Success");
+
+ FnConsoleInitialize();
+ }
+ catch (error) {
+ FnConsole.warn("Cockpit ZFS Manager, Configuration, Get: Failed, Message: Configuration does not exist. Using defaults.");
+ };
+ })
+ .fail(function (message) {
+ FnConsole.warn("Cockpit ZFS Manager, Configuration, Get: Failed, Message: Configuration does not exist. Using defaults.");
+ });
+};
+
+function FnConfigure(user = { cockpit: { manage: true }, disks: { base2: false }, loglevel: 1, samba: { manage: true, windowscompatibility: true }, updates: { check: true }, zfs: { filesystem: { cloneorigin: false, quotarestrict: true, readonlylockdown: true, snapshotactions: true }, snapshot: { filesystemlist: true }, status: { errorcolors: true, trimunsupported: false }, storagepool: { activetab: 1, boot: true, bootlockdown: true, count: true, refreshall: false, root: true } } }, modal = { name, welcome: false }) {
+ let process = {
+ command: ["/bin/sh", "-c", "echo '" + JSON.stringify(user, null, " ").replace(/^\{\n/, `{\n "#1": "COCKPIT ZFS MANAGER",\n "#2": "WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION",\n`) + "' > /etc/cockpit/zfs/config.json"]
+ };
+
+ FnConsole.log[2]("Cockpit ZFS Manager, Configure: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + " span").text("Saving configuration...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (data) {
+ FnDisplayAlert({ status: "success", title: "Configuration successfully updated", description: null, breakword: false }, { name: modal.name, id: null, timeout: 4 });
+
+ FnConsole.log[1]("Cockpit ZFS Manager, Configure: Success");
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Configuration could not be updated", description: null, breakword: false }, { name: modal.name, id: null, timeout: 4 });
+
+ FnConsole.warn("Cockpit ZFS Manager, Configure: Failed, Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if ((modal.welcome || !modal.welcome && zfsmanager.configuration.samba.manage) && !user.samba.manage) {
+ FnSambaSharesDestroyAll({ restart: false }, { silent: true }, { name: modal.name })
+ .finally(function () {
+ FnConfigureFinally({ name: modal.name, welcome: modal.welcome });
+ });
+ } else if ((modal.welcome || !modal.welcome && !zfsmanager.configuration.samba.manage) && user.samba.manage) {
+ FnSambaSharesEnableAll({ restart: false }, { silent: false }, { name: modal.name })
+ .finally(function () {
+ FnConfigureFinally({ name: modal.name, welcome: modal.welcome });
+ });
+ } else {
+ FnConfigureFinally({ name: modal.name, welcome: modal.welcome });
+ }
+ });
+}
+
+function FnConfigureFinally(modal = { name, welcome: false }) {
+ $("#spinner-" + modal.name + " span").text("Reloading Cockpit ZFS Manager...");
+
+ setTimeout(function () {
+ location.reload(true);
+ }, 2000);
+}
+
+function FnConfigurationDirectoryCreate() {
+ let process = {
+ command: ["/bin/sh", "-c", `[ ! -d /etc/cockpit/zfs ] || [ ! -d /etc/cockpit/zfs/shares ] || [ ! -d /etc/cockpit/zfs/snapshots ] && /bin/mkdir -p /etc/cockpit/zfs/shares /etc/cockpit/zfs/snapshots || printf "Skipped"`]
+ };
+
+ FnConsole.log[2]("Cockpit ZFS Manager, Configuration Directory, Create: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Cockpit ZFS Manager, Configuration Directory, Create:" }));
+
+ if (data == "Skipped") {
+ FnConsole.log[2]("Cockpit ZFS Manager, Configuration Directory, Create: Skipped");
+ } else {
+ FnConsole.log[1]("Cockpit ZFS Manager, Configuration Directory, Create: Success");
+ }
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Cockpit ZFS Manager, Configuration Directory, Create: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnConfigurationDirectoryRuntimeCreate() {
+ let process = {
+ command: ["/bin/sh", "-c", `[ ! -d /run/cockpit/zfs/shares ] && /bin/mkdir -p /run/cockpit/zfs/shares || printf "Skipped"`]
+ };
+
+ FnConsole.log[2]("Cockpit ZFS Manager, Runtime Configuration Directory, Create: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Cockpit ZFS Manager, Runtime Configuration Directory, Create:" }));
+
+ if (data == "Skipped") {
+ FnConsole.log[2]("Cockpit ZFS Manager, Runtime Configuration Directory, Create: Skipped");
+ } else {
+ FnConsole.log[1]("Cockpit ZFS Manager, Runtime Configuration Directory, Create: Success");
+ }
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Cockpit ZFS Manager, Runtime Configuration Directory, Create: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnConfigurationLegacyGet() {
+ let process = {
+ command: ["/bin/sh", "-c"]
+ };
+
+ FnCockpitPackagePathGet({ sosreport: false })
+ .done(function (data) {
+ let path = data.replace(/\s +/g, "\u22C5").replace(/\/$/, "").replace(/\n/, "").split("\u22C5")[2];
+
+ if (!path || /\/cockpit\/zfs/.test(path) == false) {
+ path = "/usr/share/cockpit/zfs"
+ }
+
+ process.command.push(`[ -e '` + path + `/config.json' ] && printf "true" || printf "false"`);
+
+ FnConsole.log[2]("Cockpit ZFS Manager, Configuration, Legacy, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ cockpit.spawn(process.command, { err: "out" })
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Cockpit ZFS Manager, Configuration, Legacy, Get:" }));
+
+ if (_data == "true") {
+ FnConsole.log[1]("Cockpit ZFS Manager, Configuration, Legacy, Get: Success");
+
+ FnModalUpdateContent({ id: $("#modal-update") });
+
+ $("#modal-update").modal("show");
+ $("#spinner-update span").text("Relocating configuration file...");
+
+ FnConfigurationLegacyRelocate({ path: path })
+ .done(function () {
+ $("#spinner-update span").text("Reloading Cockpit ZFS Manager...");
+
+ setTimeout(function () {
+ location.reload(true);
+ }, 2000);
+ })
+ .fail(function () {
+ FnModalWelcomeContent({ id: $("#modal-welcome") });
+
+ $("#modal-update").modal("hide");
+ $("#modal-welcome").modal("show");
+ });
+ } else {
+ FnConsole.log[2]("Cockpit ZFS Manager, Configuration, Legacy, Get: " + (_data == "false" ? "Skipped" : "Failed"));
+
+ FnModalWelcomeContent({ id: $("#modal-welcome") });
+
+ $("#modal-welcome").modal("show");
+ }
+ })
+ .fail(function (_message, _data) {
+ FnConsole.warn("Cockpit ZFS Manager, Configuration, Legacy, Get: Failed, Message: " + (_data ? _data : _message));
+
+ FnModalWelcomeContent({ id: $("#modal-welcome") });
+
+ $("#modal-welcome").modal("show");
+ });
+ })
+ .fail(function () {
+ FnModalWelcomeContent({ id: $("#modal-welcome") });
+
+ $("#modal-welcome").modal("show");
+ });
+}
+
+function FnConfigurationLegacyRelocate(legacy = { path }) {
+ let process = {
+ command: ["/bin/sh", "-c", `/bin/mv -f ` + legacy.path + `/config.json /etc/cockpit/zfs/config.json`]
+ };
+
+ FnConsole.log[2]("Cockpit ZFS Manager, Configuration, Legacy, Relocate: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Cockpit ZFS Manager, Configuration, Legacy, Relocate:" }));
+
+ FnConsole.log[1]("Cockpit ZFS Manager, Configuration, Legacy, Relocate: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Cockpit ZFS Manager, Configuration, Legacy, Relocate: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnUpdatesCheck(display = { alert: true }) {
+ FnConsole.log[2]("Cockpit ZFS Manager, Updates, Check: In Progress");
+
+ $.ajax({ url: "https://api.github.com/repos/optimans/cockpit-zfs-manager/releases", dataType: "json", cache: false })
+ .done(function (data) {
+ if (data[0].name) {
+ if (FnUpdatesVersionCompare({ installed: zfsmanager.version, latest: data[0].name }) < 0) {
+ setTimeout(function () {
+ $("#alert-about-update").removeClass("hidden");
+ $("#span-about-update-version").html(`` + data[0].name + ` ` + (data[0].prerelease === true ? `(Pre-release)` : `(Release)`) + ` `);
+
+ if (display.alert) {
+ FnDisplayAlert({ status: "info", title: "A new version of Cockpit ZFS Manager is now available", description: ` ` + data[0].name + ` ` + (data[0].prerelease === true ? `(Pre-release)` : `(Release)`) + ` `, breakword: true }, { name: "update", id: null, timeout: 30 });
+ }
+ }, 500);
+ }
+
+ FnConsole.log[2]("Cockpit ZFS Manager, Updates, Check: Success");
+ } else {
+ FnConsole.warn("Cockpit ZFS Manager, Updates, Check: Failed, Message: Unable to retrieve release information.");
+ }
+ })
+ .fail(function (message) {
+ FnConsole.warn("Cockpit ZFS Manager, Updates, Check: Failed, Message: " + message);
+ });
+}
+
+function FnUpdatesVersionCompare(version = { installed, latest }) {
+ version.installed = version.installed.replace(/[^0-9.-]/g, "").replace(/\s+/g, "").replace(/-/g, ".").split(".");
+ version.latest = version.latest.replace(/[^0-9.-]/g, "").replace(/\s+/g, "").replace(/-/g, ".").split(".");
+
+ let min = Math.min(version.installed.length, version.latest.length);
+
+ for (let i = 0; i < min; ++i) {
+ version.installed[i] = parseInt(version.installed[i], 10);
+ version.latest[i] = parseInt(version.latest[i], 10);
+
+ if (version.installed[i] > version.latest[i]) {
+ return 1;
+ }
+ if (version.installed[i] < version.latest[i]) {
+ return -1;
+ }
+ }
+
+ return version.installed.length == (version.latest.length ? 0 : (version.installed.length < version.latest.length ? -1 : 1));
+}
+
+function FnVersionWarning() {
+ if (/alpha|beta|dev|internal|pre|rc/gi.test(zfsmanager.version)) {
+ FnDisplayAlert({ status: "warning", title: "Pre-release version of Cockpit ZFS Manager is installed", description: zfsmanager.version + ` is an unstable build and features may not work as intended`, breakword: true }, { name: "version-warning", id: null, timeout: 60 });
+ }
+}
+
+//#endregion
+
+//#region Cockpit
+
+function FnCockpitElementsDisable() {
+ let message = `The user ` + zfsmanager.user.name + ` is not permitted to`;
+
+ //Disable buttons
+ $("#btn-configure").addClass("disabled");
+ $("#btn-storagepools-filesystems-unlock").addClass("disabled");
+ $("#btn-storagepools-create").prop("title", message + " create a storage pool").attr("data-placement", "auto bottom").attr("data-toggle", "tooltip").addClass("disabled");
+ $("#btn-storagepools-import").prop("title", message + " import a storage pool").attr("data-placement", "auto bottom").attr("data-toggle", "tooltip").addClass("disabled");
+ $("[id^=btn-storagepool-filesystems-create-]").prop("title", message + " create a file system").attr("data-placement", "auto top").attr("data-toggle", "tooltip").addClass("disabled");
+ $("[id^=btn-storagepool-snapshots-create-]").prop("title", message + " create a snapshot").attr("data-placement", "auto top").attr("data-toggle", "tooltip").addClass("disabled");
+ $("[id^=btn-storagepool-snapshot-dropdown-]").prop("title", message + " manage this snapshot").attr("data-placement", "auto left").attr("data-toggle", "tooltip").addClass("disabled");
+ $("[id^=btn-storagepool-status-dropdown-]").prop("title", message + " manage this storage pool").attr("data-placement", "auto left").attr("data-toggle", "tooltip").addClass("disabled");
+
+ //Disable privileged items
+ $(".privileged").addClass("disabled");
+
+ //Disable privileged modal items
+ $(".privileged-modal").prop("disabled", true);
+ $(".privileged-modal button").prop("disabled", true);
+ $(".privileged-modal input").prop("disabled", true);
+
+ //Disable sliders
+ $("#validationwrapper-storagepools-create-refreservation .slider-pf .slider *").addClass("disabled");
+ $("#slider-storagepools-create-refreservation").slider("disable");
+ $("[id^=validationwrapper-storagepool-filesystems-create-quota-] .slider-pf .slider *").addClass("disabled");
+ $("[id^=slider-storagepool-filesystems-create-quota-]").slider("disable");
+ $("[id^=validationwrapper-storagepool-filesystem-configure-quota-] .slider-pf .slider *").addClass("disabled");
+ $("[id^=slider-storagepool-filesystem-configure-quota-]").slider("disable");
+ $("[id^=validationwrapper-storagepool-filesystem-configure-refreservation-] .slider-pf .slider *").addClass("disabled");
+ $("[id^=slider-storagepool-filesystem-configure-refreservation-]").slider("disable");
+
+ //Remove primary color from unlock file system menu item
+ $("[id^=btn-storagepool-filesystem-unlock-] > strong").removeClass("text-ct-locked");
+ $("[id^=btn-storagepool-filesystem-unlock-icon-]").removeClass("pficon-ct-locked");
+}
+
+function FnCockpitElementsUpdate() {
+ if (!zfsmanager.user.admin) {
+ FnCockpitElementsDisable();
+ }
+}
+
+function FnCockpitManage() {
+ if (zfsmanager.user.admin) {
+ FnCockpitPackageSosReportDelete(); //SOS Report package will cause ZFS storage drives to appear offline when performing a diagnostic report
+ }
+}
+
+function FnCockpitPackagePathGet(package = { sosreport: false }) {
+ let process = {
+ command: ["/bin/sh", "-c", `cockpit-bridge --packages | /bin/grep -m1 '/cockpit/` + (package.sosreport ? `sosreport` : `zfs`) + `$' || printf "false"`] //printf fix for Debian
+ };
+
+ FnConsole.log[2]("Cockpit, " + (package.sosreport ? "SOS Report" : "Cockpit ZFS Manager") + " Package Path, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Cockpit, " + (package.sosreport ? "SOS Report" : "Cockpit ZFS Manager") + " Package Path, Get:" }));
+
+ let path = data.replace(/\s +/g, "\u22C5").replace(/\/$/, "").replace(/\n/, "").split("\u22C5")[2];
+
+ FnConsole.log[1]("Cockpit, " + (package.sosreport ? "SOS Report" : "Cockpit ZFS Manager") + " Package Path, Get: " + (path ? "Success" : "Failed"));
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Cockpit, " + (package.sosreport ? "SOS Report" : "Cockpit ZFS Manager") + " Package Path, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnCockpitPackageSosReportDelete() {
+ let process = {
+ command: ["/bin/sh", "-c"]
+ };
+
+ FnCockpitPackagePathGet({ sosreport: true })
+ .done(function (data) {
+ let path = data.replace(/\s +/g, "\u22C5").replace(/\/$/, "").replace(/\n/, "").split("\u22C5")[2];
+
+ if (!path || /\/cockpit\/sosreport$/.test(path) == false) {
+ path = "/usr/share/cockpit/sosreport"
+ }
+
+ process.command.push(`[ -e '` + path + `' ] && /bin/rm -rf ` + path + ` || printf "Skipped"`);
+
+ FnConsole.log[2]("Cockpit, Package, SOS Report, Delete: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Cockpit, Package, SOS Report, Delete:" }));
+
+ if (_data == "Skipped") {
+ FnConsole.log[2]("Cockpit, Package, SOS Report, Delete: Skipped");
+ } else {
+ FnConsole.log[1]("Cockpit, Package, SOS Report, Delete: Success");
+ }
+ })
+ .fail(function (_message, _data) {
+ FnConsole.warn("Cockpit, Package, SOS Report, Delete: Failed, Message: " + (_data ? _data : _message));
+ });
});
-}
-
-function FnDisksIdentifierHardwarePathGet() {
- let process = {
- command: ["/bin/sh", "-c", `ls -lF /dev/disk/by-path | awk '{ print $9"\t"$11 }'`]
- };
-
- FnConsole.log[2]("Disks, Identifier, Hardware Path, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[2]("Disks, Identifier, Hardware Path, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Disks, Identifier, Hardware Path, Get: Failed, Message: " + (data ? data : message));
+}
+
+function FnCockpitPermissionsGet() {
+ FnConsole.log[2]("Cockpit, Permissions, Get: In Progress");
+
+ zfsmanager.cockpit.permission = cockpit.permission({ admin: true });
+
+ $(zfsmanager.cockpit.permission).on("changed", function () {
+ zfsmanager.user.admin = zfsmanager.cockpit.permission.allowed;
+ zfsmanager.user.name = (zfsmanager.cockpit.permission.user ? zfsmanager.cockpit.permission.user.name : "");
+
+ if (zfsmanager.user.admin) {
+ FnConsole.log[2]("Cockpit, Permissions, Get: Success");
+
+ FnFirstStepsPrivileged();
+ } else {
+ FnConsole.warn("Cockpit, Permissions, Get: Warning, Message: " + zfsmanager.user.name + " does not have administrator permissions");
+
+ FnCockpitElementsDisable();
+ }
+ });
+}
+
+//#endregion
+
+//#region ZFS
+
+function FnZfsVersionCompare(version = { installed, threshold }) {
+ version.installed = version.installed.replace(/[^0-9.-]/g, "").replace(/\s+/g, "").replace(/-/g, ".").split(".");
+ version.threshold = version.threshold.replace(/\s+/g, "").replace(/-/g, ".").split(".");
+
+ if (!version.installed[0]) {
+ return -1;
+ }
+
+ let min = Math.min(version.installed.length, version.threshold.length);
+
+ for (let i = 0; i < min; ++i) {
+ version.installed[i] = parseInt(version.installed[i], 10);
+ version.threshold[i] = parseInt(version.threshold[i], 10);
+
+ if (version.installed[i] > version.threshold[i]) {
+ return 1;
+ }
+ if (version.installed[i] < version.threshold[i]) {
+ return -1;
+ }
+ }
+
+ return version.installed.length == (version.threshold.length ? 0 : (version.installed.length < version.threshold.length ? -1 : 1));
+}
+
+function FnZfsVersionGet() {
+ let process = {
+ command: ["/bin/cat", "/sys/module/zfs/version"]
+ };
+ let zfs = {
+ success: false,
+ threshold: "0.8"
+ };
+
+ FnConsole.log[2]("ZFS, Version, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "ZFS, Version, Get:" }));
+
+ if (data) {
+ zfsmanager.zfs.version = data.replace(/\s+/g, "");
+ }
+
+ if (!data || FnZfsVersionCompare({ installed: zfsmanager.zfs.version, threshold: zfs.threshold }) < 0) {
+ FnConsole.error("ZFS, Version, Get: Failed, Message: Version " + (zfsmanager.zfs.version ? zfsmanager.zfs.version : "0") + " < " + zfs.threshold);
+ } else {
+ zfs.success = true;
+
+ FnConsole.log[1]("ZFS, Version, Get: Success, Version: " + (data ? data : message));
+ }
+ })
+ .fail(function (message, data) {
+ FnConsole.error("ZFS, Version, Get: Failed, Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if (!zfs.success) {
+ zfs.message = `
+
+
+
+ This package requires ZFS version ` + zfs.threshold + ` or later
+ If ZFS is installed, check the module is loaded into the kernel.
+
+ Refresh
+
+ `;
+
+ $("#alerts-requirements").removeClass("hidden").html(zfs.message);
+ $("#container").addClass("hidden");
+ } else {
+ if (!zfsmanager.configuration.samba.manage) {
+ $("#alerts-requirements").empty().addClass("hidden");
+ $("#container").removeClass("hidden");
+ }
+ }
});
-}
-
-function FnDisksIdentifierVirtualDeviceMappingGet() {
- let process = {
- command: ["/bin/sh", "-c", `[ -d /dev/disk/by-vdev ] && ls -lF /dev/disk/by-vdev | awk '{ print $9"\t"$11 }' || printf ""`]
- };
-
- FnConsole.log[2]("Disks, Identifier, Virtual Device Mapping, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[2]("Disks, Identifier, Virtual Device Mapping, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Disks, Identifier, Virtual Device Mapping, Get: Failed, Message: " + (data ? data : message));
+}
+
+function FnZfsVersionWarnings() {
+ zfsmanager.zfs.warnings.nvmevdev = (FnZfsVersionCompare({ installed: zfsmanager.zfs.version, threshold: "0.8.3" }) < 0 ? true : false); //GitHub Issue #9730
+}
+
+//#endregion
+
+//#region Storage Pools
+
+function FnStoragePoolsGet() {
+ let process = {
+ command: ["/sbin/zpool", "list", "-H", "-o", "name,guid,health,size,alloc,free,fragmentation,readonly,altroot,autotrim,version,feature@allocation_classes,feature@async_destroy,feature@bookmark_v2,feature@bookmarks,feature@device_removal,feature@edonr,feature@embedded_data,feature@empty_bpobj,feature@enabled_txg,feature@encryption,feature@extensible_dataset,feature@filesystem_limits,feature@hole_birth,feature@large_blocks,feature@large_dnode,feature@lz4_compress,feature@multi_vdev_crash_dump,feature@obsolete_counts,feature@project_quota,feature@resilver_defer,feature@sha512,feature@skein,feature@spacemap_histogram,feature@spacemap_v2,feature@userobj_accounting,feature@zpool_checkpoint", "-p"]
+ };
+ let pools = {
+ empty: true
+ };
+
+ //Disable storage pool status auto refresh
+ zfsmanager.zfs.storagepool.refreshid.forEach((_value, _index) => {
+ clearInterval(_value);
+ });
+ zfsmanager.zfs.storagepool.refreshid = [];
+
+ $("#btn-storagepools-refresh").prop("disabled", true);
+ $("#table-storagepools > tbody").remove();
+ $("[id^=modals-storagepool-]").remove();
+ $("[id^=dynamics-storagepool-]").remove();
+ $("#spinner-storagepools").removeClass("hidden");
+
+ FnConsole.log[2]("Storage Pools, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ FnStoragePoolsSystemReservedGet()
+ .finally(function () {
+ cockpit.spawn(process.command, { err: "out" })
+ .done((data, message) => {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Get:" }));
+
+ if (data) {
+ pools.empty = false;
+
+ FnStoragePoolsGetCommand({ data: data, message: message });
+ }
+
+ FnConsole.log[1]("Storage Pools, Get: Success");
+ })
+ .fail((message, data) => {
+ FnConsole.warn("Storage Pools, Get: Failed, Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if ($("#table-storagepools > tbody").length == 0) {
+ pools.empty = true;
+ }
+
+ if (pools.empty) {
+ $("#table-storagepools").append(`No storage pools found. `);
+ }
+
+ setTimeout(function () {
+ $("#spinner-storagepools").addClass("hidden");
+ $("#table-storagepools > tbody").removeClass("hidden");
+ }, 200);
+
+ $("#btn-storagepools-refresh").prop("disabled", false);
+
+ FnCockpitElementsUpdate();
+ });
});
-}
-
-function FnDisksLsblkGet(disks = { sizeraw: true }) {
- let process = {
- command: ["/bin/sh", "-c", "/bin/lsblk -o label,model,mountpoint,name,partuuid,phy-sec,rota,serial,size,type,uuid,vendor,wwn -J" + (disks.sizeraw ? " -b" : "")]
- };
-
- FnConsole.log[2]("Disks, Lsblk, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function () {
- FnConsole.log[2]("Disks, Lsblk, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Disks, Lsblk, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnDisksStoragePoolsAttachedGet(pool = { name, id }, disks = { id: { blockdevice: true } }) {
- let process = {
- command: ["/bin/sh", "-c", ((zfsmanager.user.name == "root" || !zfsmanager.user.name) ? "ZPOOL_SCRIPTS_AS_ROOT=1 " : "") + "/sbin/zpool status -P " + (disks.id.blockdevice ? "-L " : "") + "-c upath" + (pool.name ? ` "` + pool.name + `"` : "")]
- };
-
- FnConsole.log[2]("Disks, Storage Pools, Attached, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function () {
- FnConsole.log[2]("Disks, Storage Pools, Attached, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Disks, Storage Pools, Attached, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnDisksStoragePoolsImportableAttachedGet() {
- let process = {
- command: ["/sbin/zpool", "import", "-d", "/dev"]
- };
-
- FnConsole.log[2]("Disks, Storage Pools, Importable, Attached, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[2]("Disks, Storage Pools, Importable, Attached, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Disks, Storage Pools, Importable, Attached, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnDisksStoragePoolsImportableGet() {
- let process = {
- command: ["/bin/sh", "-c", "/sbin/zpool import | /bin/grep -E 'pool:\| id:' | tr '\\\n' ','"]
- };
-
- FnConsole.log[2]("Disks, Importable Storage Pools, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[2]("Disks, Importable Storage Pools, Get: Success");
- })
- .fail(function (message, data) {
- if (/no pools available to import/gi.test(data) == false) {
- FnConsole.warn("Disks, Importable Storage Pools, Get: Failed, Message: " + (data ? data : message));
- }
- });
-}
-
-//#endregion
-
-//#region Samba
-
-function FnSambaConfigurationReload() {
- let process = {
- command: ["/usr/bin/smbcontrol", "all", "reload-config"]
- };
-
- FnConsole.log[2]("Samba, Configuration, Reload: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Samba, Configuration, Reload: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, Configuration, Reload: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnSambaConfigurationZfsSharesEnable() {
- let process = {
- command: ["/bin/sh", "-c", `[ -s /etc/samba/smb.conf ] && /usr/bin/awk -v k='\n\t# COCKPIT ZFS MANAGER\n\t# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION\n\tinclude = /etc/cockpit/zfs/shares.conf\n\tinclude = /run/cockpit/zfs/shares.conf\n' '($1=="[global]"||x&&/^\\[/)&&!(x=!x){print k} END{if(x)print k}1' /etc/samba/smb.conf > /etc/samba/smb.tmp && /bin/mv -f /etc/samba/smb.tmp /etc/samba/smb.conf \|\| { echo '/etc/samba/smb.conf file does not exist or is empty.' ; exit 1; }`]
- };
-
- FnConsole.log[2]("Samba, Configuration, ZFS Shares, Enable: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Samba, Configuration, ZFS Shares, Enable: Success");
-
- FnSambaConfigurationReload();
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, Configuration, ZFS Shares, Enable: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnSambaConfigurationZfsSharesGet() {
- let process = {
- command: ["/bin/sh", "-c", "/bin/grep -Pzoq '(?s)include = /etc/cockpit/zfs/shares.conf.*/run/cockpit/zfs/shares.conf' /etc/samba/smb.conf && echo true || echo false"]
- };
-
- FnConsole.log[2]("Samba, Configuration, ZFS Shares, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Configuration, ZFS Shares, Get:" }));
-
- data = data.replace(/\n+/g, "");
-
- if (data == "false") {
- FnSambaConfigurationZfsSharesEnable();
- } else if (data == "true") {
- FnConsole.log[2]("Samba, Configuration, ZFS Shares, Get: Success");
- } else {
- FnConsole.warn("Samba, Configuration, ZFS Shares, Get: Failed, Message: " + (data ? data : message));
- }
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, Configuration, ZFS Shares, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnSambaManage() {
- if (zfsmanager.user.admin) {
- FnSambaConfigurationZfsSharesGet();
- }
-}
-
-function FnSambaRestart() {
- let process = {
- command: ["/bin/systemctl", "restart"]
- };
-
- if (/Debian|Ubuntu/i.test(zfsmanager.system.operatingsystem)) {
- process.command.splice(2, 0, "smbd");
- } else {
- process.command.splice(2, 0, "smb");
- }
-
- FnConsole.log[2]("Samba, Restart: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Samba, Restart: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, Restart: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnSambaShareDestroy(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id }, samba = { restart: false }, display = { silent: false }) {
- let process = {
- promise: cockpit.defer()
- };
-
- FnSambaZfsShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id })
- .done(function () {
- FnSambaZfsSharesConfigurationReload()
- .done(function () {
- setTimeout(function () {
- if (samba.restart) {
- FnSambaRestart()
- .finally(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba share successfully destroyed", description: filesystem.name, breakword: false }, { name: "samba-destroy", id: filesystem.id, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, Share, Destroy: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- process.promise.resolve();
- });
- } else {
- FnSambaConfigurationReload()
- .finally(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba share successfully destroyed", description: filesystem.name, breakword: false }, { name: "samba-destroy", id: filesystem.id, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, Share, Destroy: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- process.promise.resolve();
- });
- }
- }, 500);
- })
- })
- .fail(function () {
- process.promise.resolve();
- });
-
- return process.promise.promise();
-}
-
-function FnSambaShareDisable(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id }, samba = { restart: false }, display = { modal: true, silent: false }) {
- if (display.modal) {
- $("#spinner-storagepool-filesystem-samba-disable-" + filesystem.id + " span").text("Disabling Samba share...");
- }
-
- if (!pool.readonly) {
- FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id })
- .done(function () {
- FnSambaShareDisableCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: display.modal, silent: display.silent });
- })
- .fail(function (message, data) {
- if (/property may be set/gi.test(data)) { //False error is generated when configuring filesystem
- FnSambaShareDisableCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: display.modal, silent: display.silent });
- } else {
- if (!display.silent) {
- FnDisplayAlert({ status: "danger", title: "Samba share could not be disabled", description: filesystem.name, breakword: false }, { name: "samba-disable", id: filesystem.id, timeout: 4 });
- }
-
- if (display.modal) {
- $("#modal-storagepool-filesystem-samba-disable-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
- }, 200);
- }
- }
- });
- } else {
- FnSambaShareDisableCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: display.modal, silent: display.silent });
- }
-}
-
-function FnSambaShareDisableCommand(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id }, samba = { restart: false }, display = { modal: true, silent: false }) {
- FnSambaZfsShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id })
- .done(function () {
- FnSambaZfsSharesConfigurationReload()
- .done(function () {
- setTimeout(function () {
- if (samba.restart) {
- FnSambaRestart()
- .finally(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba share successfully disabled", description: filesystem.name, breakword: false }, { name: "samba-disable", id: filesystem.id, timeout: 4 });
- }
-
- if (display.modal) {
- $("#modal-storagepool-filesystem-samba-disable-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
- }, 200);
- }
- });
- } else {
- FnSambaConfigurationReload()
- .finally(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba share successfully disabled", description: filesystem.name, breakword: false }, { name: "samba-diable", id: filesystem.id, timeout: 4 });
- }
-
- if (display.modal) {
- $("#modal-storagepool-filesystem-samba-disable-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
- }, 200);
- }
- });
- }
- }, 500);
- })
- .fail(function () {
- FnFileSystemShareSmbEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- });
- })
- .fail(function () {
- FnFileSystemShareSmbEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- });
-}
-
-function FnSambaShareEnable(pool = { name, id, readonly: false }, filesystem = { name, id, mounted: false, mountpoint }, samba = { share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }, display = { silent: false }) {
- let modal = {
- hide: true
- };
-
- $("#spinner-storagepool-filesystem-samba-enable-" + filesystem.id + " span").text("Enabling Samba share...");
-
- FnSambaShareNamesGet({ zfsonly: false })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Share, Names, Get:" }));
-
- samba.share.nameunique = true;
- samba.share.errormessage = "Share name is already in use.";
-
- if (data.replace(/\n/g, "") != "$empty") { //$empty response is received if share names list is empty
- samba.shares = data.split(/\n/g).filter(v => v);
-
- samba.shares.forEach((_value, _index) => {
- if (_value.replace(/^\[/, "").replace(/\]$/, "").toLowerCase() == samba.share.name.toLowerCase() + (samba.share.administrative ? "$" : "")) {
- samba.share.nameunique = false;
-
- return;
- }
- });
- }
-
- if (/^global$|^homes$|^printers$/gi.test(samba.share.name)) {
- samba.share.nameunique = false;
- samba.share.errormessage = "Share name can not be a restricted name.";
- }
-
- if (!samba.share.nameunique) {
- modal.hide = false;
-
- $("#validationwrapper-storagepool-filesystem-samba-enable-name-" + filesystem.id).addClass("has-error");
- $("#helpblock-storagepool-filesystem-samba-enable-name-" + filesystem.id).addClass("has-error").removeClass("hidden").text(samba.share.errormessage);
- $("#input-storagepool-filesystem-samba-enable-name-" + filesystem.id).focus();
-
- if (!modal.hide) {
- $("#spinner-storagepool-filesystem-samba-enable-" + filesystem.id).addClass("hidden");
- $("#spinner-storagepool-filesystem-samba-enable-" + filesystem.id + " span").text("");
- $("#btn-storagepool-filesystem-samba-enable-apply-" + filesystem.id).prop("disabled", false);
-
- FnConsole.warn("Samba, Share, Enable: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + samba.share.errormessage);
- }
- } else {
- FnSambaShareEnableCommand({ name: pool.name, id: pool.id, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: false, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: false }, { reload: true, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { refresh: true, silent: display.silent });
-
- $("#modal-storagepool-filesystem-samba-enable-" + filesystem.id).modal("hide");
- }
- });
-}
-
-function FnSambaShareEnableAutoGenerateName(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, force: false, mounted: false, mountpoint, sharesmb: false }, samba = { reload: true }, display = { refresh: true, silent: false }) {
- FnSambaShareNamesGet({ zfsonly: false })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Share, Names, Get:" }));
-
- samba.share = {
- name: "",
- nameunique: true,
- temporary: (pool.altroot || pool.readonly ? true : false)
- };;
-
- if (data.replace(/\n/g, "") != "$empty") { //$empty response is received if share names list is empty
- samba.shares = data.split(/\n/g).filter(v => v);
-
- samba.shares.forEach((_value, _index) => {
- if (_value.replace(/^\[/, "").replace(/\]$/, "").toLowerCase() == filesystem.name.replace(/^.*\/(.*)$/, "$1").toLowerCase()) {
- samba.share.nameunique = false;
-
- return;
- }
- });
- }
-
- if (/^global$|^homes$|^printers$/gi.test(samba.share.name)) {
- samba.share.nameunique = false;
- }
-
- if (!samba.share.nameunique) {
- samba.share.name = FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.name });
-
- if (filesystem.name == pool.name) {
- samba.share.name = "StoragePool-" + samba.share.name;
- }
-
- FnSambaShareEnableCommand({ name: pool.name, id: pool.id, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: false, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: filesystem.sharesmb }, { reload: samba.reload, share: { additional: [], administrative: false, browseable: true, guestok: false, name: samba.share.name, comment: null, readonly: null, temporary: samba.share.temporary } }, { refresh: display.refresh, silent: display.silent });
- } else {
- FnSambaShareEnableCommand({ name: pool.name, id: pool.id, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: false, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: filesystem.sharesmb }, { reload: samba.reload, share: { additional: [], administrative: false, browseable: true, guestok: false, name: null, comment: null, readonly: null, temporary: samba.share.temporary } }, { refresh: display.refresh, silent: display.silent });
- }
- });
-}
-
-function FnSambaShareEnableCommand(pool = { name, id, readonly: false }, filesystem = { name, force: false, id, mounted: false, mountpoint, sharesmb: false }, samba = { reload: true, share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }, display = { refresh: true, silent: false }) {
- if (!pool.readonly && (!filesystem.sharesmb || filesystem.sharesmb && filesystem.force)) { //Force to disable inheritance
- FnFileSystemShareSmbEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id })
- .done(function () {
- FnSambaShareEnableCommandFinally({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint }, { reload: samba.reload, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { refresh: display.refresh, silent: display.silent });
- })
- .fail(function (message, data) {
- if (/property may be set/gi.test(data)) { //False error is generated when configuring filesystem
- FnSambaShareEnableCommandFinally({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { refresh: display.refresh, silent: display.silent });
- } else {
- if (!display.silent) {
- FnDisplayAlert({ status: "danger", title: "Samba share could not be enabled", description: filesystem.name, breakword: false }, { name: "samba-enable", id: filesystem.id, timeout: 4 });
- }
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
- }, 200);
- }
- });
- } else {
- FnSambaShareEnableCommandFinally({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint }, { reload: samba.reload, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { refresh: display.refresh, silent: display.silent });
- }
-}
-
-function FnSambaShareEnableCommandFinally(pool = { name, id }, filesystem = { name, id, mounted: false, mountpoint }, samba = { reload: true, share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }, display = { refresh: true, silent: false }) {
- FnSambaZfsShareEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } })
- .done(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba share successfully enabled", description: filesystem.name, breakword: false }, { name: "samba-enable", id: filesystem.id, timeout: 4 });
- }
-
- if (samba.reload) {
- FnSambaZfsSharesConfigurationReload()
- .done(function () {
- setTimeout(function () {
- FnSambaConfigurationReload()
- .finally(function () {
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
- }, 200);
- }
- });
- }, 500);
- })
- .fail(function () {
- FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- });
- } else {
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
- }, 200);
- }
- }
- })
- .fail(function () {
- FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- });
-}
-
-function FnSambaShareEnableMountpointGet(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false }, display = { silent: false }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "mounted,mountpoint", "-t", "filesystem", filesystem.name]
- };
-
- FnConsole.log[2]("File Systems, Mountpoint, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Mountpoint, Get:" }));
-
- data = data.replace(/\n/g, "").replace(/\t/g, "\u22C5").split("\u22C5");
-
- filesystem.mounted = data[0];
- filesystem.mountpoint = data[1];
-
- if (/^\//.test(filesystem.mountpoint)) {
- FnConsole.log[1]("File Systems, Mountpoint, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- FnSambaShareEnableAutoGenerateName({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: false, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: filesystem.sharesmb }, { reload: true }, { refresh: true, silent: display.silent });
- } else {
- FnConsole.warn("File Systems, Mountpoint, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- }
- })
- .fail(function (message, data) {
- FnConsole.warn("File Systems, Mountpoint, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
-
- FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
- });
-}
-
-function FnSambaShareNamesGet(samba = { zfsonly: false }) {
- let process = {
- command: ["/bin/sh", "-c", `/bin/cat /etc/cockpit/zfs/shares/*.conf /run/cockpit/zfs/shares/*.conf ` + (!samba.zfsonly ? `/etc/samba/smb.conf ` : ``) + `2> /dev/null | /bin/grep "^\\\[.*\\\]$" || echo \\\$empty`]
- };
-
- FnConsole.log[2]("Samba, Share, Names, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function () {
- FnConsole.log[1]("Samba, Share, Names, Get: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, Share, Names, Get: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnSambaSharesDestroy(pool = { name, id, altroot: false, readonly: false }, filesystems = { id: [] }, samba = { restart: false }, display = { silent: true }) {
- let process = {
- promise: cockpit.defer()
- };
- let promise = Promise.resolve();
-
- FnConsole.log[1]("Samba, Shares, Destroy: In Progress, Pool: " + pool.name);
-
- if (filesystems.id.length > 0) {
- filesystems.id.forEach((_value, _index) => {
- let filesystem = {
- properties: _value.split(/\t/g).filter(v => v)
- };
-
- filesystem.name = filesystem.properties[0];
- filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0], attribute: true });
- filesystem.mounted = filesystem.properties[1];
- filesystem.mountpoint = filesystem.properties[2];
- filesystem.sharesmb = filesystem.properties[3];
-
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- if (_index <= (filesystems.id.length - 1)) {
- if (filesystem.sharesmb == "on") {
- FnSambaZfsShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id });
- }
- }
-
- if (_index == (filesystems.id.length - 1)) {
- setTimeout(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba shares successfully destroyed", description: pool.name, breakword: false }, { name: "samba-destroy", id: pool.id, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, Shares, Destroy: Success, Pool: " + pool.name);
-
- FnSambaZfsSharesConfigurationReload()
- .done(function () {
- setTimeout(function () {
- if (samba.restart) {
- FnSambaRestart()
- .finally(function () {
- process.promise.resolve();
- });
- } else {
- FnSambaConfigurationReload()
- .finally(function () {
- process.promise.resolve();
- });
- }
- }, 300);
- });
- }, 500);
- }
-
- resolve();
- }, 500)
- ));
- });
- } else {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba shares successfully destroyed", description: pool.name, breakword: false }, { name: "samba-destroy", id: pool.id, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, Shares, Destroy: Success, Pool: " + pool.name);
-
- process.promise.resolve();
- }
-
- return process.promise.promise();
-}
-
-function FnSambaSharesDestroyAll(samba = { restart: false }, display = { silent: false }, modal = { name }) {
- let process = {
- command: ["/bin/sh", "-c", "echo '# COCKPIT ZFS MANAGER\n# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION' > /etc/cockpit/zfs/shares.conf && echo '# COCKPIT ZFS MANAGER\n# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION' > /run/cockpit/zfs/shares.conf && /bin/rm -rf /etc/cockpit/zfs/shares/*.conf && /bin/rm -rf /run/cockpit/zfs/shares/*.conf"],
- promise: cockpit.defer()
- };
-
- FnConsole.log[1]("Samba, Shares, Destroy All: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- $("#spinner-" + modal.name + " span").text("Destroying Samba shares...");
-
- cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba shares successfully destroyed", description: null, breakword: false }, { name: "samba-destroy-all", id: null, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, Shares, Destroy All: Success");
-
- if (samba.restart) {
- FnSambaRestart()
- .finally(function () {
- process.promise.resolve();
- });
- } else {
- FnSambaConfigurationReload()
- .finally(function () {
- process.promise.resolve();
- });
- }
- })
- .fail(function (message, data) {
- if (!display.silent) {
- FnDisplayAlert({ status: "danger", title: "Samba shares could not be destroyed", description: null, breakword: false }, { name: "samba-destroy-all", id: null, timeout: 4 });
- }
-
- FnConsole.warn("Samba, Shares, Destroy All: Failed, Message: " + (data ? data : message));
-
- process.promise.resolve();
- });
-
- return process.promise.promise();
-}
-
-function FnSambaSharesEnable(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, force: false }, samba = { restart: false }, display = { refresh: false, silent: true }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name,mounted,mountpoint,sharesmb", "-r", "-t", "filesystem"],
- promise: cockpit.defer()
- };
-
- if (filesystem.name) {
- process.command.push(filesystem.name);
- } else {
- process.command.push(pool.name);
- }
-
- FnConsole.log[1]("Samba, Shares, Enable: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Enable:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
- let promise = Promise.resolve();
-
- if (filesystems.id.length > 0) {
- filesystems.id.forEach((_value, _index) => {
- let filesystem = {
- properties: _value.split(/\t/g).filter(v => v)
- };
-
- filesystem.name = filesystem.properties[0];
- filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0], attribute: true });
- filesystem.mounted = filesystem.properties[1];
- filesystem.mountpoint = filesystem.properties[2];
- filesystem.sharesmb = filesystem.properties[3];
-
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- if (_index <= (filesystems.id.length - 1)) {
- if (filesystem.sharesmb == "on") {
- FnSambaShareEnableAutoGenerateName({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: true }, { reload: false }, { refresh: false, silent: true });
- }
- }
-
- if (_index == (filesystems.id.length - 1)) {
- setTimeout(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba shares successfully enabled", description: pool.name, breakword: false }, { name: "samba-enable", id: pool.id, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, Shares, Enable: Success, Pool: " + pool.name);
-
- FnSambaZfsSharesConfigurationReload()
- .done(function () {
- setTimeout(function () {
- if (samba.restart) {
- FnSambaRestart()
- .finally(function () {
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- }
-
- process.promise.resolve();
- });
- } else {
- FnSambaConfigurationReload()
- .finally(function () {
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- }
-
- process.promise.resolve();
- });
- }
- }, 300);
- });
- }, 500);
- }
-
- resolve();
- }, 500)
- ));
- });
- } else {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba shares successfully enabled", description: pool.name, breakword: false }, { name: "samba-enable", id: pool.id, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, Shares, Enable: Success, Pool: " + pool.name);
-
- process.promise.resolve();
- }
- })
- .fail(function (message, data) {
- if (!display.silent) {
- FnDisplayAlert({ status: "danger", title: "Samba shares could not enabled", description: pool.name, breakword: false }, { name: "samba-enable", id: pool.id, timeout: 4 });
- }
-
- FnConsole.warn("Samba, Shares, Enable: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
-
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- }
-
- process.promise.resolve();
- });
-
- return process.promise.promise();
-}
-
-function FnSambaSharesEnableAll(samba = { restart: false }, display = { silent: false }, modal = { name }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name,mounted,mountpoint,sharesmb", "-r", "-t", "filesystem"],
- promise: cockpit.defer()
- };
-
- FnConsole.log[1]("Samba, Shares, Enable All: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- FnStoragePoolsTemporaryGet()
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Temporary, Get:" }));
-
- $("#spinner-" + modal.name + " span").text("Disabling Samba share inheritance...");
-
- FnFileSystemShareSmbInheritedDisable({ name: null, id: null, altroot: null }, { name: null }, { disable: false })
- .finally(function () {
- $("#spinner-" + modal.name + " span").text("Creating Samba shares...");
-
- cockpit.spawn(process.command, { err: "out" })
- .done(function (_data) {
- FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Samba, Shares, Enable All:" }));
-
- let filesystems = {
- id: _data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
- let promise = Promise.resolve();
-
- if (filesystems.id.length > 0) {
- filesystems.id.forEach((_value, _index) => {
- let filesystem = {
- properties: _value.split(/\t/g).filter(v => v)
- };
- let pool = {
- name: filesystem.properties[0].replace(/\/.*$/, ""),
- id: FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0].replace(/\/.*$/, ""), attribute: true })
- };
-
- filesystem.name = filesystem.properties[0];
- filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0], attribute: true });
- filesystem.mounted = filesystem.properties[1];
- filesystem.mountpoint = filesystem.properties[2];
- filesystem.sharesmb = filesystem.properties[3];
-
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- if (_index <= (filesystems.id.length - 1)) {
- if (filesystem.sharesmb == "on") {
-
- pool.properties = data.split(/\n/g).filter(v => v && new RegExp("^" + pool.name + "\t").test(v))[0].split(/\t/g).filter(v => v);
-
- if (pool.properties[0] == pool.name) {
- pool.altroot = (pool.properties[2] && pool.properties[2] != "-" ? true : false);
- pool.readonly = (pool.properties[1].toLowerCase() == "on" ? true : false);
-
- FnSambaShareEnableAutoGenerateName({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: false, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: true }, { reload: false }, { refresh: false, silent: true });
- }
- }
- }
-
- if (_index == (filesystems.id.length - 1)) {
- setTimeout(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba shares successfully enabled", description: null, breakword: false }, { name: "samba-enable-all", id: null, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, Shares, Enable All: Success");
-
- FnSambaZfsSharesConfigurationReload()
- .done(function () {
- setTimeout(function () {
- if (samba.restart) {
- FnSambaRestart()
- .finally(function () {
- process.promise.resolve();
- });
- } else {
- FnSambaConfigurationReload()
- .finally(function () {
- process.promise.resolve();
- });
- }
- }, 300);
- });
- }, 500);
- }
-
- resolve();
- }, 500)
- ));
- });
- } else {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba shares successfully enabled", description: null, breakword: false }, { name: "samba-enable-all", id: null, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, Shares, Enable All: Success");
-
- process.promise.resolve();
- }
- })
- .fail(function (message, data) {
- if (!display.silent) {
- FnDisplayAlert({ status: "danger", title: "Samba shares could not be enabled", description: null, breakword: false }, { name: "samba-enable-all", id: null, timeout: 4 });
- }
-
- FnConsole.warn("Samba, Shares, Enable All: Failed, Message: " + (data ? data : message));
-
- process.promise.resolve();
- });
- });
- })
- .fail(function (message, data) {
- if (!display.silent) {
- FnDisplayAlert({ status: "danger", title: "Samba shares could not be enabled", description: null, breakword: false }, { name: "samba-enable-all", id: null, timeout: 4 });
- }
-
- FnConsole.warn("Samba, Shares, Enable All: Failed, Message: " + (data ? data : message));
-
- process.promise.resolve();
- });
-
- return process.promise.promise();
-}
-
-function FnSambaSharesGet(pool = { name, id }, filesystem = { name, clones: [] }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name,mounted,mountpoint,sharesmb", "-r", "-t", "filesystem"]
- };
-
- if (filesystem.name) {
- process.command.push(filesystem.name);
- } else if (filesystem.clones.length > 0) {
- filesystem.clones.forEach(_value => _value && process.command.push(_value));
- } else {
- process.command.push(pool.name);
- }
-
- FnConsole.log[2]("Samba, Shares, Get: In Progress, Pool: " + pool.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function () {
- FnConsole.log[1]("Samba, Shares, Get: Success, Pool: " + pool.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, Shares, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnSambaSharesRename(pool = { name, id, altroot: false, readonly: false }, filesystems = { id: [], parent: { name, namenew } }, samba = { restart: false }, display = { silent: true }) {
- let process = {
- promise: cockpit.defer()
- };
- let promise = Promise.resolve();
-
- FnConsole.log[1]("Samba, Shares, Rename: In Progress, Pool: " + pool.name);
-
- if (filesystems.id.length > 0) {
- filesystems.id.forEach((_value, _index) => {
- let filesystem = {
- properties: _value.split(/\t/g).filter(v => v)
- };
-
- filesystem.name = filesystem.properties[0];
- filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0], attribute: true });
- filesystem.mounted = filesystem.properties[1];
- filesystem.mountpoint = filesystem.properties[2];
- filesystem.sharesmb = filesystem.properties[3];
-
- filesystem.namenew = filesystem.name.replace(new RegExp("^" + filesystems.parent.name), filesystems.parent.namenew);
- filesystem.idnew = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.namenew, attribute: true });
-
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- if (_index <= (filesystems.id.length - 1)) {
- if (filesystem.sharesmb == "on") {
- FnFileSystemMountpointGet({ name: pool.name, id: pool.id }, { name: filesystem.namenew, id: filesystem.idnew })
- .done(function (data) {
- filesystem.mountpoint = data.replace(/\n$/, "");
-
- FnSambaZfsShareConfigurationPathSet({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, namenew: filesystem.namenew, id: filesystem.id, mountpoint: filesystem.mountpoint })
- .finally(function () {
- FnSambaZfsShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id });
- });
- });
- }
- }
-
- if (_index == (filesystems.id.length - 1)) {
- setTimeout(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba shares successfully renamed", description: pool.name, breakword: false }, { name: "samba-rename", id: pool.id, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, Shares, Rename: Success, Pool: " + pool.name);
-
- FnSambaZfsSharesConfigurationReload()
- .done(function () {
- setTimeout(function () {
- if (samba.restart) {
- FnSambaRestart()
- .finally(function () {
- process.promise.resolve();
- });
- } else {
- FnSambaConfigurationReload()
- .finally(function () {
- process.promise.resolve();
- });
- }
- }, 300);
- });
- }, 800);
- }
-
- resolve();
- }, 800)
- ));
- });
- } else {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba shares successfully renamed", description: pool.name, breakword: false }, { name: "samba-rename", id: pool.id, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, Shares, Rename: Success, Pool: " + pool.name);
-
- process.promise.resolve();
- }
-
- return process.promise.promise();
-}
-
-function FnSambaStart() {
- let process = {
- command: ["/bin/systemctl", "start"]
- };
-
- if (/Debian|Ubuntu/i.test(zfsmanager.system.operatingsystem)) {
- process.command.splice(2, 0, "smbd");
- } else {
- process.command.splice(2, 0, "smb");
- }
-
- FnConsole.log[2]("Samba, Start: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Samba, Start: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, Start: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnSambaStop() {
- let process = {
- command: ["/bin/systemctl", "stop"]
- };
-
- if (/Debian|Ubuntu/i.test(zfsmanager.system.operatingsystem)) {
- process.command.splice(2, 0, "smbd");
- } else {
- process.command.splice(2, 0, "smb");
- }
-
- FnConsole.log[2]("Samba, Stop: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Samba, Stop: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, Stop: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnSambaUsersharesDirectoryCreate() {
- let process = {
- command: ["/bin/sh", "-c", `[ ! -d /var/lib/samba/usershares ] && /bin/mkdir -p /var/lib/samba/usershares || printf "Skipped"`]
- };
-
- FnConsole.log[2]("Samba, Usershares Directory, Create: In Progress")
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Usershares Directory, Create:" }));
-
- if (data == "Skipped") {
- FnConsole.log[2]("Samba, Usershares Directory, Create: Skipped");
- } else {
- FnConsole.log[1]("Samba, Usershares Directory, Create: Success");
- }
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, Usershares Directory, Create: Failed, Message: " + (data ? data : message));
- });
-}
-
-function FnSambaVersionGet() {
- let process = {
- command: ["/usr/sbin/smbd", "-V"]
- };
- let samba = {
- message: ""
- };
-
- FnConsole.log[2]("Samba, Version, Get: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data, message) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Version, Get:" }));
-
- FnConsole.log[1]("Samba, Version, Get: Success, Version: " + (data ? data.replace(/^Version /i, "") : message.replace(/^Version /i, "")));
-
- $("#alerts-requirements").empty().addClass("hidden");
- $("#container").removeClass("hidden");
- })
- .fail(function (message, data) {
- FnConsole.error("Samba, Version, Get: Failed, Message: " + (data ? data : message));
-
- samba.message = `
-
-
-
- This package requires Samba
- Install Samba software via your package manager
-
- Refresh
-
- `;
-
- $("#alerts-requirements").removeClass("hidden").html(samba.message);
- $("#container").addClass("hidden");
- });
-}
-
-function FnSambaZfsShareConfigurationGenerate(filesystem = { name, id, mountpoint }, samba = { enable: false, share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }) {
- samba.share.conf = {
- content: "",
- path: "/" + (samba.share.temporary ? "run" : "etc") + "/cockpit/zfs/shares/" + FnGenerateShareFileName({ name: filesystem.name }) + ".conf"
- }
-
- if (!samba.share.name) {
- samba.share.name = FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.name.replace(/^.*\/(.*)$/, "$1") });
- }
- if (samba.share.administrative) {
- samba.share.name = samba.share.name + "$";
- }
- if (!samba.share.comment && samba.enable) {
- samba.share.comment = "ZFS: " + filesystem.name;
- }
-
- samba.share.additional = samba.share.additional.reduce((a, v) => {
- let allow = true;
-
- if (/[\[\]]/g.test(v)) { //Do not allow section names
- allow = false;
- }
- if (/^[#]/.test(v) == false && /[=]/.test(v)) { //Do not allow modal configurable properties
- if (/(path|comment|browseable|read only|guest ok).*=/gi.test(v)) {
- allow = false;
- }
- }
-
- if (allow) {
- v = v.replace(/\\/g, "\\\\\\");
-
- a.push((/^[#]/.test(v) == false && /[=]/.test(v) ? "\\t" + v : v));
- }
-
- return a;
- }, []);
-
- samba.share.conf.content = "\"# COCKPIT ZFS MANAGER\n# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION\\n\[" + samba.share.name + "\]\\n\\tpath \= " + filesystem.mountpoint + "\\n\\tcomment \= " + samba.share.comment + "\\n\\tbrowseable = " + (samba.share.browseable ? "yes" : "no") + "\\n\\tread only = " + (samba.share.readonly ? "yes" : "no") + "\\n\\tguest ok = " + (samba.share.guestok ? "yes" : "no") + "\\n\\n# ADD ADDITIONAL CONFIGURATION HERE\\n" + samba.share.additional.join("\\n") + "\\n\" > \"" + samba.share.conf.path + "\"";
-
- return samba.share.conf.content;
-}
-
-function FnSambaZfsShareConfigurationGet(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id }, modal = { name, id }) {
- let process = {
- command: ["/bin/cat", "/" + (pool.altroot || pool.readonly ? "run" : "etc") + "/cockpit/zfs/shares/" + FnGenerateShareFileName({ name: filesystem.name }) + ".conf"]
- };
- let samba = {
- share: {
- name: "",
- path: "",
- comment: "",
- administrative: false,
- browseable: true,
- guestok: false,
- readonly: false,
- additional: []
- }
- };
-
- FnConsole.log[2]("Samba, ZFS Share Configuration, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, ZFS Share Configuration, Get:" }));
-
- samba.share.conf = data.split(/\n/g).filter(v => v);
-
- samba.share.conf.forEach((_value, _index) => {
- _value = _value.replace(/\t/g, "");
-
- //2=name, 3=path, 4=comment, 5=browseable, 6=read only, 7=guest ok
-
- switch (_index) {
- case 2: //2=name
- if (/^\[.*\]$/g.test(_value)) {
- samba.share.name = _value.replace(/\[/g, "").replace(/\]/g, "");
-
- if (/[$]$/.test(samba.share.name)) {
- samba.share.administrative = true;
- samba.share.name = samba.share.name.replace(/[$]$/, "");
- }
- }
-
- break;
- case 3: //3=path
- if (/path \=/gi.test(_value)) {
- samba.share.path = _value.replace("path = ", "").replace(/["]/g, "");
- }
-
- break;
- case 4: //4=comment
- if (/comment \=/gi.test(_value)) {
- samba.share.comment = _value.replace("comment = ", "").replace(/["]/g, "");
- }
-
- break;
- case 5: //5=browseable
- if (/browseable \=/gi.test(_value)) {
- samba.share.browseable = (_value.replace("browseable = ", "").replace(/["]/g, "") == "yes" ? true : false);
- }
-
- break;
- case 6: //6=read only
- if (/read only \=/gi.test(_value)) {
- samba.share.readonly = (_value.replace("read only = ", "").replace(/["]/g, "") == "yes" ? true : false);
- }
-
- break;
- case 7: //7=guest ok
- if (/guest ok \=/gi.test(_value)) {
- samba.share.guestok = (_value.replace("guest ok = ", "").replace(/["]/g, "") == "yes" ? true : false);
- }
-
- break;
- }
- });
-
- samba.share.additional = samba.share.conf.filter((v, i) => i > 8).map(v => v.replace(/^\s+/, ""));
-
- FnConsole.log[1]("Samba, ZFS Share Configuration, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, ZFS Share Configuration, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#input-" + modal.name + "-name-" + modal.id).val(samba.share.name).attr("data-field-value", samba.share.name);
- $("#input-" + modal.name + "-comment-" + modal.id).val(samba.share.comment);
- $("#textarea-" + modal.name + "-additional-" + modal.id).val(samba.share.additional.join("\n"));
-
- if (samba.share.administrative && !$("#switch-" + modal.name + "-administrative-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-administrative-" + modal.id + " input").click();
- }
- if (!samba.share.browseable && $("#switch-" + modal.name + "-browseable-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-browseable-" + modal.id + " input").click();
- }
- if (samba.share.guestok && !$("#switch-" + modal.name + "-guestok-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-guestok-" + modal.id + " input").click();
- }
- if (samba.share.readonly && !$("#switch-" + modal.name + "-readonly-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-readonly-" + modal.id + " input").click();
- }
-
- if (!samba.share.name) {
- $("#alert-" + modal.name + "-configurationmissing-" + modal.id).removeClass("hidden");
-
- $("#input-" + modal.name + "-name-" + modal.id).val(FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.name.replace(/^.*\/(.*)$/, "$1") })).focus();
- if (!samba.share.comment) {
- $("#input-" + modal.name + "-comment-" + modal.id).val("ZFS: " + filesystem.name);
- }
- }
- if (samba.share.additional.length > 0 && !$("#switch-" + modal.name + "-additional-" + modal.id + " input").prop("checked")) {
- $("#switch-" + modal.name + "-additional-" + modal.id + " input").click();
- }
- });
-}
-
-function FnSambaZfsShareConfigurationPathSet(pool = { name, id, altroot: false }, filesystem = { name, namenew, id, mountpoint }, display = { silent: true }) {
- let process = {
- command: ["/bin/cat", "/" + (pool.altroot ? "run" : "etc") + "/cockpit/zfs/shares/" + FnGenerateShareFileName({ name: filesystem.name }) + ".conf"],
- promise: cockpit.defer()
- };
- let samba = {
- share: {
- name: "",
- path: "",
- comment: "",
- administrative: false,
- browseable: true,
- guestok: false,
- readonly: false,
- temporary: (pool.altroot ? true : false),
- additional: []
- }
- };
-
- FnConsole.log[2]("Samba, ZFS Share Configuration, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, ZFS Share Configuration, Get:" }));
-
- samba.share.conf = data.split(/\n/g).filter(v => v);
-
- samba.share.conf.forEach((_value, _index) => {
- _value = _value.replace(/\t/g, "");
-
- //2=name, 3=path, 4=comment, 5=browseable, 6=read only, 7=guest ok
-
- switch (_index) {
- case 2: //2=name
- if (/^\[.*\]$/g.test(_value)) {
- samba.share.name = _value.replace(/\[/g, "").replace(/\]/g, "");
-
- if (/[$]$/.test(samba.share.name)) {
- samba.share.administrative = true;
- samba.share.name = samba.share.name.replace(/[$]$/, "");
- }
- }
-
- break;
- case 3: //3=path
- if (/path \=/gi.test(_value)) {
- samba.share.path = _value.replace("path = ", "").replace(/["]/g, "");
- }
-
- break;
- case 4: //4=comment
- if (/comment \=/gi.test(_value)) {
- samba.share.comment = _value.replace("comment = ", "").replace(/["]/g, "");
- }
-
- break;
- case 5: //5=browseable
- if (/browseable \=/gi.test(_value)) {
- samba.share.browseable = (_value.replace("browseable = ", "").replace(/["]/g, "") == "yes" ? true : false);
- }
-
- break;
- case 6: //6=read only
- if (/read only \=/gi.test(_value)) {
- samba.share.readonly = (_value.replace("read only = ", "").replace(/["]/g, "") == "yes" ? true : false);
- }
-
- break;
- case 7: //7=guest ok
- if (/guest ok \=/gi.test(_value)) {
- samba.share.guestok = (_value.replace("guest ok = ", "").replace(/["]/g, "") == "yes" ? true : false);
- }
-
- break;
- }
- });
-
- samba.share.additional = samba.share.conf.filter((v, i) => i > 8).map(v => v.replace(/^\s+/, ""));
-
- FnConsole.log[1]("Samba, ZFS Share Configuration, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- if (filesystem.mountpoint != samba.share.path || filesystem.namenew) {
- if (filesystem.namenew) {
- if ((filesystem.name.replace(/^.*\/(.*)$/, "$1") != filesystem.namenew.replace(/^.*\/(.*)$/, "$1") && samba.share.name.toLowerCase() == FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.name.replace(/^.*\/(.*)$/, "$1") }).toLowerCase()) || samba.share.name.toLowerCase() == FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.name }).toLowerCase()) {
- samba.share.nameunique = true;
-
- FnSambaShareNamesGet({ zfsonly: false })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Share, Names, Get:" }));
-
- if (data.replace(/\n/g, "") != "$empty") { //$empty response is received if share names list is empty
- samba.shares = data.split(/\n/g).filter(v => v);
-
- samba.shares.forEach((_value, _index) => {
- if (_value.replace(/^\[/, "").replace(/\]$/, "").toLowerCase() == filesystem.namenew.replace(/^.*\/(.*)$/, "$1").toLowerCase() + (samba.share.administrative ? "$" : "")) {
- samba.share.nameunique = false;
-
- return;
- }
- });
- }
-
- if (/^global$|^homes$|^printers$/gi.test(samba.share.name)) {
- samba.share.nameunique = false;
- }
-
- if (!samba.share.nameunique) {
- samba.share.name = FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.namenew });
- } else {
- samba.share.name = FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.namenew.replace(/^.*\/(.*)$/, "$1") });
- }
-
- filesystem.name = filesystem.namenew;
- samba.share.comment = "ZFS: " + filesystem.namenew;
-
- FnSambaZfsShareConfigurationPathSetCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { silent: display.silent })
- .finally(function () {
- process.promise.resolve();
- });
- })
- .fail(function () {
- filesystem.name = filesystem.namenew;
- samba.share.comment = "ZFS: " + filesystem.namenew;
- samba.share.name = FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.namenew });
-
- FnSambaZfsShareConfigurationPathSetCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { silent: display.silent })
- .finally(function () {
- process.promise.resolve();
- });
- });
- } else {
- filesystem.name = filesystem.namenew;
- samba.share.comment = "ZFS: " + filesystem.namenew;
-
- FnSambaZfsShareConfigurationPathSetCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { silent: display.silent })
- .finally(function () {
- process.promise.resolve();
- });
- }
- } else {
- FnSambaZfsShareConfigurationPathSetCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { silent: display.silent })
- .finally(function () {
- process.promise.resolve();
- });
- }
- } else {
- process.promise.resolve();
- }
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, ZFS Share Configuration, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
-
- process.promise.resolve();
- });
-
- return process.promise.promise();
-}
-
-function FnSambaZfsShareConfigurationPathSetCommand(pool = { name, id }, filesystem = { name, id, mountpoint }, samba = { share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }, display = { silent: true }) {
- let process = {
- command: ["/bin/sh", "-c", "printf " + FnSambaZfsShareConfigurationGenerate({ name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { enable: false, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } })]
- };
-
- FnConsole.log[2]("Samba, ZFS Share Configuration, Path, Set: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- if (!display.silent) {
- FnDisplayAlert({ status: "success", title: "Samba share configuration successfully updated", description: filesystem.name, breakword: false }, { name: "samba-configure-share", id: filesystem.id, timeout: 4 });
- }
-
- FnConsole.log[1]("Samba, ZFS Share Configuration, Path, Set: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- if (!display.silent) {
- FnDisplayAlert({ status: "danger", title: "Samba share configuration could not be updated", description: filesystem.name, breakword: false }, { name: "samba-configure-share", id: filesystem.id, timeout: 4 });
- }
-
- FnConsole.warn("Samba, ZFS Share Configuration, Path, Set: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnSambaZfsShareConfigurationPathsSet(pool = { name, id, altroot: false }, filesystem = { name }, samba = { restart: false }, display = { refresh: false, silent: true }) {
- let process = {
- command: ["/sbin/zfs", "list", "-H", "-o", "name,mounted,mountpoint,sharesmb", "-r", "-t", "filesystem", filesystem.name],
- promise: cockpit.defer()
- };
-
- FnConsole.log[2]("Samba, ZFS Share Configuration, Paths, Set: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- cockpit.spawn(process.command, { err: "out" })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, ZFS Share Configuration, Paths, Set:" }));
-
- let filesystems = {
- id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
- };
- let promise = Promise.resolve();
-
- if (filesystems.id.length > 0) {
- filesystems.id.forEach((_value, _index) => {
- let filesystem = {
- properties: _value.split(/\t/g).filter(v => v)
- };
-
- filesystem.name = filesystem.properties[0];
- filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0], attribute: true });
- filesystem.mounted = filesystem.properties[1];
- filesystem.mountpoint = filesystem.properties[2];
- filesystem.sharesmb = filesystem.properties[3];
-
- promise = promise.then(_ => new Promise(resolve =>
- setTimeout(function () {
- if (_index <= (filesystems.id.length - 1)) {
- if (filesystem.sharesmb == "on") {
- FnSambaZfsShareConfigurationPathSet({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, namenew: null, id: filesystem.id, mountpoint: filesystem.mountpoint })
- }
- }
-
- if (_index == (filesystems.id.length - 1)) {
- setTimeout(function () {
- FnDisplayAlert({ status: "success", title: "Samba share configurations successfully updated", description: pool.name, breakword: false }, { name: "samba-configure-share", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Samba, ZFS Share Configuration, Paths, Set: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- FnSambaZfsSharesConfigurationReload()
- .done(function () {
- setTimeout(function () {
- if (samba.restart) {
- FnSambaRestart()
- .finally(function () {
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- }
-
- process.promise.resolve();
- });
- } else {
- FnSambaConfigurationReload()
- .finally(function () {
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- }
-
- process.promise.resolve();
- });
- }
- }, 300);
- });
- }, 500);
- }
-
- resolve();
- }, 500)
- ));
- });
- } else {
- FnDisplayAlert({ status: "success", title: "Samba share configurations successfully updated", description: pool.name, breakword: false }, { name: "samba-configure-share", id: pool.id, timeout: 4 });
-
- FnConsole.log[1]("Samba, ZFS Share Configuration, Paths, Set: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- process.promise.resolve();
- }
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Samba share configurations could not updated", description: pool.name, breakword: false }, { name: "samba-configure-share", id: pool.id, timeout: 4 });
-
- FnConsole.warn("Samba, ZFS Share Configuration, Paths, Set: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
-
- if (display.refresh) {
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
- }, 500);
- }
-
- process.promise.resolve();
- });
-
- return process.promise.promise();
-}
-
-function FnSambaZfsShareConfigure(pool = { name, id }, filesystem = { name, id, mountpoint }, samba = { share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, nameexisting, readonly: false, temporary: false }, restart: false }) {
- $("#spinner-storagepool-filesystem-samba-configure-" + filesystem.id + " span").text("Configuring Samba share...");
-
- FnSambaShareNamesGet({ zfsonly: false })
- .done(function (data) {
- FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Share, Names, Get:" }));
-
- samba.share.nameunique = true;
- samba.share.errormessage = "Share name is already in use.";
-
- if (data.replace(/\n/g, "") != "$empty") { //$empty response is received if share names list is empty
- samba.shares = data.split(/\n/g).filter(v => v);
-
- samba.shares.forEach((_value, _index) => {
- if (_value.replace(/^\[/, "").replace(/\]$/, "").toLowerCase() == samba.share.name.toLowerCase() + (samba.share.administrative ? "$" : "")) {
- if (samba.share.name != samba.share.nameexisting) { //Allow the name since the share is already enabled with this name
- samba.share.nameunique = false;
-
- return;
- }
- }
- });
- }
-
- if (/^global$|^homes$|^printers$/gi.test(samba.share.name)) {
- samba.share.nameunique = false;
- samba.share.errormessage = "Share name can not be a restricted name.";
- }
-
- if (!samba.share.nameunique) {
- $("#validationwrapper-storagepool-filesystem-samba-configure-name-" + filesystem.id).addClass("has-error");
- $("#helpblock-storagepool-filesystem-samba-configure-name-" + filesystem.id).addClass("has-error").removeClass("hidden").text(samba.share.errormessage);
- $("#input-storagepool-filesystem-samba-configure-name-" + filesystem.id).focus();
-
- $("#spinner-storagepool-filesystem-samba-configure-" + filesystem.id).addClass("hidden");
- $("#spinner-storagepool-filesystem-samba-configure-" + filesystem.id + " span").text("");
- $("#btn-storagepool-filesystem-samba-configure-apply-" + filesystem.id).prop("disabled", false);
-
- FnConsole.warn("Samba, ZFS Share Configuration, Update: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + samba.share.errormessage);
- } else {
- FnSambaZfsShareConfigureCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary }, restart: samba.restart });
- }
- });
-}
-
-function FnSambaZfsShareConfigureCommand(pool = { name, id }, filesystem = { name, id, mountpoint }, samba = { share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false }, restart: false }) {
- let process = {
- command: ["/bin/sh", "-c", "printf " + FnSambaZfsShareConfigurationGenerate({ name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { enable: false, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } })]
- };
-
- FnConsole.log[2]("Samba, ZFS Share Configuration, Update: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnDisplayAlert({ status: "success", title: "Samba share configuration successfully updated", description: filesystem.name, breakword: false }, { name: "samba-configure-share", id: filesystem.id, timeout: 4 });
-
- FnConsole.log[1]("Samba, ZFS Share Configuration, Update: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
-
- if (samba.restart) {
- FnSambaRestart();
- } else {
- FnSambaConfigurationReload();
- }
- })
- .fail(function (message, data) {
- FnDisplayAlert({ status: "danger", title: "Samba share configuration could not be updated", description: filesystem.name, breakword: false }, { name: "samba-configure-share", id: filesystem.id, timeout: 4 });
-
- FnConsole.warn("Samba, ZFS Share Configuration, Update: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- })
- .finally(function () {
- $("#modal-storagepool-filesystem-samba-configure-" + filesystem.id).modal("hide");
-
- setTimeout(function () {
- FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
- }, 200);
- });
-}
-
-function FnSambaZfsShareDisable(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id }) {
- let process = {
- command: ["/bin/rm", "-f", "/" + (pool.altroot || pool.readonly ? "run" : "etc") + "/cockpit/zfs/shares/" + FnGenerateShareFileName({ name: filesystem.name }) + ".conf"]
- };
-
- FnConsole.log[2]("Samba, Share, Disable: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Samba, Share, Disable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, Share, Disable: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnSambaZfsShareEnable(pool = { name, id }, filesystem = { name, id, mountpoint }, samba = { share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }) {
- let process = {
- command: ["/bin/sh", "-c", "printf " + FnSambaZfsShareConfigurationGenerate({ name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { enable: true, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } })]
- };
-
- FnConsole.log[2]("Samba, Share, Enable: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Samba, Share, Enable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, Share, Enable: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
- });
-}
-
-function FnSambaZfsSharesConfigurationReload() {
- let process = {
- command: ["/bin/sh", "-c", "echo '# COCKPIT ZFS MANAGER\n# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION' > /etc/cockpit/zfs/shares.conf && /bin/ls /etc/cockpit/zfs/shares/*.conf 2> /dev/null | /bin/sed -e 's/^/include = /' >> /etc/cockpit/zfs/shares.conf && echo '# COCKPIT ZFS MANAGER\n# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION' > /run/cockpit/zfs/shares.conf && /bin/ls /run/cockpit/zfs/shares/*.conf 2> /dev/null | /bin/sed -e 's/^/include = /' >> /run/cockpit/zfs/shares.conf"]
- };
-
- FnConsole.log[2]("Samba, ZFS Shares Configuration, Reload: In Progress");
- FnConsole.log[3](FnConsoleCommand({ command: process.command }));
-
- return cockpit.spawn(process.command, { err: "out", superuser: "require" })
- .done(function () {
- FnConsole.log[1]("Samba, ZFS Shares Configuration, Reload: Success");
- })
- .fail(function (message, data) {
- FnConsole.warn("Samba, ZFS Shares Configuration, Reload: Failed, Message: " + (data ? data : message));
- });
-}
-
-//#endregion
-
-//#region Dynamic Content Click Actions
-
-function FnDynamicStatusDiskTrimCancel(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
- let dynamic = {
- script: ""
- };
-
- dynamic.script = `
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-trim-cancel-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolTrimCancel({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `" });
- });
- \x3C/script>
- `;
-
- $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
-}
-
-function FnDynamicStatusDiskTrimResume(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
- let dynamic = {
- script: ""
- };
-
- dynamic.script = `
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-trim-resume-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolTrimStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `" }, { resume: true, secure: false }, { name: null, id: null });
- });
- \x3C/script>
- `;
-
- $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
-}
-
-function FnDynamicStatusDiskTrimSuspend(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
- let dynamic = {
- script: ""
- };
-
- dynamic.script = `
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-trim-suspend-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolTrimSuspend({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `" });
- });
- \x3C/script>
- `;
-
- $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
-}
-
-function FnDynamicStatusStoragePoolScrubPause(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
- let dynamic = {
- script: ""
- };
-
- dynamic.script = `
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-scrub-pause-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolScrubPause({ name: "` + pool.name + `", id: "` + pool.id + `" }, { refresh: true });
- });
- \x3C/script>
- `;
-
- $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
-}
-
-function FnDynamicStatusStoragePoolScrubResume(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
- let dynamic = {
- script: ""
- };
-
- dynamic.script = `
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-scrub-resume-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolScrubStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { resume: true }), { refresh: true };
- });
- \x3C/script>
- `;
-
- $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
-}
-
-function FnDynamicStatusStoragePoolScrubStart(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
- let dynamic = {
- script: ""
- };
-
- dynamic.script = `
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-scrub-start-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolScrubStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { resume: false }, { refresh: true });
- });
- \x3C/script>
- `;
-
- $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
-}
-
-function FnDynamicStatusStoragePoolScrubStop(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
- let dynamic = {
- script: ""
- };
-
- dynamic.script = `
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-scrub-stop-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolScrubStop({ name: "` + pool.name + `", id: "` + pool.id + `" }, { refresh: true });
- });
- \x3C/script>
- `;
-
- $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
-}
-
-function FnDynamicStatusStoragePoolTrimCancel(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
- let dynamic = {
- script: ""
- };
-
- dynamic.script = `
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-trim-cancel-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolTrimCancel({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: null });
- });
- \x3C/script>
- `;
-
- $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
-}
-
-function FnDynamicStatusStoragePoolTrimResume(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
- let dynamic = {
- script: ""
- };
-
- dynamic.script = `
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-trim-resume-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolTrimStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: null }, { resume: true, secure: false }, { name: null, id: null });
- });
- \x3C/script>
- `;
-
- $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
-}
-
-function FnDynamicStatusStoragePoolTrimSuspend(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
- let dynamic = {
- script: ""
- };
-
- dynamic.script = `
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-trim-suspend-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolTrimSuspend({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: null });
- });
- \x3C/script>
- `;
-
- $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
-}
-
-//#endregion
-
-//#region Modals Register
-
-function FnModalsRegister() {
- $("#modals").append(`
`);
- $("#modals").append(`
`);
-
- FnModalAbout();
- FnModalConfigure();
- FnModalUpdate();
- FnModalWelcome();
- FnModalStoragePoolsCreate();
- FnModalStoragePoolsImport();
- FnModalFileSystemsUnlock();
-}
-
-//#endregion
-
-//#region Modal Cockpit ZFS Manager
-
-function FnModalAbout() {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
-
-
-
-
Cockpit ZFS Manager is an interactive ZFS on Linux admin package for Cockpit.
- ` + FnDisplayInlineAlert({ status: "info", title: "A new version of Cockpit ZFS Manager is now available", description: `
` }, { name: "about-update", id: null, hidden: true }) + `
-
Version: ` + zfsmanager.version + `
-
Copyright © 2019-2020 OPTIMANS Pty Ltd.
-
-
-
-
-
-
-
- `;
-
- $("#modals").append(modal.window);
-}
-
-function FnModalConfigure() {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-configure").on("click", function () {
- FnModalConfigureContent({ id: $("#modal-configure") });
- });
- \x3C/script>
- `;
-
- $("#modals").append(modal.window);
-}
-
-function FnModalConfigureContent(modal = { id }) {
- modal.content = `
-
-
-
-
- ` + (!zfsmanager.user.configuration ? FnDisplayInlineAlert({ status: "info", title: "Configuration does not exist. Configure to save a new configuration.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-configure-samba-manage input").on("click", function () {
- if (!$(this).prop("checked")) {
- $("#switch-configure-samba-windowscompatibility input").prop("disabled", true);
- $("#switch-configure-samba-windowscompatibility").parent().addClass("hidden");
- } else {
- $("#switch-configure-samba-windowscompatibility input").removeClass("hidden").prop("disabled", false);
- $("#switch-configure-samba-windowscompatibility").parent().removeClass("hidden");
- }
- });
-
- $("#switch-configure-zfs-storagepool-boot input").on("click", function () {
- if (!$(this).prop("checked")) {
- $("#switch-configure-zfs-storagepool-bootlockdown input").prop("disabled", true);
- $("#switch-configure-zfs-storagepool-bootlockdown").parent().addClass("hidden");
- } else {
- $("#switch-configure-zfs-storagepool-bootlockdown input").prop("disabled", false);
- $("#switch-configure-zfs-storagepool-bootlockdown").parent().removeClass("hidden");
- }
- });
-
- $("#btn-configure-apply").on("click", function () {
- $("#spinner-configure").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let user = {
- cockpit: {
- manage: $("#switch-configure-cockpit-manage input").prop("checked")
- },
- disks: {
- base2: $("#switch-configure-disks-base2 input").prop("checked"),
- },
- loglevel: $("#btnspan-configure-zfs-storagepool-loglevel").attr("data-field-value"),
- samba: {
- manage: $("#switch-configure-samba-manage input").prop("checked"),
- windowscompatibility: $("#switch-configure-samba-windowscompatibility input").prop("checked")
- },
- updates: {
- check: $("#switch-configure-updates-check input").prop("checked")
- },
- zfs: {
- filesystem: {
- cloneorigin: $("#switch-configure-zfs-filesystem-cloneorigin input").prop("checked"),
- quotarestrict: $("#switch-configure-zfs-filesystem-quotarestrict input").prop("checked"),
- readonlylockdown: $("#switch-configure-zfs-filesystem-readonlylockdown input").prop("checked"),
- snapshotactions: $("#switch-configure-zfs-filesystem-snapshotactions input").prop("checked")
- },
- snapshot: {
- filesystemlist: $("#switch-configure-zfs-snapshot-filesystemlist input").prop("checked")
- },
- status: {
- errorcolors: $("#switch-configure-zfs-status-errorcolors input").prop("checked"),
- trimunsupported: $("#switch-configure-zfs-status-trimunsupported input").prop("checked")
- },
- storagepool: {
- activetab: $("#btnspan-configure-zfs-storagepool-activetab").attr("data-field-value"),
- boot: $("#switch-configure-zfs-storagepool-boot input").prop("checked"),
- bootlockdown: $("#switch-configure-zfs-storagepool-bootlockdown input").prop("checked"),
- count: $("#switch-configure-zfs-storagepool-count input").prop("checked"),
- refreshall: $("#switch-configure-zfs-storagepool-refreshall input").prop("checked"),
- root: $("#switch-configure-zfs-storagepool-root input").prop("checked")
- }
- }
- };
-
- FnConfigure({ cockpit: { manage: user.cockpit.manage }, disks: { base2: user.disks.base2 }, loglevel: user.loglevel, samba: { manage: user.samba.manage, windowscompatibility: user.samba.windowscompatibility }, updates: { check: user.updates.check }, zfs: { filesystem: { cloneorigin: user.zfs.filesystem.cloneorigin, quotarestrict: user.zfs.filesystem.quotarestrict, readonlylockdown: user.zfs.filesystem.readonlylockdown, snapshotactions: user.zfs.filesystem.snapshotactions }, snapshot: { filesystemlist: user.zfs.snapshot.filesystemlist }, status: { errorcolors: user.zfs.status.errorcolors, trimunsupported: user.zfs.status.trimunsupported }, storagepool: { activetab: user.zfs.storagepool.activetab, boot: user.zfs.storagepool.boot, bootlockdown: user.zfs.storagepool.bootlockdown, count: user.zfs.storagepool.count, refreshall: user.zfs.storagepool.refreshall, root: user.zfs.storagepool.root } } }, { name: "configure", welcome: false })
- });
-
- $("#dropdown-configure-zfs-storagepool-activetab").on("click", "li a", function () {
- $("#btnspan-configure-zfs-storagepool-activetab").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-configure-zfs-storagepool-loglevel").on("click", "li a", function () {
- $("#btnspan-configure-zfs-storagepool-loglevel").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalUpdate() {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
- `;
-
- $("#modals").append(modal.window);
-}
-
-function FnModalUpdateContent(modal = { id }) {
- modal.content = `
-
- `;
-
- modal.id.empty().append(modal.content);
-
- $("#progressbar-update .progress-bar").css("width", "100%");
-}
-
-function FnModalWelcome() {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
- `;
-
- $("#modals").append(modal.window);
-}
-
-function FnModalWelcomeContent(modal = { id }) {
- modal.content = `
-
-
-
-
-
Configure initial settings to get started. Additional settings can be configured later.
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-welcome-samba-manage input").on("click", function () {
- if (!$(this).prop("checked")) {
- $("#switch-welcome-samba-windowscompatibility input").prop("disabled", true);
- $("#switch-welcome-samba-windowscompatibility").parent().addClass("hidden");
- } else {
- $("#switch-welcome-samba-windowscompatibility input").removeClass("hidden").prop("disabled", false);
- $("#switch-welcome-samba-windowscompatibility").parent().removeClass("hidden");
- }
- });
-
- $("#switch-welcome-zfs-storagepool-boot input").on("click", function () {
- if (!$(this).prop("checked")) {
- $("#switch-welcome-zfs-storagepool-bootlockdown input").prop("disabled", true);
- $("#switch-welcome-zfs-storagepool-bootlockdown").parent().addClass("hidden");
- } else {
- $("#switch-welcome-zfs-storagepool-bootlockdown input").prop("disabled", false);
- $("#switch-welcome-zfs-storagepool-bootlockdown").parent().removeClass("hidden");
- }
- });
-
- $("#btn-welcome-apply").on("click", function () {
- $("#spinner-welcome").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let user = {
- cockpit: {
- manage: $("#switch-welcome-cockpit-manage input").prop("checked")
- },
- loglevel: $("#btnspan-welcome-zfs-storagepool-loglevel").attr("data-field-value"),
- samba: {
- manage: $("#switch-welcome-samba-manage input").prop("checked"),
- windowscompatibility: $("#switch-welcome-samba-windowscompatibility input").prop("checked")
- },
- updates: {
- check: $("#switch-welcome-updates-check input").prop("checked")
- },
- zfs: {
- storagepool: {
- boot: $("#switch-welcome-zfs-storagepool-boot input").prop("checked"),
- bootlockdown: $("#switch-welcome-zfs-storagepool-bootlockdown input").prop("checked"),
- root: $("#switch-welcome-zfs-storagepool-root input").prop("checked")
- }
- }
- };
-
- FnConfigure({ cockpit: { manage: user.cockpit.manage }, disks: { base2: ` + zfsmanager.configuration.disks.base2 + ` }, loglevel: user.loglevel, samba: { manage: user.samba.manage, windowscompatibility: user.samba.windowscompatibility }, updates: { check: user.updates.check }, zfs: { filesystem: { cloneorigin: ` + zfsmanager.configuration.zfs.filesystem.cloneorigin + `, quotarestrict: ` + zfsmanager.configuration.zfs.filesystem.quotarestrict + `, readonlylockdown: ` + zfsmanager.configuration.zfs.filesystem.readonlylockdown + `, snapshotactions: ` + zfsmanager.configuration.zfs.filesystem.snapshotactions + ` }, snapshot: { filesystemlist: ` + zfsmanager.configuration.zfs.snapshot.filesystemlist + ` }, status: { errorcolors: ` + zfsmanager.configuration.zfs.status.errorcolors + `, trimunsupported: ` + zfsmanager.configuration.zfs.status.trimunsupported + ` }, storagepool: { activetab: ` + zfsmanager.configuration.zfs.storagepool.activetab + `, boot: user.zfs.storagepool.boot, bootlockdown: user.zfs.storagepool.bootlockdown, count: ` + zfsmanager.configuration.zfs.storagepool.count + `, refreshall: ` + zfsmanager.configuration.zfs.storagepool.refreshall + `, root: user.zfs.storagepool.root } } }, { name: "welcome", welcome: true })
- });
-
- $("#dropdown-welcome-zfs-storagepool-activetab").on("click", "li a", function () {
- $("#btnspan-welcome-zfs-storagepool-activetab").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-welcome-zfs-storagepool-loglevel").on("click", "li a", function () {
- $("#btnspan-welcome-zfs-storagepool-loglevel").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-//#endregion
-
-//#region Modal Storage Pools
-
-function FnModalStoragePoolsCreate() {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepools-create").on("click", function () {
- FnModalStoragePoolsCreateContent({ id: $("#modal-storagepools-create") });
- FnDisksAvailableGet({ name: "storagepools-create-disks", id: null, default: true });
-
- $("#input-storagepools-create-refreservation").val("10");
- $("#validationwrapper-storagepools-create-refreservation .min-slider-handle").attr("tabindex", "1003");
- setTimeout(function() {
- $("#input-storagepools-create-name").focus();
- }, 600);
- });
- \x3C/script>
- `;
-
- $("#modals-storagepools").append(modal.window);
-}
-
-function FnModalStoragePoolsCreateContent(modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#input-storagepools-create-refreservation").tooltip({ trigger: "manual" })
- .on("keyup", function (element) {
- let $this = $(this);
- let sd = $this.siblings("[data-provide=slider]").slider();
-
- if ($this.val().trim() && !$.isNumeric(this.value)) {
- this.value = sd.slider("getValue");
- }
- })
- .on("keypress blur", function (element) {
- if (element.which == 13 || element.type === "blur") {
- element.preventDefault();
-
- let $this = $(this);
- let sd = $this.siblings("[data-provide=slider]").slider();
- let max = sd.slider("getAttribute", "max");
- let min = sd.slider("getAttribute", "min");
-
- if (!$.isNumeric(this.value) || (this.value > max || this.value < min)) {
- let warningInfo = $.isNumeric(this.value) ? "Valid value should be between " + min + " and " + max : "Valid value should be number";
- $this.attr("data-original-title", warningInfo).tooltip("show").addClass("warning");
- this.value = sd.slider("getValue");
- setTimeout(function () {
- $this.tooltip("hide");
- }, 3000);
- } else {
- if ($this.is(".warning")) {
- $this.tooltip("hide");
- }
-
- this.value = $this.val().trim();
- sd.slider("setValue", this.value);
- }
- }
- })
- .siblings("[data-provide=slider]").each(function () {
- $("#input-storagepools-create-refreservation").val(this.value);
- $(this).slider().on("change", function (element) {
- $("#input-storagepools-create-refreservation").val(element.value.newValue);
- });
- });
-
- $("#input-storagepools-create-refreservation").on("change textInput input", function (element) {
- if ($(this).val() > 20) { //Force reset to maximum allowed value
- $(this).val(20);
- } else if ($(this).val() < 0) { //Force reset to minimum allowed value
- $(this).val(0);
- }
-
- if ($.isNumeric($(this).val())) {
- $("#slider-storagepools-create-refreservation").slider("setValue", $(this).val());
- }
- });
-
- $("#switch-storagepools-create-disks-wwn input").on("click", function () {
- $("#btnspan-storagepools-create-disks-identifier").text("Block Device");
- $("#dropdown-storagepools-create-disks-identifier li").siblings().removeClass("active");
- $("#dropdown-storagepools-create-disks-identifier li[value='blockdevice']").addClass("active");
- $("#helpblock-storagepools-create-disks-identifierwarning").addClass("hidden").text("");
- ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepools-create-disks-identifierwarningzfs").addClass("hidden");` : ``) + `
-
- let disk = {
- identifier: ($(this).prop("checked") ? "wwn" : "blockdevice"),
- identifiertext: ($(this).prop("checked") ? "WWN" : "Block Device")
- };
-
- if ($(this).prop("checked")) {
- $("#controllabel-storagepools-create-disks-identifier").addClass("hidden");
- $("#validationwrapper-storagepools-create-disks-identifier").addClass("hidden");
- } else {
- $("#controllabel-storagepools-create-disks-identifier").removeClass("hidden");
- $("#validationwrapper-storagepools-create-disks-identifier").removeClass("hidden");
- }
-
- $("#listgroup-storagepools-create-disks input[name='checkbox-storagepools-create-disks']").map(function () {
- if ($(this).attr("data-disk-id-" + disk.identifier)) {
- $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
- } else {
- $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
- $("#helpblock-storagepools-create-disks-identifierwarning").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
- }
- });
- });
-
- $("#btn-storagepools-create-apply").on("click", function () {
- $("#spinner-storagepools-create").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let disks = {
- id: []
- };
- let filesystem = {
- compression: "",
- dedup: "off",
- recordsize: "131072",
- refreservationpercent: 0,
- selinux: false
- };
- let pool = {
- ashift: 0,
- autoexpand: "",
- autoreplace: "",
- autotrim: "",
- force: false,
- name: "",
- virtualdevice: ""
- }
- let validation = {
- disks: false,
- name: false
- };
-
- $("#listgroup-storagepools-create-disks input[name='checkbox-storagepools-create-disks']:checked").map(function () {
- disks.id.push($(this).attr("data-disk-name"));
- });
-
- if ($("#input-storagepools-create-name").val().length == 0) {
- $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
-
- validation.name = false;
- } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepools-create-name").val()) == false) {
- $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
-
- validation.name = false;
- } else if (/^[0-9]/.test($("#input-storagepools-create-name").val())) {
- $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with numerical characters.");
-
- validation.name = false;
- } else if (/^[.]/.test($("#input-storagepools-create-name").val())) {
- $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
-
- validation.name = false;
- } else if (/^[_]/.test($("#input-storagepools-create-name").val())) {
- $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
-
- validation.name = false;
- } else if (/^[-]/.test($("#input-storagepools-create-name").val())) {
- $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
-
- validation.name = false;
- } else if (/^[:]/.test($("#input-storagepools-create-name").val())) {
- $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
-
- validation.name = false;
- } else if (/^[ ]/.test($("#input-storagepools-create-name").val())) {
- $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
-
- validation.name = false;
- } else if (/[ ]$/.test($("#input-storagepools-create-name").val())) {
- $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
-
- validation.name = false;
- } else if (/^c[0-9]|^log|^mirror|^raidz|^raidz1|^raidz2|^raidz3|^spare/.test($("#input-storagepools-create-name").val())) {
- $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with a reserved name.");
-
- validation.name = false;
- } else {
- $("#validationwrapper-storagepools-create-name").removeClass("has-error");
- $("#helpblock-storagepools-create-name").addClass("hidden").text("");
-
- validation.name = true;
- }
- if (disks.id.length < 1 && $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "disk") {
- $("#helpblock-storagepools-create-disks").removeClass("hidden").text("One or more disks is needed for Disk.");
-
- validation.disks = false;
- } else if (disks.id.length < 2 && $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "mirror") {
- $("#helpblock-storagepools-create-disks").removeClass("hidden").text("Two or more disks is needed for Mirror.");
-
- validation.disks = false;
- } else if (disks.id.length < 2 && $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "raidz1") {
- $("#helpblock-storagepools-create-disks").removeClass("hidden").text("Two or more disks is needed for RaidZ1.");
-
- validation.disks = false;
- } else if (disks.id.length < 3 && $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "raidz2") {
- $("#helpblock-storagepools-create-disks").removeClass("hidden").text("Three or more disks is needed for RaidZ2.");
-
- validation.disks = false;
- } else if (disks.id.length < 4 && $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "raidz3") {
- $("#helpblock-storagepools-create-disks").removeClass("hidden").text("Four or more disks is needed for RaidZ3.");
-
- validation.disks = false;
- } else {
- $("#validationwrapper-storagepools-create-disks").removeClass("has-error");
- $("#helpblock-storagepools-create-disks").removeClass("hidden").text("");
-
- validation.disks = true;
- }
-
- if (!validation.name || !validation.disks) {
- if (!validation.name) {
- $("#validationwrapper-storagepools-create-name").addClass("has-error");
- $("#input-storagepools-create-name").focus();
- }
- if (!validation.disks) {
- $("#validationwrapper-storagepools-create-disks").addClass("has-error");
- }
-
- $("#spinner-storagepools-create").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.name && validation.disks) {
- filesystem.compression = ($("#switch-storagepools-create-compression input").prop("checked") ? "lz4" : "off");
- filesystem.dedup = $("#btnspan-storagepools-create-dedup").attr("data-field-value");
- filesystem.recordsize = $("#btnspan-storagepools-create-recordsize").attr("data-field-value");
- filesystem.refreservationpercent = ($("#input-storagepools-create-refreservation").val() != "0" ? $("#input-storagepools-create-refreservation").val() : "0");
- filesystem.selinux = $("#switch-storagepools-create-selinux input").prop("checked");
-
- pool.ashift = $("#btnspan-storagepools-create-ashift").attr("data-field-value");
- pool.autoexpand = ($("#switch-storagepools-create-autoexpand input").prop("checked") ? "on" : "off");
- pool.autoreplace = ($("#switch-storagepools-create-autoreplace input").prop("checked") ? "on" : "off");
- pool.autotrim = ($("#switch-storagepools-create-autotrim input").prop("checked") ? "on" : "off");
- pool.force = $("#switch-storagepools-create-force input").prop("checked");
- pool.name = $("#input-storagepools-create-name").val();
- pool.virtualdevice = ($("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "disk" ? "" : $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value"));
-
- FnStoragePoolCreate({ name: pool.name, ashift: pool.ashift, autoexpand: pool.autoexpand, autoreplace: pool.autoreplace, autotrim: pool.autotrim, force: pool.force, virtualdevice: pool.virtualdevice }, { compression: filesystem.compression, dedup: filesystem.dedup, recordsize: filesystem.recordsize, refreservationpercent: filesystem.refreservationpercent, selinux: filesystem.selinux }, { id: disks.id });
- }
- });
-
- $("#dropdown-storagepools-create-virtualdevice").on("click", "li a", function () {
- $("#btnspan-storagepools-create-virtualdevice").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepools-create-ashift").on("click", "li a", function () {
- $("#btnspan-storagepools-create-ashift").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepools-create-disks-identifier").on("click", "li a", function () {
- $("#btnspan-storagepools-create-disks-identifier").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
-
- $("#helpblock-storagepools-create-disks-identifierwarning").addClass("hidden").text("");
- ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepools-create-disks-identifierwarningzfs").addClass("hidden");` : ``) + `
-
- let disk = {
- identifier: $(this).parent().attr("value"),
- identifiertext: $(this).parent().text()
- };
-
- $("#listgroup-storagepools-create-disks input[name='checkbox-storagepools-create-disks']").map(function () {
- if ($(this).attr("data-disk-id-" + disk.identifier)) {
- $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
- } else {
- $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
- $("#helpblock-storagepools-create-disks-identifierwarning").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
-
- ` + (zfsmanager.zfs.warnings.nvmevdev ? `
- if (disk.identifier == "vdev" && /^nvme/gi.test($(this).attr("data-disk-id-blockdevice"))) {
- $("#helpblock-storagepools-create-disks-identifierwarningzfs").removeClass("hidden");
- }
- ` : ``) + `
- }
- });
- });
-
- $("#dropdown-storagepools-create-dedup").on("click", "li a", function () {
- $("#btnspan-storagepools-create-dedup").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepools-create-recordsize").on("click", "li a", function () {
- $("#btnspan-storagepools-create-recordsize").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStoragePoolsImport() {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepools-import").on("click", function () {
- FnModalStoragePoolsImportContent({ id: $("#modal-storagepools-import") });
- FnStoragePoolsImportableGet({ destroyed: false });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepools").append(modal.window);
-}
-
-function FnModalStoragePoolsImportContent(modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepools-import-destroyed input").on("click", function () {
- $("#helpblock-storagepools-import-storagepools").addClass("hidden").text("");
- $("#helpblock-storagepools-import-storagepools-warning").addClass("hidden").text("");
-
- FnStoragePoolsImportableGet({ destroyed: ($(this).prop("checked") ? true : false) });
- });
-
- $("#switch-storagepools-import-rename input").on("click", function () {
- if ($(this).prop("checked")) {
- $("#controllabel-storagepools-import-namenew").removeClass("hidden");
- $("#validationwrapper-storagepools-import-namenew").removeClass("hidden");
- $("#input-storagepools-import-namenew").focus();
- } else {
- $("#controllabel-storagepools-import-namenew").addClass("hidden");
- $("#validationwrapper-storagepools-import-namenew").addClass("hidden");
- $("#validationwrapper-storagepools-import-namenew").removeClass("has-error");
- $("#helpblock-storagepools-import-namenew").removeClass("has-error").addClass("hidden").text("");
- $("#input-storagepools-import-namenew").val("");
- }
- });
-
- $("#switch-storagepools-import-selinux input").on("click", function () {
- if ($(this).prop("checked") && $("#switch-storagepools-import-readonly input").prop("checked")) {
- $("#switch-storagepools-import-readonly input").click();
- }
- });
-
- $("#switch-storagepools-import-readonly input").on("click", function () {
- if ($(this).prop("checked") && $("#switch-storagepools-import-selinux input").prop("checked")) {
- $("#switch-storagepools-import-selinux input").click();
- }
- });
-
- $("#btn-storagepools-import-apply").on("click", function () {
- $("#spinner-storagepools-import").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let disks = {
- id: {
- blockdevice: true,
- disk: false,
- path: false,
- vdev: false
- },
- identifier: ""
- };
-
- let filesystem = {
- mount: true,
- selinux: true
- };
-
- let pool = {
- altroot: "",
- name: [],
- namenew: "",
- guid: [],
- destroyed: false,
- force: false,
- ignoremissinglog: false,
- readonly: false,
- recoverymode: false
- };
-
- let validation = {
- altroot: false,
- name: false,
- namenew: false,
- storagepools: false
- };
-
- $("#listgroup-storagepools-import-storagepools input[name='checkbox-storagepools-import-storagepools']:checked").map(function () {
- pool.guid.push($(this).attr("data-pool-import-guid"));
- pool.name.push($(this).attr("data-pool-import-name"));
-
- disks.id.disk = ($(this).attr("data-pool-import-id-disk") == "true" ? true : false);
- disks.id.path = ($(this).attr("data-pool-import-id-path") == "true" ? true : false);
- disks.id.vdev = ($(this).attr("data-pool-import-id-vdev") == "true" ? true : false);
- });
-
- if (pool.guid.length != 1) {
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("One storage pool is needed for import.");
-
- validation.storagepools = false;
- } else {
- $("#validationwrapper-storagepools-import-storagepools").removeClass("has-error");
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("");
-
- validation.storagepools = true;
-
- pool.guid = pool.guid.join(" ");
- pool.name = pool.name.join(" ");
- }
-
- if (validation.storagepools && !$("#switch-storagepools-import-rename input").prop("checked")) {
- if (pool.name.length == 0) {
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not be empty. New name is needed.");
-
- validation.name = false;
- } else if (/^[a-zA-Z0-9-_.: ]*$/.test(pool.name) == false) {
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name contains invalid characters. New name is needed.");
-
- validation.name = false;
- } else if (/^[0-9]/.test(pool.name)) {
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with numerical characters. New name is needed.");
-
- validation.name = false;
- } else if (/^[.]/.test(pool.name)) {
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with a period (.). New name is needed.");
-
- validation.name = false;
- } else if (/^[_]/.test(pool.name)) {
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with an underscore (_). New name is needed.");
-
- validation.name = false;
- } else if (/^[-]/.test(pool.name)) {
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with a hypen (-). New name is needed.");
-
- validation.name = false;
- } else if (/^[:]/.test(pool.name)) {
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with an colon (:). New name is needed.");
-
- validation.name = false;
- } else if (/^[ ]/.test(pool.name)) {
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with whitespace ( ). New name is needed.");
-
- validation.name = false;
- } else if (/[ ]$/.test(pool.name)) {
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not end with whitespace ( ). New name is needed.");
-
- validation.name = false;
- } else if (/^c[0-9]|^log|^mirror|^raidz|^raidz1|^raidz2|^raidz3|^spare/.test(pool.name)) {
- $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with a reserved name. New name is needed.");
-
- validation.name = false;
- } else {
- validation.name = true;
- }
-
- if (!validation.name && !$("#switch-storagepools-import-rename input").prop("checked")) {
- $("#switch-storagepools-import-rename input").click();
- $("#input-storagepools-import-namenew").focus();
- }
- }
-
- if (validation.storagepools && !validation.name && $("#switch-storagepools-import-rename input").prop("checked") && $("#input-storagepools-import-namenew").val().length >= 2) {
- validation.name = true;
- }
-
- if ($("#switch-storagepools-import-rename input").prop("checked")) {
- if ($("#input-storagepools-import-namenew").val().length == 0) {
- $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not be empty.");
-
- validation.namenew = false;
- } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepools-import-namenew").val()) == false) {
- $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name contains invalid characters.");
-
- validation.namenew = false;
- } else if (/^[0-9]/.test($("#input-storagepools-import-namenew").val())) {
- $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with numerical characters.");
-
- validation.namenew = false;
- } else if (/^[.]/.test($("#input-storagepools-import-namenew").val())) {
- $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with a period (.).");
-
- validation.namenew = false;
- } else if (/^[_]/.test($("#input-storagepools-import-namenew").val())) {
- $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with an underscore (_).");
-
- validation.namenew = false;
- } else if (/^[-]/.test($("#input-storagepools-import-namenew").val())) {
- $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with a hypen (-).");
-
- validation.namenew = false;
- } else if (/^[:]/.test($("#input-storagepools-import-namenew").val())) {
- $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with an colon (:).");
-
- validation.namenew = false;
- } else if (/^[ ]/.test($("#input-storagepools-import-namenew").val())) {
- $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with whitespace ( ).");
-
- validation.namenew = false;
- } else if (/[ ]$/.test($("#input-storagepools-import-namenew").val())) {
- $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not end with whitespace ( ).");
-
- validation.namenew = false;
- } else if (/^c[0-9]|^log|^mirror|^raidz|^raidz1|^raidz2|^raidz3|^spare/.test($("#input-storagepools-import-namenew").val())) {
- $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with a reserved name.");
-
- validation.namenew = false;
- } else {
- $("#validationwrapper-storagepools-import-namenew").removeClass("has-error");
- $("#helpblock-storagepools-import-namenew").addClass("hidden").text("");
-
- validation.namenew = true;
- }
- } else {
- $("#validationwrapper-storagepools-import-namenew").removeClass("has-error");
- $("#helpblock-storagepools-import-namenew").removeClass("has-error").addClass("hidden").text("");
-
- validation.namenew = true;
- }
-
- if (/^[a-zA-Z0-9-_.:/ ]*$/.test($("#input-storagepools-import-altroot").val()) == false) {
- $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root contains invalid characters.");
-
- validation.altroot = false;
- } else if ($("#input-storagepools-import-altroot").val() && /^[/]/.test($("#input-storagepools-import-altroot").val()) == false) {
- $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root is an absolute path and must begin with a forward slash (/).");
-
- validation.altroot = false;
- } else if (/^[.]/.test($("#input-storagepools-import-altroot").val())) {
- $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not begin with a period (.).");
-
- validation.altroot = false;
- } else if (/[.]$/.test($("#input-storagepools-import-altroot").val())) {
- $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not end with a period (.).");
-
- validation.altroot = false;
- } else if (/[/][.][/]/g.test($("#input-storagepools-import-altroot").val())) {
- $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not contain a period as a sub directory (/./).");
-
- validation.altroot = false;
- } else if (/[/][.][.][/]/g.test($("#input-storagepools-import-altroot").val())) {
- $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not contain a double period as a sub directory (/../).");
-
- validation.altroot = false;
- } else if (/[/][/]/g.test($("#input-storagepools-import-altroot").val())) {
- $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not contain double forward slashes (//).");
-
- validation.altroot = false;
- } else if (/[.][.]/g.test($("#input-storagepools-import-altroot").val())) {
- $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not contain a double period (..).");
-
- validation.altroot = false;
- } else if (/^[ ]/.test($("#input-storagepools-import-altroot").val())) {
- $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not begin with whitespace ( ).");
-
- validation.altroot = false;
- } else if (/[ ]$/.test($("#input-storagepools-import-altroot").val())) {
- $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not end with whitespace ( ).");
-
- validation.altroot = false;
- } else {
- $("#validationwrapper-storagepools-import-altroot").removeClass("has-error");
- $("#helpblock-storagepools-import-altroot").addClass("hidden").text("");
-
- validation.altroot = true;
- }
-
- if (!validation.altroot || !validation.name || !validation.namenew || !validation.storagepools) {
- if (!validation.name || !validation.storagepools) {
- $("#validationwrapper-storagepools-import-storagepools").addClass("has-error");
- }
- if (!validation.namenew) {
- $("#validationwrapper-storagepools-import-namenew").addClass("has-error");
- $("#input-storagepools-import-namenew").focus();
- }
- if (!validation.altroot) {
- $("#validationwrapper-storagepools-import-altroot").addClass("has-error");
- $("#input-storagepools-import-altroot").focus();
- }
-
- $("#spinner-storagepools-import").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.altroot && validation.name && validation.namenew && validation.storagepools) {
- disks.identifier = $("#btnspan-storagepools-import-disks-identifier").attr("data-field-value");
-
- filesystem.mount = $("#switch-storagepools-import-mount input").prop("checked");
- filesystem.selinux = $("#switch-storagepools-import-selinux input").prop("checked");
-
- pool.altroot = $("#input-storagepools-import-altroot").val();
- pool.destroyed = $("#switch-storagepools-import-destroyed input").prop("checked");
- pool.force = $("#switch-storagepools-import-force input").prop("checked");
- pool.ignoremissinglog = $("#switch-storagepools-import-ignoremissinglog input").prop("checked");
- pool.namenew = ($("#switch-storagepools-import-rename input").prop("checked") ? $("#input-storagepools-import-namenew").val() : "");
- pool.readonly = $("#switch-storagepools-import-readonly input").prop("checked");
- pool.recoverymode = $("#switch-storagepools-import-recoverymode input").prop("checked");
-
- FnStoragePoolImport({ name: pool.name, altroot: pool.altroot, destroyed: pool.destroyed, force: pool.force, guid: pool.guid, ignoremissinglog: pool.ignoremissinglog, namenew: pool.namenew, readonly: pool.readonly, recoverymode: pool.recoverymode }, { mount: filesystem.mount, selinux: filesystem.selinux }, { id: { blockdevice: disks.id.blockdevice, disk: disks.id.disk, path: disks.id.path, vdev: disks.id.vdev }, identifier: disks.identifier });
- }
- });
-
- $("#dropdown-storagepools-import-disks-identifier").on("click", "li a", function () {
- $("#btnspan-storagepools-import-disks-identifier").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-//#endregion
-
-//#region Modal Storage Pool
-
-function FnModalStoragePoolConfigure(pool = { name, id, boot: false, guid, readonly: false, root: false }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-configure-` + pool.id + `").on("click", function () {
- FnModalStoragePoolConfigureContent({ name: "` + pool.name + `", id: "` + pool.id + `", guid: "` + pool.guid + `", readonly: ` + pool.readonly + ` }, { id: $("#modal-storagepool-configure-` + pool.id + `") });
- FnStoragePoolConfigurationGet({ name: "` + pool.name + `", id: "` + pool.id + `", boot: ` + pool.boot + `, root: ` + pool.root + ` }, { name: "storagepool-configure", id: "` + pool.id + `" });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-" + pool.id).append(modal.window);
-}
-
-function FnModalStoragePoolConfigureContent(pool = { name, id, guid, readonly: false }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-configure-multihost-` + pool.id + ` input").on("click", function () {
- FnSystemHostIdGet({ name: "storagepool-configure", id: "` + pool.id + `" });
-
- if (!$(this).prop("checked")) {
- $("#controllabel-storagepool-configure-hostid-` + pool.id + `").addClass("hidden");
- $("#validationwrapper-storagepool-configure-hostid-` + pool.id + `").addClass("hidden");
- }
- });
-
- $("#btn-storagepool-configure-apply-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-configure-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let modal = {
- id: ""
- };
- let pool = {
- ashift: 0,
- autoexpand: "",
- autoreplace: "",
- autotrim: "",
- comment: "",
- delegation: "",
- failmode: "",
- listsnapshots: "",
- multihost: ""
- };
- let system = {
- hostid: false
- };
- let validation = {
- comment: false
- };
-
- if ($("#input-storagepool-configure-comment-` + pool.id + `").val().length > 32) {
- $("#helpblock-storagepool-configure-comment-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Comment can not be longer than 32 characters.");
-
- validation.comment = false;
- } else if (/^[ -~]*$/.test($("#input-storagepool-configure-comment-` + pool.id + `").val()) == false) {
- $("#helpblock-storagepool-configure-comment-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Comment contains invalid characters.");
-
- validation.comment = false;
- } else {
- $("#validationwrapper-storagepool-configure-comment-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-configure-comment-` + pool.id + `").addClass("hidden").text("");
-
- validation.comment = true;
- }
-
- if (!validation.comment) {
- $("#validationwrapper-storagepool-configure-comment-` + pool.id + `").addClass("has-error");
- $("#input-storagepool-configure-comment-` + pool.id + `").focus();
-
- $("#spinner-storagepool-configure-` + pool.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.comment) {
- modal.id = $("#modal-storagepool-configure-` + pool.id + `");
-
- pool.ashift = ($("#btnspan-storagepool-configure-ashift-` + pool.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-configure-ashift-` + pool.id + `").attr("data-field-value-new") : null);
- pool.autoexpand = ($("#switch-storagepool-configure-autoexpand-` + pool.id + ` input").prop("checked") ? "on" : "off");
- pool.autoreplace = ($("#switch-storagepool-configure-autoreplace-` + pool.id + ` input").prop("checked") ? "on" : "off");
- pool.autotrim = ($("#switch-storagepool-configure-autotrim-` + pool.id + ` input").prop("checked") ? "on" : "off");
- pool.comment = $("#input-storagepool-configure-comment-` + pool.id + `").val();
- pool.delegation = ($("#switch-storagepool-configure-delegation-` + pool.id + ` input").prop("checked") ? "on" : "off");
- pool.failmode = ($("#btnspan-storagepool-configure-failmode-` + pool.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-configure-failmode-` + pool.id + `").attr("data-field-value-new") : null);
- pool.listsnapshots = ($("#switch-storagepool-configure-listsnapshots-` + pool.id + ` input").prop("checked") ? "on" : "off");
- pool.multihost = ($("#switch-storagepool-configure-multihost-` + pool.id + ` input").prop("checked") ? "on" : "off");
-
- if (!$("#validationwrapper-storagepool-configure-hostid-` + pool.id + `").hasClass("hidden")) {
- system.hostid = $("#btnspan-storagepool-configure-hostid-` + pool.id + `").attr("data-field-value");
- } else {
- if ($("#btnspan-storagepool-configure-hostid-` + pool.id + `").attr("data-field-value") == "missing") { //Host ID is missing - Generate Host ID before disabling multihost property to avoid error
- system.hostid = "libc";
- }
- }
-
- //Set values to null if unchanged, so that they are skipped in the configure function
- if (pool.ashift == $("#btnspan-storagepool-configure-ashift-` + pool.id + `").attr("data-field-value")) {
- pool.ashift = null;
- }
- if (pool.autoexpand == $("#switch-storagepool-configure-autoexpand-` + pool.id + `").attr("data-field-value")) {
- pool.autoexpand = null;
- }
- if (pool.autoreplace == $("#switch-storagepool-configure-autoreplace-` + pool.id + `").attr("data-field-value")) {
- pool.autoreplace = null;
- }
- if (pool.autotrim == $("#switch-storagepool-configure-autotrim-` + pool.id + `").attr("data-field-value")) {
- pool.autotrim = null;
- }
- if (pool.comment == $("#input-storagepool-configure-comment-` + pool.id + `").attr("data-field-value")) {
- pool.comment = null;
- } else if (pool.comment != $("#input-storagepool-configure-comment-` + pool.id + `").attr("data-field-value") && !pool.comment) {
- pool.comment = "$empty";
- }
- if (pool.failmode == $("#btnspan-storagepool-configure-failmode-` + pool.id + `").attr("data-field-value")) {
- pool.failmode = null;
- }
- if (pool.delegation == $("#switch-storagepool-configure-delegation-` + pool.id + `").attr("data-field-value")) {
- pool.delegation = null;
- }
- if (pool.listsnapshots == $("#switch-storagepool-configure-listsnapshots-` + pool.id + `").attr("data-field-value")) {
- pool.listsnapshots = null;
- }
- if (pool.multihost == $("#switch-storagepool-configure-multihost-` + pool.id + `").attr("data-field-value")) {
- pool.multihost = null;
- }
-
- FnStoragePoolConfigure({ name: "` + pool.name + `", id: "` + pool.id + `", ashift: pool.ashift, autoexpand: pool.autoexpand, autoreplace: pool.autoreplace, autotrim: pool.autotrim, comment: pool.comment, delegation: pool.delegation, failmode: pool.failmode, listsnapshots: pool.listsnapshots, multihost: pool.multihost, readonly: ` + pool.readonly + ` }, { hostid: system.hostid }, { id: modal.id });
- }
- });
-
- $("#dropdown-storagepool-configure-ashift-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-configure-ashift-` + pool.id + `").text($(this).text()).attr("data-field-value-new", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-configure-failmode-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-configure-failmode-` + pool.id + `").text($(this).text()).attr("data-field-value-new", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-configure-hostid-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-configure-hostid-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStoragePoolConfigureFeatures(pool = { name, id, boot: false, readonly: false }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-configure-features-` + pool.id + `").on("click", function () {
- FnModalStoragePoolConfigureFeaturesContent({ name: "` + pool.name + `", id: "` + pool.id + `", boot: ` + pool.boot + `, readonly: ` + pool.readonly + ` }, { id: $("#modal-storagepool-configure-features-` + pool.id + `") });
- FnStoragePoolConfigurationFeaturesGet({ name: "` + pool.name + `", id: "` + pool.id + `", boot: ` + pool.boot + ` }, { name: "storagepool-configure-features", id: "` + pool.id + `" });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-" + pool.id).append(modal.window);
-}
-
-function FnModalStoragePoolConfigureFeaturesContent(pool = { name, id, boot: false, readonly: false }, modal = { id }) {
- pool.version = $("#tr-storagepool-" + pool.id).attr("data-pool-version");
-
- modal.content = `
-
-
-
-
-
Pool: ` + pool.name + `
- ` + (pool.boot ? FnDisplayInlineAlert({ status: "danger", title: "Changes to the boot storage pool may cause an unbootable system.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
- ` + FnDisplayInlineAlert({ status: ($.isNumeric(pool.version) ? "danger" : "warning"), title: ($.isNumeric(pool.version) ? "The storage pool will no longer be accessible on software that does not support feature flags." : "Once a feature is enabled the pool may become incompatible with software that does not support the feature.") + " Features can not be disabled once they have been enabled.", description: null }, { name: "storagepool-configure-features-compatibility", id: pool.id, hidden: true }) + `
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("[id^=switch-storagepool-configure-features-][id$='-` + pool.id + `'] input").on("click", function () {
- if ($(this).prop("checked") && $(this).parent().attr("data-field-value") == "disabled") {
- $("#alert-storagepool-configure-features-compatibility-` + pool.id + `").removeClass("hidden");
- }
-
- FnModalStoragePoolConfigureFeaturesDependencies({ name: "` + pool.name + `", id: "` + pool.id + `" }, { switch: { id: $(this) } });
- });
-
- $("#btn-storagepool-configure-features-apply-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-configure-features-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let modal = {
- id: ""
- };
-
- let pool = {
- feature: {
- allocation_classes: ($("#switch-storagepool-configure-features-allocation_classes-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-allocation_classes-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- async_destroy: ($("#switch-storagepool-configure-features-async_destroy-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-async_destroy-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- bookmark_v2: ($("#switch-storagepool-configure-features-bookmark_v2-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-bookmark_v2-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- bookmarks: ($("#switch-storagepool-configure-features-bookmarks-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-bookmarks-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- device_removal: ($("#switch-storagepool-configure-features-device_removal-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-device_removal-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- edonr: ($("#switch-storagepool-configure-features-edonr-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-edonr-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- embedded_data: ($("#switch-storagepool-configure-features-embedded_data-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-embedded_data-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- empty_bpobj: ($("#switch-storagepool-configure-features-empty_bpobj-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-empty_bpobj-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- enabled_txg: ($("#switch-storagepool-configure-features-enabled_txg-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-enabled_txg-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- encryption: ($("#switch-storagepool-configure-features-encryption-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-encryption-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- extensible_dataset: ($("#switch-storagepool-configure-features-extensible_dataset-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- filesystem_limits: ($("#switch-storagepool-configure-features-filesystem_limits-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-filesystem_limits-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- hole_birth: ($("#switch-storagepool-configure-features-hole_birth-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-hole_birth-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- large_blocks: ($("#switch-storagepool-configure-features-large_blocks-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-large_blocks-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- large_dnode: ($("#switch-storagepool-configure-features-large_dnode-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-large_dnode-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- lz4_compress: ($("#switch-storagepool-configure-features-lz4_compress-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-lz4_compress-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- multi_vdev_crash_dump: ($("#switch-storagepool-configure-features-multi_vdev_crash_dump-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-multi_vdev_crash_dump-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- obsolete_counts: ($("#switch-storagepool-configure-features-obsolete_counts-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-obsolete_counts-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- project_quota: ($("#switch-storagepool-configure-features-project_quota-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-project_quota-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- resilver_defer: ($("#switch-storagepool-configure-features-resilver_defer-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-resilver_defer-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- sha512: ($("#switch-storagepool-configure-features-sha512-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-sha512-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- skein: ($("#switch-storagepool-configure-features-skein-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-skein-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- spacemap_histogram: ($("#switch-storagepool-configure-features-spacemap_histogram-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-spacemap_histogram-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- spacemap_v2: ($("#switch-storagepool-configure-features-spacemap_v2-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-spacemap_v2-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- userobj_accounting: ($("#switch-storagepool-configure-features-userobj_accounting-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-userobj_accounting-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
- zpool_checkpoint: ($("#switch-storagepool-configure-features-zpool_checkpoint-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-zpool_checkpoint-` + pool.id + ` input").prop("disabled") ? "enabled" : null)
- }
- };
-
- FnStoragePoolConfigureFeatures({ name: "` + pool.name + `", id: "` + pool.id + `", feature: { allocation_classes: pool.feature.allocation_classes, async_destroy: pool.feature.async_destroy, bookmark_v2: pool.feature.bookmark_v2, bookmarks: pool.feature.bookmarks, device_removal: pool.feature.device_removal, edonr: pool.feature.edonr, embedded_data: pool.feature.embedded_data, empty_bpobj: pool.feature.empty_bpobj, enabled_txg: pool.feature.enabled_txg, encryption: pool.feature.encryption, extensible_dataset: pool.feature.extensible_dataset, filesystem_limits: pool.feature.filesystem_limits, hole_birth: pool.feature.hole_birth, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, multi_vdev_crash_dump: pool.feature.multi_vdev_crash_dump, obsolete_counts: pool.feature.obsolete_counts, project_quota: pool.feature.project_quota, resilver_defer: pool.feature.resilver_defer, sha512: pool.feature.sha512, skein: pool.feature.skein, spacemap_histogram: pool.feature.spacemap_histogram, spacemap_v2: pool.feature.spacemap_v2, userobj_accounting: pool.feature.userobj_accounting, zpool_checkpoint: pool.feature.zpool_checkpoint }, readonly: ` + pool.readonly + ` }, { id: $("#modal-storagepool-configure-features-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStoragePoolConfigureFeaturesDependencies(pool = { name, id }, modal = { switch: { id } }) {
- if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-bookmarks-" + pool.id) {
- if ($("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
- }
- } else {
- if ($("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").click();
- }
- if ($("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-encryption-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-bookmark_v2-" + pool.id) {
- if ($("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").click();
- }
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
- }
- } else {
- if ($("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-encryption-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-device_removal-" + pool.id) {
- if (!$("#switch-storagepool-configure-features-device_removal-" + pool.id + " input").prop("checked")) {
- if ($("#switch-storagepool-configure-features-obsolete_counts-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-obsolete_counts-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-obsolete_counts-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-edonr-" + pool.id) {
- if ($("#switch-storagepool-configure-features-edonr-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-enabled_txg-" + pool.id) {
- if (!$("#switch-storagepool-configure-features-enabled_txg-" + pool.id + " input").prop("checked")) {
- if ($("#switch-storagepool-configure-features-hole_birth-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-hole_birth-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-hole_birth-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-encryption-" + pool.id) {
- if ($("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").click();
- }
- if (!$("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").click();
- }
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-extensible_dataset-" + pool.id) {
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked")) {
- if ($("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").click();
- }
- if ($("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").click();
- }
- if ($("#switch-storagepool-configure-features-edonr-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-edonr-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-edonr-" + pool.id + " input").click();
- }
- if ($("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-encryption-" + pool.id + " input").click();
- }
- if ($("#switch-storagepool-configure-features-filesystem_limits-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-filesystem_limits-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-filesystem_limits-" + pool.id + " input").click();
- }
- if ($("#switch-storagepool-configure-features-large_blocks-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-large_blocks-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-large_blocks-" + pool.id + " input").click();
- }
- if ($("#switch-storagepool-configure-features-large_dnode-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-large_dnode-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-large_dnode-" + pool.id + " input").click();
- }
- if ($("#switch-storagepool-configure-features-project_quota-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-project_quota-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-project_quota-" + pool.id + " input").click();
- }
- if ($("#switch-storagepool-configure-features-sha512-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-sha512-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-sha512-" + pool.id + " input").click();
- }
- if ($("#switch-storagepool-configure-features-skein-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-skein-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-skein-" + pool.id + " input").click();
- }
- if ($("#switch-storagepool-configure-features-userobj_accounting-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-userobj_accounting-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-userobj_accounting-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-filesystem_limits-" + pool.id) {
- if ($("#switch-storagepool-configure-features-filesystem_limits-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-hole_birth-" + pool.id) {
- if ($("#switch-storagepool-configure-features-hole_birth-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-enabled_txg-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-enabled_txg-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-enabled_txg-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-large_blocks-" + pool.id) {
- if ($("#switch-storagepool-configure-features-large_blocks-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-large_dnode-" + pool.id) {
- if ($("#switch-storagepool-configure-features-large_dnode-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-obsolete_counts-" + pool.id) {
- if ($("#switch-storagepool-configure-features-obsolete_counts-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-device_removal-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-device_removal-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-device_removal-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-project_quota-" + pool.id) {
- if ($("#switch-storagepool-configure-features-project_quota-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-sha512-" + pool.id) {
- if ($("#switch-storagepool-configure-features-sha512-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-skein-" + pool.id) {
- if ($("#switch-storagepool-configure-features-skein-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
- }
- }
- } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-userobj_accounting-" + pool.id) {
- if ($("#switch-storagepool-configure-features-userobj_accounting-" + pool.id + " input").prop("checked")) {
- if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
- $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
- }
- }
- }
-}
-
-function FnModalStoragePoolDestroy(pool = { name, id, altroot: false }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-destroy-` + pool.id + `").on("click", function () {
- FnModalStoragePoolDestroyContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { id: $("#modal-storagepool-destroy-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-" + pool.id).append(modal.window);
-}
-
-function FnModalStoragePoolDestroyContent(pool = { name, id, altroot: false }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to destroy storage pool: ` + pool.name + ` ?
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-destroy-apply-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-destroy-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let pool = {
- force: $("#switch-storagepool-destroy-force-` + pool.id + ` input").prop("checked"),
- labelclear: $("#switch-storagepool-destroy-labelclear-` + pool.id + ` input").prop("checked")
- };
- let samba = {
- restart: $("#switch-storagepool-destroy-samba-restart-` + pool.id + ` input").prop("checked")
- };
-
- FnStoragePoolDestroy({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, force: pool.force, labelclear: pool.labelclear }, { restart: samba.restart });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStoragePoolExport(pool = { name, id, altroot: false, readonly: false }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-export-` + pool.id + `").on("click", function () {
- FnModalStoragePoolExportContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { id: $("#modal-storagepool-export-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-" + pool.id).append(modal.window);
-}
-
-function FnModalStoragePoolExportContent(pool = { name, id, altroot: false, readonly: false }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to export storage pool: ` + pool.name + ` ?
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-export-apply-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-export-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let pool = {
- force: $("#switch-storagepool-export-force-` + pool.id + ` input").prop("checked")
- };
- let samba = {
- restart: $("#switch-storagepool-export-samba-restart-` + pool.id + ` input").prop("checked")
- };
-
- FnStoragePoolExport({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, force: pool.force, readonly: ` + pool.readonly + ` }, { restart: samba.restart });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-//#endregion
-
-//#region Modal File Systems
-
-function FnModalFileSystemsCreate(pool = { name, id, altroot: false, feature: { allocation_classes: true, edonr: true, encryption: true, large_blocks: true, large_dnode: true, lz4_compress: true, sha512: true, skein: true } }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystems-create-` + pool.id + `").on("click", function () {
- FnModalFileSystemsCreateContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, feature: { allocation_classes: ` + pool.feature.allocation_classes + `, edonr: ` + pool.feature.edonr + `, encryption: ` + pool.feature.encryption + `, large_blocks: ` + pool.feature.large_blocks + `, large_dnode: ` + pool.feature.large_dnode + `, lz4_compress: ` + pool.feature.lz4_compress + `, sha512: ` + pool.feature.sha512 + `, skein: ` + pool.feature.skein + ` } }, { id: $("#modal-storagepool-filesystems-create-` + pool.id + `") });
- FnFileSystemsNamesGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { existing: { name: null, clone: false, encryption: false, encryptionroot: null, origin: null}, override: true }, { dropdown: { id: $("#dropdown-storagepool-filesystems-create-parentfilesystem-` + pool.id + `"), selected: "` + pool.name + `" } });
- FnFileSystemConfigurationInheritedGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + pool.name + `" }, { name: "storagepool-filesystems-create", id: "` + pool.id + `" });
-
- $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val("0");
- $("#validationwrapper-storagepool-filesystems-create-quota-` + pool.id + ` .min-slider-handle").attr("tabindex", "15");
- setTimeout(function() {
- $("#input-storagepool-filesystems-create-name-` + pool.id + `").focus();
- }, 600);
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystems-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemsCreateContent(pool = { name, id, altroot: false, feature: { allocation_classes: true, edonr: true, encryption: true, large_blocks: true, large_dnode: true, lz4_compress: true, sha512: true, skein: true } }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#input-storagepool-filesystems-create-quota-` + pool.id + `").tooltip({ trigger: "manual" })
- .on("keyup", function (element) {
- let $this = $(this);
- let sd = $this.siblings("[data-provide=slider]").slider();
-
- if ($this.val().trim() && !$.isNumeric(this.value)) {
- this.value = sd.slider("getValue");
- }
- })
- .on("keypress blur", function (element) {
- if (element.which == 13 || element.type === "blur") {
- element.preventDefault();
-
- let $this = $(this);
- let sd = $this.siblings("[data-provide=slider]").slider();
- let max = sd.slider("getAttribute", "max");
- let min = sd.slider("getAttribute", "min");
-
- if (!$.isNumeric(this.value) || (this.value > max || this.value < min)) {
- let warningInfo = $.isNumeric(this.value) ? "Valid value should be between " + min + " and " + max : "Valid value should be number";
- $this.attr("data-original-title", warningInfo).tooltip("show").addClass("warning");
- this.value = sd.slider("getValue");
- setTimeout(function () {
- $this.tooltip("hide");
- }, 3000);
- } else {
- if ($this.is(".warning")) {
- $this.tooltip("hide");
- }
-
- this.value = $this.val().trim();
- sd.slider("setValue", this.value);
- }
- }
- })
- .siblings("[data-provide=slider]").each(function () {
- $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val(this.value);
- $(this).slider().on("change", function (element) {
- $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val(element.value.newValue);
- });
- });
-
- $("#input-storagepool-filesystems-create-quota-` + pool.id + `").on("change textInput input", function (element) {
- if ($(this).val() > 1000) { //Force reset to maximum allowed value
- $(this).val(1000);
- } else if ($(this).val() < 0) { //Force reset to minimum allowed value
- $(this).val(0);
- }
-
- if ($.isNumeric($(this).val())) {
- $("#slider-storagepool-filesystems-create-quota-` + pool.id + `").slider("setValue", $(this).val());
- }
- });
-
- $("#switch-storagepool-filesystems-create-encryption-` + pool.id + ` input").on("click", function () {
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
-
- if ($(this).prop("checked")) {
- $("#controllabel-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("hidden");
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("hidden");
- $("#controllabel-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("hidden");
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("hidden");
- $("#controllabel-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").removeClass("hidden");
- $("#validationwrapper-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").removeClass("hidden");
- } else {
- $("#controllabel-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("hidden");
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("hidden");
- $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val("");
- $("#controllabel-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").addClass("hidden");
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").addClass("hidden");
- $("#input-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").val("");
- $("#controllabel-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").addClass("hidden");
- $("#validationwrapper-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").addClass("hidden");
- }
- });
-
- $("#switch-storagepool-filesystems-create-sharenfs-` + pool.id + ` input").on("click", function () {
- $("#validationwrapper-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
-
- if ($(this).prop("checked")) {
- $("#controllabel-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").removeClass("hidden");
- $("#validationwrapper-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").removeClass("hidden");
-
- FnSystemNfsVersionGet({ alert: { id: $("#alert-storagepool-filesystems-create-sharenfs-options-` + pool.id + `") } });
- } else {
- $("#validationwrapper-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").addClass("hidden");
- $("#controllabel-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").addClass("hidden");
- }
- });
-
- $("#btn-storagepool-filesystems-create-apply-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-filesystems-create-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let filesystem = {
- name: "",
- id: "",
- atime: "",
- casesensitivity: "",
- cipher: "",
- compression: "",
- dedup: "",
- dnodesize: "",
- encryption: "",
- passphrase: "",
- quota: "none",
- readonly: "",
- recordsize: "",
- selinux: "",
- sharesmb: "",
- special_small_blocks: "",
- xattr: ""
- };
- let validation = {
- encryption: false,
- name: false,
- sharenfs: false
- };
-
- if ($("#input-storagepool-filesystems-create-name-` + pool.id + `").val().length == 0) {
- $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
-
- validation.name = false;
- } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val()) == false) {
- $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
-
- validation.name = false;
- } else if (/^[.]/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
-
- validation.name = false;
- } else if (/^[_]/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
-
- validation.name = false;
- } else if (/^[-]/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
-
- validation.name = false;
- } else if (/^[:]/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
-
- validation.name = false;
- } else if (/^[ ]/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
-
- validation.name = false;
- } else if (/[ ]$/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
-
- validation.name = false;
- } else {
- $("#validationwrapper-storagepool-filesystems-create-name-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("hidden").text("");
-
- validation.name = true;
- }
- if ($("#switch-storagepool-filesystems-create-encryption-` + pool.id + ` input").prop("checked")) {
- if ($("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val().length == 0 && $("#switch-storagepool-filesystems-create-encryption-` + pool.id + ` input").prop("disabled")) {
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
-
- validation.encryption = true;
- } else if ($("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val().length == 0) {
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Passphrase can not be empty.");
- $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").focus();
-
- validation.encryption = false;
- } else if ($("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val().length < 8) {
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
- $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").focus();
-
- validation.encryption = false;
- } else if (/^[a-zA-Z0-9-_. \`~!@#$%^\(\)+\\[\\]{}:',/?]*$/.test($("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val()) == false) {
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Passphrase contains invalid characters.");
- $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").focus();
-
- validation.encryption = false;
- } else if ($("#input-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").val().length < 8 || $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val() != $("#input-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").val()) {
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error").removeClass("hidden").text("");
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").addClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Passphrase does not match");
- $("#input-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").focus();
-
- validation.encryption = false;
- } else {
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
- $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
-
- validation.encryption = true;
- }
- } else {
- validation.encryption = true;
- }
-
- if ($("#switch-storagepool-filesystems-create-sharenfs-` + pool.id + ` input").prop("checked")) {
- if (/^[a-zA-Z0-9-_.:/@#+=!&*(), ]*$/.test($("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").val()) == false) {
- $("#validationwrapper-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").addClass("has-error");
- $("#helpblock-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").addClass("has-error").removeClass("hidden").text("NFS Share options contain invalid characters.");
- $("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").focus();
-
- validation.sharenfs = false;
- } else {
- validation.sharenfs = true;
- }
- } else {
- validation.sharenfs = true;
- }
-
- if (!validation.name || !validation.encryption || !validation.sharenfs) {
- if (!validation.name) {
- $("#validationwrapper-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error");
- $("#input-storagepool-filesystems-create-name-` + pool.id + `").focus();
- }
-
- $("#spinner-storagepool-filesystems-create-` + pool.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.name && validation.encryption && validation.sharenfs) {
- filesystem.atime = $("#btnspan-storagepool-filesystems-create-atime-` + pool.id + `").attr("data-field-value");
- filesystem.casesensitivity = $("#btnspan-storagepool-filesystems-create-casesensitivity-` + pool.id + `").attr("data-field-value");
- filesystem.cipher = $("#btnspan-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").attr("data-field-value");
- filesystem.compression = $("#btnspan-storagepool-filesystems-create-compression-` + pool.id + `").attr("data-field-value");
- filesystem.dedup = $("#btnspan-storagepool-filesystems-create-dedup-` + pool.id + `").attr("data-field-value");
- filesystem.dnodesize = $("#btnspan-storagepool-filesystems-create-dnodesize-` + pool.id + `").attr("data-field-value");
- filesystem.encryption = $("#switch-storagepool-filesystems-create-encryption-` + pool.id + ` input").prop("checked");
- filesystem.name = $("#btnspan-storagepool-filesystems-create-parentfilesystem-` + pool.id + `").attr("data-field-value") + "/" + $("#input-storagepool-filesystems-create-name-` + pool.id + `").val();
- filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.name, attribute: true });
- filesystem.passphrase = $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val();
- filesystem.readonly = ($("#switch-storagepool-filesystems-create-readonly-` + pool.id + ` input").prop("checked") ? "on" : "off");
- filesystem.recordsize = $("#btnspan-storagepool-filesystems-create-recordsize-` + pool.id + `").attr("data-field-value");
- filesystem.selinux = ($("#switch-storagepool-filesystems-create-selinux-` + pool.id + ` input").prop("checked") ? "on" : "off");
- filesystem.sharesmb = ($("#switch-storagepool-filesystems-create-samba-share-` + pool.id + ` input").prop("checked") ? "on" : "off");
- filesystem.special_small_blocks = $("#btnspan-storagepool-filesystems-create-special_small_blocks-` + pool.id + `").attr("data-field-value");
- filesystem.xattr = $("#btnspan-storagepool-filesystems-create-xattr-` + pool.id + `").attr("data-field-value");
-
- if ($("#switch-storagepool-filesystems-create-sharenfs-` + pool.id + ` input").prop("checked")) {
- if ($("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").val().toLowerCase() == "on" || $("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").val() == "sec=sys,rw,crossmnt,no_subtree_check,no_root_squash" || !$("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").val()) {
- filesystem.sharenfs = "on";
- } else {
- filesystem.sharenfs = $("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").val();
- }
- } else {
- filesystem.sharenfs = "off";
- }
-
- if ($("#input-storagepool-filesystems-create-quota-` + pool.id + `").val() > 0) { //Remove friendly text so final value is sent
- filesystem.quota = $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val() + $("#btnspan-storagepool-filesystems-create-quota-` + pool.id + `").attr("data-field-value").replace(/iB$/g, "");
- } else {
- filesystem.quota = "none";
- }
-
- FnFileSystemCreate({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { name: filesystem.name, id: filesystem.id, atime: filesystem.atime, casesensitivity: filesystem.casesensitivity, cipher: filesystem.cipher, compression: filesystem.compression, dedup: filesystem.dedup, dnodesize: filesystem.dnodesize, encryption: filesystem.encryption, passphrase: filesystem.passphrase, quota: filesystem.quota, readonly: filesystem.readonly, recordsize: filesystem.recordsize, selinux: filesystem.selinux, sharenfs: filesystem.sharenfs, sharesmb: filesystem.sharesmb, special_small_blocks: filesystem.special_small_blocks, xattr: filesystem.xattr });
- }
- });
-
- $("#dropdown-storagepool-filesystems-create-parentfilesystem-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystems-create-parentfilesystem-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
-
- FnFileSystemConfigurationInheritedGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: $(this).text() }, { name: "storagepool-filesystems-create", id: "` + pool.id + `" });
- });
-
- $("#dropdown-storagepool-filesystems-create-atime-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystems-create-atime-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystems-create-casesensitivity-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystems-create-casesensitivity-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystems-create-compression-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystems-create-compression-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystems-create-dedup-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystems-create-dedup-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystems-create-dnodesize-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystems-create-dnodesize-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystems-create-quota-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystems-create-quota-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).text());
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
-
- let size = {
- slider: {
- value: $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val(),
- valuemax: $("#input-storagepool-filesystems-create-quota-` + pool.id + `").attr("data-filesystem-quota-max-" + $(this).text().toLowerCase())
- }
- };
-
- $("#slider-storagepool-filesystems-create-quota-` + pool.id + `").data("slider").options.max = size.slider.valuemax;
- $("#slider-storagepool-filesystems-create-quota-` + pool.id + `").data("slider").options.step = (size.slider.valuemax < 10 ? "0.1" : "1");
- $("#slider-storagepool-filesystems-create-quota-` + pool.id + `").slider("setValue", 0); //Force display update
- $("#slider-storagepool-filesystems-create-quota-` + pool.id + `").slider("setValue", size.slider.value);
- $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val($("#slider-storagepool-filesystems-create-quota-` + pool.id + `").data("slider").getValue());
- });
-
- $("#dropdown-storagepool-filesystems-create-recordsize-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystems-create-recordsize-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystems-create-special_small_blocks-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystems-create-special_small_blocks-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystems-create-xattr-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystems-create-xattr-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemsUnlock() {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepools-filesystems-unlock").on("click", function () {
- FnModalFileSystemsUnlockContent({ id: $("#modal-storagepools-filesystems-unlock") });
- FnFileSystemsLockedGet();
-
- setTimeout(function() {
- $("#input-storagepools-filesystems-unlock-passphrase").focus();
- }, 600);
- });
- \x3C/script>
- `;
-
- $("#modals-storagepools-filesystems").append(modal.window);
-}
-
-function FnModalFileSystemsUnlockContent(modal = { id }) {
- modal.content = `
-
-
-
-
-
Unlock multiple file systems that use the same passphrase.
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepools-filesystems-unlock-mount input").on("click", function () {
- if ($(this).prop("checked")) {
- $("#switch-storagepools-filesystems-unlock-overlay").parent().removeClass("hidden");
- } else {
- $("#switch-storagepools-filesystems-unlock-overlay").parent().addClass("hidden");
- }
- });
-
- $("#btn-storagepools-filesystems-unlock-apply").on("click", function () {
- $("#spinner-storagepools-filesystems-unlock").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let filesystem = {
- mount: true,
- passphrase: ""
- };
- let filesystems = {
- id: []
- };
- let modal = {
- name: "storagepools-filesystems-unlock",
- id: ""
- };
- let samba = {
- enable: false
- };
- let validation = {
- filesystems: false,
- passphrase: false
- };
-
- $("#listgroup-storagepools-filesystems-unlock-filesystems input[name='checkbox-storagepools-filesystems-unlock-filesystems']:checked").map(function () {
- filesystems.id.push($(this).attr("data-filesystem-name"));
- });
-
- if (filesystems.id.length == 0) {
- $("#validationwrapper-storagepools-filesystems-unlock-filesystems").addClass("has-error");
- $("#helpblock-storagepools-filesystems-unlock-filesystems").removeClass("hidden").text("One or more file systems is needed for unlock.");
-
- validation.filesystems = false;
- } else {
- $("#validationwrapper-storagepools-filesystems-unlock-filesystems").removeClass("has-error");
- $("#helpblock-storagepools-filesystems-unlock-filesystems").removeClass("hidden").text("");
-
- validation.filesystems = true;
- }
-
- if ($("#input-storagepools-filesystems-unlock-passphrase").val().length == 0) {
- $("#helpblock-storagepools-filesystems-unlock-passphrase").addClass("has-error").removeClass("hidden").text("Passphrase can not be empty.");
-
- validation.passphrase = false;
- } else if ($("#input-storagepools-filesystems-unlock-passphrase").val().length < 8) {
- $("#helpblock-storagepools-filesystems-unlock-passphrase").addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
-
- validation.passphrase = false;
- } else if (/^[a-zA-Z0-9-_. \`~!@#$%^\(\)+\\[\\]{}:',/?]*$/.test($("#input-storagepools-filesystems-unlock-passphrase").val()) == false) {
- $("#helpblock-storagepools-filesystems-unlock-passphrase").addClass("has-error").removeClass("hidden").text("Passphrase contains invalid characters.");
-
- validation.passphrase = false;
- } else {
- $("#validationwrapper-storagepools-filesystems-unlock-passphrase").removeClass("has-error");
- $("#helpblock-storagepools-filesystems-unlock-passphrase").removeClass("has-error").addClass("hidden").text("");
-
- validation.passphrase = true;
- }
-
- if (!validation.filesystems || !validation.passphrase) {
- if (!validation.passphrase) {
- $("#validationwrapper-storagepools-filesystems-unlock-passphrase").addClass("has-error");
- $("#input-storagepools-filesystems-unlock-passphrase").focus();
- }
-
- $("#spinner-storagepools-filesystems-unlock").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.filesystems && validation.passphrase) {
- filesystem.mount = $("#switch-storagepools-filesystems-unlock-mount input").prop("checked");
- filesystem.overlay = $("#switch-storagepools-filesystems-unlock-overlay input").prop("checked");
- filesystem.passphrase = $("#input-storagepools-filesystems-unlock-passphrase").val();
-
- FnFileSystemsUnlock({ id: filesystems.id }, { mount: filesystem.mount, overlay: filesystem.overlay, passphrase: filesystem.passphrase }, { name: modal.name, id: modal.id });
- }
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-//#endregion
-
-//#region Modal File System
-
-function FnModalFileSystemChangePassphrase(pool = { name, id }, filesystem = { name, id }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-changepassphrase-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemChangePassphraseContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { id: $("#modal-storagepool-filesystem-changepassphrase-` + filesystem.id + `") });
-
- setTimeout(function() {
- $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").focus();
- }, 600);
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemChangePassphraseContent(pool = { name, id }, filesystem = { name, id }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-changepassphrase-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-changepassphrase-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let filesystem = {
- passphrase: ""
- };
- let validation = {
- passphrase: false
- };
-
- if ($("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").val().length == 0) {
- $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error");
- $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase can not be empty.");
- $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").focus();
-
- validation.passphrase = false;
- } else if ($("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").val().length < 8) {
- $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error");
- $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
- $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").focus();
-
- validation.passphrase = false;
- } else if (/^[a-zA-Z0-9-_. \`~!@#$%^\(\)+\\[\\]{}:',/?]*$/.test($("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").val()) == false) {
- $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error");
- $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase contains invalid characters.");
- $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").focus();
-
- validation.passphrase = false;
- } else if ($("#input-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").val().length < 8 || $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").val() != $("#input-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").val()) {
- $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").removeClass("has-error").removeClass("hidden").text("");
- $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").addClass("has-error");
- $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase does not match.");
- $("#input-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").focus();
-
- validation.passphrase = false;
- } else {
- $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").removeClass("has-error").removeClass("hidden").text("");
- $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").removeClass("has-error").removeClass("hidden").text("");
-
- validation.passphrase = true;
- }
-
- if (!validation.passphrase) {
- $("#spinner-storagepool-filesystem-changepassphrase-` + filesystem.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.passphrase) {
- $("#validationwrapper-storagepool-filesystem-changepassphrase-filesystem-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-changepassphrase-filesystem-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
-
- filesystem.passphrase = $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").val();
-
- FnFileSystemChangePassphrase({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", passphrase: filesystem.passphrase });
- }
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemConfigure(pool = { name, id, altroot: false, feature: { allocation_classes: true, edonr: true, large_blocks: true, large_dnode: true, lz4_compress: true, sha512: true, skein: true }, readonly: false }, filesystem = { name, id, origin, type }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-configure-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemConfigureContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, feature: { allocation_classes: ` + pool.feature.allocation_classes + `, edonr: ` + pool.feature.edonr + `, large_blocks: ` + pool.feature.large_blocks + `, large_dnode: ` + pool.feature.large_dnode + `, lz4_compress: ` + pool.feature.lz4_compress + `, sha512: ` + pool.feature.sha512 + `, skein: ` + pool.feature.skein + ` }, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", origin: "` + filesystem.origin + `", type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-configure-` + filesystem.id + `") });
- FnFileSystemConfigurationGet({ name: "` + pool.name + `", id: "` + pool.id + `", readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { name: "storagepool-filesystem-configure", id: "` + filesystem.id + `" });
- ` + (pool.altroot ? `FnStoragePoolAlternativeRootGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "storagepool-filesystem-configure", id: "` + filesystem.id + `" });` : ``) + `
-
- $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val("0");
- $("#validationwrapper-storagepool-filesystem-configure-quota-` + filesystem.id + ` .min-slider-handle").attr("tabindex", "14");
- $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val("0");
- $("#validationwrapper-storagepool-filesystem-configure-refreservation-` + filesystem.id + ` .min-slider-handle").attr("tabindex", "18");
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemConfigureContent(pool = { name, id, altroot: false, feature: { allocation_classes: true, edonr: true, large_blocks: true, large_dnode: true, lz4_compress: true, sha512: true, skein: true }, readonly: false }, filesystem = { name, id, origin, type }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").tooltip({ trigger: "manual" })
- .on("keyup", function (element) {
- let $this = $(this);
- let sd = $this.siblings("[data-provide=slider]").slider();
-
- if ($this.val().trim() && !$.isNumeric(this.value)) {
- this.value = sd.slider("getValue");
- }
- })
- .on("keypress blur", function (element) {
- if (element.which == 13 || element.type === "blur") {
- element.preventDefault();
-
- let $this = $(this);
- let sd = $this.siblings("[data-provide=slider]").slider();
- let max = sd.slider("getAttribute", "max");
- let min = sd.slider("getAttribute", "min");
-
- if (!$.isNumeric(this.value) || (this.value > max || this.value < min)) {
- let warningInfo = $.isNumeric(this.value) ? "Valid value should be between " + min + " and " + max : "Valid value should be number";
- $this.attr("data-original-title", warningInfo).tooltip("show").addClass("warning");
- this.value = sd.slider("getValue");
- setTimeout(function () {
- $this.tooltip("hide");
- }, 3000);
- } else {
- if ($this.is(".warning")) {
- $this.tooltip("hide");
- }
-
- this.value = $this.val().trim();
- sd.slider("setValue", this.value);
- }
- }
- })
- .siblings("[data-provide=slider]").each(function () {
- $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val(this.value);
- $(this).slider().on("change", function (element) {
- $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val(element.value.newValue);
- });
- });
-
- $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").on("change textInput input", function (element) {
- if ($(this).val() > 1000) { //Force reset to maximum allowed value
- $(this).val(1000);
- } else if ($(this).val() < 0) { //Force reset to minimum allowed value
- $(this).val(0);
- }
-
- if ($.isNumeric($(this).val())) {
- $("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").slider("setValue", $(this).val());
- }
- });
-
- $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").tooltip({ trigger: "manual" })
- .on("keyup", function (element) {
- let $this = $(this);
- let sd = $this.siblings("[data-provide=slider]").slider();
-
- if ($this.val().trim() && !$.isNumeric(this.value)) {
- this.value = sd.slider("getValue");
- }
- })
- .on("keypress blur", function (element) {
- if (element.which == 13 || element.type === "blur") {
- element.preventDefault();
-
- let $this = $(this);
- let sd = $this.siblings("[data-provide=slider]").slider();
- let max = sd.slider("getAttribute", "max");
- let min = sd.slider("getAttribute", "min");
-
- if (!$.isNumeric(this.value) || (this.value > max || this.value < min)) {
- let warningInfo = $.isNumeric(this.value) ? "Valid value should be between " + min + " and " + max : "Valid value should be number";
- $this.attr("data-original-title", warningInfo).tooltip("show").addClass("warning");
- this.value = sd.slider("getValue");
- setTimeout(function () {
- $this.tooltip("hide");
- }, 3000);
- } else {
- if ($this.is(".warning")) {
- $this.tooltip("hide");
- }
-
- this.value = $this.val().trim();
- sd.slider("setValue", this.value);
- }
- }
- })
- .siblings("[data-provide=slider]").each(function () {
- $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val(this.value);
- $(this).slider().on("change", function (element) {
- $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val(element.value.newValue);
- });
- });
-
- $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").on("change textInput input", function (element) {
- if ($(this).val() > 1000) { //Force reset to maximum allowed value
- $(this).val(1000);
- } else if ($(this).val() < 0) { //Force reset to minimum allowed value
- $(this).val(0);
- }
-
- if ($.isNumeric($(this).val())) {
- $("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").slider("setValue", $(this).val());
- }
- });
-
- $("#switch-storagepool-filesystem-configure-sharenfs-` + filesystem.id + ` input").on("click", function () {
- $("#validationwrapper-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
-
- if ($(this).prop("checked")) {
- $("#controllabel-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").removeClass("hidden");
- $("#validationwrapper-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").removeClass("hidden");
-
- FnSystemNfsVersionGet({ alert: { id: $("#alert-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `") } });
- } else {
- $("#validationwrapper-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").addClass("hidden");
- $("#controllabel-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").addClass("hidden");
- }
- });
-
- $("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").on("input", function (element) {
- if ($("#switch-storagepool-filesystem-configure-sharesmb-` + filesystem.id + `").attr("data-field-value") == "on") {
- if ($(this).val() != $(this).attr("data-field-value")) {
- $("#switch-storagepool-filesystem-configure-samba-restart-` + filesystem.id + `").parent().removeClass("hidden");
- } else {
- $("#switch-storagepool-filesystem-configure-samba-restart-` + filesystem.id + `").parent().addClass("hidden");
- }
- }
- });
-
- $("#btn-storagepool-filesystem-configure-apply-` + filesystem.id + `").on("click",function () {
- $("#spinner-storagepool-filesystem-configure-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let filesystem = {
- aclinherit: "",
- acltype: "",
- atime: "",
- canmount: "",
- checksum: "",
- compression: "",
- context: "",
- dedup: "",
- dnodesize: "",
- defcontext: "",
- fscontext: "",
- mountpoint: "",
- quota: "none",
- readonly: "",
- recordsize: "",
- refreservation: "0B",
- rootcontext: "",
- selinux: "",
- sharenfs: "",
- sharesmb: "",
- special_small_blocks: "0B",
- xattr: ""
- };
- let modal = {
- id: $("#modal-storagepool-filesystem-configure-` + filesystem.id + `")
- };
- let samba = {
- restart: false
- };
- let validation = {
- mountpoint: false,
- sharenfs: false
- };
-
- if ($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val().length == 0) {
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not be empty.");
-
- validation.mountpoint = false;
- } else if (/^[a-zA-Z0-9-_.:/ ]*$/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val()) == false) {
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint contains invalid characters.");
-
- validation.mountpoint = false;
- } else if ($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val() && /^[/]/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val()) == false) {
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint is an absolute path and must begin with a forward slash (/).");
-
- validation.mountpoint = false;
- } else if (/^[.]/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not begin with a period (.).");
-
- validation.mountpoint = false;
- } else if (/[.]$/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not end with a period (.).");
-
- validation.mountpoint = false;
- } else if (/[/][.][/]/g.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not contain a period as a sub directory (/./).");
-
- validation.mountpoint = false;
- } else if (/[/][.][.][/]/g.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not contain a double period as a sub directory (/../).");
-
- validation.mountpoint = false;
- } else if (/[/][/]/g.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not contain double forward slashes (//).");
-
- validation.mountpoint = false;
- } else if (/[.][.]/g.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not contain a double period (..).");
-
- validation.mountpoint = false;
- } else if (/^[ ]/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not begin with whitespace ( ).");
-
- validation.mountpoint = false;
- } else if (/[ ]$/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not end with whitespace ( ).");
-
- validation.mountpoint = false;
- } else {
- $("#validationwrapper-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("hidden").text("");
-
- validation.mountpoint = true;
- }
-
- if ($("#switch-storagepool-filesystem-configure-sharenfs-` + filesystem.id + ` input").prop("checked")) {
- if (/^[a-zA-Z0-9-_.:/@#+=!&*(), ]*$/.test($("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").val()) == false) {
- $("#validationwrapper-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").addClass("has-error");
- $("#helpblock-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("NFS Share options contain invalid characters.");
- $("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").focus();
-
- validation.sharenfs = false;
- } else {
- validation.sharenfs = true;
- }
- } else {
- validation.sharenfs = true;
- }
-
- if (!validation.mountpoint || !validation.sharenfs) {
- if (!validation.mountpoint) {
- $("#validationwrapper-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error");
- $("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").focus();
- }
-
- $("#spinner-storagepool-filesystem-configure-` + filesystem.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.mountpoint && validation.sharenfs) {
- filesystem.aclinherit = ($("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-value-new") : null);
- filesystem.acltype = ($("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-value-new") : null);
- filesystem.atime = ($("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-value-new") : null);
- filesystem.canmount = ($("#btnspan-storagepool-filesystem-configure-canmount-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-canmount-` + filesystem.id + `").attr("data-field-value-new") : null);
- filesystem.checksum = ($("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-value-new") : null);
- filesystem.compression = ($("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-value-new") : null);
- filesystem.context = ($("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + ` input").prop("checked") ? "system_u:object_r:samba_share_t:s0" : "none");
- filesystem.dedup = ($("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-value-new") : null);
- filesystem.dnodesize = ($("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-value-new") : null);
- filesystem.defcontext = ($("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + ` input").prop("checked") ? "system_u:object_r:samba_share_t:s0" : "none");
- filesystem.fscontext = ($("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + ` input").prop("checked") ? "system_u:object_r:samba_share_t:s0" : "none");
- filesystem.mountpoint = $("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val();
- filesystem.readonly = ($("#switch-storagepool-filesystem-configure-readonly-` + filesystem.id + ` input").prop("checked") ? "on" : "off");
- filesystem.recordsize = ($("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-value-new") : null);
- filesystem.rootcontext = ($("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + ` input").prop("checked") ? "system_u:object_r:samba_share_t:s0" : "none");
- filesystem.selinux = $("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + ` input").prop("checked");
- filesystem.sharesmb = ` + (zfsmanager.configuration.samba.manage ? `$("#switch-storagepool-filesystem-configure-sharesmb-` + filesystem.id + `").attr("data-field-value");` : `($("#switch-storagepool-filesystem-configure-sharesmb-` + filesystem.id + ` input").prop("checked") ? "on" : "off");`) + `
- filesystem.special_small_blocks = ($("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-value-new") : null);
- filesystem.xattr = ($("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-value-new") : null);
-
- if ($("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val() > 0) { //Remove friendly text so final value is sent
- filesystem.quota = $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val() + $("#btnspan-storagepool-filesystem-configure-quota-` + filesystem.id + `").attr("data-field-value").replace(/iB$/g, "");
- } else {
- filesystem.quota = "none";
- }
-
- if ($("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val() > 0) { //Remove friendly text so final value is sent
- filesystem.refreservation = $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val() + $("#btnspan-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").attr("data-field-value").replace(/iB$/g, "");
- } else {
- filesystem.refreservation = "0B";
- }
-
- if ($("#switch-storagepool-filesystem-configure-sharenfs-` + filesystem.id + ` input").prop("checked")) {
- if ($("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").val().toLowerCase() == "on" || $("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").val() == "sec=sys,rw,crossmnt,no_subtree_check,no_root_squash" || !$("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").val()) {
- filesystem.sharenfs = "on";
- } else {
- filesystem.sharenfs = $("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").val();
- }
- } else {
- filesystem.sharenfs = "off";
- }
-
- //Set values to null if unchanged, so that they are skipped in the configure function
- if (/^Inherited/.test(filesystem.aclinherit) && $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-source") == "inherited") {
- filesystem.aclinherit = null;
- } else if (/^Default/.test(filesystem.aclinherit) && $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-source") == "default") {
- filesystem.aclinherit = null;
- } else if (filesystem.aclinherit == $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-source") == "local") {
- filesystem.aclinherit = null;
- }
-
- if (/^Inherited/.test(filesystem.acltype) && $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-source") == "inherited") {
- filesystem.acltype = null;
- } else if (/^Default/.test(filesystem.acltype) && $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-source") == "default") {
- filesystem.acltype = null;
- } else if (filesystem.acltype == $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-source") == "local") {
- filesystem.acltype = null;
- }
-
- if (/^Inherited/.test(filesystem.atime) && $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-source") == "inherited") {
- filesystem.atime = null;
- } else if (/^Default/.test(filesystem.atime) && $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-source") == "default") {
- filesystem.atime = null;
- } else if (filesystem.atime == $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-source") == "local") {
- filesystem.atime = null;
- }
-
- if (filesystem.canmount == $("#btnspan-storagepool-filesystem-configure-canmount-` + filesystem.id + `").attr("data-field-value")) {
- filesystem.canmount = null;
- }
-
- if (/^Inherited/.test(filesystem.checksum) && $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-source") == "inherited") {
- filesystem.checksum = null;
- } else if (/^Default/.test(filesystem.checksum) && $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-source") == "default") {
- filesystem.checksum = null;
- } else if (filesystem.checksum == $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-source") == "local") {
- filesystem.checksum = null;
- }
-
- if (/^Inherited/.test(filesystem.compression) && $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-source") == "inherited") {
- filesystem.compression = null;
- } else if (/^Default/.test(filesystem.compression) && $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-source") == "default") {
- filesystem.compression = null;
- } else if (filesystem.compression == $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-source") == "local") {
- filesystem.compression = null;
- }
-
-
- if (/^Inherited/.test(filesystem.dedup) && $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-source") == "inherited") {
- filesystem.dedup = null;
- } else if (/^Default/.test(filesystem.dedup) && $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-source") == "default") {
- filesystem.dedup = null;
- } else if (filesystem.dedup == $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-source") == "local") {
- filesystem.dedup = null;
- }
-
- if (/^Inherited/.test(filesystem.dnodesize) && $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-source") == "inherited") {
- filesystem.dnodesize = null;
- } else if (/^Default/.test(filesystem.dnodesize) && $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-source") == "default") {
- filesystem.dnodesize = null;
- } else if (filesystem.dnodesize == $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-source") == "local") {
- filesystem.dnodesize = null;
- }
-
- if (filesystem.mountpoint == $("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").attr("data-field-value")) {
- filesystem.mountpoint = null;
- } else {
- ` + (pool.altroot ? `filesystem.mountpoint = filesystem.mountpoint.replace(new RegExp("^" + $("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").attr("data-field-altroot")), "");` : ``) + `
-
- samba.restart = $("#switch-storagepool-filesystem-configure-samba-restart-` + filesystem.id + ` input").prop("checked");
- }
-
- if (filesystem.quota == $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").attr("data-field-value")) {
- filesystem.quota = null;
- }
-
- if (filesystem.readonly == $("#switch-storagepool-filesystem-configure-readonly-` + filesystem.id + `").attr("data-field-value")) {
- filesystem.readonly = null;
- }
-
- if (/^Inherited/.test(filesystem.recordsize) && $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-source") == "inherited") {
- filesystem.recordsize = null;
- } else if (/^Default/.test(filesystem.recordsize) && $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-source") == "default") {
- filesystem.recordsize = null;
- } else if (filesystem.recordsize == $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-source") == "local") {
- filesystem.recordsize = null;
- }
-
- if (filesystem.refreservation == $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").attr("data-field-value")) {
- filesystem.refreservation = null;
- }
-
- if (filesystem.selinux == $("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + `").attr("data-field-value")) {
- filesystem.context = null;
- filesystem.defcontext = null;
- filesystem.fscontext = null;
- filesystem.rootcontext = null;
- filesystem.selinux = null;
- }
-
- if (filesystem.sharenfs == $("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").attr("data-field-value")) {
- filesystem.sharenfs = null;
- }
-
- if (/^Inherited/.test(filesystem.special_small_blocks) && $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-source") == "inherited") {
- filesystem.special_small_blocks = null;
- } else if (/^Default/.test(filesystem.special_small_blocks) && $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-source") == "default") {
- filesystem.special_small_blocks = null;
- } else if (filesystem.special_small_blocks == $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-source") == "local") {
- filesystem.special_small_blocks = null;
- }
-
- if (/^Inherited/.test(filesystem.xattr) && $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-source") == "inherited") {
- filesystem.xattr = null;
- } else if (/^Default/.test(filesystem.xattr) && $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-source") == "default") {
- filesystem.xattr = null;
- } else if (filesystem.xattr == $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-source") == "local") {
- filesystem.xattr = null;
- }
-
- FnFileSystemConfigure({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", aclinherit: filesystem.aclinherit, acltype: filesystem.acltype, atime: filesystem.atime, canmount: filesystem.canmount, checksum: filesystem.checksum, compression: filesystem.compression, context: filesystem.context, dedup: filesystem.dedup, dnodesize: filesystem.dnodesize, defcontext: filesystem.defcontext, fscontext: filesystem.fscontext, mountpoint: filesystem.mountpoint, quota: filesystem.quota, readonly: filesystem.readonly, recordsize: filesystem.recordsize, refreservation: filesystem.refreservation, rootcontext: filesystem.rootcontext, sharenfs: filesystem.sharenfs, sharesmb: filesystem.sharesmb, special_small_blocks: filesystem.special_small_blocks, type: "` + filesystem.type + `", xattr: filesystem.xattr }, { restart: samba.restart }, { id: modal.id });
- }
- });
-
- $("#dropdown-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystem-configure-acltype-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystem-configure-atime-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystem-configure-canmount-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-canmount-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystem-configure-checksum-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystem-configure-compression-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystem-configure-dedup-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystem-configure-quota-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-quota-` + filesystem.id + `").text($(this).text()).attr("data-field-value", $(this).text());
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
-
- let size = {
- slider: {
- value: $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val(),
- valuemax: $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").attr("data-filesystem-quota-max-" + $(this).text().toLowerCase())
- }
- };
-
- $("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").data("slider").options.max = size.slider.valuemax;
- $("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").data("slider").options.step = (size.slider.valuemax < 10 ? "0.1" : "1");
- $("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").slider("setValue", 0); //Force display update
- $("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").slider("setValue", size.slider.value);
- $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val($("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").data("slider").getValue());
- });
-
- $("#dropdown-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").text($(this).text()).attr("data-field-value", $(this).text());
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
-
- let size = {
- slider: {
- value: $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val(),
- valuemax: $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").attr("data-filesystem-refreservation-max-" + $(this).text().toLowerCase())
- }
- };
-
- $("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").data("slider").options.max = size.slider.valuemax;
- $("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").data("slider").options.step = (size.slider.valuemax < 10 ? "0.1" : "1");
- $("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").slider("setValue", 0); //Force display update
- $("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").slider("setValue", size.slider.value);
- $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val($("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").data("slider").getValue());
- });
-
- $("#dropdown-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
-
- $("#dropdown-storagepool-filesystem-configure-xattr-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemDestroy(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-destroy-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemDestroyContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-destroy-` + filesystem.id + `") });
- FnFileSystemChildDatasetsGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", clones: true }, { name: "storagepool-filesystem-destroy", id: "` + filesystem.id + `" });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemDestroyContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to destroy ` + filesystem.type.toLowerCase() + `: ` + filesystem.name + ` ?
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-filesystem-destroy-recursive-` + filesystem.id + ` input").on("click", function () {
- if ($(this).prop("checked") && $("#switch-storagepool-filesystem-destroy-recursiveall-` + filesystem.id + ` input").prop("checked")) {
- $("#switch-storagepool-filesystem-destroy-recursiveall-` + filesystem.id + ` input").click();
- }
-
- $("#panel-storagepool-filesystem-destroy-child-filesystemswithclones-` + filesystem.id + `").addClass("hidden");
- $("#panel-storagepool-filesystem-destroy-child-filesystemswithclones-` + filesystem.id + ` .collapse").collapse("hide");
- $("#panel-storagepool-filesystem-destroy-child-snapshotswithclones-` + filesystem.id + `").addClass("hidden");
- $("#panel-storagepool-filesystem-destroy-child-snapshotswithclones-` + filesystem.id + ` .collapse").collapse("hide");
-
- if ($(this).prop("checked") && $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-filesystems") > 0) {
- $("#panel-storagepool-filesystem-destroy-child-filesystems-` + filesystem.id + `").removeClass("hidden");
- } else {
- $("#panel-storagepool-filesystem-destroy-child-filesystems-` + filesystem.id + `").addClass("hidden");
- $("#panel-storagepool-filesystem-destroy-child-filesystems-` + filesystem.id + ` .collapse").collapse("hide");
- }
- if ($(this).prop("checked") && $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-snapshots") > 0) {
- $("#panel-storagepool-filesystem-destroy-child-snapshots-` + filesystem.id + `").removeClass("hidden");
- } else {
- $("#panel-storagepool-filesystem-destroy-child-snapshots-` + filesystem.id + `").addClass("hidden");
- $("#panel-storagepool-filesystem-destroy-child-snapshots-` + filesystem.id + ` .collapse").collapse("hide");
- }
- if ($(this).prop("checked") && ($("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-filesystems") > 0 || $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-snapshots") > 0)) {
- $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").addClass("modal-ct-bodytext-1");
- } else {
- $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").removeClass("modal-ct-bodytext-1");
- }
- });
-
- $("#switch-storagepool-filesystem-destroy-recursiveall-` + filesystem.id + ` input").on("click", function () {
- if ($(this).prop("checked") && $("#switch-storagepool-filesystem-destroy-recursive-` + filesystem.id + ` input").prop("checked")) {
- $("#switch-storagepool-filesystem-destroy-recursive-` + filesystem.id + ` input").click();
- }
-
- $("#panel-storagepool-filesystem-destroy-child-filesystems-` + filesystem.id + `").addClass("hidden");
- $("#panel-storagepool-filesystem-destroy-child-filesystems-` + filesystem.id + ` .collapse").collapse("hide");
- $("#panel-storagepool-filesystem-destroy-child-snapshots-` + filesystem.id + `").addClass("hidden");
- $("#panel-storagepool-filesystem-destroy-child-snapshots-` + filesystem.id + ` .collapse").collapse("hide");
-
- if ($(this).prop("checked") && $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-filesystemswithclones") > 0) {
- $("#panel-storagepool-filesystem-destroy-child-filesystemswithclones-` + filesystem.id + `").removeClass("hidden");
- } else {
- $("#panel-storagepool-filesystem-destroy-child-filesystemswithclones-` + filesystem.id + `").addClass("hidden");
- $("#panel-storagepool-filesystem-destroy-child-filesystemswithclones-` + filesystem.id + ` .collapse").collapse("hide");
- }
- if ($(this).prop("checked") && $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-snapshotswithclones") > 0) {
- $("#panel-storagepool-filesystem-destroy-child-snapshotswithclones-` + filesystem.id + `").removeClass("hidden");
- } else {
- $("#panel-storagepool-filesystem-destroy-child-snapshotswithclones-` + filesystem.id + `").addClass("hidden");
- $("#panel-storagepool-filesystem-destroy-child-snapshotswithclones-` + filesystem.id + ` .collapse").collapse("hide");
- }
- if ($(this).prop("checked") && ($("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-filesystemswithclones") > 0 || $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-snapshotswithclones") > 0)) {
- $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").addClass("modal-ct-bodytext-1");
- } else {
- $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").removeClass("modal-ct-bodytext-1");
- }
- });
-
- $("#btn-storagepool-filesystem-destroy-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-destroy-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let filesystem = {
- force: $("#switch-storagepool-filesystem-destroy-force-` + filesystem.id + ` input").prop("checked"),
- recursive: $("#switch-storagepool-filesystem-destroy-recursive-` + filesystem.id + ` input").prop("checked"),
- recursiveall: $("#switch-storagepool-filesystem-destroy-recursiveall-` + filesystem.id + ` input").prop("checked")
- };
- let samba = {
- restart: $("#switch-storagepool-filesystem-destroy-samba-restart-` + filesystem.id + ` input").prop("checked")
- };
-
- FnFileSystemDestroy({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall, sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { restart: samba.restart });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemLock(pool = { name, id }, filesystem = { name, id, type }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-lock-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemLockContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-lock-` + filesystem.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemLockContent(pool = { name, id }, filesystem = { name, id, type }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to lock ` + filesystem.type.toLowerCase() + `: ` + filesystem.name + ` ?
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-lock-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-lock-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- FnFileSystemLock({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", type: "` + filesystem.type + `" }, { refresh: true });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemMount(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-mount-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemMountContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-mount-` + filesystem.id + `") });
- FnFileSystemsMountedGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { alert: { id: $("#div-storagepool-filesystem-mount-warning-` + filesystem.id + `"), mount: true } });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemMountContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to mount ` + filesystem.type.toLowerCase() + `: ` + filesystem.name + ` ?
-
- ` + FnDisplayInlineAlert({ status: "warning", title: "Enabling Samba share on the root file system will expose all child file systems regardless of their share status.", description: null }, { name: "storagepool-filesystem-samba-warning", id: filesystem.id, hidden: true }) + `
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-filesystem-mount-samba-enable-` + filesystem.id + ` input").on("click", function () {
- if ($(this).prop("checked")) {
- ` + (filesystem.name == pool.name ? `$("#alert-storagepool-filesystem-samba-warning-` + filesystem.id + `").removeClass("hidden");` : ``) + `
- } else {
- ` + (filesystem.name == pool.name ? `$("#alert-storagepool-filesystem-samba-warning-` + filesystem.id + `").addClass("hidden");` : ``) + `
- }
- });
-
- $("#btn-storagepool-filesystem-mount-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-mount-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let filesystem = {
- overlay: $("#switch-storagepool-filesystem-mount-overlay-` + filesystem.id + ` input").prop("checked")
- };
- let samba = {
- enable: ` + ((pool.readonly || filesystem.sharesmb) ? false : `$("#switch-storagepool-filesystem-mount-samba-enable-` + filesystem.id + ` input").prop("checked")`) + `
- };
-
- FnFileSystemMount({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", overlay: filesystem.overlay, type: "` + filesystem.type + `" }, { enable: samba.enable }, { refresh: true });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemPromote(pool = { name, id }, filesystem = { name, id, origin, type }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-promote-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemPromoteContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", origin: "` + filesystem.origin + `", type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-promote-` + filesystem.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemPromoteContent(pool = { name, id }, filesystem = { name, id, origin, type }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to promote ` + filesystem.type.toLowerCase() + `: ` + filesystem.name + ` ?
-
Origin: ` + filesystem.origin + `
- ` + FnDisplayInlineAlert({ status: "info", title: "Origin file system: " + filesystem.origin.replace(/^(.*)\@.*$/, "$1") + " will be promoted to a clone file system.", description: null }, { name: null, id: null, hidden: false }) + `
- ` + (new RegExp("^" + filesystem.origin.replace(/^(.*)\@.*$/, "$1") + "/").test(filesystem.name) ? FnDisplayInlineAlert({ status: "warning", title: "Clone file system is a child of origin file system, which may create recursive dependency errors. It is recommended to rename this clone file system to a name that is not a child file system of the origin file system before promoting.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-promote-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-promote-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- FnFileSystemPromote({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", type: "` + filesystem.type + `" });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemRename(pool = { name, id, altroot: false }, filesystem = { name, id, clone: false, encryption: false, encryptionroot, origin, sharesmb: false, type }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-rename-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemRenameContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", clone: ` + filesystem.clone + `, encryption: ` + filesystem.encryption + `, origin: "` + filesystem.origin + `", sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-rename-` + filesystem.id + `") });
- FnFileSystemsNamesGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { existing: { name: "` + filesystem.name + `", clone: ` + filesystem.clone + `, encryption: ` + filesystem.encryption + `, encryptionroot: "` + filesystem.encryptionroot + `", origin: "` + filesystem.origin + `" }, override: false }, { dropdown: { id: $("#dropdown-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `"), selected: "` + filesystem.name.replace(/\/[^\/]+$/, "") + `" } });
-
- setTimeout(function() {
- $("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").focus();
- }, 600);
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemRenameContent(pool = { name, id, altroot: false }, filesystem = { name, id, clone: false, encryption: false, origin, sharesmb: false, type }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-rename-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-rename-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let filesystem = {
- createnonexistparents: false,
- force: false,
- namenew: "",
- parent: ""
- };
- let samba = {
- restart: false
- };
- let validation = {
- name: false
- };
-
- if ($("#btnspan-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").attr("data-field-value") + "/" + $("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val() == "` + filesystem.name + `") {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name or parent file system must be different.");
-
- validation.name = false;
- } else if (new RegExp("^" + "` + filesystem.name + `/").test($("#btnspan-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").attr("data-field-value") + "/" + $("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not be a descendant of current file system.");
-
- validation.name = false;
- } else if ($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val().length == 0) {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
-
- validation.name = false;
- } else if (/^[a-zA-Z0-9-_.:/ ]*$/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val()) == false) {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
-
- validation.name = false;
- } else if (/^[.]/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
-
- validation.name = false;
- } else if (/^[_]/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
-
- validation.name = false;
- } else if (/^[-]/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
-
- validation.name = false;
- } else if (/^[:]/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
-
- validation.name = false;
- } else if (/^[/]/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a forward slash (/).");
-
- validation.name = false;
- } else if (/[/]$/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with a forward slash (/).");
-
- validation.name = false;
- } else if (/^ |\\/ /.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
-
- validation.name = false;
- } else if (/ $| \\//.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
-
- validation.name = false;
- } else {
- $("#validationwrapper-storagepool-filesystem-rename-name-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("hidden").text("");
-
- validation.name = true;
- }
-
- if (!validation.name) {
- $("#validationwrapper-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error");
- $("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").focus();
-
- $("#spinner-storagepool-filesystem-rename-` + filesystem.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.name) {
- filesystem.createnonexistparents = $("#switch-storagepool-filesystem-rename-createnonexistparents-` + filesystem.id + ` input").prop("checked");
- filesystem.force = $("#switch-storagepool-filesystem-rename-force-` + filesystem.id + ` input").prop("checked");
- filesystem.namenew = $("#btnspan-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").attr("data-field-value") + "/" + $("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val();
- filesystem.parent = $("#btnspan-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").attr("data-field-value");
-
- samba.restart = $("#switch-storagepool-filesystem-rename-samba-restart-` + filesystem.id + ` input").prop("checked")
-
- FnFileSystemRename({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent, sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { restart: samba.restart });
- }
- });
-
- $("#dropdown-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemSambaConfigure(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mountpoint }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-samba-configure-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemSambaConfigureContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", mountpoint: "` + filesystem.mountpoint + `" }, { id: $("#modal-storagepool-filesystem-samba-configure-` + filesystem.id + `") });
- FnSambaZfsShareConfigurationGet({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { name: "storagepool-filesystem-samba-configure", id: "` + filesystem.id + `" });
-
- setTimeout(function() {
- $("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").focus();
- }, 600);
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemSambaConfigureContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mountpoint }, modal = { id }) {
- modal.content = `
-
-
-
-
- ` + (filesystem.name == pool.name ? FnDisplayInlineAlert({ status: "warning", title: "Samba share on the root file system exposes all child file systems regardless of their share status.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
- ` + FnDisplayInlineAlert({ status: "warning", title: "Share configuration does not exist. Configure to save a new share configuration.", description: null }, { name: "storagepool-filesystem-samba-configure-configurationmissing", id: filesystem.id, hidden: true }) + `
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-filesystem-samba-configure-additional-` + filesystem.id + ` input").on("click", function () {
- $("#validationwrapper-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
-
- if ($("#switch-storagepool-filesystem-samba-configure-additional-` + filesystem.id + ` input").prop("checked")) {
- $("#validationwrapper-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").removeClass("hidden");
- } else {
- $("#validationwrapper-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").addClass("hidden");
- }
- });
-
- $("#btn-storagepool-filesystem-samba-configure-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-samba-configure-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let samba = {
- share: {
- additional: ($("#switch-storagepool-filesystem-samba-configure-additional-` + filesystem.id + ` input").prop("checked") ? $("#textarea-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").val().split("\\n").filter(v => v) : []),
- administrative: false,
- browseable: true,
- comment: "",
- guestok: false,
- name: "",
- nameexisting: "",
- readonly: false
- }
- };
- let validation = {
- comment: false,
- name: false,
- additional: false
- };
-
- if ($("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").val().length == 0) {
- $("#helpblock-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not be empty.");
-
- validation.name = false;
- } else if (/^[a-zA-Z0-9-_.@%+!#$^,(){}~ ]*$/.test($("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").val()) == false) {
- $("#helpblock-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name contains invalid characters.");
-
- validation.name = false;
- } else if (/^[ ]/.test($("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not begin with whitespace ( ).");
-
- validation.name = false;
- } else if (/[ ]$/.test($("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not end with whitespace ( ).");
-
- validation.name = false;
- } else {
- $("#validationwrapper-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("hidden").text("");
-
- validation.name = true;
- }
-
- if (/^[ -~]*$/.test($("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").val()) == false) {
- $("#helpblock-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment contains invalid characters.");
-
- validation.comment = false;
- } else if (/^[.]/.test($("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment can not begin with a period (.).");
-
- validation.comment = false;
- } else if (/^[ ]/.test($("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment can not begin with whitespace ( ).");
-
- validation.comment = false;
- } else if (/[ ]$/.test($("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment can not end with whitespace ( ).");
-
- validation.comment = false;
- } else {
- $("#validationwrapper-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("hidden").text("");
-
- validation.comment = true;
- }
-
- if (samba.share.additional.length > 0) {
- samba.share.additional.forEach((_value, _index) => {
- if (/[\\[\\]]/g.test(_value)) { //Do not allow section names
- $("#helpblock-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must not contain brackets. Line: " + (_index + 1));
-
- validation.additional = false;
- return;
- } else if (/^[#]/.test(_value) == false && /[=]/.test(_value) && /(path|comment|browseable|read only|guest ok).*=/gi.test(_value)) {
- $("#helpblock-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must not contain duplicate properties. Line: " + (_index + 1));
-
- validation.additional = false;
- return;
- } else if (/[#=]/.test(_value) == false) {
- $("#helpblock-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must contain comments or properties only. Line: " + (_index + 1));
-
- validation.additional = false;
- return;
- } else if (_index == (samba.share.additional.length -1)) {
- $("#validationwrapper-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
-
- validation.additional = true;
- }
- });
- } else {
- validation.additional = true;
- }
-
- if (!validation.name || !validation.comment || !validation.additional) {
- if (!validation.name) {
- $("#validationwrapper-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("has-error");
- $("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").focus();
- }
- if (!validation.comment) {
- $("#validationwrapper-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("has-error");
- $("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").focus();
- }
- if (!validation.additional) {
- $("#validationwrapper-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").addClass("has-error");
- $("#textarea-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").focus();
- }
-
- $("#spinner-storagepool-filesystem-samba-configure-` + filesystem.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.name && validation.comment && validation.additional) {
- samba.restart = $("#switch-storagepool-filesystem-samba-configure-restart-` + filesystem.id + ` input").prop("checked");
- samba.share.administrative = $("#switch-storagepool-filesystem-samba-configure-administrative-` + filesystem.id + ` input").prop("checked");
- samba.share.browseable = $("#switch-storagepool-filesystem-samba-configure-browseable-` + filesystem.id + ` input").prop("checked");
- samba.share.comment = $("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").val();
- samba.share.guestok = $("#switch-storagepool-filesystem-samba-configure-guestok-` + filesystem.id + ` input").prop("checked");
- samba.share.name = $("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").val();
- samba.share.nameexisting = $("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").attr("data-field-value");
- samba.share.readonly = $("#switch-storagepool-filesystem-samba-configure-readonly-` + filesystem.id + ` input").prop("checked");
-
- FnSambaZfsShareConfigure({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", mountpoint: "` + filesystem.mountpoint + `" }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, nameexisting: samba.share.nameexisting, readonly: samba.share.readonly, temporary: ` + (pool.altroot || pool.readonly ? true : false) + ` }, restart: samba.restart });
- }
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemSambaDisable(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, type }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-samba-disable-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemSambaDisableContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-samba-disable-` + filesystem.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemSambaDisableContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, type }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to disable Samba share for ` + filesystem.type.toLowerCase() + `: ` + filesystem.name + ` ?
-
- Options
-
- Restart Samba service
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-samba-disable-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-samba-disable-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let samba = {
- restart: $("#switch-storagepool-filesystem-samba-disable-restart-` + filesystem.id + ` input").prop("checked")
- };
-
- FnSambaShareDisable({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { restart: samba.restart }, { modal: true, silent: false });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemSambaEnable(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mounted: false, mountpoint }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-samba-enable-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemSambaEnableContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", mounted: ` + filesystem.mounted + `, mountpoint: "` + filesystem.mountpoint + `" }, { id: $("#modal-storagepool-filesystem-samba-enable-` + filesystem.id + `") });
-
- setTimeout(function() {
- $("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").focus();
- }, 600);
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemSambaEnableContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mounted: false, mountpoint }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-filesystem-samba-enable-additional-` + filesystem.id + ` input").on("click", function () {
- $("#validationwrapper-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
-
- if ($(this).prop("checked")) {
- $("#validationwrapper-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").removeClass("hidden");
- } else {
- $("#validationwrapper-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").addClass("hidden");
- }
- });
-
- $("#btn-storagepool-filesystem-samba-enable-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-samba-enable-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let samba = {
- share: {
- additional: ($("#switch-storagepool-filesystem-samba-enable-additional-` + filesystem.id + ` input").prop("checked") ? $("#textarea-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").val().split("\\n").filter(v => v) : []),
- administrative: false,
- browseable: true,
- comment: "",
- guestok: false,
- name: "",
- readonly: false
- }
- };
- let validation = {
- comment: false,
- name: false,
- additional: false
- };
-
- if ($("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").val().length == 0) {
- $("#helpblock-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not be empty.");
-
- validation.name = false;
- } else if (/^[a-zA-Z0-9-_.@%+!#$^,(){}~ ]*$/.test($("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").val()) == false) {
- $("#helpblock-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name contains invalid characters.");
-
- validation.name = false;
- } else if (/^[ ]/.test($("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not begin with whitespace ( ).");
-
- validation.name = false;
- } else if (/[ ]$/.test($("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not end with whitespace ( ).");
-
- validation.name = false;
- } else {
- $("#validationwrapper-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("hidden").text("");
-
- validation.name = true;
- }
-
- if (/^[ -~]*$/.test($("#input-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").val()) == false) {
- $("#helpblock-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment contains invalid characters.");
-
- validation.comment = false;
- } else if (/^[ ]/.test($("#input-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment can not begin with whitespace ( ).");
-
- validation.comment = false;
- } else if (/[ ]$/.test($("#input-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment can not end with whitespace ( ).");
-
- validation.comment = false;
- } else {
- $("#validationwrapper-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").addClass("hidden").text("");
-
- validation.comment = true;
- }
-
- if (samba.share.additional.length > 0) {
- samba.share.additional.forEach((_value, _index) => {
- if (/[\\[\\]]/g.test(_value)) { //Do not allow section names
- $("#helpblock-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must not contain brackets. Line: " + (_index + 1));
-
- validation.additional = false;
- return;
- } else if (/^[#]/.test(_value) == false && /[=]/.test(_value) && /(path|comment|browseable|read only|guest ok).*=/gi.test(_value)) {
- $("#helpblock-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must not contain duplicate properties. Line: " + (_index + 1));
-
- validation.additional = false;
- return;
- } else if (/[#=]/.test(_value) == false) {
- $("#helpblock-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must contain comments or properties only. Line: " + (_index + 1));
-
- validation.additional = false;
- return;
- } else if (_index == (samba.share.additional.length -1)) {
- $("#validationwrapper-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
-
- validation.additional = true;
- }
- });
- } else {
- validation.additional = true;
- }
-
- if (!validation.name || !validation.comment || !validation.additional) {
- if (!validation.name) {
- $("#validationwrapper-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("has-error");
- $("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").focus();
- }
- if (!validation.comment) {
- $("#validationwrapper-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").addClass("has-error");
- $("#input-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").focus();
- }
- if (!validation.additional) {
- $("#validationwrapper-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").addClass("has-error");
- $("#textarea-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").focus();
- }
-
- $("#spinner-storagepool-filesystem-samba-enable-` + filesystem.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.name && validation.comment && validation.additional) {
- samba.share.administrative = $("#switch-storagepool-filesystem-samba-enable-administrative-` + filesystem.id + ` input").prop("checked");
- samba.share.browseable = $("#switch-storagepool-filesystem-samba-enable-browseable-` + filesystem.id + ` input").prop("checked");
- samba.share.comment = $("#input-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").val();
- samba.share.guestok = $("#switch-storagepool-filesystem-samba-enable-guestok-` + filesystem.id + ` input").prop("checked");
- samba.share.name = $("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").val();
- samba.share.readonly = $("#switch-storagepool-filesystem-samba-enable-readonly-` + filesystem.id + ` input").prop("checked");
-
- FnSambaShareEnable({ name: "` + pool.name + `", id: "` + pool.id + `", readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", mounted: ` + filesystem.mounted + `, mountpoint: "` + filesystem.mountpoint + `" }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: ` + (pool.altroot || pool.readonly ? true : false) + ` } }, { silent: false });
- }
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemSnapshotCreate(pool = { name, id }, filesystem = { name, id }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-snapshot-create-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemSnapshotCreateContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { id: $("#modal-storagepool-filesystem-snapshot-create-` + filesystem.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemSnapshotCreateContent(pool = { name, id }, filesystem = { name, id }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-filesystem-snapshot-create-customname-` + filesystem.id + ` input").on("click", function () {
- $("#validationwrapper-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
-
- if ($(this).prop("checked")) {
- $("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val("").prop("readonly", false).focus();
- } else {
- $("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val("YYYY.MM.DD-HH.MM.SS").prop("readonly", true);;
- }
- });
-
- $("#btn-storagepool-filesystem-snapshot-create-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-snapshot-create-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let snapshot = {
- name: "",
- id: "",
- recursive: false
- };
- let validation = {
- name: false
- };
-
- if ($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val().length == 0) {
- $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
-
- validation.name = false;
- } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val()) == false) {
- $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
-
- validation.name = false;
- } else if (/^[.]/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
-
- validation.name = false;
- } else if (/^[_]/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
-
- validation.name = false;
- } else if (/^[-]/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
-
- validation.name = false;
- } else if (/^[:]/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
-
- validation.name = false;
- } else if (/^[ ]/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
-
- validation.name = false;
- } else if (/[ ]$/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
- $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
-
- validation.name = false;
- } else {
- $("#validationwrapper-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("hidden").text("");
-
- validation.name = true;
- }
-
- if (!validation.name) {
- $("#validationwrapper-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error");
- $("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").focus();
-
- $("#spinner-storagepool-filesystem-snapshot-create-` + filesystem.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.name) {
- snapshot.name = "` + filesystem.name + `" + "@" + $("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val();
- snapshot.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: snapshot.name, attribute: true });
- snapshot.recursive = $("#switch-storagepool-filesystem-snapshot-create-recursive-` + filesystem.id + ` input").prop("checked");
-
- if ($("#switch-storagepool-filesystem-snapshot-create-customname-` + filesystem.id + ` input").prop("checked")) {
- FnSnapshotCreate({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive }, { name: "storagepool-filesystem-snapshot-create", id: "` + filesystem.id + `"});
- } else {
- FnSnapshotCreateDateGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive }, { name: "storagepool-filesystem-snapshot-create", id: "` + filesystem.id + `"});
- }
- }
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemUnlock(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-unlock-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemUnlockContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-unlock-` + filesystem.id + `") });
-
- setTimeout(function() {
- $("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").focus();
- }, 600);
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemUnlockContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-filesystem-unlock-mount-` + filesystem.id + ` input").on("click", function () {
- if ($(this).prop("checked")) {
- $("#switch-storagepool-filesystem-unlock-overlay-` + filesystem.id + `").parent().removeClass("hidden");
- } else {
- $("#switch-storagepool-filesystem-unlock-overlay-` + filesystem.id + `").parent().addClass("hidden");
- }
- });
-
- $("#btn-storagepool-filesystem-unlock-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-unlock-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let filesystem = {
- mount: true,
- passphrase: ""
- };
- let samba = {
- enable: false
- };
- let validation = {
- passphrase: false
- };
-
- if ($("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").val().length == 0) {
- $("#helpblock-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase can not be empty.");
-
- validation.passphrase = false;
- } else if ($("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").val().length < 8) {
- $("#helpblock-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
-
- validation.passphrase = false;
- } else if (/^[a-zA-Z0-9-_. \`~!@#$%^\(\)+\\[\\]{}:',/?]*$/.test($("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").val()) == false) {
- $("#helpblock-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase contains invalid characters.");
-
- validation.passphrase = false;
- } else {
- $("#validationwrapper-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").removeClass("has-error");
- $("#helpblock-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
-
- validation.passphrase = true;
- }
-
- if (!validation.passphrase) {
- $("#validationwrapper-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").addClass("has-error");
- $("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").focus();
-
- $("#spinner-storagepool-filesystem-unlock-` + filesystem.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.passphrase) {
- filesystem.mount = $("#switch-storagepool-filesystem-unlock-mount-` + filesystem.id + ` input").prop("checked");
- filesystem.overlay = $("#switch-storagepool-filesystem-unlock-overlay-` + filesystem.id + ` input").prop("checked");
- filesystem.passphrase = $("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").val();
-
- samba.enable = ` + ((pool.readonly || filesystem.sharesmb) ? false : `$("#switch-storagepool-filesystem-unlock-samba-enable-` + filesystem.id + ` input").prop("checked")`) + `;
-
- FnFileSystemUnlock({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", mount: filesystem.mount, overlay: filesystem.overlay, passphrase: filesystem.passphrase, type: "` + filesystem.type + `" }, { enable: samba.enable }, { name: "storagepool-filesystem-unlock", id: "` + filesystem.id + `" }, { refresh: true });
- }
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalFileSystemUnmount(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, encryptionroot, keystatus, sharesmb: false, type }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-unmount-` + filesystem.id + `").on("click", function () {
- FnModalFileSystemUnmountContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", encryptionroot: "` + filesystem.encryptionroot + `", keystatus: "` + filesystem.keystatus + `", sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-unmount-` + filesystem.id + `") });
- FnFileSystemsMountedGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { alert: { id: $("#div-storagepool-filesystem-unmount-warning-` + filesystem.id + `"), mount: false } });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
-}
-
-function FnModalFileSystemUnmountContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, encryptionroot, keystatus, sharesmb: false, type }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-filesystem-unmount-apply-` + filesystem.id + `").on("click", function () {
- $("#spinner-storagepool-filesystem-unmount-` + filesystem.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let filesystem = {
- force: $("#switch-storagepool-filesystem-unmount-force-` + filesystem.id + ` input").prop("checked"),
- lock: ` + (filesystem.keystatus == "available" && filesystem.encryptionroot == filesystem.name ? `$("#switch-storagepool-filesystem-unmount-lock-` + filesystem.id + ` input").prop("checked")` : false) + `
- };
- let samba = {
- disable: ` + ((!pool.readonly && filesystem.sharesmb) ? `$("#switch-storagepool-filesystem-unmount-samba-disable-` + filesystem.id + ` input").prop("checked")` : false) + `,
- restart: $("#switch-storagepool-filesystem-unmount-samba-restart-` + filesystem.id + ` input").prop("checked")
- };
-
- FnFileSystemUnmount({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", force: filesystem.force, lock: filesystem.lock, type: "` + filesystem.type + `" }, { disable: samba.disable, restart: samba.restart });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-//#endregion
-
-//#region Modal Snapshots
-
-function FnModalSnaphshotsCreate(pool = { name, id }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-snapshots-create-` + pool.id + `").on("click", function () {
- FnModalSnaphshotsCreateContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: $("#modal-storagepool-snapshots-create-` + pool.id + `") });
- FnFileSystemsNamesGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { existing: { name: null, clone: false, encryption: false, encryptionroot: null, origin: null }, override: true }, { dropdown: { id: $("#dropdown-storagepool-snapshots-create-filesystem-` + pool.id + `"), selected: "` + pool.name + `" } });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-snapshots-" + pool.id).append(modal.window);
-}
-
-function FnModalSnaphshotsCreateContent(pool = { name, id }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-snapshots-create-customname-` + pool.id + ` input").on("click", function () {
- $("#validationwrapper-storagepool-snapshots-create-name-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
-
- if ($(this).prop("checked")) {
- $("#input-storagepool-snapshots-create-name-` + pool.id + `").val("").prop("readonly", false).focus();
- } else {
- $("#input-storagepool-snapshots-create-name-` + pool.id + `").val("YYYY.MM.DD-HH.MM.SS").prop("readonly", true);;
- }
- });
-
- $("#btn-storagepool-snapshots-create-apply-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-snapshots-create-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let snapshot = {
- name: "",
- id: "",
- recursive: false
- };
- let validation = {
- name: false
- };
-
- if ($("#input-storagepool-snapshots-create-name-` + pool.id + `").val().length == 0) {
- $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
-
- validation.name = false;
- } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val()) == false) {
- $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
-
- validation.name = false;
- } else if (/^[.]/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
-
- validation.name = false;
- } else if (/^[_]/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
-
- validation.name = false;
- } else if (/^[-]/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
-
- validation.name = false;
- } else if (/^[:]/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
-
- validation.name = false;
- } else if (/^[ ]/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
-
- validation.name = false;
- } else if (/[ ]$/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
- $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
-
- validation.name = false;
- } else {
- $("#validationwrapper-storagepool-snapshots-create-name-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("hidden").text("");
-
- validation.name = true;
- }
-
- if (!validation.name) {
- $("#validationwrapper-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error");
- $("#input-storagepool-snapshots-create-name-` + pool.id + `").focus();
-
- $("#spinner-storagepool-snapshots-create-` + pool.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.name) {
- snapshot.name = $("#btnspan-storagepool-snapshots-create-filesystem-` + pool.id + `").attr("data-field-value") + "@" + $("#input-storagepool-snapshots-create-name-` + pool.id + `").val();
- snapshot.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: snapshot.name, attribute: true });
- snapshot.recursive = $("#switch-storagepool-snapshots-create-recursive-` + pool.id + ` input").prop("checked");
-
- if ($("#switch-storagepool-snapshots-create-customname-` + pool.id + ` input").prop("checked")) {
- FnSnapshotCreate({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive }, { name: "storagepool-snapshots-create", id: "` + pool.id + `"});
- } else {
- FnSnapshotCreateDateGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive }, { name: "storagepool-snapshots-create", id: "` + pool.id + `"});
- }
- }
- });
-
- $("#dropdown-storagepool-snapshots-create-filesystem-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-snapshots-create-filesystem-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-//#endregion
-
-//#region Modal Snapshot
-
-function FnModalSnapshotClone(pool = { name, id, altroot: false }, snapshot = { name, id, encryption: false, encryptionroot }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-snapshot-clone-` + snapshot.id + `").on("click", function () {
- FnModalSnapshotCloneContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", encryption: ` + snapshot.encryption + ` }, { id: $("#modal-storagepool-snapshot-clone-` + snapshot.id + `") });
- FnFileSystemsNamesGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { existing: { name: null, clone: false, encryption: ` + snapshot.encryption + `, encryptionroot: "` + snapshot.encryptionroot + `", origin: null }, override: false }, { dropdown: { id: $("#dropdown-storagepool-snapshot-clone-parentfilesystem-` + snapshot.id + `"), selected: "` + snapshot.name.replace(/^(.*)\@.*$/, "$1") + `" } });
-
- setTimeout(function() {
- $("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").focus();
- }, 600);
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-snapshot-" + pool.id).append(modal.window);
-}
-
-function FnModalSnapshotCloneContent(pool = { name, id, altroot: false }, snapshot = { name, id, encryption: false }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-snapshot-clone-apply-` + snapshot.id + `").on("click", function () {
- $("#spinner-storagepool-snapshot-clone-` + snapshot.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let snapshot = {
- clone: {
- createnonexistparents: false,
- name: "",
- parent: ""
- }
- };
- let validation = {
- name: false
- };
-
- if ($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val().length == 0) {
- $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
-
- validation.name = false;
- } else if (/^[a-zA-Z0-9-_.:/ ]*$/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val()) == false) {
- $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
-
- validation.name = false;
- } else if (/^[.]/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
-
- validation.name = false;
- } else if (/^[_]/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
-
- validation.name = false;
- } else if (/^[-]/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
-
- validation.name = false;
- } else if (/^[:]/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
-
- validation.name = false;
- } else if (/^[/]/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a forward slash (/).");
-
- validation.name = false;
- } else if (/[/]$/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with a forward slash (/).");
-
- validation.name = false;
- } else if (/^ |\\/ /.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
-
- validation.name = false;
- } else if (/ $| \\//.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
-
- validation.name = false;
- } else {
- $("#validationwrapper-storagepool-snapshot-clone-name-` + snapshot.id + `").removeClass("has-error");
- $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").removeClass("has-error").addClass("hidden").text("");
-
- validation.name = true;
- }
-
- if (!validation.name) {
- $("#validationwrapper-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error");
- $("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").focus();
-
- $("#spinner-storagepool-snapshot-clone-` + snapshot.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.name) {
- snapshot.clone.createnonexistparents = $("#switch-storagepool-snapshot-clone-createnonexistparents-` + snapshot.id + ` input").prop("checked");
- snapshot.clone.name = $("#btnspan-storagepool-snapshot-clone-parentfilesystem-` + snapshot.id + `").attr("data-field-value") + "/" + $("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val();
- snapshot.clone.parent = $("#btnspan-storagepool-snapshot-clone-parentfilesystem-` + snapshot.id + `").attr("data-field-value");
-
- FnSnapshotClone({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", clone: { name: snapshot.clone.name, createnonexistparents: snapshot.clone.createnonexistparents, parent: snapshot.clone.parent } });
- }
- });
-
- $("#dropdown-storagepool-snapshot-clone-parentfilesystem-` + snapshot.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-snapshot-clone-parentfilesystem-` + snapshot.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalSnapshotDestroy(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, clones: [] }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-snapshot-destroy-` + snapshot.id + `").on("click", function () {
- FnModalSnapshotDestroyContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", clones: [` + (snapshot.clones.length > 0 ? `"` + snapshot.clones.join(`","`) + `"` : ``) + `] }, { id: $("#modal-storagepool-snapshot-destroy-` + snapshot.id + `") });
- ` + (snapshot.clones.length > 0 ? `FnSnapshotChildFileSystemsGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `" }, { id: ` + (snapshot.clones.length > 0 ? `["` + snapshot.clones.join(`", "`) + `"]` : `[]`) + ` }, { name: "storagepool-snapshot-destroy", id: "` + snapshot.id + `" });` : ``) + `
- FnSnapshotChildSnapshotsGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", exclude: false }, { id: ` + (snapshot.clones.length > 0 ? `["` + snapshot.clones.join(`", "`) + `"]` : `[]`) + ` }, { name: "storagepool-snapshot-destroy", id: "` + snapshot.id + `" });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-snapshot-" + pool.id).append(modal.window);
-}
-
-function FnModalSnapshotDestroyContent(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, clones: [] }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-snapshot-destroy-recursive-` + snapshot.id + ` input").on("click", function () {
- if ($(this).prop("checked") && $("#switch-storagepool-snapshot-destroy-recursiveall-` + snapshot.id + ` input").prop("checked")) {
- $("#switch-storagepool-snapshot-destroy-recursiveall-` + snapshot.id + ` input").click();
- }
-
- $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
- $("#panel-storagepool-snapshot-destroy-child-snapshotswithclones-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-destroy-child-snapshotswithclones-` + snapshot.id + ` .collapse").collapse("hide");
-
- if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-snapshots") > 0) {
- $("#panel-storagepool-snapshot-destroy-child-snapshots-` + snapshot.id + `").removeClass("hidden");
- } else {
- $("#panel-storagepool-snapshot-destroy-child-snapshots-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-destroy-child-snapshots-` + snapshot.id + ` .collapse").collapse("hide");
- }
- if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-snapshots") > 0) {
- $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").addClass("modal-ct-bodytext-1");
- } else {
- $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").removeClass("modal-ct-bodytext-1");
- }
- });
-
- $("#switch-storagepool-snapshot-destroy-recursiveall-` + snapshot.id + ` input").on("click", function () {
- if ($(this).prop("checked") && $("#switch-storagepool-snapshot-destroy-recursive-` + snapshot.id + ` input").prop("checked")) {
- $("#switch-storagepool-snapshot-destroy-recursive-` + snapshot.id + ` input").click();
- }
-
- $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
- $("#panel-storagepool-snapshot-destroy-child-snapshots-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-destroy-child-snapshots-` + snapshot.id + ` .collapse").collapse("hide");
-
- if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-filesystems") > 0) {
- $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + `").removeClass("hidden");
- } else {
- $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
- }
- if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-snapshotswithclones") > 0) {
- $("#panel-storagepool-snapshot-destroy-child-snapshotswithclones-` + snapshot.id + `").removeClass("hidden");
- } else {
- $("#panel-storagepool-snapshot-destroy-child-snapshotswithclones-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-destroy-child-snapshotswithclones-` + snapshot.id + ` .collapse").collapse("hide");
- }
- if ($(this).prop("checked") && ($("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-snapshotswithclones") > 0 || $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-snapshotswithclones") > 0)) {
- $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").addClass("modal-ct-bodytext-1");
- } else {
- $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").removeClass("modal-ct-bodytext-1");
- }
- });
-
- $("#btn-storagepool-snapshot-destroy-apply-` + snapshot.id + `").on("click", function () {
- $("#spinner-storagepool-snapshot-destroy-` + snapshot.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let snapshot = {
- recursive: $("#switch-storagepool-snapshot-destroy-recursive-` + snapshot.id + ` input").prop("checked"),
- recursiveall: $("#switch-storagepool-snapshot-destroy-recursiveall-` + snapshot.id + ` input").prop("checked")
- };
- let samba = {
- restart: $("#switch-storagepool-snapshot-destroy-samba-restart-` + snapshot.id + ` input").prop("checked")
- };
-
- FnSnapshotDestroy({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", clones: ` + (snapshot.clones.length > 0 ? `["` + snapshot.clones.join(`", "`) + `"]` : `[]`) + `, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { restart: samba.restart });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalSnapshotRename(pool = { name, id }, snapshot = { name, id, creation }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-snapshot-rename-` + snapshot.id + `").on("click", function () {
- FnModalSnapshotRenameContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", creation: "` + snapshot.creation + `" }, { id: $("#modal-storagepool-snapshot-rename-` + snapshot.id + `") });
-
- setTimeout(function() {
- $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").focus();
- }, 600);
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-snapshot-" + pool.id).append(modal.window);
-}
-
-function FnModalSnapshotRenameContent(pool = { name, id }, snapshot = { name, id, creation }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-snapshot-rename-creationdate-` + snapshot.id + ` input").on("click", function () {
- if ($(this).prop("checked")) {
- $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val("` + FnDateTimeSnapshot({ date: new Date(snapshot.creation * 1000) }) + `").prop("readonly", true);
- } else {
- $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val("` + snapshot.name.replace(/^.*\@(.*)$/, "$1") + `").prop("readonly", false).focus();
- }
- });
-
- $("#btn-storagepool-snapshot-rename-apply-` + snapshot.id + `").on("click", function () {
- $("#spinner-storagepool-snapshot-rename-` + snapshot.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let snapshot = {
- namenew: "",
- recursive: false
- };
- let validation = {
- name: false
- };
-
- if ("` + snapshot.name.replace(/^(.*)\@.*$/, "$1") + `" + "@" + $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val() == "` + snapshot.name + `") {
- $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name must be different.");
-
- validation.name = false;
- } else if ($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val().length == 0) {
- $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
-
- validation.name = false;
- } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val()) == false) {
- $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
-
- validation.name = false;
- } else if (/^[.]/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
-
- validation.name = false;
- } else if (/^[_]/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
-
- validation.name = false;
- } else if (/^[-]/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
-
- validation.name = false;
- } else if (/^[:]/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
-
- validation.name = false;
- } else if (/^[ ]/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
-
- validation.name = false;
- } else if (/[ ]$/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
- $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
-
- validation.name = false;
- } else {
- $("#validationwrapper-storagepool-snapshot-rename-name-` + snapshot.id + `").removeClass("has-error");
- $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").removeClass("has-error").addClass("hidden").text("");
-
- validation.name = true;
- }
-
- if (!validation.name) {
- $("#validationwrapper-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error");
- $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").focus();
-
- $("#spinner-storagepool-snapshot-rename-` + snapshot.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.name) {
- snapshot.namenew = "` + snapshot.name.replace(/^(.*)\@.*$/, "$1") + `" + "@" + $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val();
- snapshot.recursive = $("#switch-storagepool-snapshot-rename-recursive-` + snapshot.id + ` input").prop("checked");
-
- FnSnapshotRename({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", namenew: snapshot.namenew, recursive: snapshot.recursive });
- }
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalSnapshotRollBack(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, creation }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-snapshot-rollback-` + snapshot.id + `").on("click", function () {
- FnModalSnapshotRollBackContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", creation: "` + snapshot.creation + `" }, { id: $("#modal-storagepool-snapshot-rollback-` + snapshot.id + `") });
- FnSnapshotRollBackSnapshotsGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", creation: "` + snapshot.creation + `" }, { name: "storagepool-snapshot-rollback", id: "` + snapshot.id + `" });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-snapshot-" + pool.id).append(modal.window);
-}
-
-function FnModalSnapshotRollBackContent(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, creation }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-snapshot-rollback-recursive-` + snapshot.id + ` input").on("click", function () {
- if ($(this).prop("checked") && $("#switch-storagepool-snapshot-rollback-recursiveall-` + snapshot.id + ` input").prop("checked")) {
- $("#switch-storagepool-snapshot-rollback-recursiveall-` + snapshot.id + ` input").click();
- }
-
- $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
- $("#panel-storagepool-snapshot-rollback-child-snapshotswithclones-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-rollback-child-snapshotswithclones-` + snapshot.id + ` .collapse").collapse("hide");
-
- if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-rollback-` + snapshot.id + `").attr("data-snapshot-snapshots") > 0) {
- $("#panel-storagepool-snapshot-rollback-snapshots-` + snapshot.id + `").removeClass("hidden");
- } else {
- $("#panel-storagepool-snapshot-rollback-snapshots-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-rollback-snapshots-` + snapshot.id + ` .collapse").collapse("hide");
- }
- });
-
- $("#switch-storagepool-snapshot-rollback-recursiveall-` + snapshot.id + ` input").on("click", function () {
- if ($(this).prop("checked") && $("#switch-storagepool-snapshot-rollback-recursive-` + snapshot.id + ` input").prop("checked")) {
- $("#switch-storagepool-snapshot-rollback-recursive-` + snapshot.id + ` input").click();
- }
-
- if ($(this).prop("checked")) {
- $("#switch-storagepool-snapshot-rollback-force-` + snapshot.id + `").parent().removeClass("hidden");
- } else {
- $("#switch-storagepool-snapshot-rollback-force-` + snapshot.id + `").parent().addClass("hidden");
-
- if ($("#switch-storagepool-snapshot-rollback-force-` + snapshot.id + ` input").prop("checked")) {
- $("#switch-storagepool-snapshot-rollback-force-` + snapshot.id + ` input").click();
- }
- }
-
- $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
- $("#panel-storagepool-snapshot-rollback-snapshots-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-rollback-snapshots-` + snapshot.id + ` .collapse").collapse("hide");
-
- if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-rollback-` + snapshot.id + `").attr("data-snapshot-child-filesystems") > 0) {
- $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + `").removeClass("hidden");
- } else {
- $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
- }
- if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-rollback-` + snapshot.id + `").attr("data-snapshot-child-snapshotswithclones") > 0) {
- $("#panel-storagepool-snapshot-rollback-child-snapshotswithclones-` + snapshot.id + `").removeClass("hidden");
- } else {
- $("#panel-storagepool-snapshot-rollback-child-snapshotswithclones-` + snapshot.id + `").addClass("hidden");
- $("#panel-storagepool-snapshot-rollback-child-snapshotswithclones-` + snapshot.id + ` .collapse").collapse("hide");
- }
- });
-
- $("#btn-storagepool-snapshot-rollback-apply-` + snapshot.id + `").on("click", function () {
- $("#spinner-storagepool-snapshot-rollback-` + snapshot.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let snapshot = {
- force: ($("#switch-storagepool-snapshot-rollback-recursiveall-` + snapshot.id + ` input").prop("checked") ? $("#switch-storagepool-snapshot-rollback-force-` + snapshot.id + ` input").prop("checked") : false),
- recursive: $("#switch-storagepool-snapshot-rollback-recursive-` + snapshot.id + ` input").prop("checked"),
- recursiveall: $("#switch-storagepool-snapshot-rollback-recursiveall-` + snapshot.id + ` input").prop("checked")
- };
- let samba = {
- restart: $("#switch-storagepool-snapshot-rollback-samba-restart-` + snapshot.id + ` input").prop("checked")
- };
-
- FnSnapshotRollBack({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", creation: "` + snapshot.creation + `", force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { restart: samba.restart });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-//#endregion
-
-//#region Modal Status
-
-function FnModalStatusDiskAttach(pool = { name, id, status: { config: { items: { index: 0 }, tier: { name, dedup: false, logs: false, special: false } } } }, virtualdevice = { id, disk: true }) {
- let modal = {
- tiername: (pool.status.config.tier.dedup ? "Dedup" : (pool.status.config.tier.logs ? "Log" : (pool.status.config.tier.special ? "Special" : pool.status.config.tier.name))),
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-attach-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusDiskAttachContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + virtualdevice.id + `" , disk: ` + virtualdevice.disk + ` }, { id: $("#modal-storagepool-status-disk-attach-` + pool.status.config.items.index + `-` + pool.id + `"), tiername: "` + modal.tiername + `" });
- FnDisksAvailableGet({ name: "storagepool-status-disk-attach-disks", id: "` + pool.status.config.items.index + `-` + pool.id + `", default: true });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusDiskAttachContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, virtualdevice = { id, disk: true }, modal = { id, tiername }) {
- modal.content = `
-
-
-
-
- ` + (virtualdevice.disk ? FnDisplayInlineAlert({ status: "info", title: "Attaching a disk will convert the virtual device from Disk to Mirror.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
-
- Virtual Device
-
-
` + virtualdevice.id + ` (` + modal.tiername + `)
-
- Disks WWN
-
-
-
- Disks Identifier
-
- Disks
-
-
-
- ` + (zfsmanager.zfs.warnings.nvmevdev ? `
Virtual Device Mapping identifiers for NVMe devices may not have been created due to a bug in the ZFS software . Update ZFS to 0.8.3 for fix. ` : ``) + `
-
-
-
- Options
-
- Forcefully attach disk
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-status-disk-attach-disks-wwn-` + pool.status.config.items.index + `-` + pool.id + ` input").on("click", function () {
- $("#btnspan-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text("Block Device");
- $("#dropdown-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li").siblings().removeClass("active");
- $("#dropdown-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li[value='blockdevice']").addClass("active");
- $("#helpblock-storagepool-status-disk-attach-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
- ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-disk-attach-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
-
- let disk = {
- identifier: ($(this).prop("checked") ? "wwn" : "blockdevice"),
- identifiertext: ($(this).prop("checked") ? "WWN" : "Block Device")
- };
-
- if ($(this).prop("checked")) {
- $("#controllabel-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- $("#validationwrapper-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- } else {
- $("#controllabel-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $("#validationwrapper-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- }
-
- $("#listgroup-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
- if ($(this).attr("data-disk-id-" + disk.identifier)) {
- $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
- } else {
- $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
- $("#helpblock-storagepool-status-disk-attach-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
- }
- });
- });
-
- $("#btn-storagepool-status-disk-attach-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-disk-attach-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let disk = {
- idnew: []
- };
- let modal = {
- name: "",
- id: ""
- };
- let pool = {
- force: false
- };
- let validation = {
- disks: false
- };
-
- $("#listgroup-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `']:checked").map(function () {
- disk.idnew.push($(this).attr("data-disk-name"));
- });
-
- if (disk.idnew.length != 1) {
- $("#helpblock-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One disk is needed.");
-
- validation.disks = false;
- } else {
- $("#validationwrapper-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("");
-
- validation.disks = true;
- }
-
- if (!validation.disks) {
- $("#validationwrapper-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `").addClass("has-error");
-
- $("#spinner-storagepool-status-disk-attach-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.disks) {
- modal.name = "storagepool-status-disk-attach";
- modal.id = "` + pool.status.config.items.index + `-` + pool.id + `";
-
- pool.force = $("#switch-storagepool-status-disk-attach-force-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked");
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolDiskAttach({ name: "` + pool.name + `", id: "` + pool.id + `", force: pool.force }, { id: "` + virtualdevice.id + `", disk: ` + virtualdevice.disk + ` }, { idnew: disk.idnew }, { name: modal.name, id: modal.id });
- }
- });
-
- $("#dropdown-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
-
- $("#helpblock-storagepool-status-disk-attach-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
- ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-disk-attach-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
-
- let disk = {
- identifier: $(this).parent().attr("value"),
- identifiertext: $(this).parent().text()
- };
-
- $("#listgroup-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
- if ($(this).attr("data-disk-id-" + disk.identifier)) {
- $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
- } else {
- $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
- $("#helpblock-storagepool-status-disk-attach-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
-
+}
+
+function FnStoragePoolsGetCommand(process = { data, message }) {
+ let pools = {
+ id: []
+ };
+
+ pools.id = process.data.split(/\n/g).filter(v => {
+ if (!zfsmanager.configuration.zfs.storagepool.boot && zfsmanager.zfs.storagepool.boot && new RegExp("^" + zfsmanager.zfs.storagepool.boot + "\t").test(v)) {
+ //Do not display boot
+ } else if (!zfsmanager.configuration.zfs.storagepool.root && zfsmanager.zfs.storagepool.root && new RegExp("^" + zfsmanager.zfs.storagepool.root + "\t").test(v)) {
+ //Do not display root
+ } else {
+ return v;
+ }
+ });
+
+ pools.id.forEach((_value, _index) => {
+ let pool = {
+ properties: _value.split(/\t/g).filter(v => v),
+ actionsmenu: {
+ register: {}
+ }
+ };
+
+ //0=name, 1=guid, 2=health, 3=size, 4=alloc, 5=free, 6=fragmentation, 7=readonly, 8=altroot, 9=autotrim, 10=version, 11=feature@allocation_classes, 12=feature@async_destroy, 13=feature@bookmark_v2, 14=feature@bookmarks, 15=feature@device_removal, 16=feature@edonr, 17=feature@embedded_data, 18=feature@empty_bpobj, 19=feature@enabled_txg, 20=feature@encryption, 21=feature@extensible_dataset, 22=feature@filesystem_limits, 23=feature@hole_birth, 24=feature@large_blocks, 25=feature@large_dnode, 26=feature@lz4_compress, 27=feature@multi_vdev_crash_dump, 28=feature@obsolete_counts, 29=feature@project_quota, 30=feature@resilver_defer, 31=feature@sha512, 32=feature@skein, 33=feature@spacemap_histogram, 34=feature@spacemap_v2, 35=feature@userobj_accounting, 36=feature@zpool_checkpoint
+
+ pool.activetab = "filesystems";
+ pool.allocated = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[4] });
+ pool.allocatedpercent = FnRound({ decimals: 2, value: (pool.properties[4] / pool.properties[3]) * 100 });
+ pool.altroot = (pool.properties[8] && pool.properties[8] != "-" ? true : false);
+ pool.autotrim = (pool.properties[9].toLowerCase() == "on" ? true : false);
+ pool.boot = (zfsmanager.zfs.storagepool.boot && pool.properties[0] == zfsmanager.zfs.storagepool.boot ? true : false);
+ pool.feature = {
+ allocation_classes: (/active|enabled/gi.test(pool.properties[11]) ? true : false),
+ async_destroy: (/active|enabled/gi.test(pool.properties[12]) ? true : false),
+ bookmark_v2: (/active|enabled/gi.test(pool.properties[13]) ? true : false),
+ bookmarks: (/active|enabled/gi.test(pool.properties[14]) ? true : false),
+ device_removal: (/active|enabled/gi.test(pool.properties[15]) ? true : false),
+ edonr: (/active|enabled/gi.test(pool.properties[16]) ? true : false),
+ embedded_data: (/active|enabled/gi.test(pool.properties[17]) ? true : false),
+ empty_bpobj: (/active|enabled/gi.test(pool.properties[18]) ? true : false),
+ enabled_txg: (/active|enabled/gi.test(pool.properties[19]) ? true : false),
+ encryption: (/active|enabled/gi.test(pool.properties[20]) ? true : false),
+ extensible_dataset: (/active|enabled/gi.test(pool.properties[21]) ? true : false),
+ filesystem_limits: (/active|enabled/gi.test(pool.properties[22]) ? true : false),
+ hole_birth: (/active|enabled/gi.test(pool.properties[23]) ? true : false),
+ large_blocks: (/active|enabled/gi.test(pool.properties[24]) ? true : false),
+ large_dnode: (/active|enabled/gi.test(pool.properties[25]) ? true : false),
+ lz4_compress: (/active|enabled/gi.test(pool.properties[26]) ? true : false),
+ multi_vdev_crash_dump: (/active|enabled/gi.test(pool.properties[27]) ? true : false),
+ obsolete_counts: (/active|enabled/gi.test(pool.properties[28]) ? true : false),
+ project_quota: (/active|enabled/gi.test(pool.properties[29]) ? true : false),
+ resilver_defer: (/active|enabled/gi.test(pool.properties[30]) ? true : false),
+ sha512: (/active|enabled/gi.test(pool.properties[31]) ? true : false),
+ skein: (/active|enabled/gi.test(pool.properties[32]) ? true : false),
+ spacemap_histogram: (/active|enabled/gi.test(pool.properties[33]) ? true : false),
+ spacemap_v2: (/active|enabled/gi.test(pool.properties[34]) ? true : false),
+ userobj_accounting: (/active|enabled/gi.test(pool.properties[35]) ? true : false),
+ zpool_checkpoint: (/active|enabled/gi.test(pool.properties[36]) ? true : false)
+ };
+ pool.fragmentation = (pool.properties[6] == "-" ? 0 : pool.properties[6]);
+ pool.free = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[5] });
+ pool.freepercent = FnRound({ decimals: 2, value: (pool.properties[5] / pool.properties[3]) * 100 });
+ pool.guid = pool.properties[1];
+ pool.health = pool.properties[2];
+ pool.healthicon = FnStoragePoolHealthIcon({ health: pool.properties[2] });
+ pool.id = FnGenerateId({ at: false, colon: true, forwardslash: false, period: true, underscore: true, whitespace: true }, { name: pool.properties[0], attribute: true });
+ pool.name = pool.properties[0];
+ pool.readonly = ((pool.properties[7].toLowerCase() == "on" || pool.boot && zfsmanager.configuration.zfs.storagepool.bootlockdown) ? true : false);
+ pool.size = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[3] });
+ pool.root = (zfsmanager.zfs.storagepool.root && pool.properties[0] == zfsmanager.zfs.storagepool.root ? true : false);
+ pool.upgrade = ($.isNumeric(pool.properties[8] && !pool.boot) ? true : false);
+ pool.version = pool.properties[10];
+
+ //Upgrade available if a requested feature flag returns false
+ if (!pool.boot) {
+ for (var x in pool.feature) {
+ if (!pool.feature[x] && !pool.upgrade) {
+ pool.upgrade = true;
+ }
+ }
+ }
+
+ $("#modals-storagepool-" + pool.id).remove();
+ $("#modals").append(`
`);
+
+ pool.output = `
+
+
+
+ Name: ` + pool.name + (pool.readonly ? ` ` : (pool.altroot ? ` ` : ``)) + `
+
+ Health: ` + pool.health + `
+
+
+ Size: ` + pool.size + `
+
+
+ Allocated: ` + pool.allocated + `
+
+
+ Free: ` + pool.free + `
+
+
+ Fragmentation: ` + pool.fragmentation + ` %
+
+
+ Usage:
+
+
+ ` + pool.allocatedpercent + `% Allocated
+
+
+ ` + pool.freepercent + `% Free
+
+
+
+
+ Upgrade Available:
+ ` + (pool.upgrade ? `Yes` : `No`) + `
+
+
+ `;
+
+ //Actions menu
+ pool.actionsmenu.items = {
+ itemconfigure: [],
+ itemconfiguredivider: function () {
+ if (this.itemconfigure.length > 0 && (this.itemconfigurefeatures.length > 0 || this.item.length > 0)) {
+ this.itemconfigure.push(this.divider);
+ }
+ },
+ itemconfigurefeatures: [],
+ itemconfigurefeaturesdivider: function () {
+ if (this.itemconfigurefeatures.length > 0 && this.item.length > 0) {
+ this.itemconfigurefeatures.push(this.divider);
+ }
+ },
+ item: [],
+ divider: ` `
+ };
+ pool.actionsmenu.display = function () {
+ if ((this.items.itemconfigure.length + this.items.itemconfigurefeatures.length + this.items.item.length) > 0) {
+ this.items.itemconfiguredivider();
+ this.items.itemconfigurefeaturesdivider();
+
+ return this.header + this.items.itemconfigure.join("\n") + this.items.itemconfigurefeatures.join("\n") + this.items.item.join("\n") + this.footer;
+ } else {
+ return "";
+ }
+ };
+ pool.actionsmenu.header = `
+
+
+
+
+
+
+ `;
+
+ //Configure Storage Pool
+ pool.actionsmenu.items.itemconfigure.push(`Configure Storage Pool `);
+
+ //Configure Storage Pool Features
+ pool.actionsmenu.items.itemconfigurefeatures.push(`Configure Storage Pool Features `);
+
+ //Export Storage Pool
+ if (!pool.boot && !pool.root) {
+ pool.actionsmenu.items.item.push(`Export Storage Pool `);
+
+ pool.actionsmenu.register.export = true;
+ }
+
+ //Destroy Storage Pool
+ if (!pool.readonly && !pool.boot && !pool.root) {
+ pool.actionsmenu.items.item.push(`Destroy Storage Pool `);
+
+ pool.actionsmenu.register.destroy = true;
+ }
+
+ pool.output += ``;
+
+ if (zfsmanager.configuration.zfs.storagepool.activetab == 2) {
+ pool.activetab = "snapshots";
+ } else if (zfsmanager.configuration.zfs.storagepool.activetab == 3) {
+ pool.activetab = "status";
+ }
+
+ pool.output += `
+
+
+
+
+
+
+
+
+
+
+
+ Create File System
+ Refresh
+
+
+
+
+
+ Name
+ Available
+ Used
+ Snapshots
+ Refreservation
+ Record Size
+ Compression
+ Deduplication
+ Share
+ Mounted
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create Snapshot
+ Refresh
+
+
+
+ ` + (zfsmanager.configuration.zfs.snapshot.filesystemlist ? `
` : ``) + `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ //Set active tab
+ $("#tab-storagepool-` + pool.activetab + `-` + pool.id + `").tab("show");
+
+ $("#btn-storagepool-filesystems-refresh-` + pool.id + `").on("click", function () {
+ $("#btn-storagepool-filesystems-create-` + pool.id + `").prop("disabled", true);
+ $("#btn-storagepool-filesystems-refresh-` + pool.id + `").prop("disabled", true);
+
+ $("[id^=btn-storagepool-filesystem-dropdown-` + pool.id + `]").addClass("disabled");
+ $("#paneltitle-storagepool-filesystems-` + pool.id + `").addClass("hidden");
+ $("#spinner-storagepool-filesystems-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolRefresh({ name: "` + pool.name + `", id: "` + pool.id + `" }, { storagepool: true, filesystems: true, snapshots: false, status: false });
+ });
+
+ $("#btn-storagepool-snapshots-refresh-` + pool.id + `").on("click", function () {
+ $("#btn-storagepool-snapshots-create-` + pool.id + `").prop("disabled", true);
+ $("#btn-storagepool-snapshots-refresh-` + pool.id + `").prop("disabled", true);
+
+ $("[id^=btn-storagepool-snapshot-dropdown-` + pool.id + `]").addClass("disabled");
+ $("#paneltitle-storagepool-snapshots-` + pool.id + `").addClass("hidden");
+ $("#spinner-storagepool-snapshots-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolRefresh({ name: "` + pool.name + `", id: "` + pool.id + `" }, { storagepool: true, filesystems: false, snapshots: true, status: false });
+ });
+
+ $("#btn-storagepool-status-refresh-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+
+ $(this).text("Refresh").prop("disabled", true);
+ $("#btn-storagepool-status-refresh-auto-` + pool.id + `").prop("disabled", true).parent().removeClass("open");;
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#paneltitle-storagepool-status-` + pool.id + `").addClass("hidden");
+ $("#spinner-storagepool-status-` + pool.id + `").removeClass("hidden");
+ $("#spinner-storagepool-status-0-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolRefresh({ name: "` + pool.name + `", id: "` + pool.id + `" }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ });
+
+ $("#dropdown-storagepool-status-refresh-` + pool.id + `").on("click", "li a", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ $("#btn-storagepool-status-refresh-` + pool.id + `").click();
+
+ if ($(this).attr("data-pool-refresh-interval") > 0) {
+ let statusrefreshtimer` + _index + ` = setInterval(function () {
+ $("#btn-storagepool-status-refresh-` + pool.id + `").prop("disabled", true);
+ $("#btn-storagepool-status-refresh-auto-` + pool.id + `").prop("disabled", true).parent().removeClass("open");
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#paneltitle-storagepool-status-` + pool.id + `").addClass("hidden");
+ $("#spinner-storagepool-status-` + pool.id + `").removeClass("hidden");
+ $("#spinner-storagepool-status-0-` + pool.id + `").removeClass("hidden");
+
+ setTimeout(function() {
+ FnStoragePoolRefresh({ name: "` + pool.name + `", id: "` + pool.id + `" }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ }, ($(this).attr("data-pool-refresh-interval") + "000"));
+
+ zfsmanager.zfs.storagepool.refreshid.push(statusrefreshtimer` + _index + `);
+
+ $("#tr-storagepool-` + pool.id + `").attr("data-pool-refresh-id", statusrefreshtimer` + _index + `);
+ $("#btn-storagepool-status-refresh-` + pool.id + `").text("Refresh: " + $(this).attr("data-pool-refresh-interval") + "s");
+
+ FnConsole.log[2]("Storage Pools, Refresh, Auto: Enabled, Pool: ` + pool.name + `");
+ }
+ });
+ \x3C/script>
+
+ `;
+
+ $("#table-storagepools").append(pool.output);
+
+ $("#progressbar-storagepool-allocated-" + pool.id).css("width", pool.allocatedpercent + "%");
+ $("#progressbar-storagepool-free-" + pool.id).css("width", pool.freepercent + "%");
+
+ //Register storage pool modals
+ FnModalStoragePoolConfigure({ name: pool.name, id: pool.id, boot: pool.boot, guid: pool.guid, readonly: false, root: pool.root });
+ FnModalStoragePoolConfigureFeatures({ name: pool.name, id: pool.id, boot: pool.boot, readonly: false });
+ if (pool.actionsmenu.register.destroy) {
+ FnModalStoragePoolDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot });
+ }
+ if (pool.actionsmenu.register.export) {
+ FnModalStoragePoolExport({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly });
+ }
+ });
+
+ $("#btn-storagepools-refresh").prop("disabled", false);
+
+ FnCockpitElementsUpdate();
+}
+
+function FnStoragePoolsImportableBlockDeviceGet(pools = { destroyed: false }) {
+ let process = {
+ command: ["/bin/sh", "-c", "/sbin/zpool import -d /dev" + (pools.destroyed ? " -D" : "") + " 2> /dev/null | /bin/grep -E 'pool:\| id:\|state:' | tr '\\\n' ','"]
+ };
+
+ FnConsole.log[2]("Storage Pools, Importable, Block Device, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Storage Pools, Importable, Block Device, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Importable, Block Device, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolsImportableDiskGet(pools = { destroyed: false }) {
+ let process = {
+ command: ["/bin/sh", "-c", "/sbin/zpool import -d /dev/disk/by-id" + (pools.destroyed ? " -D" : "") + " 2> /dev/null | /bin/grep -E 'pool:\| id:\|state:' | tr '\\\n' ','"]
+ };
+
+ FnConsole.log[2]("Storage Pools, Importable, Disk / WWN, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Storage Pools, Importable, Disk / WWN, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Importable, Disk / WWN, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolsImportableGet(pools = { destroyed: false }) {
+ let replacement = {
+ regexp: [
+ { pattern: /^(?: )+pool\:/gi, replacement: "pool\:" },
+ { pattern: /,(?: )+pool\:/gi, replacement: "\npool\:" },
+ { pattern: /,$/g, replacement: "" },
+ { pattern: /pool\: /gi, replacement: "" },
+ { pattern: /id\: /gi, replacement: "" },
+ { pattern: /state\: /gi, replacement: "" },
+ { pattern: /,(?: )+/g, replacement: "," }
+ ]
+ };
+
+ pools.importable = {
+ blockdevice: [],
+ disk: [],
+ path: [],
+ vdev: []
+ };
+
+ $("#listgroup-storagepools-import-storagepools").empty().append(`
`);
+
+ FnConsole.log[2]("Storage Pools, Importable, Get: In Progress");
+
+ FnStoragePoolsImportableDiskGet({ destroyed: pools.destroyed })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Importable, Disk / WWN, Get:" }));
+
+ if (/no pools available to import/gi.test(data) == false) {
+ pools.importable.disk = replacement.regexp.reduce((d, r) => d.replace(r.pattern, r.replacement), data).split(/\n/g).filter(v => v);
+ }
+
+ FnStoragePoolsImportableHardwarePathGet({ destroyed: pools.destroyed })
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Storage Pools, Importable, Hardware Path, Get:" }));
+
+ if (/no pools available to import/gi.test(_data) == false) {
+ pools.importable.path = replacement.regexp.reduce((d, r) => d.replace(r.pattern, r.replacement), _data).split(/\n/g).filter(v => v);
+ }
+
+ FnStoragePoolsImportableVirtualDeviceMappingGet({ destroyed: pools.destroyed })
+ .done(function (__data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: __data, message: "Storage Pools, Importable, Virtual Device Mapping, Get:" }));
+
+ if (/no pools available to import/gi.test(__data) == false) {
+ pools.importable.vdev = replacement.regexp.reduce((d, r) => d.replace(r.pattern, r.replacement), __data).split(/\n/g).filter(v => v);
+ }
+
+ FnStoragePoolsImportableBlockDeviceGet({ destroyed: pools.destroyed })
+ .done(function (___data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: ___data, message: "Storage Pools, Importable, Block Device, Get:" }));
+
+ if (/no pools available to import/gi.test(___data) == false) {
+ pools.importable.blockdevice = replacement.regexp.reduce((d, r) => d.replace(r.pattern, r.replacement), ___data).split(/\n/g).filter(v => v);
+
+ pools.importable.blockdevice.sort().forEach((_value, _index) => {
+ let pool = {
+ healthstatus: "",
+ properties: [],
+ id: {
+ blockdevice: true,
+ disk: false,
+ path: false,
+ vdev: false,
+ },
+ idtext: ["Block Device"]
+ };
+
+ pool.properties = _value.split(/,/g).filter(v => v);
+ pool.name = pool.properties[0].trim();
+ pool.guid = pool.properties[1].trim();
+ pool.health = pool.properties[2].trim();
+
+ pools.importable.disk.filter(v => { if (v.match(pool.name) && !pool.id.disk) { pool.id.disk = true; pool.idtext.push("Disk / WWN"); } });
+ pools.importable.path.filter(v => { if (v.match(pool.name) && !pool.id.path) { pool.id.path = true; pool.idtext.push("Hardware Path"); } });
+ pools.importable.vdev.filter(v => { if (v.match(pool.name) && !pool.id.vdev) { pool.id.vdev = true; pool.idtext.push("Virtual Device Mapping"); } });
+
+
+ if (/ONLINE/g.test(pool.health) == false) {
+ pool.healthstatus = ` `;
+
+ $("#helpblock-storagepools-import-storagepools-warning").html("One or more storage pools are in an unhealthy state." + pool.healthstatus);
+ }
+
+ pool.output = `
+
+
+
+
+ ` + pool.name + `
+ GUID: ` + pool.guid + `
+ Disk Identifiers: ` + pool.idtext.join(", ") + `
+
+ ` + pool.health.replace(/\(DESTROYED\)/i, "") + ` ` + pool.healthstatus + `
+
+
+ `;
+
+ $("#listgroup-storagepools-import-storagepools").append(pool.output);
+ });
+ }
+
+ setTimeout(function () {
+ $("#spinner-storagepools-import-storagepools").remove();
+ $("#listgroup-storagepools-import-storagepools > li").removeClass("hidden");
+ if ($("#helpblock-storagepools-import-storagepools-warning").text()) {
+ $("#helpblock-storagepools-import-storagepools-warning").removeClass("hidden");
+ }
+
+ if ($("#listgroup-storagepools-import-storagepools > li").length == 0) {
+ pools.output = `
+
+
+ No ` + (pools.destroyed ? "destroyed" : "importable") + ` storage pools found.
+
+
+ `;
+
+ $("#listgroup-storagepools-import-storagepools").append(pools.output);
+ }
+ }, 200);
+
+ FnConsole.log[1]("Storage Pools, Importable, Get: Success");
+ })
+ .fail(function (___message, ___data) {
+ if (/no pools available to import/gi.test(___data) == false) {
+ FnConsole.warn("Storage Pools, Importable, Get: Failed, Message: " + (___data ? ___data : ___message));
+ }
+
+ FnStoragePoolsImportableGetFail({ destroyed: pools.destroyed });
+ });
+ })
+ .fail(function (__message, __data) {
+ if (/no pools available to import/gi.test(__data) == false) {
+ FnConsole.warn("Storage Pools, Importable, Get: Failed, Message: " + (__data ? __data : __message));
+ }
+
+ FnStoragePoolsImportableGetFail({ destroyed: pools.destroyed });
+ });
+ })
+ .fail(function (_message, _data) {
+ if (/no pools available to import/gi.test(_data) == false) {
+ FnConsole.warn("Storage Pools, Importable, Get: Failed, Message: " + (_data ? _data : _message));
+ }
+
+ FnStoragePoolsImportableGetFail({ destroyed: pools.destroyed });
+ });
+ })
+ .fail(function (message, data) {
+ if (/no pools available to import/gi.test(data) == false) {
+ FnConsole.warn("Storage Pools, Importable, Get: Failed, Message: " + (data ? data : message));
+ }
+
+ FnStoragePoolsImportableGetFail({ destroyed: pools.destroyed });
+ });
+}
+
+function FnStoragePoolsImportableGetFail(pools = { destroyed: false }) {
+ setTimeout(function () {
+ $("#spinner-storagepools-import-storagepools").remove();
+ $("#listgroup-storagepools-import-storagepools > li").removeClass("hidden");
+
+ if ($("#listgroup-storagepools-import-storagepools > li").length == 0) {
+ pools.output = `
+
+
+ No ` + (pools.destroyed ? "destroyed" : "importable") + ` storage pools found.
+
+
+ `;
+
+ $("#listgroup-storagepools-import-storagepools").append(pools.output);
+ }
+ }, 200);
+}
+
+function FnStoragePoolsImportableHardwarePathGet(pools = { destroyed: false }) {
+ let process = {
+ command: ["/bin/sh", "-c", "/sbin/zpool import -d /dev/disk/by-path" + (pools.destroyed ? " -D" : "") + " 2> /dev/null | /bin/grep -E 'pool:\| id:\|state:' | tr '\\\n' ','"]
+ };
+
+ FnConsole.log[2]("Storage Pools, Importable, Hardware Path, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Storage Pools, Importable, Hardware Path, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Importable, Hardware Path, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolsImportableVirtualDeviceMappingGet(pools = { destroyed: false }) {
+ let process = {
+ command: ["/bin/sh", "-c", "/sbin/zpool import -d /dev/disk/by-vdev" + (pools.destroyed ? " -D" : "") + " 2> /dev/null | /bin/grep -E 'pool:\| id:\|state:' | tr '\\\n' ','"]
+ };
+
+ FnConsole.log[2]("Storage Pools, Importable, Virtual Device Mapping, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Storage Pools, Importable, Virtual Device Mapping, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Importable, Virtual Device Mapping, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolsSystemReservedGet() {
+ let filesystems = {
+ id: []
+ };
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name,mountpoint", "-d", "3"]
+ };
+
+ FnConsole.log[2]("Storage Pools, System Reserved, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done((data) => {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, System Reserved, Get:" }));
+
+ filesystems.id = data.split(/\n/g).filter(v => v);
+
+ filesystems.id.forEach((_value, _index) => {
+ let filesystem = {
+ properties: _value.split(/\t/g).filter(v => v)
+ };
+
+ filesystem.name = filesystem.properties[0];
+ filesystem.mountpoint = filesystem.properties[1].trim();
+
+ if (filesystem.mountpoint == "/boot" && !zfsmanager.zfs.storagepool.boot) {
+ zfsmanager.zfs.storagepool.boot = filesystem.name.split("/")[0];
+ } else if (filesystem.mountpoint == "/" && !zfsmanager.zfs.storagepool.root) {
+ zfsmanager.zfs.storagepool.root = filesystem.name.split("/")[0];
+ }
+ });
+
+ FnConsole.log[1]("Storage Pools, System Reserved, Get: Success");
+ })
+ .fail((message, data) => {
+ FnConsole.warn("Storage Pools, System Reserved, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolsTemporaryGet() {
+ let process = {
+ command: ["/sbin/zpool", "list", "-H", "-o", "name,readonly,altroot"]
+ };
+
+ FnConsole.log[2]("Storage Pools, Temporary, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function () {
+ FnConsole.log[1]("Storage Pools, Temporary, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Temporary, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+//#endregion
+
+//#region Storage Pool
+
+function FnStoragePoolAlternativeRootGet(pool = { name, id }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "list", "-H", "-o", "altroot", pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Alternative Root, Get: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Alternative Root, Get:" }));
+
+ data = data.replace(/\n+/g, "");
+
+ $("#input-" + modal.name + "-mountpoint-" + modal.id).attr("data-field-altroot", data);
+
+ FnConsole.log[1]("Storage Pools, Alternative Root, Get: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Alternative Root, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolClear(pool = { name, id }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "clear", pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Clear Errors: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Clearing storage pool errors...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Storage Pool errors successfully cleared", description: pool.name, breakword: false }, { name: "storagepool-clear", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Clear Errors: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool errors could not be cleared", description: pool.name, breakword: false }, { name: "storagepool-clear", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Clear Errors: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });
+}
+
+function FnStoragePoolConfigurationFeaturesDisabledGet(pool = { name, id }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "get", "feature@allocation_classes,feature@async_destroy,feature@bookmark_v2,feature@bookmarks,feature@device_removal,feature@edonr,feature@embedded_data,feature@empty_bpobj,feature@enabled_txg,feature@encryption,feature@extensible_dataset,feature@filesystem_limits,feature@hole_birth,feature@large_blocks,feature@large_dnode,feature@lz4_compress,feature@multi_vdev_crash_dump,feature@obsolete_counts,feature@project_quota,feature@resilver_defer,feature@sha512,feature@skein,feature@spacemap_histogram,feature@spacemap_v2,feature@userobj_accounting,feature@zpool_checkpoint", "-H", "-o", "property,value", pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Configuration, Features, Disabled, Get: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Configuration, Features, Disabled, Get:" }));
+
+ pool.configuration = data.replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v);
+ pool.disabled = [];
+
+ pool.configuration.forEach((_value, _index) => {
+ _value = _value.split("\u22C5");
+
+ pool.properties = {
+ property: _value[0].toLowerCase(),
+ value: _value[1].toLowerCase()
+ };
+
+ switch (pool.properties.property) {
+ case "feature@allocation_classes":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Allocation Classes");
+ }
+ break;
+ case "feature@async_destroy":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Asynchronous Destroy");
+ }
+ break;
+ case "feature@bookmark_v2":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Bookmarks Version 2");
+ }
+ break;
+ case "feature@bookmarks":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Bookmarks");
+ }
+ break;
+ case "feature@device_removal":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Device Removal");
+ }
+ break;
+ case "feature@edonr":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Edon-R");
+ }
+ break;
+ case "feature@embedded_data":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Embedded Data");
+ }
+ break;
+ case "feature@empty_bpobj":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Empty Block Pointer Objects");
+ }
+ break;
+ case "feature@enabled_txg":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Transaction Group Accounting");
+ }
+ break;
+ case "feature@encryption":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Encryption");
+ }
+ break;
+ case "feature@extensible_dataset":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Extensible Dataset");
+ }
+ break;
+ case "feature@filesystem_limits":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("File System Limits");
+ }
+ break;
+ case "feature@hole_birth":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Hole Birth");
+ }
+ break;
+ case "feature@large_blocks":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Large Blocks");
+ }
+ break;
+ case "feature@large_dnode":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Large DNode");
+ }
+ break;
+ case "feature@lz4_compress":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("LZ4 Compression");
+ }
+ break;
+ case "feature@multi_vdev_crash_dump":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Multi Virtual Device Crash Dump");
+ }
+ break;
+ case "feature@obsolete_counts":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Obsolete Counts");
+ }
+ break;
+ case "feature@project_quota":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Project Quota");
+ }
+ break;
+ case "feature@resilver_defer":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Resilver Defer");
+ }
+ break;
+ case "feature@sha512":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("SHA-512");
+ }
+ break;
+ case "feature@skein":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Skein");
+ }
+ break;
+ case "feature@spacemap_histogram":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Space Map Histogram");
+ }
+ break;
+ case "feature@spacemap_v2":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Space Map Version 2");
+ }
+ break;
+ case "feature@userobj_accounting":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("User Object Accounting");
+ }
+ break;
+ case "feature@zpool_checkpoint":
+ if (/disabled/gi.test(pool.properties.value)) {
+ pool.disabled.push("Checkpoint");
+ }
+ break;
+ }
+ });
+
+ $("#ul-" + modal.name + "-features-" + modal.id).append(`` + pool.disabled.sort().join(` \n`) + ` `);
+
+ FnConsole.log[1]("Storage Pools, Configuration, Features, Disabled, Get: Success, Pool: " + pool.name);
+
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Configuration, Features, Disabled, Get: In Progress, Pool: " + pool.name + " , Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolConfigurationFeaturesGet(pool = { name, id, boot: false }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "get", "readonly,feature@allocation_classes,feature@async_destroy,feature@bookmark_v2,feature@bookmarks,feature@device_removal,feature@edonr,feature@embedded_data,feature@empty_bpobj,feature@enabled_txg,feature@encryption,feature@extensible_dataset,feature@filesystem_limits,feature@hole_birth,feature@large_blocks,feature@large_dnode,feature@lz4_compress,feature@multi_vdev_crash_dump,feature@obsolete_counts,feature@project_quota,feature@resilver_defer,feature@sha512,feature@skein,feature@spacemap_histogram,feature@spacemap_v2,feature@userobj_accounting,feature@zpool_checkpoint", "-H", "-o", "property,value", pool.name]
+ };
+
+ pool.readonly = false;
+
+ FnConsole.log[2]("Storage Pools, Configuration, Features, Get: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Configuration, Features, Get:" }));
+
+ pool.configuration = data.replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v);
+
+ pool.configuration.forEach((_value, _index) => {
+ _value = _value.split("\u22C5");
+
+ pool.properties = {
+ property: _value[0].toLowerCase(),
+ value: _value[1].toLowerCase()
+ };
+
+ switch (pool.properties.property) {
+ case "feature@allocation_classes":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-allocation_classes-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-allocation_classes-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-allocation_classes-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-allocation_classes-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@async_destroy":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-async_destroy-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-async_destroy-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-async_destroy-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-async_destroy-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@bookmark_v2":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-bookmark_v2-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-bookmark_v2-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-bookmark_v2-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-bookmark_v2-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@bookmarks":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-bookmarks-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-bookmarks-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-bookmarks-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-bookmarks-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@device_removal":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-device_removal-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-device_removal-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-device_removal-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-device_removal-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@edonr":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-edonr-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-edonr-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-edonr-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-edonr-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@embedded_data":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-embedded_data-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-embedded_data-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-embedded_data-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-embedded_data-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@empty_bpobj":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-empty_bpobj-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-empty_bpobj-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-empty_bpobj-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-empty_bpobj-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@enabled_txg":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-enabled_txg-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-enabled_txg-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-enabled_txg-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-enabled_txg-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@encryption":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-encryption-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-encryption-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@extensible_dataset":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-extensible_dataset-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-extensible_dataset-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-extensible_dataset-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-extensible_dataset-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@filesystem_limits":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-filesystem_limits-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-filesystem_limits-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-filesystem_limits-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-filesystem_limits-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@hole_birth":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-hole_birth-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-hole_birth-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-hole_birth-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-hole_birth-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@large_blocks":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-large_blocks-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-large_blocks-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-large_blocks-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-large_blocks-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@large_dnode":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-large_dnode-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-large_dnode-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-large_dnode-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-large_dnode-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@lz4_compress":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-lz4_compress-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-lz4_compress-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-lz4_compress-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-lz4_compress-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@multi_vdev_crash_dump":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-multi_vdev_crash_dump-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-multi_vdev_crash_dump-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-multi_vdev_crash_dump-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-multi_vdev_crash_dump-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@obsolete_counts":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-obsolete_counts-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-obsolete_counts-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-obsolete_counts-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-obsolete_counts-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@project_quota":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-project_quota-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-project_quota-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-project_quota-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-project_quota-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@resilver_defer":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-resilver_defer-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-resilver_defer-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-resilver_defer-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-resilver_defer-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@sha512":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-sha512-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-sha512-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-sha512-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-sha512-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@skein":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-skein-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-skein-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-skein-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-skein-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@spacemap_histogram":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-spacemap_histogram-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-spacemap_histogram-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-spacemap_histogram-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-spacemap_histogram-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@spacemap_v2":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-spacemap_v2-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-spacemap_v2-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-spacemap_v2-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-spacemap_v2-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@userobj_accounting":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-userobj_accounting-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-userobj_accounting-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-userobj_accounting-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-userobj_accounting-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "feature@zpool_checkpoint":
+ if (/active|enabled/gi.test(pool.properties.value) && !$("#switch-" + modal.name + "-zpool_checkpoint-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-zpool_checkpoint-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-zpool_checkpoint-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || /active|enabled/gi.test(pool.properties.value)) {
+ $("#switch-" + modal.name + "-zpool_checkpoint-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "readonly": //Default is off
+ if (pool.properties.value == "on" || pool.boot && zfsmanager.configuration.zfs.storagepool.bootlockdown || !zfsmanager.user.admin) {
+ pool.readonly = true;
+ }
+ break;
+ }
+ });
+
+ if (pool.readonly) {
+ $("#btn-" + modal.name + "-apply-" + modal.id).prop("disabled", true);
+ }
+
+ FnConsole.log[1]("Storage Pools, Configuration, Features, Get: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Configuration, Features, Get: Failed, Pool: " + pool.name + " , Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolConfigurationGet(pool = { name, id, boot: false, root: false }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "get", "readonly,altroot,ashift,autoexpand,autoreplace,autotrim,bootfs,cachefile,comment,delegation,failmode,guid,listsnapshots,multihost,version", "-H", "-o", "property,value", pool.name]
+ };
+
+ pool.readonly = false;
+
+ FnConsole.log[2]("Storage Pools, Configuration, Get: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Configuration, Get:" }));
+
+ pool.configuration = data.replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v);
+
+ pool.configuration.forEach((_value, _index) => {
+ _value = _value.split("\u22C5");
+
+ pool.properties = {
+ property: _value[0].toLowerCase(),
+ value: _value[1].toLowerCase(),
+ valueraw: _value[1],
+ };
+
+ switch (pool.properties.property) {
+ case "altroot": //Default is empty (-)
+ if (pool.properties.valueraw && pool.properties.valueraw == "-") {
+ pool.properties.valueraw = "";
+ }
+
+ if (pool.properties.valueraw) {
+ $("#controllabel-" + modal.name + "-altroot-" + modal.id).removeClass("hidden");
+ $("#div-" + modal.name + "-altroot-" + modal.id).removeClass("hidden").text(pool.properties.valueraw);
+ }
+ break;
+ case "ashift": //Default is 0
+ pool.property = {
+ value: "Auto Detect",
+ };
+
+ switch (pool.properties.value) {
+ case "0":
+ pool.property.value = "Auto Detect";
+ break;
+ case "9":
+ pool.property.value = "512 B";
+ break;
+ case "12":
+ pool.property.value = "4 KiB";
+ break;
+ case "13":
+ pool.property.value = "8 KiB";
+ break;
+ case "14":
+ pool.property.value = "16 KiB";
+ break;
+ case "15":
+ pool.property.value = "32 KiB";
+ break;
+ case "16":
+ pool.property.value = "64 KiB";
+ break;
+ default:
+ pool.property.value = "Auto Detect";
+ break;
+ }
+
+ $("#btnspan-" + modal.name + "-ashift-" + modal.id).text(pool.property.value).attr("data-field-value", pool.properties.value);
+ $("#dropdown-" + modal.name + "-ashift-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-ashift-" + modal.id + " li[value='" + pool.properties.valueraw + "']").addClass("active");
+
+ if (pool.readonly) {
+ $("#div-" + modal.name + "-ashift-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ case "autoexpand": //Default is off
+ if (pool.properties.value == "on" && !$("#switch-" + modal.name + "-autoexpand-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-autoexpand-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-autoexpand-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly) {
+ $("#switch-" + modal.name + "-autoexpand-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "autoreplace": //Default is off
+ if (pool.properties.value == "on" && !$("#switch-" + modal.name + "-autoreplace-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-autoreplace-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-autoreplace-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly) {
+ $("#switch-" + modal.name + "-autoreplace-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "autotrim": //Default is off
+ if (pool.properties.value == "on" && !$("#switch-" + modal.name + "-autotrim-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-autotrim-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-autotrim-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly) {
+ $("#switch-" + modal.name + "-autotrim-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "comment": //Default is empty (-)
+ if (pool.properties.valueraw && pool.properties.valueraw == "-") {
+ pool.properties.valueraw = "";
+ }
+
+ $("#input-" + modal.name + "-comment-" + modal.id).val(pool.properties.valueraw);
+ $("#input-" + modal.name + "-comment-" + modal.id).attr("data-field-value", pool.properties.valueraw);
+
+ if (pool.readonly) {
+ $("#input-" + modal.name + "-comment-" + modal.id).prop("disabled", true);
+ }
+
+ break;
+ case "delegation": //Default is on
+ if (pool.properties.value == "off" && $("#switch-" + modal.name + "-delegation-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-delegation-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-delegation-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly) {
+ $("#switch-" + modal.name + "-delegation-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "failmode": //Default is wait
+ pool.property = {
+ value: pool.properties.value.charAt(0).toUpperCase() + pool.properties.value.slice(1),
+ };
+
+ $("#btnspan-" + modal.name + "-failmode-" + modal.id).text(pool.property.value).attr("data-field-value", pool.properties.value);
+ $("#dropdown-" + modal.name + "-failmode-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-failmode-" + modal.id + " li[value='" + pool.properties.valueraw + "']").addClass("active");
+
+ if (pool.readonly) {
+ $("#div-" + modal.name + "-failmode-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ case "guid":
+ $("#div-" + modal.name + "-guid-" + modal.id).html(pool.properties.value);
+ break;
+ case "listsnapshots": //Default is off
+ if (pool.properties.value == "on" && !$("#switch-" + modal.name + "-listsnapshots-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-listsnapshots-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-listsnapshots-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly) {
+ $("#switch-" + modal.name + "-listsnapshots-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "multihost": //Default is off
+ if (pool.properties.value == "on" && !$("#switch-" + modal.name + "-multihost-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-multihost-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-multihost-" + modal.id).attr("data-field-value", pool.properties.value);
+
+ if (pool.readonly || pool.boot || pool.root) {
+ $("#switch-" + modal.name + "-multihost-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "readonly": //Default is off
+ if (pool.properties.value == "on" || pool.boot && zfsmanager.configuration.zfs.storagepool.bootlockdown || !zfsmanager.user.admin) {
+ pool.readonly = true;
+ }
+
+ $("#div-" + modal.name + "-readonly-" + modal.id).html((pool.properties.value == "on" ? "Yes" : "No"));
+ break;
+ }
+ });
+
+ if (pool.readonly) {
+ $("#btn-" + modal.name + "-apply-" + modal.id).prop("disabled", true);
+ }
+
+ FnConsole.log[1]("Storage Pools, Configuration, Get: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Configuration, Get: Failed, Pool: " + pool.name + " , Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolConfigure(pool = { name, id, ashift, autoexpand, autoreplace, autotrim, comment, delegation, failmode, listsnapshots, multihost, readonly: false }, system = { hostid }, modal = { id }) {
+ pool.properties = {
+ new: []
+ };
+
+ if (pool.ashift) {
+ pool.properties.new.push("ashift=" + pool.ashift);
+ }
+ if (pool.autoexpand) {
+ pool.properties.new.push("autoexpand=" + pool.autoexpand);
+ }
+ if (pool.autoreplace) {
+ pool.properties.new.push("autoreplace=" + pool.autoreplace);
+ }
+ if (pool.autotrim) {
+ pool.properties.new.push("autotrim=" + pool.autotrim);
+ }
+ if (pool.comment) {
+ if (pool.comment == "$empty") {
+ pool.comment = "";
+ }
+
+ pool.properties.new.push("comment=" + pool.comment);
+ }
+ if (pool.delegation) {
+ pool.properties.new.push("delegation=" + pool.delegation);
+ }
+ if (pool.failmode) {
+ pool.properties.new.push("failmode=" + pool.failmode);
+ }
+ if (pool.listsnapshots) {
+ pool.properties.new.push("listsnapshots=" + pool.listsnapshots);
+ }
+ if (pool.multihost) {
+ pool.properties.new.push("multihost=" + pool.multihost);
+ }
+
+ if (system.hostid) {
+ FnSystemHostIdSet({ hostid: (system.hostid == "random" ? null : "\$\(hostid\)") })
+ .finally(function () {
+ if (pool.properties.new.length > 0 && !pool.readonly) {
+ FnConsole.log[2]("Storage Pools, Configure: In Progress, Pool: " + pool.name);
+
+ $("#spinner-storagepool-configure-" + pool.id + " span").text("Configuring storage pool...");
+
+ FnStoragePoolConfigureCommand({ name: pool.name, id: pool.id, properties: { new: pool.properties.new } }, { id: modal.id });
+ } else {
+ modal.id.modal("hide");
+ }
+ });
+ } else {
+ if (pool.properties.new.length > 0 && !pool.readonly) {
+ FnConsole.log[2]("Storage Pools, Configure: In Progress, Pool: " + pool.name);
+
+ $("#spinner-storagepool-configure-" + pool.id + " span").text("Configuring storage pool...");
+
+ FnStoragePoolConfigureCommand({ name: pool.name, id: pool.id, properties: { new: pool.properties.new } }, { id: modal.id });
+ } else {
+ modal.id.modal("hide");
+ }
+ }
+}
+
+function FnStoragePoolConfigureCommand(pool = { name, id, properties: { new: [] } }, modal = { id }) {
+ let promise = Promise.resolve();
+
+ pool.properties.errorcount = 0;
+
+ pool.properties.new.forEach((_value, _index) => {
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ let process = {
+ command: ["/sbin/zpool", "set", _value, pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Configure: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ if (_index == (pool.properties.new.length - 1)) {
+ if (pool.properties.errorcount == 0) {
+ FnDisplayAlert({ status: "success", title: "Storge Pool successfully configured", description: pool.name, breakword: false }, { name: "storagepool-configure", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Configure: Success, Pool: " + pool.name);
+ } else {
+ FnStoragePoolConfigureFail({ name: pool.name, id: pool.id });
+ }
+
+ modal.id.modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
+ }, 200);
+ }
+ })
+ .fail(function (message, data) {
+ pool.properties.errorcount++;
+
+ FnConsole.warn("Storage Pools, Property, Set: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+
+ if (_index == (pool.properties.new.length - 1)) {
+ FnStoragePoolConfigureFail({ name: pool.name, id: pool.id });
+
+ modal.id.modal("hide");
+ }
+ });
+
+ resolve();
+ }, 500)
+ ));
+ });
+}
+
+function FnStoragePoolConfigureFail(pool = { name, id }) {
+ FnDisplayAlert({ status: "danger", title: "Storge Pool could not be configured", description: pool.name, breakword: false }, { name: "storagepool-configure", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Configure: Failed, Pool: " + pool.name);
+}
+
+function FnStoragePoolConfigureFeatures(pool = { name, id, feature: { allocation_classes, async_destroy, bookmark_v2, bookmarks, device_removal, edonr, embedded_data, empty_bpobj, enabled_txg, encryption, extensible_dataset, filesystem_limits, hole_birth, large_blocks, large_dnode, lz4_compress, multi_vdev_crash_dump, obsolete_counts, project_quota, resilver_defer, sha512, skein, spacemap_histogram, spacemap_v2, userobj_accounting, zpool_checkpoint }, readonly: false }, modal = { id }) {
+ pool.features = {
+ new: []
+ };
+
+ if (pool.feature.allocation_classes) {
+ pool.features.new.push("feature@allocation_classes=" + pool.feature.allocation_classes);
+ }
+ if (pool.feature.async_destroy) {
+ pool.features.new.push("feature@async_destroy=" + pool.feature.async_destroy);
+ }
+ if (pool.feature.bookmark_v2) {
+ pool.features.new.push("feature@bookmark_v2=" + pool.feature.bookmark_v2);
+ }
+ if (pool.feature.bookmarks) {
+ pool.features.new.push("feature@bookmarks=" + pool.feature.bookmarks);
+ }
+ if (pool.feature.device_removal) {
+ pool.features.new.push("feature@device_removal=" + pool.feature.device_removal);
+ }
+ if (pool.feature.edonr) {
+ pool.features.new.push("feature@edonr=" + pool.feature.edonr);
+ }
+ if (pool.feature.embedded_data) {
+ pool.features.new.push("feature@embedded_data=" + pool.feature.embedded_data);
+ }
+ if (pool.feature.empty_bpobj) {
+ pool.features.new.push("feature@empty_bpobj=" + pool.feature.empty_bpobj);
+ }
+ if (pool.feature.enabled_txg) {
+ pool.features.new.push("feature@enabled_txg=" + pool.feature.enabled_txg);
+ }
+ if (pool.feature.encryption) {
+ pool.features.new.push("feature@encryption=" + pool.feature.encryption);
+ }
+ if (pool.feature.extensible_dataset) {
+ pool.features.new.push("feature@extensible_dataset=" + pool.feature.extensible_dataset);
+ }
+ if (pool.feature.filesystem_limits) {
+ pool.features.new.push("feature@filesystem_limits=" + pool.feature.filesystem_limits);
+ }
+ if (pool.feature.hole_birth) {
+ pool.features.new.push("feature@hole_birth=" + pool.feature.hole_birth);
+ }
+ if (pool.feature.large_blocks) {
+ pool.features.new.push("feature@large_blocks=" + pool.feature.large_blocks);
+ }
+ if (pool.feature.large_dnode) {
+ pool.features.new.push("feature@large_dnode=" + pool.feature.large_dnode);
+ }
+ if (pool.feature.lz4_compress) {
+ pool.features.new.push("feature@lz4_compress=" + pool.feature.lz4_compress);
+ }
+ if (pool.feature.multi_vdev_crash_dump) {
+ pool.features.new.push("feature@multi_vdev_crash_dump=" + pool.feature.multi_vdev_crash_dump);
+ }
+ if (pool.feature.obsolete_counts) {
+ pool.features.new.push("feature@obsolete_counts=" + pool.feature.obsolete_counts);
+ }
+ if (pool.feature.project_quota) {
+ pool.features.new.push("feature@project_quota=" + pool.feature.project_quota);
+ }
+ if (pool.feature.resilver_defer) {
+ pool.features.new.push("feature@resilver_defer=" + pool.feature.resilver_defer);
+ }
+ if (pool.feature.sha512) {
+ pool.features.new.push("feature@sha512=" + pool.feature.sha512);
+ }
+ if (pool.feature.skein) {
+ pool.features.new.push("feature@skein=" + pool.feature.skein);
+ }
+ if (pool.feature.spacemap_histogram) {
+ pool.features.new.push("feature@spacemap_histogram=" + pool.feature.spacemap_histogram);
+ }
+ if (pool.feature.spacemap_v2) {
+ pool.features.new.push("feature@spacemap_v2=" + pool.feature.spacemap_v2);
+ }
+ if (pool.feature.userobj_accounting) {
+ pool.features.new.push("feature@userobj_accounting=" + pool.feature.userobj_accounting);
+ }
+ if (pool.feature.zpool_checkpoint) {
+ pool.features.new.push("feature@zpool_checkpoint=" + pool.feature.zpool_checkpoint);
+ }
+
+ if (pool.features.new.length > 0 && !pool.readonly) {
+ FnConsole.log[2]("Storage Pools, Configure, Features: In Progress, Pool: " + pool.name);
+
+ $("#spinner-storagepool-configure-features-" + pool.id + " span").text("Configuring storage pool features...");
+
+ FnStoragePoolConfigureFeaturesCommand({ name: pool.name, id: pool.id, features: { new: pool.features.new } }, { id: modal.id });
+ } else {
+ modal.id.modal("hide");
+ }
+}
+
+function FnStoragePoolConfigureFeaturesCommand(pool = { name, id, features: { new: [] } }, modal = { id }) {
+ let promise = Promise.resolve();
+
+ pool.features.errorcount = 0;
+
+ pool.features.new.forEach((_value, _index) => {
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ let process = {
+ command: ["/sbin/zpool", "set", _value, pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Configure, Features: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ if (_index == (pool.features.new.length - 1)) {
+ if (pool.features.errorcount == 0) {
+ FnDisplayAlert({ status: "success", title: "Storge Pool features successfully configured", description: pool.name, breakword: false }, { name: "storagepool-configure-features", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Configure, Features: Success, Pool: " + pool.name);
+ } else {
+ FnStoragePoolConfigureFeaturesFail({ name: pool.name, id: pool.id });
+ }
+
+ modal.id.modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: true });
+ }, 200);
+ }
+ })
+ .fail(function (message, data) {
+ pool.features.errorcount++;
+
+ FnConsole.warn("Storage Pools, Feature, Set: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+
+ if (_index == (pool.features.new.length - 1)) {
+ FnStoragePoolConfigureFeaturesFail({ name: pool.name, id: pool.id });
+
+ modal.id.modal("hide");
+ }
+ });
+
+ resolve();
+ }, 500)
+ ));
+ });
+}
+
+function FnStoragePoolConfigureFeaturesFail(pool = { name, id }) {
+ FnDisplayAlert({ status: "danger", title: "Storge Pool features could not be configured", description: pool.name, breakword: false }, { name: "storagepool-configure-features", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Configure, Features: Failed, Pool: " + pool.name);
+}
+
+function FnStoragePoolCreate(pool = { name, ashift, autoexpand, autoreplace, autotrim, force, virtualdevice }, filesystem = { compression, dedup, recordsize, refreservationpercent, selinux }, disks = { id: [] }) {
+ let process = {
+ command: ["/sbin/zpool", "create", "-o", "ashift=" + pool.ashift, "-o", "autoexpand=" + pool.autoexpand, "-o", "autoreplace=" + pool.autoreplace, "-o", "autotrim=" + pool.autotrim, "-O", "aclinherit=passthrough", "-O", "acltype=posixacl", "-O", "casesensitivity=sensitive", "-O", "compression=" + filesystem.compression, "-O", "normalization=formD", "-O", "recordsize=" + filesystem.recordsize, "-O", "sharenfs=off", "-O", "sharesmb=off", "-O", "utf8only=on", "-O", "xattr=sa", pool.name]
+ };
+ let modal = {
+ hide: true
+ };
+
+ if (filesystem.selinux) {
+ process.command.splice((process.command.length - 1), 0, "-O");
+ process.command.splice((process.command.length - 1), 0, "context=system_u:object_r:samba_share_t:s0");
+ process.command.splice((process.command.length - 1), 0, "-O");
+ process.command.splice((process.command.length - 1), 0, "fscontext=system_u:object_r:samba_share_t:s0");
+ process.command.splice((process.command.length - 1), 0, "-O");
+ process.command.splice((process.command.length - 1), 0, "defcontext=system_u:object_r:samba_share_t:s0");
+ process.command.splice((process.command.length - 1), 0, "-O");
+ process.command.splice((process.command.length - 1), 0, "rootcontext=system_u:object_r:samba_share_t:s0");
+ }
+ if (filesystem.dedup) {
+ process.command.splice((process.command.length - 1), 0, "-O");
+ process.command.splice((process.command.length - 1), 0, "dedup=" + filesystem.dedup);
+ }
+ if (pool.force) {
+ process.command.splice(2, 0, "-f");
+ }
+ if (pool.virtualdevice) {
+ process.command.push(pool.virtualdevice);
+ }
+
+ disks.id.forEach(_value => _value && process.command.push(_value));
+
+ pool.id = FnGenerateId({ at: false, colon: true, forwardslash: false, period: true, underscore: true, whitespace: true }, { name: pool.name, attribute: true });
+
+ FnConsole.log[1]("Storage Pools, Create: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-storagepools-create span").text("Creating storage pool...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Storage Pool successfully created", description: pool.name, breakword: false }, { name: "storagepool-create", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Create: Success, Pool: " + pool.name);
+
+ if (filesystem.refreservationpercent > 0) {
+ FnStoragePoolSizeGet({ name: pool.name, id: null })
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Storage Pools, Size, Get:" }));
+
+ if (_data) {
+ _data = _data.replace(/\n+/g, "");
+
+ filesystem.refreservation = ((_data / 100) * filesystem.refreservationpercent);
+
+ FnStoragePoolRefreservationSet({ name: pool.name, id: null }, { refreservation: filesystem.refreservation });
+ }
+ });
+ }
+ })
+ .fail(function (message, data) {
+ if (/pool already exists/gi.test(data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepools-create-name").addClass("has-error");
+ $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name already exists.");
+ $("#input-storagepools-create-name").focus();
+ } else if (/contains devices of different sizes/gi.test(data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepools-create-disks").addClass("has-error");
+ $("#helpblock-storagepools-create-disks").addClass("has-error").removeClass("hidden").text("Disks are of different sizes. Forcefully create storage pool to override.");
+ } else {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool could not be created", description: pool.name, breakword: false }, { name: "storagepool-create", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.warn("Storage Pools, Create: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+
+ if (!modal.hide) {
+ $("#spinner-storagepools-create").addClass("hidden");
+ $("#spinner-storagepools-create span").text("");
+ $("#btn-storagepools-create-apply").prop("disabled", false);
+ }
+ })
+ .finally(function () {
+ if (modal.hide) {
+ $("#modal-storagepools-create").modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ });
+}
+
+function FnStoragePoolDestroy(pool = { name, id, altroot: false, force: false, labelclear: false }, samba = { restart: false }) {
+ let disks = {
+ attached: []
+ };
+
+ pool.attached = [];
+ pool.attachedconfig = [];
+
+ if (pool.labelclear) {
+ FnDisksStoragePoolsAttachedGet({ name: pool.name, id: pool.id }, { id: { blockdevice: true } })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Disks, Storage Pools, Attached, Get:" }));
+
+ pool.attached = data.replace(/\n\t+/g, "[TAB1]").split(/\n/g).filter(v => v);
+
+ pool.attached.forEach((_value, _index) => {
+ if (/\[TAB1\]NAME/g.test(_value)) { //Config header row
+ _value = _value.split("upath").slice(1).join("."); //Remove config header row (and any previous text if exists)
+
+ if (new RegExp("^\\[TAB1\\]" + pool.name).test(_value)) { //Confirm config rows
+ _value.split("[TAB1]").filter(v => v && pool.attachedconfig.push(v));
+ }
+ }
+ });
+
+ pool.attachedconfig.forEach((_value, _index) => {
+ let config = {
+ disk: {
+ upath: ""
+ },
+ tier: {
+ level: (_value.match(/^\s*/g)[0].length / 2)
+ }
+ };
+
+ _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
+
+ if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[5])) { //upath
+ config.disk.upath = _value[5];
+ } else if (!$.isNumeric(_value[0]) && _value[5] != "was") { //upath appears after error messages and before trim messages
+ for (let i = 5; i < _value.length; i++) {
+ if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[i])) {
+ config.disk.upath = _value[i];
+ }
+ }
+ }
+
+ if (config.tier.level > 0) {
+ if (/^\/dev\/nvme|^\/dev\/sd/gi.test(config.disk.upath)) { //Block Device via upath
+ disks.attached.push(config.disk.upath.replace(/^\/dev\//gi, ""));
+ } else if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[0])) { //Block Device
+ if (/^\/dev\/nvme\d+n\d+p\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/p\d+$/, ""));
+ } else if (/^\/dev\/sd.*\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/\d+$/, ""));
+ } else {
+ disks.attached.push(_value[0]);
+ }
+ } else if (/^nvme-nvme/gi.test(_value[0]) || /^wwn-/gi.test(_value[0])) { //WWN
+ if (/^nvme-nvme.*-part\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/-part\d+$/, ""));
+ } else if (/^wwn-.*-part\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/-part\d+$/, ""));
+ } else {
+ disks.attached.push(_value[0]);
+ }
+ }
+ }
+ });
+
+ disks.attached.sort();
+ });
+ }
+
+ if (samba.restart) {
+ FnSambaStop()
+ .finally(function () {
+ if (zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: [] })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Destroying storage pool...");
+
+ if (filesystems.id.length > 0) {
+ FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
+ .done(function () {
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Destroying Samba shares...");
+
+ FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
+ .finally(function () {
+ if (pool.labelclear) {
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
+
+ FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
+ .finally(function () {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ });
+ } else {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ })
+ });
+ } else {
+ FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
+ .done(function () {
+ if (pool.labelclear) {
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
+
+ FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
+ .finally(function () {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ });
+ } else {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ })
+ .finally(function () {
+ FnSambaStart();
+ });
+ }
+ })
+ .fail(function (message, data) {
+ FnStoragePoolDestroyFail({ name: pool.name, id: pool.id }, { data: data, message: message });
+ FnSambaStart();
+ });
+ } else {
+ FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
+ .done(function () {
+ if (pool.labelclear) {
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
+
+ FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
+ .finally(function () {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ });
+ } else {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ })
+ .finally(function () {
+ FnSambaStart();
+ });
+ }
+ });
+ } else {
+ if (zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: [] })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Destroying storage pool...");
+
+ if (filesystems.id.length > 0) {
+ FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
+ .done(function () {
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Destroying Samba shares...");
+
+ FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
+ .finally(function () {
+ if (pool.labelclear) {
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
+
+ FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
+ .finally(function () {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ });
+ } else {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ })
+ });
+ } else {
+ FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
+ .done(function () {
+ if (pool.labelclear) {
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
+
+ FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
+ .finally(function () {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ });
+ } else {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ });
+ }
+ })
+ .fail(function (message, data) {
+ FnStoragePoolDestroyFail({ name: pool.name, id: pool.id }, { data: data, message: message });
+ });
+ } else {
+ FnStoragePoolDestroyCommand({ name: pool.name, id: pool.id, force: pool.force })
+ .done(function () {
+ if (pool.labelclear) {
+ $("#spinner-storagepool-destroy-" + pool.id + " span").text("Clearing disk labels...");
+
+ FnStoragePoolDestroyLabelClear({ name: pool.name, id: pool.id }, { id: disks.attached })
+ .finally(function () {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ });
+ } else {
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ });
+ }
+ }
+}
+
+function FnStoragePoolDestroyCommand(pool = { name, id, force: false }) {
+ let process = {
+ command: ["/sbin/zpool", "destroy", pool.name]
+ };
+
+ if (pool.force) {
+ process.command.splice(2, 0, "-f");
+ }
+
+ FnConsole.log[1]("Storage Pools, Destroy: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Storage Pool successfully destroyed", description: pool.name, breakword: false }, { name: "storagepool-destroy", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Destroy: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnStoragePoolDestroyFail({ name: pool.name, id: pool.id }, { data: data, message: message });
+ });
+}
+
+function FnStoragePoolDestroyFail(pool = { name, id }, process = { data, message }) {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool could not be destroyed", description: pool.name, breakword: false }, { name: "storagepool-destroy", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Destroy: Failed, Pool: " + pool.name + ", Message: " + (process.data ? process.data : process.message));
+
+ $("#modal-storagepool-destroy-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+}
+
+function FnStoragePoolDestroyLabelClear(pool = { name, id }, disks = { id: [] }) {
+ let process = {
+ promise: cockpit.defer()
+ };
+ let promise = Promise.resolve();
+
+ disks.clear = {
+ error: 0
+ };
+
+ FnConsole.log[2]("Storage Pools, Disk Labels, Clear: In Progress");
+
+ if (disks.id.length > 0) {
+ disks.id.forEach((_value, _index) => {
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ FnStoragePoolDiskLabelClear({ name: pool.name, id: pool.id }, { id: _value, inactive: true }, { silent: true })
+ .fail(function () {
+ disks.clear.error++;
+ });
+
+ if (_index == (disks.id.length - 1)) {
+ setTimeout(function () {
+ if (disks.clear.error == 0) {
+ FnDisplayAlert({ status: "success", title: "Storage Pool disk labels successfully cleared", description: pool.name, breakword: false }, { name: "storagepool-destroy-labelclear", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Disk Labels, Clear: Success");
+ } else {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool disk labels could not be cleared", description: pool.name, breakword: false }, { name: "storagepool-destroy-labelclear", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Disk Labels, Clear: Failed");
+ }
+
+ process.promise.resolve();
+ }, 2000);
+ }
+
+ resolve();
+ }, 2000)
+ ));
+ });
+ } else {
+ process.promise.resolve();
+ }
+
+ return process.promise.promise();
+}
+
+function FnStoragePoolDiskAttach(pool = { name, id, force: false }, virtualdevice = { id, disk: true }, disk = { idnew: [] }, modal = { name, id }) {
+ virtualdevice.mirror = {
+ start: null,
+ end: null
+ };
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Attaching disk...");
+
+ if (!virtualdevice.disk && /^mirror-/.test(virtualdevice.id)) {
+ disk.id = "";
+
+ FnDisksStoragePoolsAttachedGet({ name: pool.name, id: pool.id }, { id: { blockdevice: false } })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Disks, Storage Pools, Attached, Get:" }));
+
+ pool.attached = data.replace(/\n\t+/g, "[TAB1]").split(/\n/g).filter(v => v);
+ pool.attachedconfig = [];
+
+ pool.attached.forEach((_value, _index) => {
+ if (/\[TAB1\]NAME/g.test(_value)) { //Config header row
+ _value = _value.split("upath").slice(1).join("."); //Remove config header row (and any previous text if exists)
+
+ if (new RegExp("^\\[TAB1\\]" + pool.name).test(_value)) { //Confirm config rows
+ _value.split("[TAB1]").filter(v => v && pool.attachedconfig.push(v));
+ }
+ }
+ });
+
+ pool.attachedconfig.forEach((_value, _index) => { //Find disks in Mirror virtual device and get hierarchy information
+ let config = {
+ tier: {
+ level: (_value.match(/^\s*/g)[0].length / 2)
+ }
+ };
+
+ _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
+
+ virtualdevice.mirror.regexp = new RegExp(virtualdevice.id, "g");
+
+ if (config.tier.level == 1 && virtualdevice.mirror.regexp.test(_value[0])) {
+ if (!virtualdevice.mirror.start) {
+ virtualdevice.mirror.start = _index;
+ }
+ }
+
+ if (virtualdevice.mirror.start && _index > virtualdevice.mirror.start) {
+ if (config.tier.level == 1) {
+ if (!virtualdevice.mirror.end) {
+ virtualdevice.mirror.end = _index;
+ }
+ }
+ }
+ });
+
+ if (!virtualdevice.mirror.end) {
+ virtualdevice.mirror.end = pool.attachedconfig.length;
+ }
+
+ pool.attachedconfig.forEach((_value, _index) => { //Find first healthy disk in the mirror virtual device
+ let config = {
+ disk: {
+ upath: ""
+ },
+ tier: {
+ level: (_value.match(/^\s*/g)[0].length / 2)
+ }
+ };
+
+ _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
+
+ if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[5])) { //upath
+ config.disk.upath = _value[5];
+ } else if (!$.isNumeric(_value[0]) && _value[5] != "was") { //upath appears after error messages and before trim messages
+ for (let i = 5; i < _value.length; i++) {
+ if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[i])) {
+ config.disk.upath = _value[i];
+ }
+ }
+ }
+
+ if (config.tier.level == 2 && _index > virtualdevice.mirror.start && _index < virtualdevice.mirror.end && _value[1] == "ONLINE") {
+ if (/^\/dev\/nvme|^\/dev\/sd/gi.test(config.disk.upath) || /^\/dev\/nvme|^\/dev\/sd/gi.test(_value[0])) { //Block Device
+ if (/^\/dev\/nvme\d+n\d+p\d+$/gi.test(_value[0])) {
+ if (!disk.id) {
+ disk.id = _value[0].replace(/p\d+$/, "");
+ }
+ } else if (/^\/dev\/sd.*\d+$/gi.test(_value[0])) {
+ if (!disk.id) {
+ disk.id = _value[0].replace(/\d+$/, "");
+ }
+ } else {
+ if (!disk.id) {
+ disk.id = _value[0].replace(/-part\d+$/, "");
+ }
+ }
+ } else if (/^nvme-nvme/gi.test(_value[0]) || /^wwn-/gi.test(_value[0])) { //WWN
+ if (!disk.id) {
+ disk.id = _value[0].replace(/-part\d+$/, "");
+ }
+ }
+ }
+ });
+
+ if (!disk.id || /^mirror-/g.test(disk.id)) {
+ FnStoragePoolDiskAttachFail({ name: pool.name, id: pool.id }, { id: virtualdevice.id, disk: virtualdevice.disk }, { idnew: disk.idnew }, { name: modal.name, id: modal.id }, { data: null, message: "There are no healthy disks to attach to." });
+ } else {
+ FnStoragePoolDiskAttachCommand({ name: pool.name, id: pool.id, force: pool.force }, { id: virtualdevice.id, disk: virtualdevice.disk }, { id: disk.id, idnew: disk.idnew }, { name: modal.name, id: modal.id });
+ }
+ })
+ .fail(function (message, data) {
+ FnStoragePoolDiskAttachFail({ name: pool.name, id: pool.id }, { id: virtualdevice.id, disk: virtualdevice.disk }, { idnew: disk.idnew }, { name: modal.name, id: modal.id }, { data: data, message: message });
+ });
+ } else {
+ FnStoragePoolDiskAttachCommand({ name: pool.name, id: pool.id, force: pool.force }, { id: virtualdevice.id, disk: virtualdevice.disk }, { id: virtualdevice.id, idnew: disk.idnew }, { name: modal.name, id: modal.id });
+ }
+}
+
+function FnStoragePoolDiskAttachCommand(pool = { name, id, force: false }, virtualdevice = { id, disk: true }, disk = { id, idnew }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "attach", pool.name, disk.id, disk.idnew]
+ };
+
+ if (pool.force) {
+ process.command.splice(2, 0, "-f");
+ }
+
+ FnConsole.log[1]("Storage Pools, Disk, Attach: In Progress, Pool: " + pool.name + ", " + (!virtualdevice.disk ? "Virtual Device: " + virtualdevice.id + ", " : "") + "Disk: " + disk.idnew);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Disk attached successfully to Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-attach", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Disk, Attach: Success, Pool: " + pool.name + ", " + (!virtualdevice.disk ? "Virtual Device: " + virtualdevice.id + ", " : "") + "Disk: " + disk.idnew);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Disk could not be attached to Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-attach", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Disk, Attach: Failed, Pool: " + pool.name + ", " + (!virtualdevice.disk ? "Virtual Device: " + virtualdevice.id + ", " : "") + "Disk: " + disk.idnew + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });;
+}
+
+function FnStoragePoolDiskAttachFail(pool = { name, id }, virtualdevice = { id, disk: true }, disk = { idnew }, modal = { name, id }, process = { data, message }) {
+ FnDisplayAlert({ status: "danger", title: "Disk could not be attached to Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-attach", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Disk, Attach: Failed, Pool: " + pool.name + ", " + (!virtualdevice.disk ? "Virtual Device: " + virtualdevice.id + ", " : "") + "Disk: " + disk.idnew + ", Message: " + (process.data ? process.data : process.message));
+
+ if (modal.id) {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ }
+}
+
+function FnStoragePoolDiskClear(pool = { name, id }, disk = { id }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "clear", pool.name, disk.id]
+ };
+
+ FnConsole.log[2]("Storage Pools, Disk, Clear Errors: In Progress, Pool: " + pool.name + ", Disk: " + disk.id);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Clearing disk errors...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Disk errors successfully cleared", description: disk.id, breakword: false }, { name: "storagepool-disk-clear", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Disk, Clear Errors: Success, Pool: " + pool.name + ", Disk: " + disk.id);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Disk errors could not be cleared", description: disk.id, breakword: false }, { name: "storagepool-disk-clear", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Disk, Clear Errors: Failed, Pool: " + pool.name + ", Disk: " + disk.id + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });
+}
+
+function FnStoragePoolDiskDetach(pool = { name, id }, disk = { id, labelclear: false }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "detach", pool.name, disk.id]
+ };
+
+ modal.hide = true;
+
+ FnConsole.log[1]("Storage Pools, Disk, Detach: In Progress, Pool: " + pool.name + ", Disk: " + disk.id);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Detaching disk...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Disk detached successfully from Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-detach", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Disk, Detach: Success, Pool: " + pool.name + ", Disk: " + disk.id);
+
+ if (disk.labelclear) {
+ modal.hide = false;
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Clearing disk label...");
+
+ setTimeout(function () {
+ FnStoragePoolDiskLabelClear({ name: pool.name, id: pool.id }, { id: disk.id, inactive: false }, { silent: false })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ })
+ }, 2000);
+ }
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Disk could not be detached from Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-detach", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Disk, Detach: Failed, Pool: " + pool.name + ", Disk: " + disk.id + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if (modal.hide) {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ }
+ });;
+}
+
+function FnStoragePoolDiskLabelClear(pool = { name, id }, disk = { id, inactive: false }, display = { silent: false }) {
+ let process = {
+ command: ["/sbin/zpool", "labelclear", disk.id]
+ };
+
+ if (disk.inactive) {
+ process.command.splice(2, 0, "-f");
+ }
+
+ FnConsole.log[2]("Storage Pools, Disk Label, Clear: In Progress, Disk: " + disk.id);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Disk label successfully cleared", description: disk.id, breakword: false }, { name: "storagepool-disk-labelclear", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Storage Pools, Disk Label, Clear: Success, Disk: " + disk.id);
+
+ setTimeout(function () {
+ FnDisksBlkidGet();
+ }, 200);
+ })
+ .fail(function (message, data) {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "danger", title: "Disk label could not be cleared", description: disk.id, breakword: false }, { name: "storagepool-disk-labelclear", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.warn("Storage Pools, Disk Label, Clear: Failed, Disk: " + disk.id + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolDiskOffline(pool = { name, id }, disk = { id, force: false, temporary: false }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "offline", pool.name, disk.id]
+ };
+
+ if (disk.force) {
+ process.command.splice(2, 0, "-f");
+ }
+ if (disk.temporary) {
+ process.command.splice(2, 0, "-t");
+ }
+
+ FnConsole.log[1]("Storage Pools, Disk, Offline: In Progress, Pool: " + pool.name + ", Disk: " + disk.id);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Setting disk offline...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Disk successfully set offline", description: disk.id, breakword: false }, { name: "storagepool-disk-offline", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Disk, Offline: Success, Pool: " + pool.name + ", Disk: " + disk.id);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Disk could not be set offline", description: disk.id, breakword: false }, { name: "storagepool-disk-offline", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Disk, Offline: Failed, Pool: " + pool.name + ", Disk: " + disk.id + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });;
+}
+
+function FnStoragePoolDiskOnline(pool = { name, id, scrub: false }, disk = { id, expand: false }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "online", pool.name, disk.id]
+ };
+
+ if (disk.expand) {
+ process.command.splice(2, 0, "-e");
+ }
+
+ FnConsole.log[1]("Storage Pools, Disk, Online: In Progress, Pool: " + pool.name + ", Disk: " + disk.id);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Setting disk online...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Disk, Online:" }));
+
+ if (/^warning:/gi.test(data)) {
+ FnDisplayAlert({ status: "warning", title: "Disk set online but remains in faulted state", description: disk.id, breakword: false }, { name: "storagepool-disk-online", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Disk, Online: Warning, Pool: " + pool.name + ", Message: " + (data ? data.replace(/^warning: /gi, "") : message));
+ } else {
+ FnDisplayAlert({ status: "success", title: "Disk successfully set online", description: disk.id, breakword: false }, { name: "storagepool-disk-online", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Disk, Online: Success, Pool: " + pool.name + ", Disk: " + disk.id);
+ }
+
+ if (pool.scrub) {
+ FnStoragePoolScrubStart({ name: pool.name, id: pool.id }, { resume: false }, { refresh: false });
+ }
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Disk could not be set online", description: disk.id, breakword: false }, { name: "storagepool-disk-online", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Disk, Online: Failed, Pool: " + pool.name + ", Disk: " + disk.id + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });;
+}
+
+function FnStoragePoolDiskReplace(pool = { name, id, force: false }, disk = { id, idnew }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "replace", pool.name, disk.id, disk.idnew]
+ };
+
+ if (pool.force) {
+ process.command.splice(2, 0, "-f");
+ }
+
+ FnConsole.log[1]("Storage Pools, Disk, Replace: In Progress, Pool: " + pool.name + ", Disk: " + disk.id);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Replacing disk...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Disk replaced successfully on Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-replace", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Disk, Replace: Success, Pool: " + pool.name + ", Disk: " + disk.id);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Disk could not be replaced on Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-disk-replace", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Disk, Replace: Failed, Pool: " + pool.name + ", Disk: " + disk.id + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });;
+}
+
+function FnStoragePoolExport(pool = { name, id, altroot: false, force: false, readonly: false }, samba = { restart: false }) {
+ if (samba.restart) {
+ FnSambaStop()
+ .finally(function () {
+ if (zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-export-" + pool.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: [] })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-export-" + pool.id + " span").text("Exporting storage pool...");
+
+ if (filesystems.id.length > 0) {
+ FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: false })
+ .done(function () {
+ $("#spinner-storagepool-export-" + pool.id + " span").text("Destroying Samba shares...");
+
+ FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
+ .finally(function () {
+ $("#modal-storagepool-export-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ });
+ });
+ } else {
+ FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: true })
+ .finally(function () {
+ FnSambaStart();
+ });
+ }
+ })
+ .fail(function (message, data) {
+ FnStoragePoolExportFail({ name: pool.name, id: pool.id }, { data: data, message: message }, { refresh: true });
+ FnSambaStart();
+ });
+ } else {
+ FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: true })
+ .finally(function () {
+ FnSambaStart();
+ });
+ }
+ });
+ } else {
+ if (zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-export-" + pool.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: [] })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-export-" + pool.id + " span").text("Exporting storage pool...");
+
+ if (filesystems.id.length > 0) {
+ FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: false })
+ .done(function () {
+ $("#spinner-storagepool-export-" + pool.id + " span").text("Destroying Samba shares...");
+
+ FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
+ .finally(function () {
+ $("#modal-storagepool-export-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ });
+ });
+ } else {
+ FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: true });
+ }
+ })
+ .fail(function (message, data) {
+ FnStoragePoolExportFail({ name: pool.name, id: pool.id }, { data: data, message: message }, { refresh: true });
+ });
+ } else {
+ FnStoragePoolExportCommand({ name: pool.name, id: pool.id, force: pool.force }, { refresh: true });
+ }
+ }
+}
+
+function FnStoragePoolExportCommand(pool = { name, id, force: false }, display = { refresh: true }) {
+ let process = {
+ command: ["/sbin/zpool", "export", pool.name]
+ };
+
+ if (pool.force) {
+ process.command.splice(2, 0, "-f");
+ }
+
+ FnConsole.log[1]("Storage Pools, Export: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Storage Pool successfully exported", description: pool.name, breakword: false }, { name: "storagepool-export", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Export: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnStoragePoolExportFail({ name: pool.name, id: pool.id }, { data: data, message: message }, { refresh: false });
+
+ display.refresh = true;
+ })
+ .finally(function () {
+ if (display.refresh) {
+ $("#modal-storagepool-export-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ });
+}
+
+function FnStoragePoolExportFail(pool = { name, id }, process = { data, message }, display = { refresh: true }) {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool could not be exported", description: pool.name, breakword: false }, { name: "storagepool-export", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Export: Failed, Pool: " + pool.name + ", Message: " + (process.data ? process.data : process.message));
+
+ if (display.refresh) {
+ $("#modal-storagepool-export-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+}
+
+function FnStoragePoolHealthIcon(pool = { health }) {
+ switch (pool.health.toLowerCase()) {
+ case "online":
+ pool.healthicon = "pficon pficon-ok list-view-pf-icon-sm";
+ break;
+ case "offline":
+ pool.healthicon = "fa pficon-info list-view-pf-icon-sm";
+ break;
+ case "split":
+ pool.healthicon = "fa pficon-info list-view-pf-icon-sm";
+ break;
+ case "degraded":
+ pool.healthicon = "pficon pficon-warning-triangle-o list-view-pf-icon-sm";
+ break;
+ case "unknown":
+ pool.healthicon = "pficon pficon-warning-triangle-o list-view-pf-icon-sm";
+ break;
+ case "removed":
+ pool.healthicon = "pficon pficon-error-circle-o list-view-pf-icon-sm";
+ break;
+ case "faulted":
+ pool.healthicon = "pficon pficon-error-circle-o list-view-pf-icon-sm";
+ break;
+ case "unavail":
+ pool.healthicon = "pficon pficon-error-circle-o list-view-pf-icon-sm";
+ break;
+ case "avail":
+ pool.healthicon = "pficon pficon-ok list-view-pf-icon-sm";
+ break;
+ case "inuse":
+ pool.healthicon = "pficon pficon-ok list-view-pf-icon-sm";
+ break;
+ case "fail":
+ pool.healthicon = "pficon pficon-error-circle-o list-view-pf-icon-sm";
+ break;
+ case "destroyed":
+ pool.healthicon = "pficon pficon-error-circle-o list-view-pf-icon-sm";
+ break;
+ default:
+ pool.healthicon = "fa pficon-info list-view-pf-icon-sm";
+ break;
+ }
+
+ return pool.healthicon;
+}
+
+function FnStoragePoolImport(pool = { name, altroot, destroyed: false, force: false, guid, ignoremissinglog: false, namenew, readonly: false, recoverymode: false }, filesystem = { mount: true, selinux: true }, disks = { id: { blockdevice: true, disk: false, path: false, vdev: false }, identifier }) {
+ let process = {
+ command: ["/sbin/zpool", "import", pool.guid]
+ };
+ let modal = {
+ hide: true
+ };
+
+ disks.devpath = "/dev";
+ disks.fallback = false;
+ disks.identifiertext = "Block Device";
+
+ if (pool.namenew) {
+ pool.name = pool.namenew;
+ }
+
+ process.command.push(pool.name);
+
+ pool.id = FnGenerateId({ at: false, colon: true, forwardslash: false, period: true, underscore: true, whitespace: true }, { name: pool.name, attribute: true });
+ pool.imported = false;
+
+ if (!filesystem.mount) {
+ process.command.splice(2, 0, "-N");
+ }
+
+ if (pool.altroot) {
+ process.command.splice(2, 0, "-o");
+ process.command.splice(3, 0, "altroot=" + pool.altroot);
+ }
+ if (pool.destroyed) {
+ process.command.splice(2, 0, "-D");
+ }
+ if (pool.force) {
+ process.command.splice(2, 0, "-f");
+ }
+ if (pool.recoverymode) {
+ process.command.splice(2, 0, "-F");
+ }
+ if (pool.ignoremissinglog) {
+ process.command.splice(2, 0, "-m");
+ }
+ if (pool.readonly) {
+ process.command.splice(2, 0, "-o");
+ process.command.splice(3, 0, "readonly=on");
+ }
+
+ process.command.splice(2, 0, "-d");
+
+ switch (disks.identifier) { //Fallback to block device to prevent import error when selected identifier is not available
+ case "disk":
+ if (disks.id.disk) {
+ disks.devpath = "/dev/disk/by-id";
+ } else {
+ disks.fallback = true;
+ }
+ disks.identifiertext = "Disk / WWN";
+ break;
+ case "path":
+ if (disks.id.path) {
+ disks.devpath = "/dev/disk/by-path";
+ } else {
+ disks.fallback = true;
+ }
+ disks.identifiertext = "Hardware Path";
+ break;
+ case "vdev":
+ if (disks.id.vdev) {
+ disks.devpath = "/dev/disk/by-vdev";
+ } else {
+ disks.fallback = true;
+ }
+ disks.identifiertext = "Virtual Device Mapping";
+ break;
+ }
+
+ process.command.splice(3, 0, disks.devpath);
+
+ FnConsole.log[1]("Storage Pools, Import: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-storagepools-import span").text("Importing storage pool...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ pool.imported = true;
+
+ if (disks.fallback) {
+ FnDisplayAlert({ status: "warning", title: "Storage Pool imported with errors", description: pool.name, breakword: false }, { name: "storagepools-import", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Import: Warning, Pool: " + pool.name + ", Message: " + disks.identifiertext + " disks identifier was not available during import. Block Device disks identifier was used.");
+ } else {
+ FnDisplayAlert({ status: "success", title: "Storage Pool successfully imported", description: pool.name, breakword: false }, { name: "storagepools-import", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Import: Success, Pool: " + pool.name);
+ }
+ })
+ .fail(function (message, data) {
+ if (/cannot mount.*directory is not empty|smb add share failed|cannot share/gi.test(data)) { //Storage pool has successfully imported, however a file system error is generated
+ pool.imported = true;
+
+ FnDisplayAlert({ status: "warning", title: "Storage Pool imported with errors", description: pool.name, breakword: false }, { name: "storagepools-import", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Import: Warning, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ } else if (/cannot import.*pool already exists/gi.test(data)) {
+ modal.hide = false;
+
+ if (!$("#switch-storagepools-import-rename input").prop("checked")) {
+ $("#switch-storagepools-import-rename input").click();
+ }
+ $("#validationwrapper-storagepools-import-storagepools").addClass("has-error");
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name already exists. New name is needed.");
+ $("#input-storagepools-import-namenew").focus();
+ } else {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool could not be imported", description: pool.name, breakword: false }, { name: "storagepools-import", id: pool.id, timeout: 4 });
+ }
+
+ if (!modal.hide) {
+ $("#spinner-storagepools-import").addClass("hidden");
+ $("#spinner-storagepools-import span").text("");
+ $("#btn-storagepools-import-apply").prop("disabled", false);
+ }
+
+ if (!pool.imported) {
+ FnConsole.warn("Storage Pools, Import: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ }
+ })
+ .finally(function () {
+ if (pool.imported) {
+ if (filesystem.selinux && !pool.readonly) {
+ $("#spinner-storagepools-import span").text("Configuring SELinux contexts for Samba...");
+
+ FnStoragePoolSelinuxContextsSambaSet({ name: pool.name, id: pool.id })
+ .finally(function () {
+ if (zfsmanager.configuration.samba.manage) {
+ if (!pool.readonly) {
+ $("#spinner-storagepools-import span").text("Disabling Samba share inheritance...");
+
+ FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false) }, { name: null }, { disable: false })
+ .finally(function () {
+ $("#spinner-storagepools-import span").text("Creating Samba shares...");
+
+ FnSambaSharesEnable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false), readonly: pool.readonly }, { name: null, force: true }, { restart: false }, { refresh: false, silent: false })
+ .finally(function () {
+ if (modal.hide) {
+ $("#modal-storagepools-import").modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ });
+ });
+ } else {
+ $("#spinner-storagepools-import span").text("Creating Samba shares...");
+
+ FnSambaSharesEnable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false), readonly: pool.readonly }, { name: null, force: true }, { restart: false }, { refresh: false, silent: false })
+ .finally(function () {
+ if (modal.hide) {
+ $("#modal-storagepools-import").modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ });
+ }
+ } else {
+ if (modal.hide) {
+ $("#modal-storagepools-import").modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ }
+ });
+ } else {
+ if (zfsmanager.configuration.samba.manage) {
+ if (!pool.readonly) {
+ $("#spinner-storagepools-import span").text("Disabling Samba share inheritance...");
+
+ FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false) }, { name: null }, { disable: false })
+ .finally(function () {
+ $("#spinner-storagepools-import span").text("Creating Samba shares...");
+
+ FnSambaSharesEnable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false), readonly: pool.readonly }, { name: null, force: true }, { restart: false }, { refresh: false, silent: false })
+ .finally(function () {
+ if (modal.hide) {
+ $("#modal-storagepools-import").modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ });
+ });
+ } else {
+ $("#spinner-storagepools-import span").text("Creating Samba shares...");
+
+ FnSambaSharesEnable({ name: pool.name, id: pool.id, altroot: (pool.altroot ? true : false), readonly: pool.readonly }, { name: null, force: true }, { restart: false }, { refresh: false, silent: false })
+ .finally(function () {
+ if (modal.hide) {
+ $("#modal-storagepools-import").modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ });
+ }
+ } else {
+ if (modal.hide) {
+ $("#modal-storagepools-import").modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ }
+ }
+ } else {
+ if (modal.hide) {
+ $("#modal-storagepools-import").modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 200);
+ }
+ }
+ });
+}
+
+function FnStoragePoolRefreservationSet(pool = { name, id }, filesystem = { refreservation }) {
+ let process = {
+ command: ["/sbin/zfs", "set", "refreservation=" + filesystem.refreservation, pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Refreservation, Set: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[2]("Storage Pools, Refreservation, Set: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Refreservation, Set: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolRefresh(pool = { name, id }, refresh = { storagepool: true, filesystems: false, snapshots: false, status: false }) {
+ if (zfsmanager.configuration.zfs.storagepool.refreshall || refresh.storagepool) {
+ FnStoragePoolRefreshCommand({ name: pool.name, id: pool.id });
+ }
+
+ setTimeout(function () {
+ if (zfsmanager.configuration.zfs.storagepool.refreshall) {
+ FnStoragePoolRefreshAutoDisable({ name: pool.name, id: pool.id });
+ }
+
+ if (zfsmanager.configuration.zfs.storagepool.refreshall || refresh.filesystems) {
+ $("#btn-storagepool-filesystems-create-" + pool.id).prop("disabled", true);
+ $("#btn-storagepool-filesystems-refresh-" + pool.id).prop("disabled", true);
+ $("[id^=btn-storagepool-filesystem-dropdown-" + pool.id + "]").addClass("disabled");
+ $("#paneltitle-storagepool-filesystems-" + pool.id).addClass("hidden");
+ $("#spinner-storagepool-filesystems-" + pool.id).removeClass("hidden");
+
+ FnFileSystemsGet({ name: pool.name, id: pool.id });
+ }
+
+ if (zfsmanager.configuration.zfs.storagepool.refreshall || refresh.snapshots) {
+ $("#btn-storagepool-snapshots-create-" + pool.id).prop("disabled", true);
+ $("#btn-storagepool-snapshots-refresh-" + pool.id).prop("disabled", true);
+ $("[id^=btn-storagepool-snapshot-dropdown-" + pool.id + "]").addClass("disabled");
+ $("#paneltitle-storagepool-snapshots-" + pool.id).addClass("hidden");
+ $("#spinner-storagepool-snapshots-" + pool.id).removeClass("hidden");
+
+ FnSnapshotsGet({ name: pool.name, id: pool.id });
+ }
+
+ if (zfsmanager.configuration.zfs.storagepool.refreshall || refresh.status) {
+ $("#btn-storagepool-status-refresh-" + pool.id).prop("disabled", true);
+ $("[id^=btn-storagepool-status-dropdown-][id$=" + pool.id + "]").addClass("disabled");
+ $("#paneltitle-storagepool-status-" + pool.id).addClass("hidden");
+ $("#spinner-storagepool-status-" + pool.id).removeClass("hidden");
+ $("#spinner-storagepool-status-0-" + pool.id).removeClass("hidden");
+
+ FnStatusGet({ name: pool.name, id: pool.id });
+ }
+ }, 200);
+}
+
+function FnStoragePoolRefreshAutoDisable(pool = { name, id }) {
+ if ($("#tr-storagepool-" + pool.id).attr("data-pool-refresh-id") != "") {
+ FnConsole.log[2]("Storage Pools, Refresh, Auto: Disabled, Pool: " + pool.name);
+ }
+
+ clearInterval($("#tr-storagepool-" + pool.id).attr("data-pool-refresh-id"));
+
+ $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-id", "");
+ $("#btn-storagepool-status-refresh-" + pool.id).text("Refresh");
+}
+
+function FnStoragePoolRefreshCommand(pool = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "list", "-H", "-o", "guid,health,size,alloc,free,fragmentation,autotrim,version,feature@allocation_classes,feature@async_destroy,feature@bookmark_v2,feature@bookmarks,feature@device_removal,feature@edonr,feature@embedded_data,feature@empty_bpobj,feature@enabled_txg,feature@encryption,feature@extensible_dataset,feature@filesystem_limits,feature@hole_birth,feature@large_blocks,feature@large_dnode,feature@lz4_compress,feature@multi_vdev_crash_dump,feature@obsolete_counts,feature@project_quota,feature@resilver_defer,feature@sha512,feature@skein,feature@spacemap_histogram,feature@spacemap_v2,feature@userobj_accounting,feature@zpool_checkpoint", "-p", pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Refresh: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Refresh:" }));
+
+ pool.properties = data.trim().split(/\t/g).filter(v => v);
+
+ //0=guid, 1=health, 2=size, 3=alloc, 4=free, 5=fragmentation, 6=autotrim, 7=version, 8=feature@allocation_classes, 9=feature@async_destroy, 10=feature@bookmark_v2, 11=feature@bookmarks, 12=feature@device_removal, 13=feature@edonr, 14=feature@embedded_data, 15=feature@empty_bpobj, 16=feature@enabled_txg, 17=feature@encryption, 18=feature@extensible_dataset, 19=feature@filesystem_limits, 20=feature@hole_birth, 21=feature@large_blocks, 22=feature@large_dnode, 23=feature@lz4_compress, 24=feature@multi_vdev_crash_dump, 25=feature@obsolete_counts, 26=feature@project_quota, 27=feature@resilver_defer, 28=feature@sha512, 29=feature@skein, 30=feature@spacemap_histogram, 31=feature@spacemap_v2, 32=feature@userobj_accounting, 33=feature@zpool_checkpoint
+
+ pool.allocated = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[3] });
+ pool.allocatedpercent = FnRound({ decimals: 2, value: (pool.properties[3] / pool.properties[2]) * 100 });
+ pool.autotrim = (pool.properties[6].toLowerCase() == "on" ? true : false);
+ pool.boot = (zfsmanager.zfs.storagepool.boot && pool.name == zfsmanager.zfs.storagepool.boot ? true : false);
+ pool.feature = {
+ allocation_classes: (/active|enabled/gi.test(pool.properties[8]) ? true : false),
+ async_destroy: (/active|enabled/gi.test(pool.properties[9]) ? true : false),
+ bookmark_v2: (/active|enabled/gi.test(pool.properties[10]) ? true : false),
+ bookmarks: (/active|enabled/gi.test(pool.properties[11]) ? true : false),
+ device_removal: (/active|enabled/gi.test(pool.properties[12]) ? true : false),
+ edonr: (/active|enabled/gi.test(pool.properties[13]) ? true : false),
+ embedded_data: (/active|enabled/gi.test(pool.properties[14]) ? true : false),
+ empty_bpobj: (/active|enabled/gi.test(pool.properties[15]) ? true : false),
+ enabled_txg: (/active|enabled/gi.test(pool.properties[16]) ? true : false),
+ encryption: (/active|enabled/gi.test(pool.properties[17]) ? true : false),
+ extensible_dataset: (/active|enabled/gi.test(pool.properties[18]) ? true : false),
+ filesystem_limits: (/active|enabled/gi.test(pool.properties[19]) ? true : false),
+ hole_birth: (/active|enabled/gi.test(pool.properties[20]) ? true : false),
+ large_blocks: (/active|enabled/gi.test(pool.properties[21]) ? true : false),
+ large_dnode: (/active|enabled/gi.test(pool.properties[22]) ? true : false),
+ lz4_compress: (/active|enabled/gi.test(pool.properties[23]) ? true : false),
+ multi_vdev_crash_dump: (/active|enabled/gi.test(pool.properties[24]) ? true : false),
+ obsolete_counts: (/active|enabled/gi.test(pool.properties[25]) ? true : false),
+ project_quota: (/active|enabled/gi.test(pool.properties[26]) ? true : false),
+ resilver_defer: (/active|enabled/gi.test(pool.properties[27]) ? true : false),
+ sha512: (/active|enabled/gi.test(pool.properties[28]) ? true : false),
+ skein: (/active|enabled/gi.test(pool.properties[29]) ? true : false),
+ spacemap_histogram: (/active|enabled/gi.test(pool.properties[30]) ? true : false),
+ spacemap_v2: (/active|enabled/gi.test(pool.properties[31]) ? true : false),
+ userobj_accounting: (/active|enabled/gi.test(pool.properties[32]) ? true : false),
+ zpool_checkpoint: (/active|enabled/gi.test(pool.properties[33]) ? true : false)
+ };
+ pool.fragmentation = (pool.properties[5] == "-" ? 0 : pool.properties[5]);
+ pool.free = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[4] });
+ pool.freepercent = FnRound({ decimals: 2, value: (pool.properties[4] / pool.properties[2]) * 100 });
+ pool.guid = pool.properties[0];
+ pool.health = pool.properties[1];
+ pool.healthicon = FnStoragePoolHealthIcon({ health: pool.health });
+ pool.root = (zfsmanager.zfs.storagepool.root && pool.name == zfsmanager.zfs.storagepool.root ? true : false);
+ pool.size = FnFormatBytes({ base2: true, decimals: 2, value: pool.properties[2] });
+ pool.upgrade = ($.isNumeric(pool.properties[6] && !pool.boot) ? true : false);
+ pool.version = pool.properties[7];
+
+ //Upgrade available if a requested feature flag returns false
+ if (!pool.boot) {
+ for (var x in pool.feature) {
+ if (!pool.feature[x] && !pool.upgrade) {
+ pool.upgrade = true;
+ }
+ }
+ }
+
+ if (pool.upgrade) {
+ $("#span-storagepool-upgrade-" + pool.id).removeClass("hidden");
+ } else {
+ $("#span-storagepool-upgrade-" + pool.id).addClass("hidden");
+ }
+
+ $("#div-storagepool-health-" + pool.id).empty().html(` ` + pool.health);
+ $("#div-storagepool-size-" + pool.id).text(pool.size);
+ $("#div-storagepool-allocated-" + pool.id).text(pool.allocated);
+ $("#div-storagepool-free-" + pool.id).text(pool.free);
+ $("#div-storagepool-fragmentation-" + pool.id).text(pool.fragmentation + " %");
+
+ $("#progressbar-storagepool-allocated-" + pool.id).attr("aria-valuenow", pool.allocatedpercent);
+ $("#progressbar-storagepool-allocated-" + pool.id).attr("title", pool.allocatedpercent + "% Allocated");
+ $("#progressbar-storagepool-allocated-" + pool.id).attr("data-original-title", pool.allocatedpercent + "% Allocated");
+ $("#progressbar-storagepool-allocated-" + pool.id).css("width", pool.allocatedpercent + "%");
+ $("#progressbar-storagepool-allocated-" + pool.id + " .sr-only").text(pool.allocatedpercent + "% Allocated");
+
+ $("#progressbar-storagepool-free-" + pool.id).attr("aria-valuenow", pool.freepercent);
+ $("#progressbar-storagepool-free-" + pool.id).attr("title", pool.freepercent + "% Free");
+ $("#progressbar-storagepool-free-" + pool.id).attr("data-original-title", pool.freepercent + "% Free");
+ $("#progressbar-storagepool-free-" + pool.id).css("width", pool.freepercent + "%");
+ $("#progressbar-storagepool-free-" + pool.id + " .sr-only").text(pool.freepercent + "% Free");
+
+ $("#tr-storagepool-" + pool.id).attr("data-pool-autotrim", pool.autotrim);
+ $("#tr-storagepool-" + pool.id).attr("data-pool-feature-allocation_classes", pool.feature.allocation_classes);
+ $("#tr-storagepool-" + pool.id).attr("data-pool-feature-device_removal", pool.feature.device_removal);
+ $("#tr-storagepool-" + pool.id).attr("data-pool-feature-edonr", pool.feature.edonr);
+ $("#tr-storagepool-" + pool.id).attr("data-pool-feature-encryption", pool.feature.encryption);
+ $("#tr-storagepool-" + pool.id).attr("data-pool-feature-large_blocks", pool.feature.large_blocks);
+ $("#tr-storagepool-" + pool.id).attr("data-pool-feature-lz4_compress", pool.feature.lz4_compress);
+ $("#tr-storagepool-" + pool.id).attr("data-pool-feature-resilver_defer", pool.feature.resilver_defer);
+ $("#tr-storagepool-" + pool.id).attr("data-pool-feature-sha512", pool.feature.sha512);
+ $("#tr-storagepool-" + pool.id).attr("data-pool-feature-skein", pool.feature.skein);
+ $("#tr-storagepool-" + pool.id).attr("data-pool-guid", pool.guid);
+ $("#tr-storagepool-" + pool.id).attr("data-pool-version", pool.version);
+
+ FnConsole.log[1]("Storage Pools, Refresh: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Refresh: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolRegenerateGuid(pool = { name, id }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "reguid", pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Regenerate GUID: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Regenerating storage pool GUID...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Storage Pool GUID successfully regenerated", description: pool.name, breakword: false }, { name: "storagepool-regenerateguid", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Regenerate GUID: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool GUID could not be regenerated", description: pool.name, breakword: false }, { name: "storagepool-regenerateguid", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Regenerate GUID: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });;
+}
+
+function FnStoragePoolResilver(pool = { name, id }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "resilver", pool.name]
+ };
+
+ FnConsole.log[1]("Storage Pools, Resilver, Start: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Starting storage pool resilver...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Storage Pool resilver successfully started", description: pool.name, breakword: false }, { name: "storagepool-resilver", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Resilver, Start: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool resilver could not be started", description: pool.name, breakword: false }, { name: "storagepool-resilver", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Resilver, Start: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });
+}
+
+function FnStoragePoolScrubPause(pool = { name, id }, display = { refresh: true }) {
+ let process = {
+ command: ["/sbin/zpool", "scrub", "-p", pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Scrub, Pause: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Storage Pool scrub successfully paused", description: pool.name, breakword: false }, { name: "storagepool-scrub-pause", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Scrub, Pause: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool scrub could not be paused", description: pool.name, breakword: false }, { name: "storagepool-scrub-pause", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Scrub, Pause: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ }
+ });;
+}
+
+function FnStoragePoolScrubStart(pool = { name, id }, scrub = { resume: false }, display = { refresh: true }) {
+ let process = {
+ command: ["/sbin/zpool", "scrub", pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Scrub, " + (scrub.resume ? "Resume" : "Start") + ": In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Storage Pool scrub successfully " + (scrub.resume ? "resumed" : "started"), description: pool.name, breakword: false }, { name: "storagepool-scrub-start", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Scrub, " + (scrub.resume ? "Resume" : "Start") + ": Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ if (/currently scrubbing/gi.test(data)) { //Start scrub will fail if the storage pool has already initiated scrub
+ FnDisplayAlert({ status: "success", title: "Storage Pool scrub successfully " + (scrub.resume ? "resumed" : "started"), description: pool.name, breakword: false }, { name: "storagepool-scrub-start", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Scrub, " + (scrub.resume ? "Resume" : "Start") + ": Success, Pool: " + pool.name);
+ } else {
+ if (/currently resilvering/gi.test(data)) { //Start scrub will fail if the storage pool has initiated resilver
+ FnDisplayAlert({ status: "warning", title: "Storage Pool scrub could not be " + (scrub.resume ? "resumed" : "started") + ". Resilver in progress", description: pool.name, breakword: false }, { name: "storagepool-scrub-start", id: pool.id, timeout: 4 });
+ } else {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool scrub could not be " + (scrub.resume ? "resumed" : "started"), description: pool.name, breakword: false }, { name: "storagepool-scrub-start", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.warn("Storage Pools, Scrub, " + (scrub.resume ? "Resume" : "Start") + ": Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ }
+ })
+ .finally(function () {
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ }
+ });
+}
+
+function FnStoragePoolScrubStop(pool = { name, id }, display = { refresh: true }) {
+ let process = {
+ command: ["/sbin/zpool", "scrub", "-s", pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Scrub, Stop: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Storage Pool scrub successfully stopped", description: pool.name, breakword: false }, { name: "storagepool-scrub-stop", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Scrub, Stop: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool scrub could not be stopped", description: pool.name, breakword: false }, { name: "storagepool-scrub-stop", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Scrub, Stop: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ }
+ });;
+}
+
+function FnStoragePoolSelinuxContextsSambaSet(pool = { name, id }, display = { silent: false }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name", "-r", "-t", "filesystem", pool.name],
+ promise: cockpit.defer()
+ };
+
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, SELinux Contexts, Samba, Set:" }));
+
+ let filesystems = data.split(/\n/g).filter(v => v);
+ let promise = Promise.resolve();
+
+ if (filesystems.length > 0) {
+ filesystems.forEach((_value, _index) => {
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ FnFileSystemSelinuxContextsSambaSet({ name: pool.name, id: pool.id }, { name: _value })
+ .finally(function () {
+ if (_index == (filesystems.length - 1)) {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "SELinux contexts for Samba successfully configured", description: pool.name, breakword: false }, { name: "selinux-enable", id: pool.id, timeout: 4 });
+ }
+
+ process.promise.resolve();
+ }
+ });
+
+ resolve();
+ }, 500)
+ ));
+ });
+ } else {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "SELinux contexts for Samba successfully configured", description: pool.name, breakword: false }, { name: "selinux-enable", id: pool.id, timeout: 4 });
+ }
+
+ process.promise.resolve();
+ }
+ })
+ .fail(function (message, data) {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "danger", title: "SELinux contexts for Samba could not be configured", description: pool.name, breakword: false }, { name: "selinux-enable", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.warn("Storage Pools, SELinux Contexts, Samba, Set: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+
+ process.promise.resolve();
+ });
+
+ return process.promise.promise();
+}
+
+function FnStoragePoolSizeGet(pool = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "get", "size", "-H", "-o", "value", "-p", pool.name]
+ };
+
+ FnConsole.log[2]("Storage Pools, Size, Get: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function () {
+ FnConsole.log[2]("Storage Pools, Size, Get: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Storage Pools, Size. Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnStoragePoolSpinnerHide(pool = { name, id }) {
+ if ($("#tr-storagepool-" + pool.id).attr("data-pool-refresh-filesystems") == "true" && $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-snapshots") == "true" && $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-status") == "true") {
+ setTimeout(function () {
+ $("#spinner-storagepool-" + pool.id).addClass("hidden");
+ $("#listingcthead-storagepool-" + pool.id).removeClass("hidden");
+ $("#listingctbody-storagepool-" + pool.id).removeClass("hidden");
+ }, 200);
+ }
+}
+
+function FnStoragePoolTrimCancel(pool = { name, id }, disk = { id }) {
+ let process = {
+ command: ["/sbin/zpool", "trim", "-c", pool.name]
+ };
+
+ if (disk.id) {
+ process.command.push(disk.id);
+ }
+
+ FnConsole.log[2]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Cancel: In Progress, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM successfully cancelled", description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-cancel", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Cancel: Success, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM could not be cancelled", description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-cancel", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Cancel: Failed, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : "") + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });
+}
+
+function FnStoragePoolTrimStart(pool = { name, id }, disk = { id }, trim = { resume: false, secure: false }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "trim", pool.name]
+ };
+
+ if (trim.secure) {
+ process.command.splice(2, 0, "-d");
+ }
+ if (disk.id) {
+ process.command.push(disk.id);
+ }
+
+ FnConsole.log[2]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, " + (trim.resume ? "Resume" : "Start") + ": In Progress, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ if (!trim.resume) {
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Starting " + (disk.id ? "disk" : "storage pool") + " TRIM...");
+ }
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM successfully " + (trim.resume ? "resumed" : "started"), description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-start", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, " + (trim.resume ? "Resume" : "Start") + ": Success, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM could not be " + (trim.resume ? "resumed" : "started"), description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-start", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, " + (trim.resume ? "Resume" : "Start") + ": Failed, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : "") + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if (modal.name && modal.id) {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+ }
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });
+}
+
+function FnStoragePoolTrimSuspend(pool = { name, id }, disk = { id }) {
+ let process = {
+ command: ["/sbin/zpool", "trim", "-s", pool.name]
+ };
+
+ if (disk.id) {
+ process.command.push(disk.id);
+ }
+
+ FnConsole.log[2]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Suspend: In Progress, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM successfully suspended", description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-suspend", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Suspend: Success, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : ""));
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: (disk.id ? "Disk" : "Storage Pool") + " TRIM could not be suspended", description: (disk.id ? disk.id : pool.name), breakword: false }, { name: "storagepool-" + (disk.id ? "disk-" : "") + "trim-suspend", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, " + (disk.id ? "Disk, " : "") + "TRIM, Suspend: Failed, Pool: " + pool.name + (disk.id ? ", Disk: " + disk.id : "") + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });
+}
+
+function FnStoragePoolUpgrade(pool = { name, id }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "upgrade", pool.name]
+ };
+
+ FnConsole.log[1]("Storage Pools, Upgrade: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Upgrading storage pool...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Upgrade:" }));
+
+ if (/Successfully upgraded|Enabled the following features/gi.test(data)) {
+ FnDisplayAlert({ status: "success", title: "Storage Pool successfully upgraded", description: pool.name, breakword: false }, { name: "storagepool-upgrade", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Upgrade: Success, Pool: " + pool.name);
+ } else {
+ FnStoragePoolUpgradeFail({ name: pool.name, id: pool.id }, { data: data, message: message });
+ }
+ })
+ .fail(function (message, data) {
+ FnStoragePoolUpgradeFail({ name: pool.name, id: pool.id }, { data: data, message: message });
+ })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true , snapshots: true, status: true });
+ }, 200);
+ });;
+}
+
+function FnStoragePoolUpgradeFail(pool = { name, id }, process = { data, message }) {
+ FnDisplayAlert({ status: "danger", title: "Storage Pool could not be upgraded", description: pool.name, breakword: false }, { name: "storagepool-upgrade", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Upgrade: Failed, Pool: " + pool.name + ", Message: " + (process.data ? process.data : process.message));
+}
+
+function FnStoragePoolVirtualDeviceAdd(pool = { name, id, force: false, virtualdevice }, disks = { id: [] }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "add", pool.name]
+ };
+
+ modal.hide = true;
+
+ if (pool.force) {
+ process.command.splice(2, 0, "-f");
+ }
+ if (pool.virtualdevice) {
+ if (pool.virtualdevice == "dedup mirror") {
+ process.command.push("dedup");
+ process.command.push("mirror");
+ } else if (pool.virtualdevice == "log mirror") {
+ process.command.push("log");
+ process.command.push("mirror");
+ } else if (pool.virtualdevice == "special mirror") {
+ process.command.push("special");
+ process.command.push("mirror");
+ } else {
+ process.command.push(pool.virtualdevice);
+ }
+ }
+
+ disks.id.forEach(_value => _value && process.command.push(_value));
+
+ FnConsole.log[1]("Storage Pools, Virtual Device, Add: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Adding virtual device...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Virtual Device successfully added to Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-virtualdevice-add", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Virtual Device, Add: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ if (/contains devices of different sizes/gi.test(data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-" + modal.name + "-disks-" + modal.id).addClass("has-error");
+ $("#helpblock-" + modal.name + "-disks-" + modal.id).addClass("has-error").removeClass("hidden").text("Disks are of different sizes. Forcefully add virtual device to override.");
+ } else if (/mismatched replication level/gi.test(data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-" + modal.name + "-disks-" + modal.id).addClass("has-error");
+ $("#helpblock-" + modal.name + "-disks-" + modal.id).addClass("has-error").removeClass("hidden").text("Mismatched replication level. Forcefully add virtual device to override.");
+ }
+
+ if (!modal.hide) {
+ $("#spinner-" + modal.name + "-" + modal.id).addClass("hidden");
+ $("#btn-" + modal.name + "-apply-" + modal.id).prop("disabled", false);
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=" + pool.id + "]").removeClass("disabled");
+ $("#spinner-storagepool-status-" + modal.id).addClass("hidden");
+ }
+
+ if (modal.hide) {
+ FnDisplayAlert({ status: "danger", title: "Virtual Device could not be added to Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-virtualdevice-add", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.warn("Storage Pools, Virtual Device, Add: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if (modal.hide) {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: true });
+ }, 200);
+ }
+ });
+}
+
+function FnStoragePoolVirtualDeviceClear(pool = { name, id }, virtualdevice = { id }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "clear", pool.name, virtualdevice.id]
+ };
+
+ FnConsole.log[2]("Storage Pools, Virtual Device, Clear Errors: In Progress, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Clearing virtual device errors...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Virtual Device errors successfully cleared", description: virtualdevice.id, breakword: false }, { name: "storagepool-virtualdevice-clear", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Virtual Device, Clear Errors: Success, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Virtual Device errors could not be cleared", description: virtualdevice.id, breakword: false }, { name: "storagepool-virtualdevice-clear", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Virtual Device, Clear Errors: Failed, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: false, snapshots: false, status: true });
+ }, 200);
+ });
+}
+
+function FnStoragePoolVirtualDeviceRemove(pool = { name, id }, virtualdevice = { id, labelclear: false }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zpool", "remove", pool.name, virtualdevice.id]
+ };
+
+ modal.hide = true;
+
+ FnConsole.log[1]("Storage Pools, Virtual Device, Remove: In Progress, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Removing virtual device...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Virtual Device successfully removed from Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-virtualdevice-remove", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Storage Pools, Virtual Device, Remove: Success, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id);
+
+ if (virtualdevice.labelclear) {
+ modal.hide = false;
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Clearing disk label...");
+
+ setTimeout(function () {
+ FnStoragePoolDiskLabelClear({ name: pool.name, id: pool.id }, { id: virtualdevice.id, inactive: true }, { silent: false })
+ .finally(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: true });
+ }, 200);
+ });
+ }, 2000);
+ }
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Virtual Device could not be removed from Storage Pool", description: pool.name, breakword: false }, { name: "storagepool-virtualdevice-remove", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Storage Pools, Virtual Device, Remove: Failed, Pool: " + pool.name + ", Virtual Device: " + virtualdevice.id + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if (modal.hide) {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: true });
+ }, 200);
+ }
+ });
+}
+
+//#endregion
+
+//#region File Systems
+
+function FnFileSystemsGet(pool = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "readonly,name,avail,used,usedsnap,usedrefreserv,recordsize,compression,dedup,sharenfs,sharesmb,mountpoint,mounted,origin,encryption,encryptionroot,keyformat,keystatus", "-r", "-p", pool.name]
+ };
+ let filesystems = {
+ empty: true
+ };
+
+ pool.altroot = (($("#tr-storagepool-" + pool.id).attr("data-pool-altroot") == "true") ? true : false);
+ pool.boot = (($("#tr-storagepool-" + pool.id).attr("data-pool-boot") == "true") ? true : false);
+ pool.readonly = (($("#tr-storagepool-" + pool.id).attr("data-pool-readonly") == "true") ? true : false);
+ pool.feature = {
+ allocation_classes: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-allocation_classes") == "true") ? true : false),
+ edonr: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-edonr") == "true") ? true : false),
+ encryption: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-encryption") == "true") ? true : false),
+ large_blocks: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-large_blocks") == "true") ? true : false),
+ large_dnode: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-large_dnode") == "true") ? true : false),
+ lz4_compress: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-lz4_compress") == "true") ? true : false),
+ sha512: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-sha512") == "true") ? true : false),
+ skein: (($("#tr-storagepool-" + pool.id).attr("data-pool-feature-skein") == "true") ? true : false)
+ };
+
+ FnConsole.log[2]("File Systems, Get: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Get:" }));
+
+ if (data) {
+ filesystems.empty = false;
+
+ FnStoragePoolSizeGet({ name: pool.name, id: pool.id })
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Storage Pools, Size, Get:" }));
+
+ if (_data) {
+ pool.sizeraw = _data.replace(/\n+/g, "");
+
+ FnFileSystemsGetCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, boot: pool.boot, feature: { allocation_classes: pool.feature.allocation_classes, edonr: pool.feature.edonr, encryption: pool.feature.encryption, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, sha512: pool.feature.sha512, skein: pool.feature.skein }, readonly: pool.readonly, sizeraw: pool.sizeraw }, { data: data, message: message });
+ }
+ })
+ .fail(function () {
+ FnFileSystemsGetCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, boot: pool.boot, feature: { allocation_classes: pool.feature.allocation_classes, edonr: pool.feature.edonr, encryption: pool.feature.encryption, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, sha512: pool.feature.sha512, skein: pool.feature.skein }, readonly: pool.readonly, sizeraw: null }, { data: data, message: message });
+ });
+ }
+
+ FnConsole.log[1]("File Systems, Get: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if (filesystems.empty) {
+ $("#tbody-storagepool-filesystems-" + pool.id).empty();
+ $("#tbody-storagepool-filesystems-" + pool.id).append(`No file systems found. `);
+ $("#modals-storagepool-filesystems-" + pool.id).remove();
+ $("#modals-storagepool-filesystem-" + pool.id).remove();
+ $("#modals").append(`
`);
+
+ //Register file systems modals
+ if (!pool.readonly) {
+ FnModalFileSystemsCreate({ name: pool.name, id: pool.id, altroot: pool.altroot, feature: { allocation_classes: pool.feature.allocation_classes, edonr: pool.feature.edonr, encryption: pool.feature.encryption, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, sha512: pool.feature.sha512, skein: pool.feature.skein } });
+ }
+
+ $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-filesystems", "true");
+
+ $("#spinner-storagepool-filesystems-" + pool.id).addClass("hidden");
+ $("#paneltitle-storagepool-filesystems-" + pool.id).removeClass("hidden").text(FnDateTime());
+ $("#btn-storagepool-filesystems-create-" + pool.id).prop("disabled", false);
+ $("#btn-storagepool-filesystems-refresh-" + pool.id).prop("disabled", false);
+ }
+
+ FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
+ FnCockpitElementsUpdate();
+ });
+}
+
+function FnFileSystemsGetCommand(pool = { name, id, altroot: false, boot: false, feature: { allocation_classes: true, edonr: true, encryption: true, large_blocks: true, large_dnode: true, lz4_compress: true, sha512: true, skein: true }, readonly: false, sizeraw: 0 }, process = { data, message }) {
+ let filesystems = process.data.split(/\n/g).filter(v => v);
+
+ $("#tbody-storagepool-filesystems-" + pool.id).empty();
+ $("#modals-storagepool-filesystems-" + pool.id).remove();
+ $("#modals-storagepool-filesystem-" + pool.id).remove();
+ $("#modals").append(`
`);
+ $("#modals").append(`
`);
+
+ filesystems.forEach((_value, _index) => {
+ let filesystem = {
+ properties: _value.split(/\t/g).filter(v => v),
+ clone: false,
+ compression: "",
+ dedup: "",
+ encryption: false,
+ encryptionroot: "",
+ id: "",
+ keyformat: "",
+ keystatus: "",
+ mounted: false,
+ mountpoint: "",
+ name: "",
+ origin: "",
+ readonly: false,
+ recordsize: "",
+ shares: [],
+ sharenfs: false,
+ sharesmb: false,
+ type: "File System",
+ actionsmenu: {
+ register: {
+ samba: {},
+ snapshot: {}
+ }
+ }
+ };
+
+ filesystem.output = ``;
+
+ filesystem.properties.forEach((__value, __index) => {
+ //0=readonly, 1=name, 2=avail, 3=used, 4=usedsnap, 5=usedrefreserv, 6=recordsize, 7=compression, 8=dedup, 9=sharenfs, 10=sharesmb, 11=mountpoint, 12=mounted, 13=origin, 14=encryption, 15=encryptionroot, 16=keyformat, 17=keystatus
+
+ switch (__index) {
+ case 0: //0=readonly
+ if (__value.toLowerCase() == "on" || pool.boot && zfsmanager.configuration.zfs.storagepool.bootlockdown) {
+ filesystem.readonly = true;
+ }
+
+ break;
+ case 1: //1=name
+ filesystem.name = __value;
+ filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.name, attribute: true });
+
+ filesystem.output += `Name: ` + __value + (filesystem.readonly ? ` ` : ``) + ` `;
+
+ break;
+ case 2: //2=avail
+ filesystem.output += `Available: ` + FnFormatBytes({ base2: true, decimals: 2, value: __value }) + ` `;
+
+ break;
+ case 3: //3=used
+ filesystem.output += `Used: ` + FnFormatBytes({ base2: true, decimals: 2, value: __value }) + ` `;
+
+ break;
+ case 4: //4=usedsnap
+ filesystem.output += `Snapshots: ` + FnFormatBytes({ base2: true, decimals: 2, value: __value }) + ` `;
+
+ break;
+ case 5: //5=usedrefreserv
+ if (pool.sizeraw) {
+ filesystem.usedrefreservpercent = FnRound({ decimals: 1, value: (__value / pool.sizeraw) * 100 });
+
+ __value = FnFormatBytes({ base2: true, decimals: 2, value: __value });
+
+ if ($.isNumeric(filesystem.usedrefreservpercent) && filesystem.usedrefreservpercent > 0) {
+ __value += " (" + filesystem.usedrefreservpercent + " %)";
+ }
+ } else {
+ __value = FnFormatBytes({ base2: true, decimals: 2, value: __value });
+ }
+
+ filesystem.output += `Refreservation: ` + __value + ` `;
+
+ break;
+ case 6: //6=recordsize
+ filesystem.recordsize = __value;
+
+ filesystem.output += `Record Size: ` + FnFormatBytes({ base2: true, decimals: 0, value: __value }) + ` `;
+
+ break;
+ case 7: //7=compression
+ filesystem.compression = __value;
+
+ if (/off|on/gi.test(__value)) {
+ __value = __value.charAt(0).toUpperCase() + __value.slice(1);
+ } else {
+ __value = __value.toUpperCase();
+ }
+
+ filesystem.output += `Compression: ` + __value + ` `;
+
+ break;
+ case 8: //8=dedup
+ filesystem.dedup = __value;
+
+ if (/sha256|sha512/gi.test(__value)) {
+ __value = __value.replace(/sha/gi, "SHA-");
+ }
+ if (/off|on|verify|skein/gi.test(__value)) {
+ __value = __value.charAt(0).toUpperCase() + __value.slice(1);
+ }
+ if (/edonr/gi.test(__value)) {
+ __value = __value.replace(/edonr/gi, "Edon-R");
+ }
+
+ filesystem.output += `Deduplication: ` + __value.replace(/,verify/g, " + Verify") + ` `;
+
+ break;
+ case 9: //9=sharenfs
+ filesystem.sharenfs = __value;
+
+ if (__value.toLowerCase() != "off" && __value.toLowerCase() != "-") {
+ filesystem.sharenfs = true;
+ filesystem.shares.push("NFS");
+ } else {
+ filesystem.sharenfs = false;
+ }
+
+ break;
+ case 10: //10=sharesmb
+ filesystem.sharesmb = __value;
+
+ if (__value.toLowerCase() == "on") {
+ filesystem.sharesmb = true;
+ filesystem.shares.push("SMB");
+ } else {
+ filesystem.sharesmb = false;
+ }
+
+ if (/off|on/gi.test(__value)) {
+ __value = __value.charAt(0).toUpperCase() + __value.slice(1);
+ } else {
+ __value = __value.toUpperCase();
+ }
+
+ filesystem.output += `Share: ` + (filesystem.shares.length > 0 ? filesystem.shares.join(" + ") : "Off") + ` `;
+
+ break;
+ case 11: //11=mountpoint
+ filesystem.mountpoint = __value;
+ break;
+ case 12: //12=mounted
+ if (__value.toLowerCase() == "yes") {
+ filesystem.mounted = true;
+ } else {
+ filesystem.mounted = false;
+ }
+
+ if (/yes|no/gi.test(__value)) {
+ __value = __value.charAt(0).toUpperCase() + __value.slice(1);
+ }
+
+ filesystem.output += `Mounted: ` + __value + ` `;
+
+ break;
+ case 13: //13=origin
+ if (__value != "-") {
+ filesystem.origin = __value;
+ filesystem.clone = true;
+ filesystem.type = "Clone File System";
+ } else {
+ filesystem.clone = false;
+ filesystem.type = "File System";
+ }
+
+ break;
+ case 14: //14=encryption
+ if (__value.toLowerCase() != "off") {
+ filesystem.encryption = true;
+ } else {
+ filesystem.encryption = false;
+ }
+
+ break;
+ case 15: //15=encryptionroot
+ filesystem.encryptionroot = __value;
+
+ break;
+ case 16: //16=keyformat
+ if (filesystem.encryption && __value.toLowerCase() == "passphrase") {
+ filesystem.keyformat = "passphrase";
+ }
+
+ break;
+ case 17: //17=keystatus
+ if (__value != "-") {
+ filesystem.keystatus = __value;
+ } else {
+ filesystem.keystatus = "";
+ }
+
+ break;
+ }
+
+ //Add icons and actions menu at end of array
+ if (__index >= (filesystem.properties.length - 1)) {
+ filesystem.icons = {
+ clone: ` `,
+ keystatus: {
+ locked: ` `,
+ unlocked: ` `
+ }
+ };
+
+ filesystem.output += `Clone: ` + (filesystem.clone ? `Yes ` + filesystem.icons.clone : `No`) + ` `;
+ filesystem.output += `Encrypted: ` + (/available|unavailable/.test(filesystem.keystatus) ? `Yes` : `No`) + ` `;
+
+ if (filesystem.keystatus == "unavailable") {
+ filesystem.output += filesystem.icons.keystatus.locked;
+ } else if (filesystem.keystatus == "available") {
+ filesystem.output += filesystem.icons.keystatus.unlocked;
+ }
+
+ filesystem.output += ` `;
+
+ //Actions menu
+ filesystem.actionsmenu.items = {
+ itemconfigure: [],
+ itemconfiguredivider: function () {
+ if (this.itemconfigure.length > 0 && this.item.length > 0) {
+ this.itemconfigure.push(this.divider);
+ }
+ },
+ item: [],
+ itemdivider: function () {
+ if (this.item.length > 0 && this.itemencrypted.length > 0) {
+ this.item.push(this.divider);
+ }
+ },
+ itemencrypted: [],
+ itemencrypteddivider: function () {
+ if ((this.item.length > 0 || this.itemencrypted.length > 0) && (this.itemsamba.length > 0 || this.itemsnapshot.length > 0)) {
+ this.itemencrypted.push(this.divider);
+ }
+ },
+ itemsamba: [],
+ itemsambadivider: function () {
+ if ((this.item.length > 0 || this.itemencrypted.length > 0) && this.itemsamba.length > 0 && this.itemsnapshot.length > 0) {
+ this.itemsamba.push(this.divider);
+ }
+ },
+ itemsnapshot: [],
+ divider: ` `
+ };
+ filesystem.actionsmenu.display = function () {
+ if (/@/g.test(filesystem.name) == false && (this.items.itemconfigure.length + this.items.item.length + this.items.itemencrypted.length + this.items.itemsamba.length + this.items.itemsnapshot.length) > 0) {
+ this.items.itemconfiguredivider();
+ this.items.itemdivider();
+ this.items.itemencrypteddivider();
+ this.items.itemsambadivider();
+
+ return this.header + this.items.itemconfigure.join("\n") + this.items.item.join("\n") + this.items.itemencrypted.join("\n") + this.items.itemsamba.join("\n") + this.items.itemsnapshot.join("\n") + this.footer;
+ } else {
+ return "";
+ }
+ };
+ filesystem.actionsmenu.header = `
+
+
+
+
+
+
+ `;
+
+ //Configure File System
+ filesystem.actionsmenu.items.itemconfigure.push(`Configure ` + filesystem.type + ` `);
+
+ //Rename File System
+ if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && filesystem.name != pool.name) {
+ filesystem.actionsmenu.items.item.push(`Rename ` + filesystem.type + ` `);
+
+ filesystem.actionsmenu.register.rename = true;
+ }
+
+ //Promote Clone File System
+ if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && filesystem.clone && filesystem.origin.replace(/^(.*)\@.*$/, "$1") != pool.name) {
+ filesystem.actionsmenu.items.item.push(`Promote ` + filesystem.type + ` `);
+
+ filesystem.actionsmenu.register.promote = true;
+ }
+
+ //Mount File System / Unmount File System
+ if (!pool.boot || pool.boot && !zfsmanager.configuration.zfs.storagepool.bootlockdown) {
+ if (!filesystem.mounted && filesystem.keystatus != "unavailable") {
+ filesystem.actionsmenu.items.item.push(`Mount ` + filesystem.type + ` `);
+
+ filesystem.actionsmenu.register.mount = true;
+ } else if (filesystem.mounted) {
+ filesystem.actionsmenu.items.item.push(`Unmount ` + filesystem.type + ` `);
+
+ filesystem.actionsmenu.register.unmount = true;
+ }
+ }
+
+ //Unlock File System / Lock File System
+ if (filesystem.keystatus == "unavailable" && !filesystem.clone && filesystem.encryptionroot == filesystem.name) {
+ filesystem.actionsmenu.items.item.push(`Unlock File System `);
+
+ filesystem.actionsmenu.register.unlock = true;
+ } else if (filesystem.keystatus == "available" && !filesystem.mounted && !filesystem.clone && filesystem.encryptionroot == filesystem.name) {
+ filesystem.actionsmenu.items.item.push(`Lock File System `);
+
+ filesystem.actionsmenu.register.lock = true;
+ }
+
+ //Change Passphrase
+ if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && filesystem.keystatus == "available" && !filesystem.clone && filesystem.encryptionroot == filesystem.name) {
+ filesystem.actionsmenu.items.itemencrypted.push(`Change Passphrase `);
+
+ filesystem.actionsmenu.register.changepassphrase = true;
+ }
+
+ //Destroy File System
+ if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && filesystem.name != pool.name) {
+ if (!filesystem.clone || filesystem.clone && new RegExp("^" + filesystem.name + "/").test(filesystem.origin.replace(/^(.*)\@.*$/, "$1")) == false) { //Do not display if clone origin is a child file system - will generate recursive dependency error
+ filesystem.actionsmenu.items.item.push(`Destroy ` + filesystem.type + ` `);
+
+ filesystem.actionsmenu.register.destroy = true;
+ }
+ }
+
+ //Enable Samba Share
+ if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && !filesystem.sharesmb && zfsmanager.configuration.samba.manage) {
+ filesystem.actionsmenu.items.itemsamba.push(`Enable Samba Share `);
+
+ filesystem.actionsmenu.register.samba.enable = true;
+ }
+
+ //Configure Samba Share
+ if (filesystem.sharesmb && zfsmanager.configuration.samba.manage) {
+ filesystem.actionsmenu.items.itemsamba.push(`Configure Samba Share `);
+
+ filesystem.actionsmenu.register.samba.configure = true;
+ }
+
+ //Disable Samba Share
+ if (!pool.readonly && (!filesystem.readonly || filesystem.readonly && !zfsmanager.configuration.zfs.filesystem.readonlylockdown) && filesystem.sharesmb && zfsmanager.configuration.samba.manage) {
+ filesystem.actionsmenu.items.itemsamba.push(`Disable Samba Share `);
+
+ filesystem.actionsmenu.register.samba.disable = true;
+ }
+
+ //Create Snapshot
+ if (!pool.readonly && zfsmanager.configuration.zfs.filesystem.snapshotactions) {
+ filesystem.actionsmenu.items.itemsnapshot.push(`Create Snapshot `);
+
+ filesystem.actionsmenu.register.snapshot.create = true;
+ }
+
+ filesystem.output += ``;
+ }
+ });
+
+ filesystem.output += ` `;
+
+ $("#tbody-storagepool-filesystems-" + pool.id).append(filesystem.output);
+
+ //Register file system modals
+ FnModalFileSystemConfigure({ name: pool.name, id: pool.id, altroot: pool.altroot, feature: { allocation_classes: pool.feature.allocation_classes, edonr: pool.feature.edonr, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, sha512: pool.feature.sha512, skein: pool.feature.skein }, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, origin: filesystem.origin, type: filesystem.type });
+ if (filesystem.actionsmenu.register.changepassphrase) {
+ FnModalFileSystemChangePassphrase({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ }
+ if (filesystem.actionsmenu.register.destroy) {
+ FnModalFileSystemDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, sharesmb: filesystem.sharesmb, type: filesystem.type });
+ }
+ if (filesystem.actionsmenu.register.lock) {
+ FnModalFileSystemLock({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, type: filesystem.type });
+ }
+ if (filesystem.actionsmenu.register.mount) {
+ FnModalFileSystemMount({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, sharesmb: filesystem.sharesmb, type: filesystem.type });
+ }
+ if (filesystem.actionsmenu.register.promote) {
+ FnModalFileSystemPromote({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, origin: filesystem.origin, type: filesystem.type });
+ }
+ if (filesystem.actionsmenu.register.rename) {
+ FnModalFileSystemRename({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, id: filesystem.id, clone: filesystem.clone, encryption: filesystem.encryption, encryptionroot: filesystem.encryptionroot, origin: filesystem.origin, sharesmb: filesystem.sharesmb, type: filesystem.type });
+ }
+ if (filesystem.actionsmenu.register.samba.configure) {
+ FnModalFileSystemSambaConfigure({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint });
+ }
+ if (filesystem.actionsmenu.register.samba.disable) {
+ FnModalFileSystemSambaDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, type: filesystem.type });
+ }
+ if (filesystem.actionsmenu.register.samba.enable) {
+ FnModalFileSystemSambaEnable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint });
+ }
+ if (filesystem.actionsmenu.register.snapshot.create) {
+ FnModalFileSystemSnapshotCreate({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ }
+ if (filesystem.actionsmenu.register.unlock) {
+ FnModalFileSystemUnlock({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, sharesmb: filesystem.sharesmb, type: filesystem.type });
+ }
+ if (filesystem.actionsmenu.register.unmount) {
+ FnModalFileSystemUnmount({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, encryptionroot: filesystem.encryptionroot, keystatus: filesystem.keystatus, sharesmb: filesystem.sharesmb, type: filesystem.type });
+ }
+ });
+
+ //Register file systems modals
+ if (!pool.readonly) {
+ FnModalFileSystemsCreate({ name: pool.name, id: pool.id, altroot: pool.altroot, feature: { allocation_classes: pool.feature.allocation_classes, edonr: pool.feature.edonr, encryption: pool.feature.encryption, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, sha512: pool.feature.sha512, skein: pool.feature.skein } });
+ }
+
+ $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-filesystems", "true");
+
+ $("#spinner-storagepool-filesystems-" + pool.id).addClass("hidden");
+ $("#paneltitle-storagepool-filesystems-" + pool.id).removeClass("hidden").html(FnDateTime() + (zfsmanager.configuration.zfs.storagepool.count ? ` ` + filesystems.length + ` ` : ``));
+ $("#btn-storagepool-filesystems-create-" + pool.id).prop("disabled", false);
+ $("#btn-storagepool-filesystems-refresh-" + pool.id).prop("disabled", false);
+
+ FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
+ FnCockpitElementsUpdate();
+}
+
+function FnFileSystemsLockedGet() {
+ let filesystems = {
+ id: []
+ };
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name,encryption,encryptionroot,keyformat,keystatus", "-r", "-t", "filesystem"]
+ };
+
+ $("#listgroup-storagepools-filesystems-unlock-filesystems").empty().append(`
`);
+
+ FnConsole.log[2]("File Systems, Locked, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Locked, Get:" }));
+
+ filesystems.id = data.split(/\n/g).filter(v => {
+ if (!zfsmanager.configuration.zfs.storagepool.boot && zfsmanager.zfs.storagepool.boot && new RegExp("^" + zfsmanager.zfs.storagepool.boot + "\t|^" + zfsmanager.zfs.storagepool.boot + "/").test(v)) {
+ //Do not display boot
+ } else if (!zfsmanager.configuration.zfs.storagepool.root && zfsmanager.zfs.storagepool.root && new RegExp("^" + zfsmanager.zfs.storagepool.root + "\t|^" + zfsmanager.zfs.storagepool.root + "/").test(v)) {
+ //Do not display root
+ } else {
+ return v;
+ }
+ });
+
+ filesystems.id.forEach((_value, _index) => {
+ let filesystem = {
+ properties: _value.split(/\t/g).filter(v => v)
+ };
+
+ filesystem.name = filesystem.properties[0];
+ filesystem.encryption = filesystem.properties[1];
+ filesystem.encryptionroot = filesystem.properties[2];
+ filesystem.keyformat = filesystem.properties[3];
+ filesystem.keystatus = filesystem.properties[4];
+
+ if (filesystem.encryptionroot == filesystem.name && filesystem.keyformat == "passphrase" && filesystem.keystatus == "unavailable") {
+ filesystems.output = `
+
+
+
+ ` + filesystem.name + `
+
+
+
+ `;
+
+ $("#listgroup-storagepools-filesystems-unlock-filesystems").append(filesystems.output);
+ }
+ });
+
+ setTimeout(function () {
+ $("#spinner-storagepools-filesystems-unlock-filesystems").remove();
+ $("#listgroup-storagepools-filesystems-unlock-filesystems > li").removeClass("hidden");
+ if ($("#helpblock-storagepools-filesystems-unlock-filesystems-warning").text()) {
+ $("#helpblock-storagepools-filesystems-unlock-filesystems-warning").removeClass("hidden");
+ }
+
+ if ($("#listgroup-storagepools-filesystems-unlock-filesystems > li").length == 0) {
+ filesystems.output = `
+
+
+ No locked file systems found.
+
+
+ `;
+
+ $("#listgroup-storagepools-filesystems-unlock-filesystems").append(filesystems.output);
+ }
+ }, 200);
+
+ FnConsole.log[1]("File Systems, Locked, Get: Success");
+ })
+ .fail(function (message, data) {
+ $("#spinner-storagepools-filesystems-unlock-filesystems").remove();
+ $("#listgroup-storagepools-filesystems-unlock-filesystems > li").removeClass("hidden");
+
+ if ($("#listgroup-storagepools-filesystems-unlock-filesystems > li").length == 0) {
+ filesystems.output = `
+
+
+ No locked file systems found.
+
+
+ `;
+
+ $("#listgroup-storagepools-filesystems-unlock-filesystems").append(filesystems.output);
+ }
+
+ FnConsole.warn("File Systems, Locked, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnFileSystemsMountedGet(pool = { name, id }, filesystem = { name, id }, modal = { alert: { id, mount: true } }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name,mounted", "-r", "-t", "filesystem", filesystem.name]
+ };
+
+ filesystem.children = {
+ mounted: false
+ }
+
+ FnConsole.log[2]("File Systems, Mounted, Get: In Progress: Success, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Mounted, Get:" }));
+
+ let filesystems = data.split(/\n/g).filter((v, i) => v && i > 0);
+
+ filesystems.forEach((_value, _index) => {
+ filesystem.properties = _value.split(/\t/g).filter(v => v);
+
+ if (filesystem.properties[1] == "yes" && !filesystem.children.mount) {
+ filesystem.children.mounted = true;
+ }
+ });
+
+ if (filesystem.children.mounted) {
+ modal.alert.id.html(FnDisplayInlineAlert({ status: "warning", title: "There are child file systems currently mounted. " + (modal.alert.mount ? "Mounting" : "Unmounting") + " this file system may adversely affect the child file systems.", description: null }, { name: null, id: null, hidden: false }));
+ }
+
+ FnConsole.log[1]("File Systems, Mounted, Get: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, Mounted, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnFileSystemsNamesGet(pool = { name, id }, filesystem = { existing: { name, clone: false, encryption: false, encryptionroot, origin }, override: false }, modal = { dropdown: { id, selected } }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name,encryption,encryptionroot,keystatus", "-r", "-t", "filesystem", pool.name]
+ };
+
+ FnConsole.log[2]("File Systems, Names, Get: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Names, Get:" }));
+
+ let filesystems = data.split(/\n/g).filter(v => v);
+
+ modal.dropdown.items = [];
+
+ modal.dropdown.id.empty();
+
+ filesystems.forEach((_value, _index) => {
+ filesystem.properties = _value.split(/\t/g).filter(v => v);
+ filesystem.name = filesystem.properties[0];
+ filesystem.encryption = (filesystem.properties[1].toLowerCase() != "off" ? true : false);
+ filesystem.encryptionroot = (filesystem.properties[2] && filesystem.properties[2] != "-" ? filesystem.properties[2] : "");
+ filesystem.encryptionstatus = "";
+ filesystem.existing.regexp = {
+ name: new RegExp("^" + filesystem.existing.name + "/", "g")
+ };
+ filesystem.keystatus = filesystem.properties[3].toLowerCase();
+
+ if (filesystem.encryption && /^available$|^unavailable$/.test(filesystem.keystatus)) {
+ filesystem.encryptionstatus = ` `
+ }
+
+ modal.dropdown.add = false;
+ modal.dropdown.item = `` + filesystem.name + filesystem.encryptionstatus + ` `;
+
+ if ((filesystem.override || filesystem.existing.encryption) && filesystem.existing.clone) { //Encrypted clone file systems can only move within origin and child file systems
+ filesystem.existing.regexp.origin = new RegExp("^" + filesystem.existing.origin.replace(/^(.*)\@.*$/, "$1\/"), "g");
+
+ if (filesystem.name == filesystem.existing.origin.replace(/^(.*)\@.*$/, "$1")) { //Origin file system
+ modal.dropdown.add = true;
+ } else if (filesystem.name == filesystem.existing.name.replace(/\/[^\/]+$/, "")) { //File System parent
+ modal.dropdown.add = true;
+ } else if (filesystem.name != filesystem.existing.name && filesystem.existing.regexp.origin.test(filesystem.name) && !filesystem.existing.regexp.name.test(filesystem.name)) { //Origin child file systems
+ modal.dropdown.add = true;
+ }
+ } else if (filesystem.override || filesystem.existing.encryption) { //Encrypted file systems that are their own encryption root can move anywhere, child file system of the encryption root can only move within encryption root and its child file systems
+ if (filesystem.name != filesystem.existing.name && !filesystem.existing.regexp.name.test(filesystem.name)) {
+ if (filesystem.existing.name == filesystem.existing.encryptionroot) { //File system is its own encryption root
+ modal.dropdown.add = true;
+ } else if (filesystem.encryptionroot == filesystem.existing.encryptionroot) { //File system is a child of the encryption root
+ modal.dropdown.add = true;
+ }
+ }
+ } else { //Unencrypted file systems can only move to unencrypted file systems
+ if (!filesystem.encryption && filesystem.name != filesystem.existing.name && !filesystem.existing.regexp.name.test(filesystem.name)) {
+ modal.dropdown.add = true;
+ }
+ }
+
+ if (modal.dropdown.add) {
+ modal.dropdown.items.push(modal.dropdown.item);
+ }
+ });
+
+ modal.dropdown.id.append(modal.dropdown.items.join("\n"));
+
+ FnConsole.log[1]("File Systems, Names, Get: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, Names, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnFileSystemsUnlock(filesystems = { id: [] }, filesystem = { mount: true, overlay: true, passphrase }, modal = { name, id }) {
+ let promise = Promise.resolve();
+
+ filesystems.count = {
+ available: 0,
+ error: 0,
+ success: 0
+ };
+
+ $("#listgroup-" + modal.name + modal.id + "-filesystems > li.list-group-item > label > span.pficon").removeClass("list-group-ct-warning");
+
+ if (filesystems.id.length > 0) {
+ FnConsole.log[2]("File Systems, Unlock: In Progress");
+
+ $("#spinner-" + modal.name + modal.id + " span").text("Unlocking file system" + (filesystems.id.length > 1 ? "s" : "") + "...");
+
+ filesystems.id.forEach((_value, _index) => {
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ let pool = {
+ name: _value.replace(/\/.*$/, ""),
+ id: FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: _value.replace(/\/.*$/, ""), attribute: true })
+ };
+
+ filesystem.name = _value;
+ filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: _value, attribute: true });
+
+ FnFileSystemUnlock({ name: pool.name, id: pool.id, altroot: false, readonly: false }, { name: filesystem.name, id: filesystem.id, mount: filesystem.mount, overlay: filesystem.overlay, passphrase: filesystem.passphrase, type: "File System" }, { enable: false }, { name: modal.name, id: modal.id }, { refresh: false })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Unlock:" }));
+
+ if (/error|Incorrect key/i.test(data)) {
+ filesystems.count.error++;
+
+ $("#listgroup-" + modal.name + modal.id + "-filesystems > li.list-group-item[data-filesystem-name='" + filesystem.name + "'] > label > span.pficon").addClass("list-group-ct-warning");
+ } else {
+ filesystems.count.success++;
+
+ $("#listgroup-" + modal.name + modal.id + "-filesystems > li.list-group-item[data-filesystem-name='" + filesystem.name + "']").remove();
+ }
+ })
+ .fail(function (message, data) {
+ if (/Key already loaded/i.test(data)) {
+ filesystems.count.success++;
+
+ $("#listgroup-" + modal.name + modal.id + "-filesystems > li.list-group-item[data-filesystem-name='" + filesystem.name + "']").remove();
+ } else {
+ filesystems.count.error++;
+
+ $("#listgroup-" + modal.name + modal.id + "-filesystems > li.list-group-item[data-filesystem-name='" + filesystem.name + "'] > label > span.pficon").addClass("list-group-ct-warning");
+ }
+ })
+ .finally(function () {
+ if (_index == (filesystems.id.length - 1)) {
+ $("#listgroup-storagepools-filesystems-unlock-filesystems input[name='checkbox-storagepools-filesystems-unlock-filesystems']").map(function () {
+ filesystems.count.available++;
+ });
+
+ if (filesystems.count.error == 0) {
+ FnConsole.log[1]("File Systems, Unlock: Success");
+ } else {
+ FnConsole.warn("File Systems, Unlock: Failed");
+ }
+
+ if (filesystems.count.available == 0) {
+ $("#modal-" + modal.name + modal.id).modal("hide");
+ } else {
+ $("#spinner-" + modal.name + modal.id).addClass("hidden");
+ $("#spinner-" + modal.name + modal.id + " span").text("");
+ $("#btn-" + modal.name + "-apply" + modal.id).prop("disabled", false);
+ }
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 1000);
+ }
+ });
+
+ resolve();
+ }, 1000)
+ ));
+ });
+ } else {
+ $("#modal-" + modal.name + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolsGet();
+ }, 1000);
+ }
+}
+
+//#endregion
+
+//#region File System
+
+function FnFileSystemChangePassphrase(pool = { name, id }, filesystem = { name, id, passphrase }) {
+ let process = {
+ command: []
+ };
+
+ if (!filesystem.passphrase || filesystem.passphrase.length < 8) {
+ FnFileSystemChangePassphraseFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: "Passphrase requires a minimum of 8 characters.", message: null });
+ return;
+ }
+
+ //Escape percentage and single quote special character for printf
+ if (/\%/g.test(filesystem.passphrase)) {
+ filesystem.passphrase = filesystem.passphrase.replace(/\%/g, "\%\%");
+ }
+ if (/\'/g.test(filesystem.passphrase)) {
+ filesystem.passphrase = filesystem.passphrase.replace(/\'/g, "\'\"\'\"\'");
+ }
+
+ process.command = ["/bin/sh", "-c", "printf '" + filesystem.passphrase + "' | /sbin/zfs change-key \"" + filesystem.name + "\""];
+
+ FnConsole.log[2]("File Systems, Change Passphrase: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-storagepool-filesystem-changepassphrase-" + filesystem.id + " span").text("Changing passphrase...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Change Passphrase:" }));
+
+ if (/error|Key must be loaded/i.test(data)) {
+ FnFileSystemChangePassphraseFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: data, message: message });
+ return;
+ }
+
+ FnDisplayAlert({ status: "success", title: "File System passphrase successfully changed", description: filesystem.name, breakword: false }, { name: "filesystem-changepassphrase", id: filesystem.id, timeout: 4 });
+
+ FnConsole.log[1]("File Systems, Change Passphrase: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ $("#modal-storagepool-filesystem-changepassphrase-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ })
+ .fail(function (message, data) {
+ FnFileSystemChangePassphraseFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: data, message: message });
+ });
+}
+
+function FnFileSystemChangePassphraseFail(pool = { name, id }, filesystem = { name, id }, process = { data, message }) {
+ let modal = {
+ hide: true
+ };
+
+ if (/Passphrase requires a minimum of 8 characters./i.test(process.data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
+ $("#input-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).focus();
+ } else if (/Key must be loaded/i.test(process.data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-filesystem-changepassphrase-filesystem-" + filesystem.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystem-changepassphrase-filesystem-" + filesystem.id).addClass("has-error").removeClass("hidden").text("File System is locked.");
+ $("#input-storagepool-filesystem-changepassphrase-filesystem-" + filesystem.id).focus();
+ } else if (/encryption failure/i.test(process.data)) { //Error message when pool is read only
+ modal.hide = true;
+ } else if (/error/i.test(process.data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Passphrase is incorrect.");
+ $("#input-storagepool-filesystem-changepassphrase-passphrase-" + filesystem.id).focus();
+ }
+
+ if (!modal.hide) {
+ $("#spinner-storagepool-filesystem-changepassphrase-" + filesystem.id).addClass("hidden");
+ $("#spinner-storagepool-filesystem-changepassphrase-" + filesystem.id + " span").text("");
+ $("#btn-storagepool-filesystem-changepassphrase-apply-" + filesystem.id).prop("disabled", false);
+ }
+
+ FnConsole.warn("File Systems, Change Passphrase: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
+
+ if (modal.hide) {
+ FnDisplayAlert({ status: "danger", title: "File System passphrase could not be changed", description: filesystem.name, breakword: false }, { name: "filesystem-changepassphrase", id: filesystem.id, timeout: 4 });
+
+ $("#modal-storagepool-filesystem-changepassphrase-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+}
+
+function FnFileSystemChildDatasetsGet(pool = { name, id }, filesystem = { name, id, clones: true }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name,clones", "-r", "-t", "filesystem,snapshot", filesystem.name]
+ };
+
+ FnConsole.log[2]("File Systems, Child, Datasets, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Child, Datasets, Get:" }));
+
+ data = data.split(/\n/g).filter(v => v);
+
+ let filesystems = {
+ id: []
+ };
+ let snapshots = {
+ id: []
+ };
+
+ if (data.length > 0) {
+ data.forEach((_value, _index) => {
+ let dataset = {
+ properties: _value.split(/\t/g).filter(v => v)
+ };
+
+ dataset.name = dataset.properties[0];
+ dataset.clones = (dataset.properties[1] ? dataset.properties[1] : "");
+
+ if (new RegExp("^" + filesystem.name + ".*@").test(dataset.name)) {
+ snapshots.id.push(dataset.name);
+
+ if (dataset.clones && filesystem.clones) {
+ dataset.clones = dataset.clones.split(",").filter(v => v);
+
+ dataset.clones.forEach((_value, _index) => {
+ filesystems.id.push(_value);
+ });
+ }
+
+ } else if (new RegExp("^" + filesystem.name + ".*@").test(dataset.name) == false) {
+ filesystems.id.push(dataset.name);
+ }
+ });
+ }
+
+ filesystems.id.sort();
+ snapshots.id.sort();
+
+ FnConsole.log[1]("File Systems, Child, Datasets, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ FnFileSystemChildFileSystemsGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { id: filesystems.id }, { name: modal.name, id: modal.id });
+ FnFileSystemChildSnapshotsGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { id: filesystems.id }, { name: modal.name, id: modal.id });
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, Child, Datasets, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnFileSystemChildFileSystemsGet(pool = { name, id }, filesystem = { name, id }, filesystems = { id: [] }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name", "-r", "-t", "filesystem"]
+ };
+
+ filesystems.id.forEach(_value => _value && process.command.push(_value));
+
+ FnConsole.log[2]("File Systems, Child, File Systems, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Child, File Systems, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v),
+ count: {
+ filesystems: 0,
+ filesystemswithclones: 0
+ }
+ };
+
+ if (filesystems.id.length > 0) {
+ filesystems.id.forEach((_value, _index) => {
+ if (new RegExp("^" + filesystem.name + "/").test(_value)) {
+ filesystems.count.filesystems++;
+
+ $("#ul-" + modal.name + "-child-filesystems-" + modal.id).append("" + _value + " \n");
+ }
+
+ if (_value != filesystem.name) {
+ filesystems.count.filesystemswithclones++;
+
+ $("#ul-" + modal.name + "-child-filesystemswithclones-" + modal.id).append("" + _value + " \n");
+ }
+ });
+
+ $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-filesystem-child-filesystems", filesystems.count.filesystems);
+ $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-filesystem-child-filesystemswithclones", filesystems.count.filesystemswithclones);
+ }
+
+ FnConsole.log[1]("File Systems, Child, File Systems, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, Child, File Systems, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnFileSystemChildSnapshotsGet(pool = { name, id }, filesystem = { name, id }, snapshots = { id: [] }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name", "-r", "-t", "snapshot"]
+ };
+
+ snapshots.id.forEach(_value => _value && process.command.push(_value));
+
+ FnConsole.log[2]("File Systems, Child, Snapshots, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Child, Snapshots, Get:" }));
+
+ let snapshots = {
+ id: data.split(/\n/g).filter(v => v),
+ count: {
+ snapshots: 0,
+ snapshotswithclones: 0
+ }
+ };
+
+ if (snapshots.id.length > 0) {
+ snapshots.id.forEach((_value, _index) => {
+ if (new RegExp("^" + filesystem.name + ".*@").test(_value)) {
+ snapshots.count.snapshots++;
+
+ $("#ul-" + modal.name + "-child-snapshots-" + modal.id).append("" + _value + " \n");
+ }
+
+ snapshots.count.snapshotswithclones++;
+
+ $("#ul-" + modal.name + "-child-snapshotswithclones-" + modal.id).append("" + _value + " \n");
+ });
+
+ $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-filesystem-child-snapshots", snapshots.count.snapshots);
+ $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-filesystem-child-snapshotswithclones", snapshots.count.snapshotswithclones);
+ }
+
+ FnConsole.log[1]("File Systems, Child, Snapshots, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, Child, Snapshots, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnFileSystemConfigurationGet(pool = { name, id, readonly: false }, filesystem = { name, id }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "get", "readonly,aclinherit,acltype,atime,available,canmount,casesensitivity,checksum,compression,context,dedup,dnodesize,defcontext,encryption,encryptionroot,fscontext,guid,mountpoint,quota,recordsize,refreservation,rootcontext,sharenfs,sharesmb,special_small_blocks,used,xattr", "-H", "-o", "property,value,source", "-p", filesystem.name]
+ };
+
+ if (!zfsmanager.user.admin) {
+ pool.readonly = true;
+ }
+
+ filesystem.available = "";
+ filesystem.context = false;
+ filesystem.fscontext = false;
+ filesystem.defcontext = false;
+ filesystem.readonly = false;
+ filesystem.rootcontext = false;
+
+ FnConsole.log[2]("File Systems, Configuration, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Configuration, Get:" }));
+
+ process.data = data.replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v);
+
+ process.data.forEach((_value, _index) => {
+ _value = _value.split("\u22C5");
+
+ filesystem.properties = {
+ property: _value[0].toLowerCase(),
+ value: _value[1].toLowerCase(),
+ valueraw: _value[1],
+ source: _value[2]
+ };
+
+ let size = {};
+
+ switch (filesystem.properties.property) {
+ case "aclinherit": //Default is restricted
+ filesystem.property = {
+ value: "Restricted",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "discard":
+ filesystem.property.value = "Discard";
+ break;
+ case "noallow":
+ filesystem.property.value = "No Allow";
+ break;
+ case "restricted":
+ filesystem.property.value = "Restricted";
+ break;
+ case "passthrough":
+ filesystem.property.value = "Passthrough";
+ break;
+ case "passthrough-x":
+ filesystem.property.value = "Passthrough-X";
+ break;
+ default:
+ filesystem.property.value = "Restricted";
+ break;
+ }
+
+ if (/^inherited/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "inherited";
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ } else if (/^default|^local/gi.test(filesystem.properties.source)) {
+ $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
+
+ if (/^default/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "default";
+ filesystem.property.valueinherited = "Default (Restricted)";
+
+ $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
+ filesystem.property.source = "local";
+
+ $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='InheritedReset'] a").text("Default (Restricted)");
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
+ filesystem.property.source = "local";
+
+ FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "aclinherit" }, { name: modal.name, id: modal.id });
+ }
+ }
+
+ $("#btnspan-" + modal.name + "-aclinherit-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
+ $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-aclinherit-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#div-" + modal.name + "-aclinherit-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+
+ break;
+ case "acltype": //Default is off
+ filesystem.property = {
+ value: "Off",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "off":
+ filesystem.property.value = "Off";
+ break;
+ case "noacl":
+ filesystem.property.value = "No ACL";
+ break;
+ case "posixacl":
+ filesystem.property.value = "POSIX ACL";
+ break;
+ default:
+ filesystem.property.value = "Off";
+ break;
+ }
+
+ if (/^inherited/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "inherited";
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ } else if (/^default|^local/gi.test(filesystem.properties.source)) {
+ $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
+
+ if (/^default/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "default";
+ filesystem.property.valueinherited = "Default (Off)";
+
+ $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
+ filesystem.property.source = "local";
+
+ $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='InheritedReset'] a").text("Default (Off)");
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
+ filesystem.property.source = "local";
+
+ FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "acltype" }, { name: modal.name, id: modal.id });
+ }
+ }
+
+ $("#btnspan-" + modal.name + "-acltype-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
+ $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-acltype-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#div-" + modal.name + "-acltype-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ case "atime": //Default is on
+ filesystem.property = {
+ source: "",
+ value: "On",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "off":
+ filesystem.property.value = "Off";
+ break;
+ case "on":
+ filesystem.property.value = "On";
+ break;
+ default:
+ filesystem.property.value = "On";
+ break;
+ }
+
+ if (/^inherited/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "inherited";
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ } else if (/^default|^local/gi.test(filesystem.properties.source)) {
+ $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
+
+ if (/^default/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "default";
+ filesystem.property.valueinherited = "Default (On)";
+
+ $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
+ filesystem.property.source = "local";
+
+ $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='InheritedReset'] a").text("Default (On)");
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
+ filesystem.property.source = "local";
+
+ FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "atime" }, { name: modal.name, id: modal.id });
+ }
+ }
+
+ $("#btnspan-" + modal.name + "-atime-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
+ $("#dropdown-" + modal.name + "-atime-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#div-" + modal.name + "-atime-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ case "available":
+ filesystem.available = filesystem.properties.value;
+
+ filesystem.property = {
+ value: "0 B"
+ };
+
+ if (filesystem.properties.value == "none" || filesystem.properties.value == "0" || filesystem.properties.value == "0b") {
+ filesystem.property.value = "0 B";
+ } else {
+ filesystem.property.value = FnFormatBytes({ base2: true, decimals: 2, value: filesystem.properties.value });
+ }
+
+ $("#helpblock-" + modal.name + "-available-" + modal.id).text("Available size: " + filesystem.property.value);
+ break;
+ case "canmount": //Default is on
+ filesystem.property = {
+ value: "On"
+ };
+
+ switch (filesystem.properties.value) {
+ case "on":
+ filesystem.property.value = "On";
+ break;
+ case "off":
+ filesystem.property.value = "Off";
+ break;
+ case "noauto":
+ filesystem.property.value = "No Auto";
+ break;
+ default:
+ filesystem.property.value = "On";
+ break;
+ }
+
+ $("#btnspan-" + modal.name + "-canmount-" + modal.id).text(filesystem.property.value).attr("data-field-value", filesystem.properties.value);
+ $("#dropdown-" + modal.name + "-canmount-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-canmount-" + modal.id + " li[value='" + filesystem.properties.valueraw + "']").addClass("active");
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#div-" + modal.name + "-canmount-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ case "casesensitivity": //Default is sensitive
+ $("#div-" + modal.name + "-casesensitivity-" + modal.id).text(filesystem.properties.value.charAt(0).toUpperCase() + filesystem.properties.value.slice(1));
+ break;
+ case "checksum": //Default is on
+ filesystem.property = {
+ value: "On",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "on":
+ filesystem.property.value = "On";
+ break;
+ case "off":
+ filesystem.property.value = "Off";
+ break;
+ case "edonr":
+ filesystem.property.value = "Edon-R";
+ break;
+ case "fletcher2":
+ filesystem.property.value = "Fletcher2";
+ break;
+ case "fletcher4":
+ filesystem.property.value = "Fletcher4";
+ break;
+ case "noparity":
+ filesystem.property.value = "No Parity";
+ break;
+ case "sha256":
+ filesystem.property.value = "SHA-256";
+ break;
+ case "sha512":
+ filesystem.property.value = "SHA-512";
+ break;
+ case "skein":
+ filesystem.property.value = "Skein";
+ break;
+ default:
+ filesystem.property.value = "On";
+ break;
+ }
+
+ if (/^inherited/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "inherited";
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ } else if (/^default|^local/gi.test(filesystem.properties.source)) {
+ $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
+
+ if (/^default/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "default";
+ filesystem.property.valueinherited = "Default (On)";
+
+ $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
+ filesystem.property.source = "local";
+
+ $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='InheritedReset'] a").text("Default (On)");
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
+ filesystem.property.source = "local";
+
+ FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "checksum" }, { name: modal.name, id: modal.id });
+ }
+ }
+
+ $("#btnspan-" + modal.name + "-checksum-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
+ $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-checksum-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#div-" + modal.name + "-checksum-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ case "compression": //Default is off
+ filesystem.property = {
+ value: "Off",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "on":
+ filesystem.property.value = "On";
+ break;
+ case "gzip":
+ filesystem.property.value = "GZIP";
+ break;
+ case "lz4":
+ filesystem.property.value = "LZ4";
+ break;
+ case "lzjb":
+ filesystem.property.value = "LZJB";
+ break;
+ case "zle":
+ filesystem.property.value = "ZLE";
+ break;
+ default:
+ filesystem.property.value = "Off";
+ break;
+ }
+
+ if (/^inherited/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "inherited";
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ } else if (/^default|^local/gi.test(filesystem.properties.source)) {
+ $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
+
+ if (/^default/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "default";
+ filesystem.property.valueinherited = "Default (Off)";
+
+ $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
+ filesystem.property.source = "local";
+
+ $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='InheritedReset'] a").text("Default (Off)");
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
+ filesystem.property.source = "local";
+
+ FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "compression" }, { name: modal.name, id: modal.id });
+ }
+ }
+
+ $("#btnspan-" + modal.name + "-compression-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
+ $("#dropdown-" + modal.name + "-compression-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#div-" + modal.name + "-compression-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ case "context": //Default is empty
+ if (filesystem.properties.value == "system_u:object_r:samba_share_t:s0") {
+ filesystem.context = true;
+ }
+ break;
+ case "dedup": //Default is off
+ filesystem.property = {
+ value: "Off",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "on":
+ filesystem.property.value = "On";
+ break;
+ case "off":
+ filesystem.property.value = "Off";
+ break;
+ case "edonr,verify":
+ filesystem.property.value = "Edon-R + Verify";
+ break;
+ case "sha256":
+ filesystem.property.value = "SHA-256";
+ break;
+ case "sha256,verify":
+ filesystem.property.value = "SHA-256 + Verify";
+ break;
+ case "sha512":
+ filesystem.property.value = "SHA-512";
+ break;
+ case "sha512,verify":
+ filesystem.property.value = "SHA-512 + Verify";
+ break;
+ case "skein":
+ filesystem.property.value = "Skein";
+ break;
+ case "skein,verify":
+ filesystem.property.value = "Skein + Verify";
+ break;
+ case "verify":
+ filesystem.property.value = "Verify";
+ break;
+ default:
+ filesystem.property.value = "Off";
+ break;
+ }
+
+ if (/^inherited/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "inherited";
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ } else if (/^default|^local/gi.test(filesystem.properties.source)) {
+ $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
+
+ if (/^default/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "default";
+ filesystem.property.valueinherited = "Default (Off)";
+
+ $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
+ filesystem.property.source = "local";
+
+ $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='InheritedReset'] a").text("Default (Off)");
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
+ filesystem.property.source = "local";
+
+ FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "dedup" }, { name: modal.name, id: modal.id });
+ }
+ }
+
+ $("#btnspan-" + modal.name + "-dedup-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
+ $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#div-" + modal.name + "-dedup-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ case "dnodesize": //Default is legacy
+ filesystem.property = {
+ value: "Off",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "1k":
+ filesystem.property.value = "1 KiB";
+ break;
+ case "2k":
+ filesystem.property.value = "2 KiB";
+ break;
+ case "4k":
+ filesystem.property.value = "4 KiB";
+ break;
+ case "8k":
+ filesystem.property.value = "8 KiB";
+ break;
+ case "16k":
+ filesystem.property.value = "16 KiB";
+ break;
+ case "auto":
+ filesystem.property.value = "Auto";
+ break;
+ case "legacy":
+ filesystem.property.value = "Legacy";
+ break;
+ default:
+ filesystem.property.value = "Legacy";
+ break;
+ }
+
+ if (/^inherited/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "inherited";
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ } else if (/^default|^local/gi.test(filesystem.properties.source)) {
+ $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
+
+ if (/^default/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "default";
+ filesystem.property.valueinherited = "Default (Legacy)";
+
+ $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
+ filesystem.property.source = "local";
+
+ $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='InheritedReset'] a").text("Default (Legacy)");
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
+ filesystem.property.source = "local";
+
+ FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "dnodesize" }, { name: modal.name, id: modal.id });
+ }
+ }
+
+ $("#btnspan-" + modal.name + "-dnodesize-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
+ $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#div-" + modal.name + "-dnodesize-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ case "defcontext": //Default is empty
+ if (filesystem.properties.value == "system_u:object_r:samba_share_t:s0") {
+ filesystem.defcontext = true;
+ }
+ break;
+ case "encryption": //Default is off
+ filesystem.property = {
+ value: "Off"
+ };
+
+ switch (filesystem.properties.value) {
+ case "on":
+ filesystem.property.value = "On";
+ break;
+ case "off":
+ filesystem.property.value = "Off";
+ break;
+ case "aes-128-ccm":
+ filesystem.property.value = "AES-128-CCM";
+ break;
+ case "aes-192-ccm":
+ filesystem.property.value = "AES-192-CCM";
+ break;
+ case "aes-256-ccm":
+ filesystem.property.value = "AES-256-CCM";
+ break;
+ case "aes-128-gcm":
+ filesystem.property.value = "AES-128-GCM";
+ break;
+ case "aes-192-gcm":
+ filesystem.property.value = "AES-192-GCM";
+ break;
+ case "aes-256-gcm":
+ filesystem.property.value = "AES-256-GCM";
+ break;
+ default:
+ filesystem.property.value = "Off";
+ break;
+ }
+
+ $("#div-" + modal.name + "-encryption-" + modal.id).text(filesystem.property.value);
+
+ if (filesystem.property.value != "Off") {
+ $("#controllabel-" + modal.name + "-encryption-" + modal.id).removeClass("hidden");
+ $("#div-" + modal.name + "-encryption-" + modal.id).removeClass("hidden");
+ }
+ break;
+ case "encryptionroot":
+ if (filesystem.properties.valueraw && filesystem.properties.valueraw == "-") {
+ filesystem.properties.valueraw = "";
+ }
+
+ if (filesystem.properties.valueraw && filesystem.properties.valueraw != filesystem.name) {
+ $("#controllabel-" + modal.name + "-encryptionroot-" + modal.id).removeClass("hidden");
+ $("#div-" + modal.name + "-encryptionroot-" + modal.id).text(filesystem.properties.valueraw).removeClass("hidden");
+ }
+ break;
+ case "fscontext": //Default is empty
+ if (filesystem.properties.value == "system_u:object_r:samba_share_t:s0") {
+ filesystem.fscontext = true;
+ }
+ break;
+ case "guid":
+ $("#div-" + modal.name + "-guid-" + modal.id).text(filesystem.properties.value);
+ break;
+ case "mountpoint":
+ $("#input-" + modal.name + "-mountpoint-" + modal.id).val(filesystem.properties.valueraw).attr("data-field-value", filesystem.properties.valueraw);
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#input-" + modal.name + "-mountpoint-" + modal.id).prop("disabled", true);
+ }
+ break;
+ case "quota": //Default is none
+ filesystem.property = {
+ value: "0 B",
+ valueraw: "0",
+ valueunit: "KiB"
+ };
+
+ if (filesystem.properties.value == "none" || filesystem.properties.value == "0" || filesystem.properties.value == "0b") {
+ filesystem.property.value = "0 B";
+ } else {
+ filesystem.property.value = FnFormatBytes({ base2: true, decimals: 1, value: filesystem.properties.value });
+
+ if (/KiB/g.test(filesystem.property.value)) {
+ filesystem.property.valueunit = "KiB";
+ } else if (/MiB/g.test(filesystem.property.value)) {
+ filesystem.property.valueunit = "MiB";
+ } else if (/GiB/g.test(filesystem.property.value)) {
+ filesystem.property.valueunit = "GiB";
+ } else if (/TiB/g.test(filesystem.property.value)) {
+ filesystem.property.valueunit = "TiB";
+ }
+
+ filesystem.property.valueraw = filesystem.property.value.toString().replace(" " + filesystem.property.valueunit, "");
+ }
+
+ $("#input-" + modal.name + "-quota-" + modal.id).val(filesystem.property.valueraw);
+
+ size.quota = {
+ quota: parseInt(filesystem.properties.value),
+ max: {
+ raw: 1099511627776000,
+ unit: "",
+ unitnumber: 0
+ },
+ slider: {
+ valuemax: 1000
+ },
+ property: filesystem.property
+ };
+
+ FnStoragePoolSizeGet({ name: pool.name, id: null })
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Storage Pools, Size, Get:" }));
+
+ if (_data && zfsmanager.configuration.zfs.filesystem.quotarestrict) {
+ size.quota.max.raw = parseInt(_data.replace(/\n+/g, ""));
+ }
+ })
+ .finally(function () {
+ size.quota.max.raw = (size.quota.max.raw > size.quota.quota ? size.quota.max.raw : size.quota.quota);
+ size.quota.max.unitnumber = FnFormatBytes({ base2: true, decimals: 2, value: size.quota.max.raw }).replace(/ .*$/g, "");
+ size.quota.max.unit = FnFormatBytes({ base2: true, decimals: 2, value: size.quota.max.raw }).replace(/ /g, "").replace(/^[0-9.]/, "");
+
+ if (size.quota.max.raw <= 1024000) {
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.max.unitnumber);
+ }
+ if (size.quota.max.raw > 1024000) {
+ $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='MiB']").removeClass("hidden");
+
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.max.unitnumber);
+ }
+ if (size.quota.max.raw > 1048576000) {
+ $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='GiB']").removeClass("hidden");
+
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib", size.quota.max.unitnumber);
+ }
+ if (size.quota.max.raw > 1073741824000) {
+ $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='TiB']").removeClass("hidden");
+
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-tib", size.quota.max.unitnumber);
+ }
+
+ if (size.quota.property.valueunit == "KiB") {
+ size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib");
+ }
+ if (size.quota.property.valueunit == "MiB") {
+ size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib");
+ }
+ if (size.quota.property.valueunit == "GiB") {
+ size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib");
+ }
+ if (size.quota.property.valueunit == "TiB") {
+ size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-tib");
+ }
+
+ $("#slider-" + modal.name + "-quota-" + modal.id).data("slider").options.max = size.quota.slider.valuemax;
+ $("#slider-" + modal.name + "-quota-" + modal.id).data("slider").options.step = (size.quota.slider.valuemax < 10 ? "0.1" : "1");
+ $("#slider-" + modal.name + "-quota-" + modal.id).slider("setValue", size.quota.property.valueraw);
+
+ $("#btnspan-" + modal.name + "-quota-" + modal.id).text(size.quota.property.valueunit).attr("data-field-value", size.quota.property.valueunit);
+ $("#dropdown-" + modal.name + "-quota-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='" + size.quota.property.valueunit + "']").addClass("active");
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-field-value", size.quota.property.value.toString().replace(/ /g, "").replace(/iB$/g, ""));
+ });
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#input-" + modal.name + "-quota-" + modal.id).prop("disabled", true);
+ $("#div-" + modal.name + "-quota-dropdown-" + modal.id + " button").prop("disabled", true);
+ $("#validationwrapper-" + modal.name + "-quota-" + modal.id + " .slider-pf .slider *").addClass("disabled");
+ $("#slider-" + modal.name + "-quota-" + modal.id).slider("disable");
+ }
+ break;
+ case "readonly": //Default is off
+ if (filesystem.properties.value == "on") {
+ filesystem.readonly = true;
+ }
+
+ if (filesystem.properties.value == "on" && !$("#switch-" + modal.name + "-readonly-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-readonly-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-readonly-" + modal.id).attr("data-field-value", filesystem.properties.value);
+
+ if (pool.readonly) {
+ $("#switch-" + modal.name + "-readonly-" + modal.id + " input").prop("disabled", true);
+ }
+ break;
+ case "recordsize": //Default is 128K
+ filesystem.property = {
+ value: FnFormatBytes({ base2: true, decimals: 0, value: filesystem.properties.value }),
+ valueinherited: ""
+ };
+
+ if (/^inherited/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "inherited";
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ } else if (/^default|^local/gi.test(filesystem.properties.source)) {
+ $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
+
+ if (/^default/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "default";
+ filesystem.property.valueinherited = "Default (128 KiB)";
+
+ $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
+ filesystem.property.source = "local";
+
+ $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='InheritedReset'] a").text("Default (128 KiB)");
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
+ filesystem.property.source = "local";
+
+ FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "recordsize" }, { name: modal.name, id: modal.id });
+ }
+ }
+
+ $("#btnspan-" + modal.name + "-recordsize-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
+ $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#div-" + modal.name + "-recordsize-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ case "refreservation": //Default is none / 0
+ filesystem.property = {
+ value: "0 B",
+ valueraw: "0",
+ valueunit: "KiB"
+ };
+
+ if (filesystem.properties.value == "none" || filesystem.properties.value == "0" || filesystem.properties.value == "0b") {
+ filesystem.property.value = "0 B";
+ } else {
+ filesystem.property.value = FnFormatBytes({ base2: true, decimals: 1, value: filesystem.properties.value });
+
+ if (/KiB/g.test(filesystem.property.value)) {
+ filesystem.property.valueunit = "KiB";
+ } else if (/MiB/g.test(filesystem.property.value)) {
+ filesystem.property.valueunit = "MiB";
+ } else if (/GiB/g.test(filesystem.property.value)) {
+ filesystem.property.valueunit = "GiB";
+ } else if (/TiB/g.test(filesystem.property.value)) {
+ filesystem.property.valueunit = "TiB";
+ }
+
+ filesystem.property.valueraw = filesystem.property.value.toString().replace(" " + filesystem.property.valueunit, "");
+ }
+
+ $("#input-" + modal.name + "-refreservation-" + modal.id).val(filesystem.property.valueraw);
+
+ size.refreservation = {
+ available: parseInt(filesystem.available),
+ refreservation: parseInt(filesystem.properties.value),
+ max: {
+ raw: 0,
+ unit: "",
+ unitnumber: 0
+ },
+ slider: {
+ valuemax: 1000
+ }
+ };
+
+ size.refreservation.max.raw = (size.refreservation.available > size.refreservation.refreservation ? size.refreservation.available : size.refreservation.refreservation);
+ size.refreservation.max.unitnumber = FnFormatBytes({ base2: true, decimals: 2, value: size.refreservation.max.raw }).replace(/ .*$/g, "");
+ size.refreservation.max.unit = FnFormatBytes({ base2: true, decimals: 2, value: size.refreservation.max.raw }).replace(/ /g, "").replace(/^[0-9.]/, "");
+
+ if (size.refreservation.max.raw <= 1024000) {
+ $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-kib", size.refreservation.max.unitnumber);
+ }
+ if (size.refreservation.max.raw > 1024000) {
+ $("#dropdown-" + modal.name + "-refreservation-" + modal.id + " li[value='MiB']").removeClass("hidden");
+
+ $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-kib", size.refreservation.slider.valuemax);
+ $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-mib", size.refreservation.max.unitnumber);
+ }
+ if (size.refreservation.max.raw > 1048576000) {
+ $("#dropdown-" + modal.name + "-refreservation-" + modal.id + " li[value='GiB']").removeClass("hidden");
+
+ $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-kib", size.refreservation.slider.valuemax);
+ $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-mib", size.refreservation.slider.valuemax);
+ $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-gib", size.refreservation.max.unitnumber);
+ }
+ if (size.refreservation.max.raw > 1073741824000) {
+ $("#dropdown-" + modal.name + "-refreservation-" + modal.id + " li[value='TiB']").removeClass("hidden");
+
+ $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-kib", size.refreservation.slider.valuemax);
+ $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-mib", size.refreservation.slider.valuemax);
+ $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-gib", size.refreservation.slider.valuemax);
+ $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-tib", size.refreservation.max.unitnumber);
+ }
+
+ if (filesystem.property.valueunit == "KiB") {
+ size.refreservation.slider.valuemax = $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-kib");
+ }
+ if (filesystem.property.valueunit == "MiB") {
+ size.refreservation.slider.valuemax = $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-mib");
+ }
+ if (filesystem.property.valueunit == "GiB") {
+ size.refreservation.slider.valuemax = $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-gib");
+ }
+ if (filesystem.property.valueunit == "TiB") {
+ size.refreservation.slider.valuemax = $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-filesystem-refreservation-max-tib");
+ }
+
+ $("#slider-" + modal.name + "-refreservation-" + modal.id).data("slider").options.max = size.refreservation.slider.valuemax;
+ $("#slider-" + modal.name + "-refreservation-" + modal.id).data("slider").options.step = (size.refreservation.slider.valuemax < 10 ? "0.1" : "1");
+ $("#slider-" + modal.name + "-refreservation-" + modal.id).slider("setValue", filesystem.property.valueraw);
+
+ $("#btnspan-" + modal.name + "-refreservation-" + modal.id).text(filesystem.property.valueunit).attr("data-field-value", filesystem.property.valueunit);
+ $("#dropdown-" + modal.name + "-refreservation-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-refreservation-" + modal.id + " li[value='" + filesystem.property.valueunit + "']").addClass("active");
+ $("#input-" + modal.name + "-refreservation-" + modal.id).attr("data-field-value", filesystem.property.value.toString().replace(/ /g, "").replace(/iB$/g, ""));
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#input-" + modal.name + "-refreservation-" + modal.id).prop("disabled", true);
+ $("#div-" + modal.name + "-refreservation-dropdown-" + modal.id + " button").prop("disabled", true);
+ $("#validationwrapper-" + modal.name + "-refreservation-" + modal.id + " .slider-pf .slider *").addClass("disabled");
+ $("#slider-" + modal.name + "-refreservation-" + modal.id).slider("disable");
+ }
+ break;
+ case "rootcontext": //Default is empty
+ if (filesystem.properties.value == "system_u:object_r:samba_share_t:s0") {
+ filesystem.rootcontext = true;
+ }
+ break;
+ case "sharenfs": //Default is off
+ if (filesystem.properties.value != "off") {
+ if (!$("#switch-" + modal.name + "-sharenfs-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-sharenfs-" + modal.id + " input").click();
+ }
+
+ $("#controllabel-" + modal.name + "-sharenfs-options-" + modal.id).removeClass("hidden");
+ $("#validationwrapper-" + modal.name + "-sharenfs-options-" + modal.id).removeClass("hidden");
+ $("#input-" + modal.name + "-sharenfs-options-" + modal.id).val((filesystem.properties.value == "on" ? "sec=sys,rw,crossmnt,no_subtree_check,no_root_squash" : filesystem.properties.value));
+
+ FnSystemNfsVersionGet({ alert: { id: $("#alert-" + modal.name + "-sharenfs-options-" + modal.id) } });
+ }
+
+ $("#input-" + modal.name + "-sharenfs-options-" + modal.id).attr("data-field-value", filesystem.properties.value);
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#switch-" + modal.name + "-sharenfs-" + modal.id + " input").prop("disabled", true);
+ $("#input-" + modal.name + "-sharenfs-options-" + modal.id).prop("disabled", true);
+ }
+ break;
+ case "sharesmb":
+ if (filesystem.properties.value == "on" && !$("#switch-" + modal.name + "-sharesmb-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-sharesmb-" + modal.id + " input").click();
+ }
+
+ if (pool.readonly || zfsmanager.configuration.samba.manage) {
+ $("#switch-" + modal.name + "-sharesmb-" + modal.id + " input").prop("disabled", true);
+ }
+
+ $("#switch-" + modal.name + "-sharesmb-" + modal.id).attr("data-field-value", filesystem.properties.value);
+ break;
+ case "special_small_blocks": //Default is 0
+ filesystem.property = {
+ value: FnFormatBytes({ base2: true, decimals: 0, value: filesystem.properties.value }),
+ valueinherited: ""
+ };
+
+ if (/^inherited/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "inherited";
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ } else if (/^default|^local/gi.test(filesystem.properties.source)) {
+ $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
+
+ if (/^default/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "default";
+ filesystem.property.valueinherited = "Default (0 B)";
+
+ $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
+ filesystem.property.source = "local";
+
+ $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='InheritedReset'] a").text("Default (0 B)");
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
+ filesystem.property.source = "local";
+
+ FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "special_small_blocks" }, { name: modal.name, id: modal.id });
+ }
+ }
+
+ $("#btnspan-" + modal.name + "-special_small_blocks-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
+ $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#div-" + modal.name + "-special_small_blocks-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ case "used":
+ filesystem.used = filesystem.properties.value;
+
+ filesystem.property = {
+ value: "0 B"
+ };
+
+ if (filesystem.properties.value == "none" || filesystem.properties.value == "0" || filesystem.properties.value == "0b") {
+ filesystem.property.value = "0 B";
+ } else {
+ filesystem.property.value = FnFormatBytes({ base2: true, decimals: 2, value: filesystem.properties.value });
+ }
+
+ $("#helpblock-" + modal.name + "-used-" + modal.id).text("Used size: " + filesystem.property.value);
+ break;
+ case "xattr": //Default is on
+ filesystem.property = {
+ value: "On",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "off":
+ filesystem.property.value = "Off";
+ break;
+ case "sa":
+ filesystem.property.value = "System Attribute";
+ break;
+ default:
+ filesystem.property.value = "On";
+ break;
+ }
+
+ if (/^inherited/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "inherited";
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ } else if (/^default|^local/gi.test(filesystem.properties.source)) {
+ $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='InheritedReset']").removeClass("hidden");
+
+ if (/^default/gi.test(filesystem.properties.source)) {
+ filesystem.property.source = "default";
+ filesystem.property.valueinherited = "Default (On)";
+
+ $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='InheritedReset'] a").text(filesystem.property.valueinherited);
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name == pool.name) {
+ filesystem.property.source = "local";
+
+ $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='InheritedReset'] a").text("Default (On)");
+ } else if (/^local/gi.test(filesystem.properties.source) && filesystem.name != pool.name) {
+ filesystem.property.source = "local";
+
+ FnFileSystemConfigurationInheritedPropertyGet({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, property: "xattr" }, { name: modal.name, id: modal.id });
+ }
+ }
+
+ $("#btnspan-" + modal.name + "-xattr-" + modal.id).text((filesystem.property.valueinherited ? filesystem.property.valueinherited : filesystem.property.value)).attr("data-field-value", filesystem.properties.valueraw).attr("data-field-source", filesystem.property.source);
+ $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='" + (filesystem.property.valueinherited ? (filesystem.property.source == "inherited" ? "Inherited" : "InheritedReset") : filesystem.properties.valueraw) + "']").addClass("active");
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#div-" + modal.name + "-xattr-dropdown-" + modal.id + " button").prop("disabled", true);
+ }
+ break;
+ }
+ });
+
+ if (filesystem.context && filesystem.fscontext && filesystem.defcontext && filesystem.rootcontext) {
+ if (!$("#switch-" + modal.name + "-selinux-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-selinux-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-selinux-" + modal.id).attr("data-field-value", "true");
+ } else {
+ $("#switch-" + modal.name + "-selinux-" + modal.id).attr("data-field-value", "false");
+ }
+
+ if (filesystem.readonly && zfsmanager.configuration.zfs.filesystem.readonlylockdown || pool.readonly) {
+ $("#switch-" + modal.name + "-selinux-" + modal.id + " input").prop("disabled", true);
+ }
+ if (pool.readonly) {
+ $("#btn-" + modal.name + "-apply-" + modal.id).prop("disabled", true);
+ }
+
+ FnConsole.log[1]("File Systems, Configuration, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, Configuration, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + " , Message: " + (data ? data : message));
+ });
+}
+
+function FnFileSystemConfigurationInheritedGet(pool = { name, id }, filesystem = { name }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "get", "atime,casesensitivity,compression,dedup,dnodesize,encryption,recordsize,special_small_blocks,xattr", "-H", "-o", "property,value,source", "-p", filesystem.name]
+ };
+
+ FnConsole.log[2]("File Systems, Configuration, Inherited, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Configuration, Inherited, Get:" }));
+
+ process.data = data.replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v);
+
+ process.data.forEach((_value, _index) => {
+ _value = _value.split("\u22C5");
+
+ filesystem.properties = {
+ property: _value[0].toLowerCase(),
+ value: _value[1].toLowerCase(),
+ valueraw: _value[1],
+ source: _value[2]
+ };
+
+ switch (filesystem.properties.property) {
+ case "atime": //Default is on
+ filesystem.property = {
+ value: "On",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "on":
+ filesystem.property.value = "On";
+ break;
+ case "gzip":
+ filesystem.property.value = "GZIP";
+ break;
+ case "lz4":
+ filesystem.property.value = "LZ4";
+ break;
+ case "lzjb":
+ filesystem.property.value = "LZJB";
+ break;
+ case "zle":
+ filesystem.property.value = "ZLE";
+ break;
+ default:
+ filesystem.property.value = "Off";
+ break;
+ }
+
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#btnspan-" + modal.name + "-atime-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
+ $("#dropdown-" + modal.name + "-atime-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ $("#dropdown-" + modal.name + "-atime-" + modal.id + " li[value='Inherited']").addClass("active");
+ break; case "casesensitivity": //Default is sensitive
+ filesystem.property = {
+ value: "Sensitive",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "insensitive":
+ filesystem.property.value = "Insensitive";
+ break;
+ case "mixed":
+ filesystem.property.value = "Mixed";
+ break;
+ case "sensitive":
+ filesystem.property.value = "Sensitive";
+ break;
+ default:
+ filesystem.property.value = "Sensitive";
+ break;
+ }
+
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#btnspan-" + modal.name + "-casesensitivity-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
+ $("#dropdown-" + modal.name + "-casesensitivity-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-casesensitivity-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-casesensitivity-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ $("#dropdown-" + modal.name + "-casesensitivity-" + modal.id + " li[value='Inherited']").addClass("active");
+ break;
+ case "compression": //Default is off
+ filesystem.property = {
+ value: "Off",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "on":
+ filesystem.property.value = "On";
+ break;
+ case "gzip":
+ filesystem.property.value = "GZIP";
+ break;
+ case "lz4":
+ filesystem.property.value = "LZ4";
+ break;
+ case "lzjb":
+ filesystem.property.value = "LZJB";
+ break;
+ case "zle":
+ filesystem.property.value = "ZLE";
+ break;
+ default:
+ filesystem.property.value = "Off";
+ break;
+ }
+
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#btnspan-" + modal.name + "-compression-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
+ $("#dropdown-" + modal.name + "-compression-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ $("#dropdown-" + modal.name + "-compression-" + modal.id + " li[value='Inherited']").addClass("active");
+ break;
+ case "dedup": //Default is off
+ filesystem.property = {
+ value: "Off",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "on":
+ filesystem.property.value = "On";
+ break;
+ case "off":
+ filesystem.property.value = "Off";
+ break;
+ case "verify":
+ filesystem.property.value = "Verify";
+ break;
+ case "sha256":
+ filesystem.property.value = "SHA-256";
+ break;
+ case "sha256,verify":
+ filesystem.property.value = "SHA-256 + Verify";
+ break;
+ case "sha512":
+ filesystem.property.value = "SHA-512";
+ break;
+ case "sha512,verify":
+ filesystem.property.value = "SHA-512 + Verify";
+ break;
+ case "skein":
+ filesystem.property.value = "Skein";
+ break;
+ case "skein,verify":
+ filesystem.property.value = "Skein + Verify";
+ break;
+ case "edonr,verify":
+ filesystem.property.value = "Edon-R + Verify";
+ break;
+ default:
+ filesystem.property.value = "Off";
+ break;
+ }
+
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#btnspan-" + modal.name + "-dedup-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
+ $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ $("#dropdown-" + modal.name + "-dedup-" + modal.id + " li[value='Inherited']").addClass("active");
+ break;
+ case "dnodesize": //Default is legacy
+ filesystem.property = {
+ value: "Off",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "1k":
+ filesystem.property.value = "1 KiB";
+ break;
+ case "2k":
+ filesystem.property.value = "2 KiB";
+ break;
+ case "4k":
+ filesystem.property.value = "4 KiB";
+ break;
+ case "8k":
+ filesystem.property.value = "8 KiB";
+ break;
+ case "16k":
+ filesystem.property.value = "16 KiB";
+ break;
+ case "auto":
+ filesystem.property.value = "Auto";
+ break;
+ case "legacy":
+ filesystem.property.value = "Legacy";
+ break;
+ default:
+ filesystem.property.value = "Legacy";
+ break;
+ }
+
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#btnspan-" + modal.name + "-dnodesize-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
+ $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ $("#dropdown-" + modal.name + "-dnodesize-" + modal.id + " li[value='Inherited']").addClass("active");
+ break;
+ case "encryption": //Default is off
+ filesystem.property = {
+ value: "Off",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "on":
+ filesystem.property.value = "On";
+ break;
+ case "off":
+ filesystem.property.value = "Off";
+ break;
+ case "aes-128-ccm":
+ filesystem.property.value = "AES-128-CCM";
+ break;
+ case "aes-192-ccm":
+ filesystem.property.value = "AES-192-CCM";
+ break;
+ case "aes-256-ccm":
+ filesystem.property.value = "AES-256-CCM";
+ break;
+ case "aes-128-gcm":
+ filesystem.property.value = "AES-128-GCM";
+ break;
+ case "aes-192-gcm":
+ filesystem.property.value = "AES-192-GCM";
+ break;
+ case "aes-256-gcm":
+ filesystem.property.value = "AES-256-GCM";
+ break;
+ }
+
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ if (filesystem.properties.value != "off") {
+ if (!$("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-encryption-" + modal.id + " input").click();
+ }
+
+ $("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("disabled", true);
+ $("#btnspan-" + modal.name + "-encryption-cipher-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
+ $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='Inherited']").addClass("active");
+ $("#helpblock-" + modal.name + "-encryption-passphrase-" + modal.id).removeClass("has-error").removeClass("hidden").text("Passphrase is not required.");
+ } else if (filesystem.properties.value == "off") {
+ $("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("disabled", false);
+
+ if ($("#switch-" + modal.name + "-encryption-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-encryption-" + modal.id + " input").click();
+ }
+
+ $("#btnspan-" + modal.name + "-encryption-cipher-" + modal.id).text("AES-256-GCM").attr("data-field-value", "aes-256-gcm");
+ $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='aes-256-gcm']").addClass("active");
+ $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='Inherited']").addClass("hidden");
+ $("#dropdown-" + modal.name + "-encryption-cipher-" + modal.id + " li[value='Inherited'] a").text("Inherited");
+
+ if ($("#input-" + modal.name + "-encryption-passphrase-" + modal.id).val().length == 0) {
+ $("#validationwrapper-" + modal.name + "-encryption-passphrase-" + modal.id).removeClass("has-error");
+ $("#helpblock-" + modal.name + "-encryption-passphrase-" + modal.id).removeClass("has-error").addClass("hidden").text("");
+ $("#validationwrapper-" + modal.name + "-encryption-passphrase-confirm-" + modal.id).removeClass("has-error");
+ $("#helpblock-" + modal.name + "-encryption-passphrase-" + modal.id).removeClass("has-error").addClass("hidden").text("");
+ }
+ }
+ break;
+ case "recordsize": //Default is 128K
+ filesystem.property = {
+ value: FnFormatBytes({ base2: true, decimals: 0, value: filesystem.properties.value }),
+ valueinherited: ""
+ };
+
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#btnspan-" + modal.name + "-recordsize-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
+ $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ $("#dropdown-" + modal.name + "-recordsize-" + modal.id + " li[value='Inherited']").addClass("active");
+ break;
+ case "special_small_blocks": //Default is 0
+ filesystem.property = {
+ value: FnFormatBytes({ base2: true, decimals: 0, value: filesystem.properties.value }),
+ valueinherited: ""
+ };
+
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#btnspan-" + modal.name + "-special_small_blocks-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
+ $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ $("#dropdown-" + modal.name + "-special_small_blocks-" + modal.id + " li[value='Inherited']").addClass("active");
+ break;
+ case "xattr": //Default is on
+ filesystem.property = {
+ value: "On",
+ valueinherited: ""
+ };
+
+ switch (filesystem.properties.value) {
+ case "on":
+ filesystem.property.value = "On";
+ break;
+ case "off":
+ filesystem.property.value = "Off";
+ break;
+ case "sa":
+ filesystem.property.value = "System Attribute";
+ break;
+ default:
+ filesystem.property.value = "On";
+ break;
+ }
+
+ filesystem.property.valueinherited = "Inherited (" + filesystem.property.value + ")";
+
+ $("#btnspan-" + modal.name + "-xattr-" + modal.id).text(filesystem.property.valueinherited).attr("data-field-value", "Inherited");
+ $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='Inherited']").removeClass("hidden");
+ $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='Inherited'] a").text(filesystem.property.valueinherited);
+ $("#dropdown-" + modal.name + "-xattr-" + modal.id + " li[value='Inherited']").addClass("active");
+ break;
+ }
+ });
+
+ //Quota
+ let size = {
+ quota: {
+ max: {
+ raw: 1099511627776000,
+ unit: "",
+ unitnumber: 0
+ },
+ slider: {
+ valuemax: 1000
+ },
+ property: {
+ value: "0 B",
+ valueraw: "0",
+ valueunit: "KiB"
+ }
+ }
+ };
+
+ FnStoragePoolSizeGet({ name: pool.name, id: null })
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Storage Pools, Size, Get:" }));
+
+ if (_data && zfsmanager.configuration.zfs.filesystem.quotarestrict) {
+ size.quota.max.raw = parseInt(_data.replace(/\n+/g, ""));
+ }
+ })
+ .finally(function () {
+ size.quota.max.unitnumber = FnFormatBytes({ base2: true, decimals: 2, value: size.quota.max.raw }).replace(/ .*$/g, "");
+ size.quota.max.unit = FnFormatBytes({ base2: true, decimals: 2, value: size.quota.max.raw }).replace(/ /g, "").replace(/^[0-9.]/, "");
+
+ if (size.quota.max.raw <= 1024000) {
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.max.unitnumber);
+ }
+ if (size.quota.max.raw > 1024000) {
+ $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='MiB']").removeClass("hidden");
+
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.max.unitnumber);
+ }
+ if (size.quota.max.raw > 1048576000) {
+ $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='GiB']").removeClass("hidden");
+
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib", size.quota.max.unitnumber);
+ }
+ if (size.quota.max.raw > 1073741824000) {
+ $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='TiB']").removeClass("hidden");
+
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib", size.quota.slider.valuemax);
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-tib", size.quota.max.unitnumber);
+ }
+
+ if (size.quota.property.valueunit == "KiB") {
+ size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-kib");
+ }
+ if (size.quota.property.valueunit == "MiB") {
+ size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-mib");
+ }
+ if (size.quota.property.valueunit == "GiB") {
+ size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-gib");
+ }
+ if (size.quota.property.valueunit == "TiB") {
+ size.quota.slider.valuemax = $("#input-" + modal.name + "-quota-" + modal.id).attr("data-filesystem-quota-max-tib");
+ }
+
+ $("#slider-" + modal.name + "-quota-" + modal.id).data("slider").options.max = size.quota.slider.valuemax;
+ $("#slider-" + modal.name + "-quota-" + modal.id).data("slider").options.step = (size.quota.slider.valuemax < 10 ? "0.1" : "1");
+ $("#slider-" + modal.name + "-quota-" + modal.id).slider("setValue", size.quota.property.valueraw);
+
+ $("#btnspan-" + modal.name + "-quota-" + modal.id).text(size.quota.property.valueunit).attr("data-field-value", size.quota.property.valueunit);
+ $("#dropdown-" + modal.name + "-quota-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-quota-" + modal.id + " li[value='" + size.quota.property.valueunit + "']").addClass("active");
+ $("#input-" + modal.name + "-quota-" + modal.id).attr("data-field-value", size.quota.property.value.toString().replace(/ /g, "").replace(/iB$/g, ""));
+ });
+
+ FnConsole.log[1]("File Systems, Configuration, Inherited, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, Configuration, Inherited, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + " , Message: " + (data ? data : message));
+ });
+}
+
+function FnFileSystemConfigurationInheritedPropertyGet(pool = { name, id }, filesystem = { name, id, property }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "get", filesystem.property, "-H", "-o", "value", "-p", "-d", "0", filesystem.name.replace(/\/[^\/]+$/, "")]
+ };
+
+ FnConsole.log[2]("File Systems, Configuration, Property, Inherited, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Configuration, Property, Get:" }));
+
+ filesystem.properties = {
+ value: data.trim()
+ };
+
+ switch (filesystem.properties.value) {
+ case "edonr":
+ filesystem.properties.value = "Edon-R";
+ break;
+ case "edonr,verify":
+ filesystem.properties.value = "Edon-R + Verify";
+ break;
+ case "gzip":
+ filesystem.properties.value = "GZIP";
+ break;
+ case "lz4":
+ filesystem.properties.value = "LZ4";
+ break;
+ case "lzjb":
+ filesystem.properties.value = "LZJB";
+ break;
+ case "noacl":
+ filesystem.properties.value = "No ACL";
+ break;
+ case "noallow":
+ filesystem.properties.value = "No Allow";
+ break;
+ case "noparity":
+ filesystem.properties.value = "No Parity";
+ break;
+ case "passthrough-x":
+ filesystem.properties.value = "Passthrough-X";
+ break;
+ case "posixacl":
+ filesystem.properties.value = "POSIX ACL";
+ break;
+ case "sa":
+ filesystem.properties.value = "System Attribute";
+ break;
+ case "sha256":
+ filesystem.properties.value = "SHA-256";
+ break;
+ case "sha256,verify":
+ filesystem.properties.value = "SHA-256 + Verify";
+ break;
+ case "sha512":
+ filesystem.properties.value = "SHA-512";
+ break;
+ case "sha512,verify":
+ filesystem.properties.value = "SHA-512 + Verify";
+ break;
+ case "skein,verify":
+ filesystem.properties.value = "Skein + Verify";
+ break;
+ case "zle":
+ filesystem.properties.value = "ZLE";
+ break;
+ default:
+ filesystem.properties.value = ($.isNumeric(filesystem.properties.value) ? FnFormatBytes({ base2: true, decimals: 0, value: filesystem.properties.value }) : filesystem.properties.value.charAt(0).toUpperCase() + filesystem.properties.value.slice(1));
+ }
+
+ $("#dropdown-" + modal.name + "-" + filesystem.property + "-" + modal.id + " li[value='InheritedReset'] a").text("Inherited" + (filesystem.properties.value ? " (" + filesystem.properties.value + ")" : ""));
+
+ FnConsole.log[2]("File Systems, Configuration, Property, Inherited, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ $("#dropdown-" + modal.name + "-" + filesystem.property + "-" + modal.id + " li[value='InheritedReset'] a").text("Inherited");
+
+ FnConsole.warn("File Systems, Configuration, Property, Inherited, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + " , Message: " + (data ? data : message));
+ });
+}
+
+function FnFileSystemConfigure(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, aclinherit, acltype, atime, canmount, checksum, compression, context, dedup, dnodesize, defcontext, fscontext, mountpoint, quota, readonly, recordsize, refreservation, rootcontext, sharenfs, sharesmb, special_small_blocks, type, xattr }, samba = { restart: false }, modal = { id }) {
+ filesystem.properties = {
+ inherit: [],
+ new: []
+ };
+
+ if (filesystem.aclinherit) {
+ if (/^Default|^Inherited/g.test(filesystem.aclinherit)) {
+ filesystem.properties.inherit.push("aclinherit");
+ } else {
+ filesystem.properties.new.push("aclinherit=" + filesystem.aclinherit);
+ }
+ }
+ if (filesystem.acltype) {
+ if (/^Default|^Inherited/g.test(filesystem.acltype)) {
+ filesystem.properties.inherit.push("acltype");
+ } else {
+ filesystem.properties.new.push("acltype=" + filesystem.acltype);
+ }
+ }
+ if (filesystem.atime) {
+ if (/^Default|^Inherited/g.test(filesystem.atime)) {
+ filesystem.properties.inherit.push("atime");
+ } else {
+ filesystem.properties.new.push("atime=" + filesystem.atime);
+ }
+ }
+ if (filesystem.canmount) {
+ filesystem.properties.new.push("canmount=" + filesystem.canmount);
+ }
+ if (filesystem.checksum) {
+ if (/^Default|^Inherited/g.test(filesystem.checksum)) {
+ filesystem.properties.inherit.push("checksum");
+ } else {
+ filesystem.properties.new.push("checksum=" + filesystem.checksum);
+ }
+ }
+ if (filesystem.compression) {
+ if (/^Default|^Inherited/g.test(filesystem.compression)) {
+ filesystem.properties.inherit.push("compression");
+ } else {
+ filesystem.properties.new.push("compression=" + filesystem.compression);
+ }
+ }
+ if (filesystem.context) {
+ filesystem.properties.new.push("context=" + filesystem.context);
+ }
+ if (filesystem.dedup) {
+ if (/^Default|^Inherited/g.test(filesystem.dedup)) {
+ filesystem.properties.inherit.push("dedup");
+ } else {
+ filesystem.properties.new.push("dedup=" + filesystem.dedup);
+ }
+ }
+ if (filesystem.dnodesize) {
+ if (/^Default|^Inherited/g.test(filesystem.dnodesize)) {
+ filesystem.properties.inherit.push("dnodesize");
+ } else {
+ filesystem.properties.new.push("dnodesize=" + filesystem.dnodesize);
+ }
+ }
+ if (filesystem.defcontext) {
+ filesystem.properties.new.push("defcontext=" + filesystem.defcontext);
+ }
+ if (filesystem.fscontext) {
+ filesystem.properties.new.push("fscontext=" + filesystem.fscontext);
+ }
+ if (filesystem.mountpoint) {
+ filesystem.properties.new.push(`mountpoint="` + filesystem.mountpoint + `"`);
+ }
+ if (filesystem.quota) {
+ filesystem.properties.new.push(`quota="` + filesystem.quota + `"`);
+ }
+ if (filesystem.readonly) {
+ filesystem.properties.new.push("readonly=" + filesystem.readonly);
+ }
+ if (filesystem.recordsize) {
+ if (/^Default|^Inherited/g.test(filesystem.recordsize)) {
+ filesystem.properties.inherit.push("recordsize");
+ } else {
+ filesystem.properties.new.push("recordsize=" + filesystem.recordsize);
+ }
+ }
+ if (filesystem.refreservation) {
+ filesystem.properties.new.push("refreservation=" + filesystem.refreservation);
+ }
+ if (filesystem.rootcontext) {
+ filesystem.properties.new.push("rootcontext=" + filesystem.rootcontext);
+ }
+ if (filesystem.sharenfs) {
+ filesystem.properties.new.push(`sharenfs="` + filesystem.sharenfs + `"`);
+ }
+ if (filesystem.sharesmb && !zfsmanager.configuration.samba.manage) {
+ filesystem.properties.new.push("sharesmb=" + filesystem.sharesmb);
+ }
+ if (filesystem.special_small_blocks) {
+ if (/^Default|^Inherited/g.test(filesystem.special_small_blocks)) {
+ filesystem.properties.inherit.push("special_small_blocks");
+ } else {
+ filesystem.properties.new.push("special_small_blocks=" + filesystem.special_small_blocks);
+ }
+ }
+ if (filesystem.xattr) {
+ if (/^Default|^Inherited/g.test(filesystem.xattr)) {
+ filesystem.properties.inherit.push("xattr");
+ } else {
+ filesystem.properties.new.push("xattr=" + filesystem.xattr);
+ }
+ }
+
+ if (filesystem.properties.inherit.length > 0 && !pool.readonly) {
+ FnFileSystemConfigureInheritance({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, properties: { inherit: filesystem.properties.inherit }, type: filesystem.type })
+ .finally(function () {
+ if (filesystem.properties.new.length > 0 && !pool.readonly) {
+ FnFileSystemConfigureCommand({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint, properties: { new: filesystem.properties.new }, type: filesystem.type }, { restart: samba.restart }, { id: modal.id });
+ } else {
+ modal.id.modal("hide");
+ }
+ });
+ } else if (filesystem.properties.new.length > 0 && !pool.readonly) {
+ FnFileSystemConfigureCommand({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint, properties: { new: filesystem.properties.new }, type: filesystem.type }, { restart: samba.restart }, { id: modal.id });
+ } else {
+ modal.id.modal("hide");
+ }
+}
+
+function FnFileSystemConfigureCommand(pool = { name, id, altroot: false }, filesystem = { name, id, mountpoint, properties: { new: [] }, type }, samba = { restart: false }, modal = { id }) {
+ let process = {
+ command: ["/bin/sh", "-c", "/sbin/zfs set " + filesystem.properties.new.join(" ") + " " + `"` + filesystem.name + `"`]
+ };
+
+ modal.hide = true;
+
+ FnConsole.log[2]("File Systems, Configure: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-storagepool-filesystem-configure-" + filesystem.id + " span").text("Configuring " + filesystem.type.toLowerCase() + "...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "File System successfully configured", description: filesystem.name, breakword: false }, { name: "filesystem-configure", id: filesystem.id, timeout: 4 });
+
+ FnConsole.log[1]("File Systems, Configure: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ if (zfsmanager.configuration.samba.manage) {
+ if (filesystem.mountpoint) {
+ modal.hide = false;
+
+ $("#spinner-storagepool-filesystem-configure-" + filesystem.id + " span").text("Updating Samba shares...");
+
+ FnSambaZfsShareConfigurationPathsSet({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name }, { restart: samba.restart }, display = { refresh: false, silent: true })
+ .finally(function () {
+ modal.id.modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+ } else if (samba.restart) {
+ FnSambaRestart();
+ }
+ } else {
+ if (samba.restart) {
+ FnSambaRestart();
+ }
+ }
+ })
+ .fail(function (message, data) {
+ filesystem.configured = false;
+
+ if (/size is greater than available space/gi.test(data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-filesystem-configure-refreservation-" + filesystem.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystem-configure-refreservation-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Refreservation can not be greater than available size.");
+ $("#input-storagepool-filesystem-configure-refreservation-" + filesystem.id).focus();
+ } else if (/size is less than current used or reserved space/gi.test(data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-filesystem-configure-quota-" + filesystem.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystem-configure-quota-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Quota can not be less than used size.");
+ $("#input-storagepool-filesystem-configure-quota-" + filesystem.id).focus();
+ } else if (/property may be set/gi.test(data)) {
+ filesystem.configured = true;
+
+ FnDisplayAlert({ status: "warning", title: "File system configured with errors", description: filesystem.name, breakword: false }, { name: "filesystem-configure", id: filesystem.id, timeout: 4 });
+
+ FnConsole.warn("File Systems, Configure: Warning, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ }
+
+ if (!filesystem.configured) {
+ if (modal.hide) {
+ FnDisplayAlert({ status: "danger", title: "File System could not be configured", description: filesystem.name, breakword: false }, { name: "filesystem-configure", id: filesystem.id, timeout: 4 });
+ }
+
+ FnConsole.warn("File Systems, Configure: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ }
+
+ if (!modal.hide) {
+ $("#spinner-storagepool-filesystem-configure-" + filesystem.id).addClass("hidden");
+ $("#spinner-storagepool-filesystem-configure-" + filesystem.id + " span").text("");
+ $("#btn-storagepool-filesystem-configure-apply-" + filesystem.id).prop("disabled", false);
+ }
+ })
+ .finally(function () {
+ if (modal.hide) {
+ modal.id.modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ });
+}
+
+function FnFileSystemConfigureInheritance(pool = { name, id }, filesystem = { name, id, properties: { inherit: [] }, type }) {
+ let process = {
+ promise: cockpit.defer()
+ };
+ let promise = Promise.resolve();
+
+ filesystem.properties.errorcount = 0;
+
+ $("#spinner-storagepool-filesystem-configure-" + filesystem.id + " span").text("Configuring " + filesystem.type.toLowerCase() + " inheritance...");
+
+ filesystem.properties.inherit.forEach((_value, _index) => {
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ process.command = ["/sbin/zfs", "inherit", _value, filesystem.name];
+
+ FnConsole.log[2]("File Systems, Configure, Inheritance: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[2]("File Systems, Configure, Inheritance: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ if (_index == (filesystem.properties.inherit.length - 1)) {
+ if (filesystem.properties.errorcount == 0) {
+ FnDisplayAlert({ status: "success", title: "File System inheritance successfully configured", description: filesystem.name, breakword: false }, { name: "filesystem-configure-inheritance", id: filesystem.id, timeout: 4 });
+ } else {
+ FnDisplayAlert({ status: "danger", title: "File System inheritance could not be configured", description: filesystem.name, breakword: false }, { name: "filesystem-configure-inheritance", id: filesystem.id, timeout: 4 });
+ }
+
+ process.promise.resolve();
+ }
+ })
+ .fail(function (message, data) {
+ filesystem.properties.errorcount++;
+
+ FnConsole.warn("File Systems, Configure, Inheritance: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+
+ if (_index == (filesystem.properties.inherit.length - 1)) {
+ FnDisplayAlert({ status: "danger", title: "File System inheritance could not be configured", description: filesystem.name, breakword: false }, { name: "filesystem-configure-inheritance", id: filesystem.id, timeout: 4 });
+
+ process.promise.resolve();
+ }
+ });
+
+ resolve();
+ }, 500)
+ ));
+ });
+
+ return process.promise.promise();
+}
+
+function FnFileSystemCreate(pool = { name, id, altroot: false }, filesystem = { name, id, atime, casesensitivity, cipher, compression, dedup, dnodesize, encryption, passphrase, quota, readonly, recordsize, selinux, sharenfs, sharesmb, special_small_blocks, xattr }) {
+ let process = {
+ command: [],
+ options: `-o normalization=formD -o sharenfs="` + filesystem.sharenfs + `" -o sharesmb=` + filesystem.sharesmb + ` -o utf8only=on`
+ };
+
+ if (filesystem.quota) {
+ process.options += " -o quota=" + filesystem.quota;
+ }
+ if (filesystem.readonly) {
+ process.options += " -o readonly=" + filesystem.readonly;
+ }
+ if (filesystem.selinux) {
+ process.options += " -o context=system_u:object_r:samba_share_t:s0 -o fscontext=system_u:object_r:samba_share_t:s0 -o defcontext=system_u:object_r:samba_share_t:s0 -o rootcontext=system_u:object_r:samba_share_t:s0";
+ }
+ if (/^Inherited/g.test(filesystem.atime) == false) {
+ process.options += " -o atime=" + filesystem.atime;
+ }
+ if (/^Inherited/g.test(filesystem.casesensitivity) == false) {
+ process.options += " -o casesensitivity=" + filesystem.casesensitivity;
+ }
+ if (/^Inherited/g.test(filesystem.dedup) == false) {
+ process.options += " -o dedup=" + filesystem.dedup;
+ }
+ if (/^Inherited/g.test(filesystem.dnodesize) == false) {
+ process.options += " -o dnodesize=" + filesystem.dnodesize;
+ }
+ if (/^Inherited/g.test(filesystem.compression) == false) {
+ process.options += " -o compression=" + filesystem.compression;
+ }
+ if (/^Inherited/g.test(filesystem.recordsize) == false) {
+ process.options += " -o recordsize=" + filesystem.recordsize;
+ }
+ if (/^Inherited/g.test(filesystem.special_small_blocks) == false) {
+ process.options += " -o special_small_blocks=" + filesystem.special_small_blocks;
+ }
+ if (/^Inherited/g.test(filesystem.xattr) == false) {
+ process.options += " -o xattr=" + filesystem.xattr;
+ }
+ if (/^Inherited/g.test(filesystem.cipher) == false && filesystem.encryption) {
+ process.options += " -o encryption=" + filesystem.cipher;
+ }
+
+ if (filesystem.encryption && filesystem.passphrase) {
+ process.options += " -o keyformat=passphrase -o keylocation=prompt";
+
+ if (filesystem.passphrase.length < 8) {
+ FnFileSystemCreateFail({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, id: filesystem.id, sharesmb: filesystem.sharesmb }, { data: "Passphrase requires a minimum of 8 characters.", message: null });
+ return;
+ }
+
+ //Escape percentage and single quote special character for printf
+ if (/\%/g.test(filesystem.passphrase)) {
+ filesystem.passphrase = filesystem.passphrase.replace(/\%/g, "\%\%");
+ }
+ if (/\'/g.test(filesystem.passphrase)) {
+ filesystem.passphrase = filesystem.passphrase.replace(/\'/g, "\'\"\'\"\'");
+ }
+
+ process.command = ["/bin/sh", "-c", "printf '" + filesystem.passphrase + "' | /sbin/zfs create " + process.options + ` "` + filesystem.name + `"`];
+ } else {
+ process.command = ["/bin/sh", "-c", "/sbin/zfs create " + process.options + ` "` + filesystem.name + `"`];
+ }
+
+ FnConsole.log[1]("File Systems, Create: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-storagepool-filesystems-create-" + pool.id + " span").text("Creating file system...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "File System successfully created", description: filesystem.name, breakword: false }, { name: "filesystem-create", id: filesystem.id, timeout: 4 });
+
+ FnConsole.log[1]("File Systems, Create: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ if (filesystem.sharesmb == "on" && zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-filesystems-create-" + pool.id + " span").text("Enabling Samba share...");
+
+ FnSambaShareEnableMountpointGet({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { name: filesystem.name, id: filesystem.id, sharesmb: true }, { silent: false });
+ }
+
+ setTimeout(function () {
+ $("#modal-storagepool-filesystems-create-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }, (filesystem.sharesmb == "on" && zfsmanager.configuration.samba.manage ? 500 : 0));
+ })
+ .fail(function (message, data) {
+ FnFileSystemCreateFail({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, id: filesystem.id, sharesmb: filesystem.sharesmb }, { data: data, message: message });
+ });
+}
+
+function FnFileSystemCreateFail(pool = { name, id, altroot: false }, filesystem = { name, id, sharesmb }, process = { data, message }) {
+ let modal = {
+ hide: true
+ };
+
+ filesystem.created = false;
+
+ if (/dataset already exists/gi.test(process.data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-filesystems-create-name-" + pool.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-name-" + pool.id).addClass("has-error").removeClass("hidden").text("Name already exists.");
+ $("#input-storagepool-filesystems-create-name-" + pool.id).focus();
+ } else if (/encryption root's key is not loaded or provided/gi.test(process.data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-" + pool.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-" + pool.id).addClass("has-error").removeClass("hidden").html("Parent file system is locked. Unlock parent file system or enter a passphrase to create an independent encryption root.");
+ $("#input-storagepool-filesystems-create-encryption-passphrase-" + pool.id).focus();
+ } else if (/Passphrase requires a minimum of 8 characters./i.test(process.data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-" + pool.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-" + pool.id).addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
+ $("#input-storagepool-filesystems-create-encryption-passphrase-" + pool.id).focus();
+ } else if (/filesystem successfully created/gi.test(process.data)) {
+ filesystem.created = true;
+
+ FnDisplayAlert({ status: "warning", title: "File system created with errors", description: filesystem.name, breakword: false }, { name: "filesystem-create", id: filesystem.id, timeout: 4 });
+
+ FnConsole.warn("File Systems, Create: Warning, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
+
+ if (filesystem.sharesmb == "on" && zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-filesystems-create-" + pool.id + " span").text("Enabling Samba share...");
+
+ FnSambaShareEnableMountpointGet({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { name: filesystem.name, id: filesystem.id, sharesmb: true }, { silent: false });
+ }
+ }
+
+ if (!modal.hide) {
+ $("#spinner-storagepool-filesystems-create-" + pool.id).addClass("hidden");
+ $("#spinner-storagepool-filesystems-create-" + pool.id + " span").text("");
+ $("#btn-storagepool-filesystems-create-apply-" + pool.id).prop("disabled", false);
+ }
+
+ if (!filesystem.created) {
+ FnConsole.warn("File Systems, Create: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
+ }
+
+ if (modal.hide) {
+ if (!filesystem.created) {
+ FnDisplayAlert({ status: "danger", title: "File System could not be created", description: filesystem.name, breakword: false }, { name: "filesystem-create", id: filesystem.id, timeout: 4 });
+ }
+
+ $("#modal-storagepool-filesystems-create-" + pool.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+}
+
+function FnFileSystemDestroy(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, force: false, recursive: false, recursiveall: false, sharesmb: false, type }, samba = { restart: false }) {
+ if (samba.restart) {
+ FnSambaStop()
+ .finally(function () {
+ if ((filesystem.recursive || filesystem.recursiveall) && zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: filesystem.name, clones: [] })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying " + filesystem.type.toLowerCase() + "s...");
+
+ if (filesystems.id.length > 0) {
+ FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: false })
+ .done(function () {
+ $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying Samba shares...");
+
+ FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: true })
+ .finally(function () {
+ $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+ });
+ } else {
+ FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: true })
+ }
+ })
+ .fail(function (message, data) {
+ FnFileSystemDestroyFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: data, message: message }, { refresh: true });
+ FnSambaStart();
+ });
+ } else {
+ $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying " + filesystem.type.toLowerCase() + "...");
+
+ if (filesystem.sharesmb && zfsmanager.configuration.samba.manage) {
+ FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: false })
+ .done(function () {
+ $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying Samba share...");
+
+ FnSambaShareDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { silent: true })
+ .finally(function () {
+ $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+ });
+ } else {
+ FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: true })
+ .finally(function () {
+ if (!filesystem.sharesmb || !zfsmanager.configuration.samba.manage) {
+ FnSambaStart();
+ }
+ });
+ }
+ }
+ });
+ } else {
+ if ((filesystem.recursive || filesystem.recursiveall) && zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: filesystem.name, clones: [] })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying " + filesystem.type.toLowerCase() + "s...");
+
+ if (filesystems.id.length > 0) {
+ FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: false })
+ .done(function () {
+ $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying Samba shares...");
+
+ FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: true })
+ .finally(function () {
+ $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+ });
+ } else {
+ FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: true })
+ }
+ })
+ .fail(function (message, data) {
+ FnFileSystemDestroyFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: data, message: message }, { refresh: true });
+ });
+ } else {
+ $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying " + filesystem.type.toLowerCase() + "...");
+
+ if (filesystem.sharesmb && zfsmanager.configuration.samba.manage) {
+ FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: false })
+ .done(function () {
+ $("#spinner-storagepool-filesystem-destroy-" + filesystem.id + " span").text("Destroying Samba share...");
+
+ FnSambaShareDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { silent: true })
+ .finally(function () {
+ $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+ });
+ } else {
+ FnFileSystemDestroyCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall }, { refresh: true })
+ }
+ }
+ }
+}
+
+function FnFileSystemDestroyCommand(pool = { name, id }, filesystem = { name, id, force: false, recursive: false, recursiveall: false }, display = { refresh: true }) {
+ let process = {
+ command: ["/sbin/zfs", "destroy", filesystem.name]
+ };
+
+ if (filesystem.force) {
+ process.command.splice(2, 0, "-f");
+ }
+ if (filesystem.recursive) {
+ process.command.splice(2, 0, "-r");
+ }
+ if (filesystem.recursiveall) {
+ process.command.splice(2, 0, "-R");
+ }
+
+ FnConsole.log[1]("File Systems, Destroy: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "File System successfully destroyed", description: filesystem.name, breakword: false }, { name: "filesystem-destroy", id: filesystem.id, timeout: 4 });
+
+ FnConsole.log[1]("File Systems, Destroy: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnFileSystemDestroyFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id }, { data: data, message: message }, { refresh: false });
+
+ display.refresh = true;
+ })
+ .finally(function () {
+ if (display.refresh) {
+ $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ });
+}
+
+function FnFileSystemDestroyFail(pool = { name, id }, filesystem = { name, id }, process = { data, message }, display = { refresh: true }) {
+ FnDisplayAlert({ status: "danger", title: "File System could not be destroyed", description: filesystem.name, breakword: false }, { name: "filesystem-destroy", id: filesystem.id, timeout: 4 });
+
+ FnConsole.warn("File Systems, Destroy: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
+
+ if (display.refresh) {
+ $("#modal-storagepool-filesystem-destroy-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+}
+
+function FnFileSystemLock(pool = { name, id }, filesystem = { name, id, type }, display = { refresh: true }) {
+ let process = {
+ command: ["/sbin/zfs", "unload-key", filesystem.name]
+ };
+
+ FnConsole.log[2]("File Systems, Lock: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-storagepool-filesystem-lock-" + filesystem.id + " span").text("Locking " + filesystem.type.toLowerCase() + "...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "File System successfully locked", description: filesystem.name, breakword: false }, { name: "filesystem-lock", id: filesystem.id, timeout: 4 });
+
+ FnConsole.log[1]("File Systems, Lock: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "File System could not be locked", description: filesystem.name, breakword: false }, { name: "filesystem-lock", id: filesystem.id, timeout: 4 });
+
+ FnConsole.warn("File Systems, Lock: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if (display.refresh) {
+ $("#modal-storagepool-filesystem-lock-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ });
+}
+
+function FnFileSystemMount(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, overlay: true, type }, samba = { enable: false }, display = { refresh: true }) {
+ let process = {
+ command: ["/sbin/zfs", "mount", filesystem.name]
+ };
+
+ if (filesystem.overlay) {
+ process.command.splice(2, 0, "-O");
+ }
+
+ FnConsole.log[2]("File Systems, Mount: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-storagepool-filesystem-mount-" + filesystem.id + " span").text("Mounting " + filesystem.type.toLowerCase() + "...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "File System successfully mounted", description: filesystem.name, breakword: false }, { name: "filesystem-mount", id: filesystem.id, timeout: 4 });
+
+ FnConsole.log[1]("File Systems, Mount: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ if (samba.enable) {
+ $("#spinner-storagepool-filesystem-mount-" + filesystem.id + " span").text("Enabling Samba share...");
+
+ if (zfsmanager.configuration.samba.manage) {
+ FnSambaShareEnableMountpointGet({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, sharesmb: false }, { silent: false });
+ } else {
+ FnFileSystemShareSmbEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ }
+ }
+ })
+ .fail(function (message, data) {
+ if (/filesystem already mounted/gi.test(data)) {
+ FnDisplayAlert({ status: "warning", title: "File System was already mounted", description: filesystem.name, breakword: false }, { name: "filesystem-mount", id: filesystem.id, timeout: 4 });
+ } else {
+ FnDisplayAlert({ status: "danger", title: "File System could not be mounted", description: filesystem.name, breakword: false }, { name: "filesystem-mount", id: filesystem.id, timeout: 4 });
+ }
+
+ FnConsole.warn("File Systems, Mount: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ setTimeout(function () {
+ $("#modal-storagepool-filesystem-mount-" + filesystem.id).modal("hide");
+
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
+ }, 200);
+ }
+ }, (samba.enable ? 500 : 0));
+ });
+}
+
+function FnFileSystemMountpointGet(pool = { name, id }, filesystem = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "get", "mountpoint", "-H", "-o", "value", filesystem.name]
+ };
+
+ FnConsole.log[2]("File Systems, Mountpoint, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function () {
+ FnConsole.log[1]("File Systems, Mountpoint, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, Mountpoint, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnFileSystemPromote(pool = { name, id }, filesystem = { name, id, type }) {
+ let process = {
+ command: ["/sbin/zfs", "promote", filesystem.name]
+ };
+
+ FnConsole.log[2]("File Systems, Promote: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-storagepool-filesystem-promote-" + filesystem.id + " span").text("Promoting " + filesystem.type.toLowerCase() + "...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "File System successfully promoted", description: filesystem.name, breakword: false }, { name: "filesystem-promote", id: filesystem.id, timeout: 4 });
+
+ FnConsole.log[1]("File Systems, Promote: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "File System could not be promoted", description: filesystem.name, breakword: false }, { name: "filesystem-promote", id: filesystem.id, timeout: 4 });
+
+ FnConsole.warn("File Systems, Promote: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#modal-storagepool-filesystem-promote-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+}
+
+function FnFileSystemRename(pool = { name, id, altroot: false }, filesystem = { name, id, createnonexistparents: false, force: false, namenew, parent, sharesmb: false, type }, samba = { restart: false }) {
+ if (samba.restart) {
+ FnSambaStop()
+ .finally(function () {
+ if (zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: filesystem.name, clones: [] })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Renaming " + filesystem.type.toLowerCase() + "...");
+
+ if (filesystems.id.length > 0) {
+ FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: false })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Rename:" }));
+
+ if (/dataset already exists/i.test(data) == false) {
+ $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Renaming Samba share" + (filesystems.id.length > 1 ? "s" : "") + "...");
+
+ FnSambaSharesRename({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, filesystems = { id: filesystems.id, parent: { name: filesystem.name, namenew: filesystem.namenew } }, { restart: samba.restart }, { silent: false })
+ .finally(function () {
+ if (filesystem.createnonexistparents) {
+ FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.parent }, { disable: true })
+ .finally(function () {
+ $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ });
+ } else {
+ $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ }
+ });
+
+ }
+ });
+ } else {
+ FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: (filesystem.createnonexistparents ? false : true) })
+ .done(function () {
+ if (filesystem.createnonexistparents) {
+ $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Disabling Samba share inheritance...");
+
+ FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.parent }, { disable: true })
+ .finally(function () {
+ $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+
+ FnSambaStart();
+ });
+ } else {
+ FnSambaStart();
+ }
+ })
+ .fail(function () {
+ FnSambaStart();
+ });
+ }
+ })
+ .fail(function (message, data) {
+ FnFileSystemRenameFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, parent: filesystem.parent }, { data: data, message: message }, { refresh: true });
+ FnSambaStart();
+ });
+ } else {
+ FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: true })
+ .finally(function () {
+ FnSambaStart();
+ });
+ }
+ });
+ } else {
+ if (zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: filesystem.name, clones: [] })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Renaming " + filesystem.type.toLowerCase() + "...");
+
+ if (filesystems.id.length > 0) {
+ FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: false })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Rename:" }));
+
+ if (/dataset already exists/i.test(data) == false) {
+ $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Renaming Samba share" + (filesystems.id.length > 1 ? "s" : "") + "...");
+
+ FnSambaSharesRename({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, filesystems = { id: filesystems.id, parent: { name: filesystem.name, namenew: filesystem.namenew } }, { restart: samba.restart }, { silent: false })
+ .finally(function () {
+ if (filesystem.createnonexistparents) {
+ FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.parent }, { disable: true })
+ .finally(function () {
+ $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ });
+ } else {
+ $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ }
+ });
+ }
+ });
+ } else {
+ FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: (filesystem.createnonexistparents ? false : true) })
+ .done(function () {
+ if (filesystem.createnonexistparents) {
+ $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("Disabling Samba share inheritance...");
+
+ FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.parent }, { disable: true })
+ .finally(function () {
+ $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ });
+ }
+ });
+ }
+ })
+ .fail(function (message, data) {
+ FnFileSystemRenameFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, parent: filesystem.parent }, { data: data, message: message }, { refresh: true });
+ });
+ } else {
+ FnFileSystemRenameCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent }, { refresh: true });
+ }
+ }
+}
+
+function FnFileSystemRenameCommand(pool = { name, id }, filesystem = { name, id, createnonexistparents: false, force: false, namenew, parent }, display = { refresh: true }) {
+ let process = {
+ command: ["/sbin/zfs", "rename", filesystem.name, filesystem.namenew]
+ };
+
+ if (filesystem.force) {
+ process.command.splice(2, 0, "-f");
+ }
+ if (filesystem.createnonexistparents) {
+ process.command.splice(2, 0, "-p");
+ }
+
+ FnConsole.log[1]("File Systems, Rename: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Rename:" }));
+
+ if (/dataset already exists/i.test(data)) {
+ FnFileSystemRenameFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, parent: filesystem.parent }, { data: data, message: message }, { refresh: true });
+ return;
+ }
+
+ FnDisplayAlert({ status: "success", title: "File System successfully renamed", description: filesystem.name, breakword: false }, { name: "filesystem-rename", id: filesystem.id, timeout: 4 });
+
+ FnConsole.log[1]("File Systems, Rename: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ if (display.refresh) {
+ $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ }
+ })
+ .fail(function (message, data) {
+ FnFileSystemRenameFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, createnonexistparents: filesystem.createnonexistparents, parent: filesystem.parent }, { data: data, message: message }, { refresh: true });
+ });
+}
+
+function FnFileSystemRenameFail(pool = { name, id }, filesystem = { name, id, createnonexistparents: false, parent }, process = { data, message }, display = { refresh: true }) {
+ let modal = {
+ hide: true
+ };
+
+ if (/dataset already exists/i.test(process.data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-filesystem-rename-name-" + filesystem.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystem-rename-name-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Name already exists.");
+ $("#input-storagepool-filesystem-rename-name-" + filesystem.id).focus();
+ } else if (/parent does not exist/i.test(process.data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-filesystem-rename-name-" + filesystem.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystem-rename-name-" + filesystem.id).addClass("has-error").removeClass("hidden").text("Parent file system does not exist.");
+ $("#input-storagepool-filesystem-rename-name-" + filesystem.id).focus();
+ }
+
+ if (!modal.hide) {
+ $("#spinner-storagepool-filesystem-rename-" + filesystem.id).addClass("hidden");
+ $("#spinner-storagepool-filesystem-rename-" + filesystem.id + " span").text("");
+ $("#btn-storagepool-filesystem-rename-apply-" + filesystem.id).prop("disabled", false);
+ }
+
+ FnConsole.warn("File Systems, Rename: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
+
+ if (modal.hide) {
+ FnDisplayAlert({ status: "danger", title: "File System could not be renamed", description: filesystem.name, breakword: false }, { name: "filesystem-rename", id: filesystem.id, timeout: 4 });
+
+ $("#modal-storagepool-filesystem-rename-" + filesystem.id).modal("hide");
+
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ }
+}
+
+function FnFileSystemSelinuxContextsSambaSet(pool = { name, id }, filesystem = { name }) {
+ let process = {
+ command: ["/sbin/zfs", "set", "context=system_u:object_r:samba_share_t:s0", "defcontext=system_u:object_r:samba_share_t:s0", "fscontext=system_u:object_r:samba_share_t:s0", "rootcontext=system_u:object_r:samba_share_t:s0", filesystem.name]
+ };
+
+ FnConsole.log[2]("File Systems, SELinux Contexts, Samba, Set: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("File Systems, SELinux Contexts, Samba, Set: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, SELinux Contexts, Samba, Set: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ })
+}
+
+function FnFileSystemShareSmbDisable(pool = { name, id }, filesystem = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "set", "sharesmb=off", filesystem.name]
+ };
+
+ FnConsole.log[2]("File Systems, Share SMB, Disable: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("File Systems, Share SMB, Disable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ if (/property may be set/gi.test(data)) { //False error is generated when configuring filesystem
+ FnConsole.log[1]("File Systems, Share SMB, Disable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ } else {
+ FnConsole.warn("File Systems, Share SMB, Disable: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ }
+ });
+}
+
+function FnFileSystemShareSmbEnable(pool = { name, id }, filesystem = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "set", "sharesmb=on", filesystem.name]
+ };
+
+ FnConsole.log[2]("File Systems, Share SMB, Enable: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("File Systems, Share SMB, Enable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ if (/property may be set/gi.test(data)) { //False error is generated when configuring filesystem
+ FnConsole.log[1]("File Systems, Share SMB, Enable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ } else {
+ FnConsole.warn("File Systems, Share SMB, Enable: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ }
+ });
+}
+
+function FnFileSystemShareSmbInheritedDisable(pool = { name, id, altroot: false }, filesystem = { name }, force = { disable: false }) {
+ let process = {
+ command: ["/sbin/zfs", "get", "-H", "name,sharesmb", "-o", "property,value,source", "-r", "-t", "filesystem"],
+ promise: cockpit.defer()
+ };
+
+ if (filesystem.name) {
+ process.command.push(filesystem.name);
+ } else if (pool.name) {
+ process.command.push(pool.name);
+ }
+
+ FnConsole.log[2]("File Systems, Share SMB, Inherited, Disable: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Share SMB, Inherited, Disable:" }));
+
+ let filesystems = data.replace(/\nsharesmb/g, "\u22C5sharesmb").replace(/\t+/g, "\u22C5").split(/\n/g).filter(v => v && /\u22C5sharesmb\u22C5on\u22C5inherited from|\u22C5sharesmb\u22C5off\u22C5inherited from/gi.test(v));
+ let promise = Promise.resolve();
+
+ if (filesystems.length > 0) {
+ filesystems.forEach((_value, _index) => {
+ _value = _value.split("\u22C5");
+
+ let filesystem = {
+ name: _value[1],
+ id: FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: _value[1], attribute: true }),
+ sharesmb: {
+ enabled: (_value[4].toLowerCase() == "on" ? true : false),
+ source: _value[5]
+ }
+ };
+ let pool = {
+ name: filesystem.name.replace(/\/.*$/, ""),
+ id: FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.name, attribute: true })
+ };
+
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ if (filesystem.sharesmb.enabled && !force.disable) {
+ FnFileSystemShareSmbEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id })
+ .finally(function () {
+ if (_index == (filesystems.length - 1)) {
+ FnConsole.log[1]("File Systems, Share SMB, Inherited, Disable: Success");
+
+ process.promise.resolve();
+ }
+ });
+ } else {
+ if (force.disable) {
+ FnSambaShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { name: filesystem.name, id: filesystem.id }, { restart: false }, { modal: false, silent: true });
+
+ if (_index == (filesystems.length - 1)) {
+ setTimeout(function () {
+ FnConsole.log[1]("File Systems, Share SMB, Inherited, Disable: Success");
+
+ process.promise.resolve();
+ }, 1000);
+ }
+ } else {
+ FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id })
+ .finally(function () {
+ if (_index == (filesystems.length - 1)) {
+ FnConsole.log[1]("File Systems, Share SMB, Inherited, Disable: Success");
+
+ process.promise.resolve();
+ }
+ });
+ }
+ }
+
+ resolve();
+ }, (force.disable ? 1000 : 500))
+ ));
+ });
+ } else {
+ FnConsole.log[1]("File Systems, Share SMB, Inherited, Disable: Success" + (pool.name ? ", Pool: " + pool.name : ""));
+
+ process.promise.resolve();
+ }
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, Share SMB, Inherited, Disable: Failed" + ", Message: " + (data ? data : message));
+
+ process.promise.resolve();
+ });
+
+ return process.promise.promise();
+}
+
+function FnFileSystemUnlock(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mount: true, overlay: true, passphrase, type }, samba = { enable: false }, modal = { name, id }, display = { refresh: true }) {
+ let process = {
+ command: []
+ };
+
+ modal.id = (modal.id ? "-" + modal.id : "");
+
+ //Escape percentage and single quote special character for printf
+ if (/\%/g.test(filesystem.passphrase)) {
+ filesystem.passphrase = filesystem.passphrase.replace(/\%/g, "\%\%");
+ }
+ if (/\'/g.test(filesystem.passphrase)) {
+ filesystem.passphrase = filesystem.passphrase.replace(/\'/g, "\'\"\'\"\'");
+ }
+
+ process.command = ["/bin/sh", "-c", "printf '" + filesystem.passphrase + "' | /sbin/zfs load-key \"" + filesystem.name + "\""];
+
+ FnConsole.log[2]("File Systems, Unlock: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ if (display.refresh) {
+ $("#spinner-" + modal.name + modal.id + " span").text("Unlocking " + filesystem.type.toLowerCase() + "...");
+ }
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Unlock:" }));
+
+ if (/error|Incorrect key/i.test(data)) {
+ FnFileSystemUnlockFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, type: filesystem.type }, { name: modal.name, id: modal.id }, { refresh: display.refresh }, { data: data, message: message });
+ return;
+ }
+
+ FnDisplayAlert({ status: "success", title: "File System successfully unlocked", description: filesystem.name, breakword: false }, { name: "filesystem-unlock", id: filesystem.id, timeout: 4 });
+
+ FnConsole.log[1]("File Systems, Unlock: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ if (filesystem.mount) {
+ setTimeout(function () {
+ FnFileSystemMount({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, overlay: filesystem.overlay, type: filesystem.type }, { enable: samba.enable }, { refresh: display.refresh })
+ .finally(function () {
+ if (display.refresh) {
+ $("#modal-" + modal.name + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ });
+ }, 200);
+ } else if (display.refresh) {
+ $("#modal-" + modal.name + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ })
+ .fail(function (message, data) {
+ if (/Key already loaded/i.test(data)) {
+ FnFileSystemUnlockWarn({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, mount: filesystem.mount, overlay: filesystem.overlay, type: filesystem.type }, { enable: samba.enable }, { name: modal.name, id: modal.id }, { refresh: display.refresh }, { data: data, message: message });
+ } else {
+ FnFileSystemUnlockFail({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, type: filesystem.type }, { name: modal.name, id: modal.id }, { refresh: display.refresh }, { data: data, message: message });
+ }
+ });
+}
+
+function FnFileSystemUnlockFail(pool = { name, id }, filesystem = { name, id, type }, modal = { name, id }, display = { refresh: true }, process = { data, message }) {
+ modal.hide = true;
+
+ if (/Incorrect key provided/gi.test(process.data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-" + modal.name + "-passphrase" + modal.id).addClass("has-error");
+ $("#helpblock-" + modal.name + "-passphrase" + modal.id).addClass("has-error").removeClass("hidden").text("Passphrase is incorrect.");
+ $("#input-" + modal.name + "-passphrase" + modal.id).focus();
+ }
+
+ if (!modal.hide && display.refresh) {
+ $("#spinner-" + modal.name + modal.id).addClass("hidden");
+ $("#spinner-" + modal.name + modal.id + " span").text("");
+ $("#btn-" + modal.name + "-apply" + modal.id).prop("disabled", false);
+ }
+
+ if (modal.hide || !display.refresh) {
+ FnDisplayAlert({ status: "danger", title: "File System could not be unlocked", description: filesystem.name, breakword: false }, { name: "filesystem-unlock", id: filesystem.id, timeout: 4 });
+ }
+
+ if (modal.hide) {
+ if (display.refresh) {
+ $("#modal-" + modal.name + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ }
+
+ FnConsole.warn("File Systems, Unlock: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
+}
+
+function FnFileSystemUnlockWarn(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mount: true, overlay: true, type }, samba = { enable: false }, modal = { name, id }, display = { refresh: true }, process = { data, message }) {
+ FnDisplayAlert({ status: "warning", title: "File System was already unlocked", description: filesystem.name, breakword: false }, { name: "filesystem-unlock", id: filesystem.id, timeout: 4 });
+
+ FnConsole.warn("File Systems, Unlock: Warning, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (process.data ? process.data : process.message));
+
+ if (filesystem.mount) {
+ setTimeout(function () {
+ FnFileSystemMount({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, overlay: filesystem.overlay, type: filesystem.type }, { enable: samba.enable }, { refresh: display.refresh })
+ .finally(function () {
+ if (display.refresh) {
+ $("#modal-" + modal.name + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ });
+ }, 200);
+ } else if (display.refresh) {
+ $("#modal-" + modal.name + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+}
+
+function FnFileSystemUnmount(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, force: false, lock: false, type }, samba = { disable: false, restart: false }) {
+ if (samba.restart) {
+ FnSambaStop()
+ .finally(function () {
+ $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Unmounting " + filesystem.type.toLowerCase() + "...");
+
+ FnFileSystemUnmountCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, lock: filesystem.lock }, { refresh: ((filesystem.lock || samba.disable) ? false : true) })
+ .done(function () {
+ if (filesystem.lock) {
+ $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Locking " + filesystem.type.toLowerCase() + "...");
+
+ FnFileSystemLock({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, type: filesystem.type }, { refresh: false })
+ .finally(function () {
+ if (samba.disable) {
+ $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Disabling Samba share...");
+
+ if (zfsmanager.configuration.samba.manage) {
+ FnSambaShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: false, silent: false });
+ } else {
+ FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ }
+ }
+
+ setTimeout(function () {
+ $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }, (samba.disable ? 1000 : 200));
+ });
+ } else {
+ if (samba.disable) {
+ $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Disabling Samba share...");
+
+ if (zfsmanager.configuration.samba.manage) {
+ FnSambaShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: false, silent: false });
+ } else {
+ FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ }
+ }
+
+ setTimeout(function () {
+ $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }, (samba.disable ? 1000 : 200));
+ }
+ })
+ .finally(function () {
+ if (!samba.disable || !zfsmanager.configuration.samba.manage) {
+ FnSambaStart();
+ }
+ });
+ });
+ } else {
+ $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Unmounting " + filesystem.type.toLowerCase() + "...");
+
+ FnFileSystemUnmountCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, lock: filesystem.lock }, { refresh: ((filesystem.lock || samba.disable) ? false : true) })
+ .done(function () {
+ if (filesystem.lock) {
+ $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Locking " + filesystem.type.toLowerCase() + "...");
+
+ FnFileSystemLock({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, type: filesystem.type }, { refresh: false })
+ .finally(function () {
+ if (samba.disable) {
+ $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Disabling Samba share...");
+
+ if (zfsmanager.configuration.samba.manage) {
+ FnSambaShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: false, silent: false });
+ } else {
+ FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ }
+ }
+
+ setTimeout(function () {
+ $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }, (samba.disable ? 1000 : 200));
+ });
+ } else {
+ if (samba.disable) {
+ $("#spinner-storagepool-filesystem-unmount-" + filesystem.id + " span").text("Disabling Samba share...");
+
+ if (zfsmanager.configuration.samba.manage) {
+ FnSambaShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: false, silent: false });
+ } else {
+ FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ }
+ }
+
+ setTimeout(function () {
+ $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }, (samba.disable ? 1000 : 200));
+ }
+ });
+ }
+}
+
+function FnFileSystemUnmountCommand(pool = { name, id }, filesystem = { name, id, force: false, lock: false }, display = { refresh: true }) {
+ let process = {
+ command: ["/sbin/zfs", "unmount", filesystem.name]
+ };
+
+ if (filesystem.force) {
+ process.command.splice(2, 0, "-f");
+ }
+
+ FnConsole.log[2]("File Systems, Unmount: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "File System successfully unmounted", description: filesystem.name, breakword: false }, { name: "filesystem-unmount", id: filesystem.id, timeout: 4 });
+
+ FnConsole.log[1]("File Systems, Unmount: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ if (display.refresh) {
+ $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "File System could not be unmounted", description: filesystem.name, breakword: false }, { name: "filesystem-unmount", id: filesystem.id, timeout: 4 });
+
+ FnConsole.warn("File Systems, Unmount: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+
+ $("#modal-storagepool-filesystem-unmount-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+}
+
+//#endregion
+
+//#region Snapshots
+
+function FnSnapshotsGet(pool = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name,creation,used,refer,encryption,encryptionroot,keystatus,clones", "-r", "-p", "-t", "snapshot", pool.name]
+ };
+ let snapshots = {
+ empty: true
+ };
+
+ pool.altroot = (($("#tr-storagepool-" + pool.id).attr("data-pool-altroot") == "true") ? true : false);
+ pool.readonly = (($("#tr-storagepool-" + pool.id).attr("data-pool-readonly") == "true") ? true : false);
+
+ FnConsole.log[2]("Snapshots, Get: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Get:" }));
+
+ if (data) {
+ snapshots.empty = false;
+
+ FnSnapshotsGetCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { data: data, message: message });
+ }
+
+ FnConsole.log[1]("Snapshots, Get: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Snapshots, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if (snapshots.empty) {
+ if (zfsmanager.configuration.zfs.snapshot.filesystemlist) {
+ $("#div-storagepool-snapshots-" + pool.id).empty();
+ }
+ $("#tbody-storagepool-snapshots-" + pool.id).empty();
+ $("#" + (zfsmanager.configuration.zfs.snapshot.filesystemlist ? "div" : "tbody") + "-storagepool-snapshots-" + pool.id).append((zfsmanager.configuration.zfs.snapshot.filesystemlist ? `` : ``) + `No snapshots found. ` + (zfsmanager.configuration.zfs.snapshot.filesystemlist ? `
` : ``));
+ $("#modals-storagepool-snapshots-" + pool.id).remove();
+ $("#modals-storagepool-snapshot-" + pool.id).remove();
+ $("#modals").append(`
`);
+
+ //Register snapshots modals
+ if (!pool.readonly) {
+ FnModalSnaphshotsCreate({ name: pool.name, id: pool.id });
+ }
+
+ $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-snapshots", "true");
+
+ $("#spinner-storagepool-snapshots-" + pool.id).addClass("hidden");
+ $("#paneltitle-storagepool-snapshots-" + pool.id).removeClass("hidden").text(FnDateTime());
+ $("#btn-storagepool-snapshots-create-" + pool.id).prop("disabled", false);
+ $("#btn-storagepool-snapshots-refresh-" + pool.id).prop("disabled", false);
+ }
+
+ FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
+ FnCockpitElementsUpdate();
+ });
+}
+
+function FnSnapshotsGetCommand(pool = { name, id, altroot: false, readonly: false }, process = { data, message }) {
+ let snapshots = {
+ data: process.data.split(/\n/g).filter(v => v),
+ filesystemlist: {
+ count: 0,
+ name: ""
+ }
+ };
+
+ if (zfsmanager.configuration.zfs.snapshot.filesystemlist) {
+ $("#div-storagepool-snapshots-" + pool.id).empty();
+ }
+ $("#tbody-storagepool-snapshots-" + pool.id).empty();
+ $("#modals-storagepool-snapshots-" + pool.id).remove();
+ $("#modals-storagepool-snapshot-" + pool.id).remove();
+ $("#modals").append(`
`);
+ $("#modals").append(`
`);
+
+ snapshots.data.forEach((_value, _index) => {
+ let snapshot = {
+ properties: _value.split(/\t/g).filter(v => v),
+ clones: [],
+ creation: "",
+ encryption: false,
+ encryptionroot: "",
+ id: "",
+ keystatus: "",
+ name: "",
+ actionsmenu: {
+ register: {}
+ }
+ };
+
+ if (!snapshot.properties[7]) { //Append clones property if not included after split
+ snapshot.properties[7] = "";
+ }
+
+ snapshot.filesystem = {
+ id: FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: snapshot.properties[0].replace(/^(.*)\@.*$/, "$1"), attribute: true })
+ };
+
+ snapshot.output = "";
+
+ if (zfsmanager.configuration.zfs.snapshot.filesystemlist) {
+ if (_index == 0 || (snapshots.filesystemlist.name != "" && snapshots.filesystemlist.name != snapshot.properties[0].replace(/^(.*)\@.*$/, "$1"))) {
+ snapshot.output += `
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#table-storagepool-snapshots-listing-` + snapshot.filesystem.id + ` > tbody > tr.listing-ct-item").on("click", function () {
+ if (!$(this).parent().hasClass("open")) {
+ $(this).parent().addClass("open");
+ } else {
+ $(this).parent().removeClass("open");
+ }
+ });
+ \x3C/script>
+
+
+
+ Name: ` + snapshot.properties[0].replace(/^(.*)\@.*$/, "$1") + (zfsmanager.configuration.zfs.storagepool.count ? ` ` : ``) + `
+
+
+
+
+
+
+
+
+ `;
+
+ $("#div-storagepool-snapshots-" + pool.id).append(snapshot.output);
+
+ snapshot.output = "";
+ snapshots.filesystemlist.count = 0;
+ }
+
+ snapshots.filesystemlist.count++;
+ $("#span-storagepool-snapshots-listing-" + snapshot.filesystem.id + "-count").html(snapshots.filesystemlist.count);
+ }
+
+ snapshot.output += ``;
+
+ snapshot.properties.forEach((__value, __index) => {
+ //0=name, 1=creation, 2=used, 3=refer, 4=encryption, 5=encryptionroot, 6=keystatus, 7=clones
+
+ switch (__index) {
+ case 0: //0=name
+ snapshot.name = __value;
+ snapshot.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: snapshot.name, attribute: true });
+
+ snapshot.output += `Name: ` + __value + ` `;
+ break;
+ case 1: //1=creation
+ snapshot.creation = __value;
+
+ snapshot.output += `Created: ` + FnDateTimeEpoch({ date: __value }) + ` `;
+ break;
+ case 2: //2=used
+ snapshot.output += `Used: ` + FnFormatBytes({ base2: true, decimals: 2, value: __value }) + ` `;
+ break;
+ case 3: //3=refer
+ snapshot.output += `Referenced: ` + FnFormatBytes({ base2: true, decimals: 2, value: __value }) + ` `;
+ break;
+ case 4: //4=encryption
+ if (__value.toLowerCase() != "off") {
+ snapshot.encryption = true;
+ } else {
+ snapshot.encryption = false;
+ }
+ break;
+ case 5: //5=encryptionroot
+ snapshot.encryptionroot = __value;
+ break;
+ case 6: //6=keystatus
+ snapshot.keystatus = __value;
+ break;
+ case 7: //7=clones
+ snapshot.clones = __value.split(",").filter(v => v).sort();
+
+ snapshot.output += `Clones: ` + (snapshot.clones.length > 0 ? snapshot.clones.join(", ") : `None `) + ` `;
+ break;
+ }
+
+ //Add action menu at end of array
+ if (__index >= (snapshot.properties.length - 1)) {
+ snapshot.icons = {
+ keystatus: {
+ locked: ` `,
+ unlocked: ` `
+ }
+ };
+
+ snapshot.output += `Encrypted: ` + (/available|unavailable/.test(snapshot.keystatus) ? `Yes` : `No`) + ` `;
+
+ if (snapshot.keystatus == "unavailable") {
+ snapshot.output += snapshot.icons.keystatus.locked;
+ } else if (snapshot.keystatus == "available") {
+ snapshot.output += snapshot.icons.keystatus.unlocked;
+ }
+
+ snapshot.output += ` `;
+
+ //Actions menu
+ snapshot.actionsmenu.items = {
+ item: [],
+ itemdivider: function () {
+ if (this.item.length > 0 && this.itemdestroy.length > 0) {
+ this.item.push(this.divider);
+ }
+ },
+ itemdestroy: [],
+ divider: ` `
+ };
+ snapshot.actionsmenu.display = function () {
+ if ((this.items.item.length + this.items.itemdestroy.length) > 0 || pool.readonly) {
+ this.items.itemdivider();
+
+ return this.header + this.items.item.join("\n") + this.items.itemdestroy.join("\n") + this.footer;
+ } else {
+ return "";
+ }
+ };
+ snapshot.actionsmenu.header = `
+
+
+
+
+
+
+ `;
+
+ //Clone Snapshot
+ if (!pool.readonly) {
+ snapshot.actionsmenu.items.item.push(`Clone Snapshot `);
+
+ snapshot.actionsmenu.register.clone = true;
+ }
+
+ //Rename Snapshot
+ if (!pool.readonly && snapshot.name != pool.name) {
+ snapshot.actionsmenu.items.item.push(`Rename Snapshot `);
+
+ snapshot.actionsmenu.register.rename = true;
+ }
+
+ //Roll Back Snapshot
+ if (!pool.readonly) {
+ snapshot.actionsmenu.items.item.push(`Roll Back Snapshot `);
+
+ snapshot.actionsmenu.register.rollback = true;
+ }
+
+ //Destroy Snapshot
+ if (!pool.readonly) {
+ snapshot.actionsmenu.items.itemdestroy.push(`Destroy Snapshot `);
+
+ snapshot.actionsmenu.register.destroy = true;
+ }
+
+ snapshot.output += ``;
+ }
+ });
+
+ snapshot.output += ` `;
+
+ if (zfsmanager.configuration.zfs.snapshot.filesystemlist) {
+ $("#tbody-storagepool-snapshots-list-" + snapshot.filesystem.id).append(snapshot.output);
+
+ snapshots.filesystemlist.name = snapshot.properties[0].replace(/^(.*)\@.*$/, "$1");
+ } else {
+ $("#tbody-storagepool-snapshots-" + pool.id).append(snapshot.output);
+ }
+
+
+ //Register snapshot modals
+ if (snapshot.actionsmenu.register.clone) {
+ FnModalSnapshotClone({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: snapshot.name, id: snapshot.id, encryption: snapshot.encryption, encryptionroot: snapshot.encryptionroot });
+ }
+ if (snapshot.actionsmenu.register.destroy) {
+ FnModalSnapshotDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: snapshot.name, id: snapshot.id, clones: snapshot.clones });
+ }
+ if (snapshot.actionsmenu.register.rename) {
+ FnModalSnapshotRename({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, creation: snapshot.creation });
+ }
+ if (snapshot.actionsmenu.register.rollback) {
+ FnModalSnapshotRollBack({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: snapshot.name, id: snapshot.id, creation: snapshot.creation });
+ }
+ });
+
+ //Register snapshots modals
+ if (!pool.readonly) {
+ FnModalSnaphshotsCreate({ name: pool.name, id: pool.id });
+ }
+
+ $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-snapshots", "true");
+
+ $("#spinner-storagepool-snapshots-" + pool.id).addClass("hidden");
+ $("#paneltitle-storagepool-snapshots-" + pool.id).removeClass("hidden").html(FnDateTime() + (zfsmanager.configuration.zfs.storagepool.count ? ` ` + snapshots.data.length + ` ` : ``));
+ $("#btn-storagepool-snapshots-create-" + pool.id).prop("disabled", false);
+ $("#btn-storagepool-snapshots-refresh-" + pool.id).prop("disabled", false);
+
+ FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
+ FnCockpitElementsUpdate();
+}
+
+//#endregion
+
+//#region Snapshot
+
+function FnSnapshotChildFileSystemsGet(pool = { name, id }, snapshot = { name, id }, filesystems = { id: [] }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name", "-r", "-t", "filesystem"]
+ };
+
+ filesystems.id.forEach(_value => _value && process.command.push(_value));
+
+ FnConsole.log[2]("Snapshots, Child, File Systems, Get: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Child, File Systems, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v),
+ count: {
+ filesystems: 0
+ }
+ };
+
+ if (filesystems.id.length > 0) {
+ filesystems.id.forEach((_value, _index) => {
+ if (_value != snapshot.name.replace(/^(.*)\@.*$/, "$1")) {
+ filesystems.count.filesystems++;
+
+ $("#ul-" + modal.name + "-child-filesystems-" + modal.id).append("" + _value + " \n");
+ }
+ });
+
+ $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-child-filesystems", filesystems.count.filesystems);
+ }
+
+ FnConsole.log[1]("Snapshots, Child, File Systems, Get: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Snapshots, Child, File Systems, Get: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnSnapshotChildSnapshotsGet(pool = { name, id }, snapshot = { name, id, exclude: false }, filesystems = { id: [] }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name", "-r", "-t", "snapshot"]
+ };
+
+ if (!snapshot.exclude) {
+ process.command.push(snapshot.name.replace(/^(.*)\@.*$/, "$1"));
+ }
+
+ filesystems.id.forEach(_value => _value && process.command.push(_value));
+
+ FnConsole.log[2]("Snapshots, Child, Snapshots, Get: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Child, Snapshots, Get:" }));
+
+ let snapshots = {
+ id: data.split(/\n/g).filter(v => v),
+ count: {
+ snapshots: 0,
+ snapshotswithclones: (snapshot.exclude ? $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-child-snapshotswithclones") : 0) //Exclude for Roll Back and append
+ }
+ };
+
+ if (snapshots.id.length > 0) {
+ snapshots.id.forEach((_value, _index) => {
+ if (_value != snapshot.name) {
+ //Recursive all will delete child file system snapshots with same name only. If clones are also found, all clone snapshots will be deleted
+ if (new RegExp("^" + snapshot.name.replace(/^(.*)\@.*$/, "$1") + "/.*@" + snapshot.name.replace(/^.*\@(.*)$/, "$1") + "$").test(_value)) { //Child file system snapshots with same name
+ if (!snapshot.exclude) {
+ snapshots.count.snapshots++;
+
+ $("#ul-" + modal.name + "-child-snapshots-" + modal.id).append("" + _value + " \n");
+ }
+
+ snapshots.count.snapshotswithclones++;
+
+ $("#ul-" + modal.name + "-child-snapshotswithclones-" + modal.id).append("" + _value + " \n");
+ } else {
+ filesystems.id.forEach((__value, __index) => {
+ if (new RegExp("^" + __value.replace(/^(.*)\@.*$/, "$1") + "@").test(_value) || new RegExp("^" + __value.replace(/^(.*)\@.*$/, "$1") + "/.*@").test(_value)) { //Snapshots of clone file system
+ snapshots.count.snapshotswithclones++;
+
+ $("#ul-" + modal.name + "-child-snapshotswithclones-" + modal.id).append("" + _value + " \n");
+ }
+ });
+ }
+ }
+ });
+
+ if (!snapshot.exclude) {
+ $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-child-snapshots", snapshots.count.snapshots);
+ }
+ $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-child-snapshotswithclones", snapshots.count.snapshotswithclones);
+ }
+
+ FnConsole.log[1]("Snapshots, Child, Snapshots, Get: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Snapshots, Child, Snapshots, Get: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnSnapshotClone(pool = { name, id, altroot: false }, snapshot = { name, id, clone: { name, createnonexistparents: false, parent } }) {
+ let process = {
+ command: ["/sbin/zfs", "clone", "-o", "sharenfs=off", "-o", "sharesmb=off", snapshot.name, snapshot.clone.name]
+ };
+
+ if (snapshot.clone.createnonexistparents) {
+ process.command.splice(2, 0, "-p");
+ }
+
+ FnConsole.log[2]("Snapshots, Clone: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-storagepool-snapshot-clone-" + snapshot.id + " span").text("Cloning snapshot...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Clone:" }));
+
+ if (/dataset already exists/i.test(data)) {
+ FnSnapshotCloneFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message });
+ return;
+ }
+
+ FnDisplayAlert({ status: "success", title: "Snapshot successfully cloned", description: snapshot.name, breakword: false }, { name: "snapshot-clone", id: snapshot.id, timeout: 4 });
+
+ FnConsole.log[1]("Snapshots, Clone: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+
+ if (snapshot.clone.createnonexistparents && zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-snapshot-clone-" + snapshot.id + " span").text("Disabling Samba share inheritance...");
+
+ FnFileSystemShareSmbInheritedDisable({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: snapshot.clone.parent }, { disable: true })
+ .finally(function () {
+ $("#modal-storagepool-snapshot-clone-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+ } else {
+ $("#modal-storagepool-snapshot-clone-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ })
+ .fail(function (message, data) {
+ FnSnapshotCloneFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message });
+ });
+}
+
+function FnSnapshotCloneFail(pool = { name, id }, snapshot = { name, id }, process = { data, message }) {
+ let modal = {
+ hide: true
+ };
+
+ if (/filesystem successfully created/gi.test(process.data)) {
+ FnDisplayAlert({ status: "warning", title: "Snapshot cloned with errors", description: snapshot.name, breakword: false }, { name: "snapshot-clone", id: snapshot.id, timeout: 4 });
+
+ FnConsole.warn("Snapshots, Clone: Warning, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (process.data ? process.data : process.message));
+ } else {
+ if (/dataset already exists/i.test(process.data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-snapshot-clone-name-" + snapshot.id).addClass("has-error");
+ $("#helpblock-storagepool-snapshot-clone-name-" + snapshot.id).addClass("has-error").removeClass("hidden").text("Name already exists.");
+ $("#input-storagepool-snapshot-clone-name-" + snapshot.id).focus();
+ } else if (/parent does not exist/i.test(process.data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-snapshot-clone-name-" + snapshot.id).addClass("has-error");
+ $("#helpblock-storagepool-snapshot-clone-name-" + snapshot.id).addClass("has-error").removeClass("hidden").text("Parent file system does not exist.");
+ $("#input-storagepool-snapshot-clone-name-" + snapshot.id).focus();
+ }
+
+ if (modal.hide) {
+ FnDisplayAlert({ status: "danger", title: "Snapshot could not be cloned", description: snapshot.name, breakword: false }, { name: "snapshot-clone", id: snapshot.id, timeout: 4 });
+ }
+
+ FnConsole.warn("Snapshots, Clone: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (process.data ? process.data : process.message));
+ }
+
+ if (!modal.hide) {
+ $("#spinner-storagepool-snapshot-clone-" + snapshot.id).addClass("hidden");
+ $("#spinner-storagepool-snapshot-clone-" + snapshot.id + " span").text("");
+ $("#btn-storagepool-snapshot-clone-apply-" + snapshot.id).prop("disabled", false);
+ }
+
+ if (modal.hide) {
+ $("#modal-storagepool-snapshot-clone-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+}
+
+function FnSnapshotCreate(pool = { name, id }, snapshot = { name, id, recursive: false }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "snapshot", snapshot.name]
+ };
+
+ modal.hide = true;
+
+ if (snapshot.recursive) {
+ process.command.splice(2, 0, "-r");
+ }
+
+ FnConsole.log[2]("Snapshots, Create: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Creating snapshot" + (snapshot.recursive ? "s" : "") + "...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Snapshot successfully created", description: snapshot.name, breakword: false }, { name: "snapshot-create", id: snapshot.id, timeout: 4 });
+
+ FnConsole.log[1]("Snapshots, Create: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ })
+ .fail(function (message, data) {
+ if (/dataset already exists/gi.test(data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-" + modal.name + "-name-" + modal.id).addClass("has-error");
+ $("#helpblock-" + modal.name + "-name-" + modal.id).addClass("has-error").removeClass("hidden").text("Name already exists.");
+ $("#input-" + modal.name + "-name-" + modal.id).focus();
+ }
+
+ if (!modal.hide) {
+ $("#spinner-" + modal.name + "-" + modal.id).addClass("hidden");
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("");
+ $("#btn-" + modal.name + "-apply-" + modal.id).prop("disabled", false);
+ }
+
+ if (modal.hide) {
+ FnDisplayAlert({ status: "danger", title: "Snapshot could not be created", description: snapshot.name, breakword: false }, { name: "snapshot-create", id: snapshot.id, timeout: 4 });
+ }
+
+ FnConsole.warn("Snapshots, Create: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ if (modal.hide) {
+ setTimeout(function () {
+ $("#modal-" + modal.name + "-" + modal.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }, 700);
+ }
+ });
+}
+
+function FnSnapshotCreateDateGet(pool = { name, id }, snapshot = { name, id, recursive: false }, modal = { name, id }) {
+ let process = {
+ command: ["/bin/date", "\+\%Y.\%m.\%d-\%H.\%M.\%S"]
+ };
+
+ snapshot.date = "";
+
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + "-" + modal.id + " span").text("Creating snapshot" + (snapshot.recursive ? "s" : "") + "...");
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Create, Date, Get:" }));
+
+ snapshot.date = data.replace(/[ \t\n]+/g, "");
+ })
+ .fail(function () {
+ snapshot.date = FnDateTimeSnapshot({ date: null });
+ })
+ .finally(function () {
+ snapshot.name = snapshot.name.replace(/^(.*)\@.*$/, "$1") + "@" + snapshot.date;
+ snapshot.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: snapshot.name, attribute: true });
+
+ $("#input-" + modal.name + "-name-" + modal.id).val(snapshot.date);
+
+ FnSnapshotCreate({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive }, { name: modal.name, id: modal.id });
+ });
+}
+
+function FnSnapshotDestroy(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, clones: [], recursive: false, recursiveall: false }, samba = { restart: false }) {
+ if (samba.restart) {
+ FnSambaStop()
+ .finally(function () {
+ if (snapshot.recursiveall && snapshot.clones.length > 0 && zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: snapshot.clones })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
+
+ if (filesystems.id.length > 0) {
+ FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: false })
+ .done(function () {
+ $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying Samba shares...");
+
+ FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
+ .finally(function () {
+ $("#modal-storagepool-snapshot-destroy-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+ });
+ } else {
+ $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
+
+ FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true })
+ .finally(function () {
+ FnSambaStart();
+ });
+ }
+ })
+ .fail(function (message, data) {
+ FnSnapshotDestroyFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message }, { refresh: true });
+ FnSambaStart();
+ });
+ } else {
+ $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
+
+ FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true })
+ .finally(function () {
+ FnSambaStart();
+ });
+ }
+ });
+ } else {
+ if (snapshot.recursiveall && snapshot.clones.length > 0 && zfsmanager.configuration.samba.manage) {
+ $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: snapshot.clones })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
+
+ if (filesystems.id.length > 0) {
+ FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: false })
+ .done(function () {
+ $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying Samba shares...");
+
+ FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
+ .finally(function () {
+ $("#modal-storagepool-snapshot-destroy-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+ });
+ } else {
+ $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
+
+ FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true });
+ }
+ })
+ .fail(function (message, data) {
+ FnSnapshotDestroyFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message }, { refresh: true });
+ });
+ } else {
+ $("#spinner-storagepool-snapshot-destroy-" + snapshot.id + " span").text("Destroying snapshot...");
+
+ FnSnapshotDestroyCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true });
+ }
+ }
+}
+
+function FnSnapshotDestroyCommand(pool = { name, id }, snapshot = { name, id, recursive: false, recursiveall: false }, display = { refresh: true }) {
+ let process = {
+ command: ["/sbin/zfs", "destroy", snapshot.name]
+ };
+
+ if (snapshot.recursive) {
+ process.command.splice(2, 0, "-r");
+ }
+ if (snapshot.recursiveall) {
+ process.command.splice(2, 0, "-R");
+ }
+
+ FnConsole.log[1]("Snapshots, Destroy: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Snapshot successfully destroyed", description: snapshot.name, breakword: false }, { name: "snapshot-destroy", id: snapshot.id, timeout: 4 });
+
+ FnConsole.log[1]("Snapshots, Destroy: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ })
+ .fail(function (message, data) {
+ FnSnapshotDestroyFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message }, { refresh: false });
+
+ display.refresh = true;
+ })
+ .finally(function () {
+ if (display.refresh) {
+ $("#modal-storagepool-snapshot-destroy-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ });
+}
+
+function FnSnapshotDestroyFail(pool = { name, id }, snapshot = { name, id }, process = { data, message }, display = { refresh: true }) {
+ FnDisplayAlert({ status: "danger", title: "Snapshot could not be destroyed", description: snapshot.name, breakword: false }, { name: "snapshot-destroy", id: snapshot.id, timeout: 4 });
+
+ FnConsole.warn("Snapshots, Destroy: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (process.data ? process.data : process.message));
+
+ if (display.refresh) {
+ $("#modal-storagepool-snapshot-destroy-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+}
+
+function FnSnapshotRename(pool = { name, id }, snapshot = { name, id, namenew, recursive: false }) {
+ let process = {
+ command: ["/sbin/zfs", "rename", snapshot.name, snapshot.namenew]
+ };
+ let modal = {
+ hide: true
+ };
+
+ if (snapshot.recursive) {
+ process.command.splice(2, 0, "-r");
+ }
+
+ FnConsole.log[1]("Snapshots, Rename: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-storagepool-snapshot-rename-" + snapshot.id + " span").text("Renaming snapshot...");
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Snapshot successfully renamed", description: snapshot.name, breakword: false }, { name: "snapshot-rename", id: snapshot.id, timeout: 4 });
+
+ FnConsole.log[1]("Snapshots, Rename: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ })
+ .fail(function (message, data) {
+ if (/dataset already exists|child dataset already has a snapshot with the new name/gi.test(data)) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-snapshot-rename-name-" + snapshot.id).addClass("has-error");
+ $("#helpblock-storagepool-snapshot-rename-name-" + snapshot.id).addClass("has-error").removeClass("hidden").text("Name already exists.");
+ $("#input-storagepool-snapshot-rename-name-" + snapshot.id).focus();
+ }
+
+ if (!modal.hide) {
+ $("#spinner-storagepool-snapshot-rename-" + snapshot.id).addClass("hidden");
+ $("#spinner-storagepool-snapshot-rename-" + snapshot.id + " span").text("");
+ $("#btn-storagepool-snapshot-rename-apply-" + snapshot.id).prop("disabled", false);
+ }
+
+ FnConsole.warn("Snapshots, Rename: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (data ? data : message));
+
+ if (modal.hide) {
+ FnDisplayAlert({ status: "danger", title: "Snapshot could not be renamed", description: snapshot.name, breakword: false }, { name: "snapshot-rename", id: snapshot.id, timeout: 4 });
+ }
+ })
+ .finally(function () {
+ if (modal.hide) {
+ $("#modal-storagepool-snapshot-rename-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ });
+}
+
+function FnSnapshotRollBack(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, creation, force: false, recursive: false, recursiveall: false }, samba = { restart: false }) {
+ if (samba.restart) {
+ FnSambaStop()
+ .finally(function () {
+ if (snapshot.recursiveall && zfsmanager.configuration.samba.manage) {
+ FnSnapshotRollBackSnapshotsGet({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, creation: snapshot.creation }, { name: null, id: null })
+ .done(function (data) {
+ let snapshots = {
+ id: data.split(/\n/g).filter(v => v),
+ clones: []
+ };
+
+ if (snapshots.id.length > 0) {
+ snapshots.id.forEach((_value, _index) => {
+ _value = _value.split(/\t/g).filter(v => v);
+
+ snapshots.properties = {
+ clones: (_value[2] ? _value[2].split(",").filter(v => v) : []),
+ creation: _value[1],
+ name: _value[0]
+ };
+
+ if (snapshots.properties.name != snapshot.name && snapshots.properties.creation > snapshot.creation && snapshots.properties.clones.length > 0) {
+ snapshots.properties.clones.forEach((_value, _index) => {
+ snapshots.clones.push(_value);
+ });
+ }
+ });
+ }
+
+ if (snapshots.clones.length > 0) {
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: snapshots.clones })
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: _data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
+
+ if (filesystems.id.length > 0) {
+ FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: false })
+ .done(function () {
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Destroying Samba shares...");
+
+ FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
+ .finally(function () {
+ $("#modal-storagepool-snapshot-rollback-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+ });
+ } else {
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
+
+ FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true })
+ .finally(function () {
+ FnSambaStart();
+ });
+ }
+ })
+ .fail(function (_message, _data) {
+ FnSnapshotRollBackCommandFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: _data, message: _message }, { refresh: true });
+ FnSambaStart();
+ });
+ } else {
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
+
+ FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true })
+ .finally(function () {
+ FnSambaStart();
+ });
+ }
+ });
+ } else {
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
+
+ FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true })
+ .finally(function () {
+ FnSambaStart();
+ });
+ }
+ });
+ } else {
+ if (snapshot.recursiveall && zfsmanager.configuration.samba.manage) {
+ FnSnapshotRollBackSnapshotsGet({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, creation: snapshot.creation }, { name: null, id: null })
+ .done(function (data) {
+ let snapshots = {
+ id: data.split(/\n/g).filter(v => v),
+ clones: []
+ };
+
+ if (snapshots.id.length > 0) {
+ snapshots.id.forEach((_value, _index) => {
+ _value = _value.split(/\t/g).filter(v => v);
+
+ snapshots.properties = {
+ clones: (_value[2] ? _value[2].split(",").filter(v => v) : []),
+ creation: _value[1],
+ name: _value[0]
+ };
+
+ if (snapshots.properties.name != snapshot.name && snapshots.properties.creation > snapshot.creation && snapshots.properties.clones.length > 0) {
+ snapshots.properties.clones.forEach((_value, _index) => {
+ snapshots.clones.push(_value);
+ });
+ }
+ });
+ }
+
+ if (snapshots.clones.length > 0) {
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Retrieving Samba shares...");
+
+ FnSambaSharesGet({ name: pool.name, id: pool.id }, { name: null, clones: snapshots.clones })
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Samba, Shares, Get:" }));
+
+ let filesystems = {
+ id: _data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
+
+ if (filesystems.id.length > 0) {
+ FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: false })
+ .done(function () {
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Destroying Samba shares...");
+
+ FnSambaSharesDestroy({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: false }, { id: filesystems.id }, { restart: samba.restart }, { silent: false })
+ .finally(function () {
+ $("#modal-storagepool-snapshot-rollback-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ });
+ });
+ } else {
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
+
+ FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true });
+ }
+ })
+ .fail(function (_message, _data) {
+ FnSnapshotRollBackCommandFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: _data, message: _message }, { refresh: true });
+ });
+ } else {
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
+
+ FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true });
+ }
+ });
+ } else {
+ $("#spinner-storagepool-snapshot-rollback-" + snapshot.id + " span").text("Rolling back snapshot...");
+
+ FnSnapshotRollBackCommand({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { refresh: true });
+ }
+ }
+}
+
+function FnSnapshotRollBackCommand(pool = { name, id }, snapshot = { name, id, force: false, recursive: false, recursiveall: false }, display = { refresh: true }) {
+ let process = {
+ command: ["/sbin/zfs", "rollback", snapshot.name]
+ };
+
+ if (snapshot.force) {
+ process.command.splice(2, 0, "-f");
+ }
+ if (snapshot.recursive) {
+ process.command.splice(2, 0, "-r");
+ }
+ if (snapshot.recursiveall) {
+ process.command.splice(2, 0, "-R");
+ }
+
+ FnConsole.log[1]("Snapshots, Roll Back: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Snapshot successfully rolled back", description: snapshot.name, breakword: false }, { name: "snapshot-rollback", id: snapshot.id, timeout: 4 });
+
+ FnConsole.log[1]("Snapshots, Roll Back: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ })
+ .fail(function (message, data) {
+ FnSnapshotRollBackCommandFail({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, { data: data, message: message }, { refresh: false });
+
+ display.refresh = true;
+ })
+ .finally(function () {
+ if (display.refresh) {
+ $("#modal-storagepool-snapshot-rollback-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+ });
+}
+
+function FnSnapshotRollBackCommandFail(pool = { name, id }, snapshot = { name, id }, process = { data, message }, display = { refresh: true }) {
+ FnDisplayAlert({ status: "danger", title: "Snapshot could not be rolled back", description: snapshot.name, breakword: false }, { name: "snapshot-rollback", id: snapshot.id, timeout: 4 });
+
+ FnConsole.warn("Snapshots, Roll Back: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (process.data ? process.data : process.message));
+
+ if (display.refresh) {
+ $("#modal-storagepool-snapshot-rollback-" + snapshot.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 200);
+ }
+}
+
+function FnSnapshotRollBackSnapshotsGet(pool = { name, id }, snapshot = { name, id, creation }, modal = { name, id }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name,creation,clones", "-p", "-t", "snapshot"]
+ };
+
+ process.command.push(snapshot.name.replace(/^(.*)\@.*$/, "$1"));
+
+ FnConsole.log[2]("Snapshots, Roll Back, Snapshots, Get: In Progress, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Snapshots, Roll Back, Snapshots, Get:" }));
+
+ if (modal.name && modal.id) {
+ let snapshots = {
+ id: data.split(/\n/g).filter(v => v),
+ clones: [],
+ count: {
+ snapshots: 0,
+ snapshotswithclones: 0
+ }
+ };
+
+ if (snapshots.id.length > 0) {
+ snapshots.id.forEach((_value, _index) => {
+ _value = _value.split(/\t/g).filter(v => v);
+
+ snapshots.properties = {
+ clones: (_value[2] ? _value[2].split(",").filter(v => v) : []),
+ creation: _value[1],
+ name: _value[0]
+ };
+
+ if (snapshots.properties.name != snapshot.name && snapshots.properties.creation > snapshot.creation) {
+ snapshots.count.snapshots++;
+ snapshots.count.snapshotswithclones++;
+
+ if (snapshots.properties.clones.length > 0) {
+ snapshots.properties.clones.forEach((_value, _index) => {
+ snapshots.clones.push(_value);
+ });
+ }
+
+ $("#ul-" + modal.name + "-snapshots-" + modal.id).append("" + snapshots.properties.name + " \n");
+ $("#ul-" + modal.name + "-child-snapshotswithclones-" + modal.id).append("" + snapshots.properties.name + " \n");
+ }
+ });
+
+ $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-snapshots", snapshots.count.snapshots);
+ $("#panelgroup-" + modal.name + "-" + modal.id).attr("data-snapshot-child-snapshotswithclones", snapshots.count.snapshotswithclones);
+ }
+
+ if (snapshots.clones.length > 0) {
+ FnSnapshotChildFileSystemsGet({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id }, filesystems = { id: snapshots.clones }, { name: modal.name, id: modal.id });
+ FnSnapshotChildSnapshotsGet({ name: pool.name, id: pool.id }, { name: snapshot.name, id: snapshot.id, exclude: true }, { id: snapshots.clones }, { name: modal.name, id: modal.id });
+ }
+ }
+
+ FnConsole.log[1]("Snapshots, Roll Back, Snapshots, Get: Success, Pool: " + pool.name + ", Snapshot: " + snapshot.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Snapshots, Roll Back, Snapshots, Get: Failed, Pool: " + pool.name + ", Snapshot: " + snapshot.name + ", Message: " + (data ? data : message));
+ });
+}
+
+//#endregion
+
+//#region Status
+
+function FnStatusErrorColors(status = { count }) {
+ if (!$.isNumeric(status.count)) {
+ return status.count;
+ }
+
+ if (status.count >= 5 && status.count <= 20) {
+ return (`` + status.count + ` `);
+ } else if (status.count >= 21) {
+ return (`` + status.count + ` `);
+ } else {
+ return status.count;
+ }
+}
+
+function FnStatusGet(pool = { name, id }) {
+ let process = {
+ command: ["/bin/sh", "-c", ((zfsmanager.user.name == "root" || !zfsmanager.user.name) ? "ZPOOL_SCRIPTS_AS_ROOT=1 " : "") + `/sbin/zpool status -p -t -c upath "` + pool.name + `"`]
+ };
+
+ pool.autotrim = ($("#tr-storagepool-" + pool.id).attr("data-pool-autotrim") == "true" ? true : false);
+ pool.boot = ($("#tr-storagepool-" + pool.id).attr("data-pool-boot") == "true" ? true : false);
+ pool.feature = {
+ allocation_classes: ($("#tr-storagepool-" + pool.id).attr("data-pool-feature-allocation_classes") == "true" ? true : false),
+ device_removal: ($("#tr-storagepool-" + pool.id).attr("data-pool-feature-device_removal") == "true" ? true : false),
+ resilver_defer: ($("#tr-storagepool-" + pool.id).attr("data-pool-feature-resilver_defer") == "true" ? true : false)
+ };
+ pool.guid = $("#tr-storagepool-" + pool.id).attr("data-pool-guid");
+ pool.readonly = ($("#tr-storagepool-" + pool.id).attr("data-pool-readonly") == "true" ? true : false);
+ pool.root = ($("#tr-storagepool-" + pool.id).attr("data-pool-root") == "true" ? true : false);
+ pool.status = {
+ empty: true
+ };
+ pool.upgrade = ($("#tr-storagepool-" + pool.id).attr("data-pool-upgrade") == "true" ? true : false);
+ pool.version = $("#tr-storagepool-" + pool.id).attr("data-pool-version");
+
+ FnConsole.log[2]("Status, Get: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Status, Get:" }));
+
+ FnDisksLsblkGet({ sizeraw: true })
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Disks, Lsblk, Get:" }));
+
+ if (data) {
+ pool.status.empty = false;
+
+ let disks = {
+ lsblkjson: JSON.parse(_data)
+ };
+
+ FnStatusGetCommand({ name: pool.name, id: pool.id, autotrim: pool.autotrim, boot: pool.boot, feature: { allocation_classes: pool.feature.allocation_classes, device_removal: pool.feature.device_removal, resilver_defer: pool.feature.resilver_defer }, guid: pool.guid, readonly: pool.readonly, root: pool.root, upgrade: pool.upgrade, version: pool.version }, { lsblk: disks.lsblkjson }, { data: data, message: message });
+ }
+
+ FnConsole.log[1]("Status, Get: Success, Pool: " + pool.name);
+
+ if (pool.status.empty) {
+ $("#tbody-storagepool-status-messages-" + pool.id).empty();
+ $("#tbody-storagepool-status-config-" + pool.id).empty();
+ $("#tbody-storagepool-status-messages-" + pool.id).append(`Status not available `);
+ $("#modals-storagepool-status-" + pool.id).remove();
+ $("#dynamics-storagepool-status-" + pool.id).remove();
+
+ $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-status", "true");
+
+ $("#spinner-storagepool-status-" + pool.id).addClass("hidden");
+ $("#paneltitle-storagepool-status-" + pool.id).removeClass("hidden").text(FnDateTime());
+ $("#btn-storagepool-status-refresh-" + pool.id).prop("disabled", false);
+ $("#btn-storagepool-status-refresh-auto-" + pool.id).prop("disabled", false);
+ }
+
+ FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
+ FnCockpitElementsUpdate();
+ })
+ .fail(function (_message, _data) {
+ FnConsole.warn("Status, Get: Failed, Pool: " + pool.name + ", Message: " + (_data ? _data : _message));
+
+ FnStatusGetFail({ name: pool.name, id: pool.id, status: { empty: pool.status.empty } });
+ });
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Status, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+
+ FnStatusGetFail({ name: pool.name, id: pool.id, status: { empty: pool.status.empty } });
+ });
+}
+
+function FnStatusGetCommand(pool = { name, id, autotrim: false, boot: false, feature: { allocation_classes: true, device_removal: true, resilver_defer: true }, guid, readonly: false, root: false, upgrade: false, version }, disks = { lsblk: {} }, process = { data, message }) {
+ process.data = process.data.replace(/\n\t+/g, "[TAB1]").split(/\n/g).filter(v => v); //Replace new line with [TAB1] for multi line messages and config
+
+ pool.status = {
+ state: "",
+ status: "",
+ action: "",
+ see: "",
+ scan: "",
+ remove: "",
+ memory: "",
+ errors: "",
+ upgrade: false,
+ resilver: {
+ started: false
+ },
+ scrub: {
+ started: false,
+ paused: false
+ },
+ trim: {
+ started: false,
+ suspended: false
+ },
+ disks: {
+ count: 0,
+ ssd: false,
+ trim: {
+ unsupportedcount: 0
+ }
+ },
+ config: {
+ items: [],
+ regexp: {},
+ replacement: {},
+ tier: {
+ count: 0,
+ nametier0: "",
+ nametier1: "",
+ nametier2: "",
+ nametier3: ""
+ },
+ virtualdevice: {
+ count: 0
+ }
+ }
+ };
+
+ $("#modals-storagepool-status-" + pool.id).remove();
+ $("#modals").append(`
`);
+ $("#dynamics-storagepool-status-" + pool.id).remove();
+ $("#dynamics").append(`
`);
+
+ pool.status.output = `Pool: ` + pool.name + ` `;
+
+ process.data.forEach((_value, _index) => {
+ if (/^(?: )+pool:/g.test(_value)) {
+ _value = "";
+ }
+ if (/^(?: )+state:/g.test(_value)) {
+ pool.status.state = _value.replace(/\[TAB1\]/g, " ").replace(/^(?: )+state:/g, "").trim();
+ _value = "";
+
+ pool.status.output += `State: ` + (pool.status.state ? ` ` + pool.status.state : ``) + ` `;
+ }
+ if (/^status:/g.test(_value)) {
+ pool.status.status = _value.replace(/\[TAB1\]/g, " ").replace(/^status:/g, "").trim();
+ _value = "";
+
+ if (/currently being resilvered/gi.test(pool.status.status)) {
+ pool.status.resilver.started = true;
+ }
+
+ pool.status.output += `Status: ` + pool.status.status + ` `;
+ }
+ if (/^action:/g.test(_value)) {
+ pool.status.action = _value.replace(/\[TAB1\]/g, " ").replace(/^action:/g, "").trim();
+ pool.status.upgrade = ((pool.upgrade || /Upgrade the pool|zpool upgrade/gi.test(pool.status.action)) && !pool.boot ? true : false);
+ _value = "";
+
+ if (/Upgrade the pool|zpool upgrade/gi.test(pool.status.action) && !pool.boot) { //Hide upgrade message for boot pool. Upgrading version may cause an unbootable system
+ pool.status.output += `Action: ` + pool.status.action + ` `;
+ }
+ }
+ if (/^(?: )+see:/g.test(_value)) {
+ pool.status.see = _value.replace(/\[TAB1\]/g, " ").replace(/^(?: )+see:(?: )+/g, "").trim();
+ _value = "";
+
+ if (/http/g.test(pool.status.see)) {
+ pool.status.see = `` + pool.status.see + ` `;
+ }
+
+ pool.status.output += `See: ` + pool.status.see + ` `;
+ }
+ if (/^(?: )+scan:/g.test(_value)) {
+ pool.status.scan = _value.replace(/\[TAB1\]/g, " ").replace(/^(?: )+scan:/g, "").trim();
+ _value = "";
+
+ if (/scrub in progress/gi.test(pool.status.scan)) {
+ pool.status.scrub.started = true;
+ } else if (/scrub paused/gi.test(pool.status.scan)) {
+ pool.status.scrub.paused = true;
+ }
+
+ if (/resilver in progress/gi.test(pool.status.scan)) {
+ pool.status.resilver.started = true;
+ }
+
+ pool.status.output += `Scan: ` + pool.status.scan + ` `;
+ }
+ if (/^remove:/g.test(_value)) {
+ pool.status.remove = _value.replace(/\[TAB1\]/g, " ").replace(/^remove:/g, "").trim();
+ _value = "";
+
+ pool.status.output += `Remove: ` + pool.status.remove + ` `;
+ }
+ if (/memory used for/g.test(_value)) {
+ pool.status.memory = ". " + _value.replace(/\[TAB1\]/g, " ").trim();
+ _value = "";
+ }
+ if (/^config:/g.test(_value)) {
+ _value = "";
+ }
+ if (/^errors:/g.test(_value)) {
+ pool.status.errors = _value.replace(/\[TAB1\]/g, " ").replace(/^errors:/g, "").trim();
+ _value = "";
+
+ pool.status.output += `Errors: ` + pool.status.errors + ` `;
+ }
+ if (/\[TAB1\]NAME/g.test(_value)) { //Config header row
+ _value = _value.split("upath").slice(1).join("."); //Remove config header row (and any previous text if exists)
+
+ pool.status.config.regexp.tabspace = new RegExp("^\\[TAB1\\]" + pool.name);
+
+ if (pool.status.config.regexp.tabspace.test(_value)) { //Confirm config rows
+ pool.status.config.items = _value.split("[TAB1]").filter(v => v);
+ }
+
+ if (/trimmed, started|trimmed started/i.test(pool.status.config.items.join(" "))) { //Storage pool contains a disk with TRIM started
+ pool.status.trim.started = true;
+ } else if (/trimmed, suspended|trimmed suspended/i.test(pool.status.config.items.join(" "))) { //Storage pool contains a disk with TRIM suspended
+ pool.status.trim.suspended = true;
+ }
+ }
+ });
+
+ pool.status.output += ` `;
+ pool.status.output += ` `;
+
+ $("#tbody-storagepool-status-messages-" + pool.id).html(pool.status.output);
+ $("#td-storagepool-status-messages-remove-" + pool.id).append(pool.status.memory);
+
+ pool.status.config.output = `
+
+ Name
+ State
+ Read
+ Write
+ Checksum
+ Message
+ Product
+
+
+
+ `;
+
+ $("#tbody-storagepool-status-config-" + pool.id).html(pool.status.config.output);
+
+ pool.status.config.items.forEach((_value, _index) => {
+ pool.status.config.disk = false;
+ pool.status.config.tier.level = (_value.match(/^\s*/g)[0].length / 2);
+ pool.status.config.tier.cache = false;
+ pool.status.config.tier.dedup = false;
+ pool.status.config.tier.logs = false;
+ pool.status.config.tier.pool = false;
+ pool.status.config.tier.spares = false;
+ pool.status.config.tier.special = false;
+ pool.status.config.tier.replacing = false;
+ pool.status.config.output = "";
+
+ pool.status.disks.disk = {
+ ssd: false,
+ trim: {
+ started: false,
+ suspended: false,
+ unsupported: false
+ },
+ replacing: false,
+ messages: [],
+ upath: ""
+ }
+
+ if (_index == 0 && /[ ]/g.test(pool.name)) { //Fix for storage pool name if it contains whitespace
+ pool.status.config.regexp.poolname = new RegExp("^" + pool.name, "g");
+ _value = _value.replace(pool.status.config.regexp.poolname, "[POOLNAME]");
+ }
+
+ _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
+
+ if (_index == 0 && _value[0] == "[POOLNAME]") {
+ _value[0] = pool.name;
+ }
+
+ switch (pool.status.config.tier.level) {
+ case 0: //Pool / Cache / Dedup / Log / Spares / Special tier
+ pool.status.config.tier.nametier0 = _value[0].trim();
+ break;
+ case 1: //Virtual device tier
+ pool.status.config.tier.nametier1 = _value[0];
+
+ if (pool.status.config.tier.nametier0 == pool.name) {
+ pool.status.config.virtualdevice.count++;
+ }
+ break;
+ case 2: //Drive tier
+ pool.status.config.tier.nametier2 = _value[0];
+ break;
+ case 3: //Action tier
+ pool.status.config.tier.nametier3 = _value[0];
+ break;
+ case 4: //Action Drive tier
+ break;
+ }
+
+ if (pool.status.config.tier.level == 0) { //1= Pool, 2+= / Cache / Dedup / Log / Spares / Special
+ pool.status.config.tier.count++;
+ }
+
+ if (pool.status.config.tier.level > 0) {
+ if (pool.status.config.tier.nametier0 == pool.name && pool.status.config.tier.count == 1) { //Virtual Device / Disk is member of pool
+ pool.status.config.tier.pool = true;
+ }
+ if (/^cache/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) { //Virtual Device / Disk is member of cache
+ pool.status.config.tier.cache = true;
+ }
+ if (/^dedup/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) { //Virtual Device / Disk is member of dedup
+ pool.status.config.tier.dedup = true;
+ }
+ if (/^logs/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) { //Virtual Device / Disk is member of logs
+ pool.status.config.tier.logs = true;
+ }
+ if (/^spares/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) { //Virtual Device / Disk is member of spares
+ pool.status.config.tier.spares = true;
+ }
+ if (/^special/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) { //Virtual Device / Disk is member of special
+ pool.status.config.tier.special = true;
+ }
+ }
+
+ pool.status.config.tier.virtualdevice = ((pool.status.config.tier.level == 0 && /^cache|^dedup|^logs|^spares|^special/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) ? true : false);
+
+ if (pool.status.config.tier.level == 0 && /^special/g.test(pool.status.config.tier.nametier0) && pool.status.config.tier.count > 1) {
+ $("#tr-storagepool-" + pool.id).attr("data-pool-special", true);
+ }
+
+ if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[5])) { //upath
+ pool.status.disks.disk.upath = _value[5];
+ _value[5] = "";
+ } else if ($.isNumeric(_value[0]) && _value[5] == "was") { //upath appears after was device path message
+ pool.status.disks.disk.upath = _value[7];
+ _value[7] = "";
+ } else if (!$.isNumeric(_value[0]) && _value[5] != "was") { //upath appears after error messages and before trim messages
+ for (let i = 5; i < _value.length; i++) { //Collect messages
+ if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[i])) {
+ pool.status.disks.disk.upath = _value[i];
+ _value[i] = "";
+ }
+ }
+ }
+
+ if ((/^\/dev\/nvme|^\/dev\/sd/gi.test(pool.status.disks.disk.upath) || /^nvme-nvme/gi.test(_value[0]) || /^wwn-/gi.test(_value[0]) || $.isNumeric(_value[0])) && pool.status.config.tier.level > 0) {
+ pool.status.config.disk = true;
+ pool.status.disks.count++;
+ }
+
+ if (pool.status.config.disk && (pool.status.config.tier.level == 2 && /^replacing-/g.test(pool.status.config.tier.nametier1) || pool.status.config.tier.level == 3 && /^replacing-/g.test(pool.status.config.tier.nametier2) || pool.status.config.tier.level == 4 && /^replacing-/g.test(pool.status.config.tier.nametier3))) {
+ pool.status.disks.disk.replacing = true;
+ }
+
+ if (pool.status.config.tier.level > 0 && /^replacing-/g.test(_value[0])) {
+ pool.status.config.tier.replacing = true;
+ }
+
+ pool.status.config.output += ``;
+ pool.status.config.output += `` + (pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name ? `Pool` : (pool.status.config.disk ? `Disk` : `Virtual Device`)) + `: ` + _value[0] + ` `; //Pool / Virtual Device / Disk
+ pool.status.config.output += `State: ` + (_value[1] ? ` ` + _value[1] : ``) + ` `; //State
+
+ if (_value[2] && /^spares/g.test(pool.status.config.tier.nametier0)) { //Read
+ pool.status.disks.disk.messages.push(_value[2]);
+
+ pool.status.config.output += ` `;
+ } else {
+ pool.status.config.output += `` + (_value[2] ? `Read: ` + (zfsmanager.configuration.zfs.status.errorcolors ? FnStatusErrorColors({ count: _value[2] }) : _value[2]) : ``) + ` `;
+ }
+
+ if (_value[3] && /^spares/g.test(pool.status.config.tier.nametier0)) { //Write
+ pool.status.disks.disk.messages.push(_value[3]);
+
+ pool.status.config.output += ` `;
+ } else {
+ pool.status.config.output += `` + (_value[3] ? `Write: ` + (zfsmanager.configuration.zfs.status.errorcolors ? FnStatusErrorColors({ count: _value[3] }) : _value[3]) : ``) + ` `;
+ }
+
+ if (/^spares/g.test(pool.status.config.tier.nametier0)) { //Checksum
+ if (_value[4]) {
+ pool.status.disks.disk.messages.push(_value[4]);
+ }
+
+ pool.status.config.output += ` `;
+ } else {
+ pool.status.config.output += `` + (_value[4] ? `Checksum: ` + (zfsmanager.configuration.zfs.status.errorcolors ? FnStatusErrorColors({ count: _value[4] }) : _value[4]) : ``) + ` `;
+ }
+
+ for (let i = 5; i < _value.length; i++) { //Collect messages
+ if (_value[i]) {
+ pool.status.disks.disk.messages.push(_value[i]);
+ }
+ }
+
+ pool.status.disks.disk.messages = pool.status.disks.disk.messages.join(" "); //Join Messages for output
+
+ if (pool.status.config.disk && /\(trim unsupported\)/gi.test(pool.status.disks.disk.messages)) {
+ pool.status.disks.disk.trim.unsupported = true;
+ pool.status.disks.trim.unsupportedcount++;
+ }
+
+ if (!zfsmanager.configuration.zfs.status.trimunsupported) {
+ pool.status.disks.disk.messages = pool.status.disks.disk.messages.replace(/\(trim unsupported\)/gi, "");
+ }
+ if (pool.status.config.tier.cache || pool.status.config.tier.spares) { //Cache and spare disks can not be trimmed
+ pool.status.disks.disk.messages = pool.status.disks.disk.messages.replace(/\(untrimmed\)/gi, "");
+ }
+
+ pool.status.config.replacement.messages = [
+ { pattern: /^\(/g, replacement: "" },
+ { pattern: /\)$/g, replacement: "" },
+ { pattern: / \(/g, replacement: ", " },
+ { pattern: /\),/g, replacement: "," },
+ { pattern: /\) /g, replacement: " " }
+ ];
+
+ pool.status.config.output += `Message: ` + pool.status.config.replacement.messages.reduce((m, r) => m.replace(r.pattern, r.replacement), pool.status.disks.disk.messages) + ` `; //Message
+
+ if (pool.status.config.disk) {
+ if (/trimmed, started|trimmed started/i.test(pool.status.disks.disk.messages)) {
+ pool.status.disks.disk.trim.started = true;
+
+ if (!pool.status.trim.started) { //Storage pool contains a disk with TRIM started
+ pool.status.trim.started = true;
+ }
+ } else if (/trimmed, suspended|trimmed suspended/i.test(pool.status.disks.disk.messages)) {
+ pool.status.disks.disk.trim.suspended = true;
+
+ if (!pool.status.trim.suspended) { //Storage pool contains a disk with TRIM suspended
+ pool.status.trim.suspended = true;
+ }
+ }
+ }
+
+ pool.status.config.output += `Product: `; //Product
+
+ if (pool.status.config.disk) {
+ disks.lsblk.blockdevices.forEach((__value, __index) => {
+ if (__value.type == "disk") {
+ if (pool.status.disks.disk.upath.replace(/^\/dev\//gi, "") == __value.name || "nvme-" + __value.wwn == _value[0] || "wwn-" + __value.wwn == _value[0]) {
+ if (__value.rota == 0 || __value.rota === "false") {
+ pool.status.disks.disk.ssd = true;
+
+ if (!pool.status.ssd) { //Storage pool contains an SSD
+ pool.status.disks.ssd = true;
+ }
+ }
+
+ pool.status.config.output += FnFormatBytes({ base2: zfsmanager.configuration.disks.base2, decimals: 2, value: __value.size }) + " " + __value.model + (__value.serial ? " (" + __value.serial + ")" : "");
+ }
+ }
+ });
+ }
+
+ pool.status.config.output += ` `;
+
+ //Actions Menu
+ pool.status.config.actionsmenu = {
+ items: {
+ storagepool: [],
+ storagepooldivider: function () {
+ if (this.storagepool.length > 0 && (this.virtualdevice.length > 0 || this.disk.length > 0)) {
+ this.storagepool.push(this.divider);
+ }
+ },
+ virtualdevice: [],
+ virtualdevicedivider: function () {
+ if (this.virtualdevice.length > 0 && this.disk.length > 0) {
+ this.virtualdevice.push(this.divider);
+ }
+ },
+ disk: [],
+ divider: ` `
+ },
+ display: function () {
+ if ((this.items.virtualdevice.length + this.items.virtualdevice.length + this.items.disk.length) > 0 || pool.readonly) {
+ this.items.storagepooldivider();
+ this.items.virtualdevicedivider();
+ return this.header + this.items.storagepool.join("\n") + this.items.virtualdevice.join("\n") + this.items.disk.join("\n") + this.footer;
+ } else {
+ return "";
+ }
+ }
+ }
+ pool.status.config.actionsmenu.header = `
+
+
+
+
+
+
+ `;
+ pool.status.config.actionsmenu.register = {
+ storagepool: {
+ scrub: {},
+ trim: {}
+ },
+ virtualdevice: {},
+ disk: {
+ trim: {}
+ }
+ };
+
+ //Clear storage pool errors
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name) {
+ pool.status.config.actionsmenu.items.storagepool.push(`Clear Storage Pool Errors `);
+
+ pool.status.config.actionsmenu.register.storagepool.clear = true;
+ }
+
+ //Resilver Storage Pool
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.feature.resilver_defer) {
+ pool.status.config.actionsmenu.items.storagepool.push(`Resilver Storage Pool `);
+
+ pool.status.config.actionsmenu.register.storagepool.resilver = true;
+ }
+
+ //Start Storage Pool Scrub
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && !pool.status.scrub.started && !pool.status.scrub.paused) {
+ pool.status.config.actionsmenu.items.storagepool.push(`Scrub Storage Pool `);
+
+ pool.status.config.actionsmenu.register.storagepool.scrub.start = true;
+ }
+
+ //Resume Storage Pool Scrub
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.status.scrub.paused) {
+ pool.status.config.actionsmenu.items.storagepool.push(`Resume Storage Pool Scrub `);
+
+ pool.status.config.actionsmenu.register.storagepool.scrub.resume = true;
+ }
+
+ //Pause Storage Pool Scrub
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.status.scrub.started) {
+ pool.status.config.actionsmenu.items.storagepool.push(`Pause Storage Pool Scrub `);
+
+ pool.status.config.actionsmenu.register.storagepool.scrub.pause = true;
+ }
+
+ //Stop Storage Pool Scrub
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && (pool.status.scrub.started || pool.status.scrub.paused)) {
+ pool.status.config.actionsmenu.items.storagepool.push(`Stop Storage Pool Scrub `);
+
+ pool.status.config.actionsmenu.register.storagepool.scrub.stop = true;
+ }
+
+ //TRIM Storage Pool
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && !pool.status.trim.started && !pool.status.trim.suspended) {
+ pool.status.config.actionsmenu.items.storagepool.push(`TRIM Storage Pool `);
+
+ pool.status.config.actionsmenu.register.storagepool.trim.start = true;
+ }
+
+ //Resume Storage Pool TRIM
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.status.trim.suspended) {
+ pool.status.config.actionsmenu.items.storagepool.push(`Resume Storage Pool TRIM `);
+
+ pool.status.config.actionsmenu.register.storagepool.trim.resume = true;
+ }
+
+ //Suspend Storage Pool TRIM
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.status.trim.started) {
+ pool.status.config.actionsmenu.items.storagepool.push(`Suspend Storage Pool TRIM `);
+
+ pool.status.config.actionsmenu.register.storagepool.trim.suspend = true;
+ }
+
+ //Cancel Storage Pool TRIM
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && (pool.status.trim.started || pool.status.trim.suspended)) {
+ pool.status.config.actionsmenu.items.storagepool.push(`Cancel Storage Pool TRIM `);
+
+ pool.status.config.actionsmenu.register.storagepool.trim.cancel = true;
+ }
+
+ //Upgrade Storage Pool
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name && pool.status.upgrade) {
+ pool.status.config.actionsmenu.items.storagepool.push(`Upgrade Storage Pool `);
+
+ pool.status.config.actionsmenu.register.storagepool.upgrade = true;
+ }
+
+ //Regenerate Storage Pool GUID
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name) {
+ pool.status.config.actionsmenu.items.storagepool.push(`Regenerate Storage Pool GUID `);
+
+ pool.status.config.actionsmenu.register.storagepool.regenerateguid = true;
+ }
+
+ //Clear Virtual Device Errors
+ if (!pool.readonly && pool.status.config.tier.level > 0 && !pool.status.config.disk) {
+ pool.status.config.actionsmenu.items.virtualdevice.push(`Clear Virtual Device Errors `);
+
+ pool.status.config.actionsmenu.register.virtualdevice.clear = true;
+ }
+
+ //Add Virtual Device
+ if (!pool.readonly && pool.status.config.tier.level == 0 && pool.status.config.tier.count == 1 && _value[0] == pool.name) {
+ pool.status.config.actionsmenu.items.virtualdevice.push(`Add Virtual Device `);
+
+ pool.status.config.actionsmenu.register.virtualdevice.add = true;
+ }
+
+ //Remove Virtual Device
+ if (!pool.readonly && pool.status.config.tier.level == 1 && !pool.status.config.tier.replacing && (pool.feature.device_removal || pool.status.config.tier.spares)) {
+ pool.status.config.actionsmenu.items.virtualdevice.push(`Remove Virtual Device `);
+
+ pool.status.config.actionsmenu.register.virtualdevice.remove = true;
+ }
+
+ //Clear Disk Errors
+ if (!pool.readonly && pool.status.config.tier.level > 0 && !pool.status.config.tier.spares && pool.status.config.disk) {
+ pool.status.config.actionsmenu.items.disk.push(`Clear Disk Errors `);
+
+ pool.status.config.actionsmenu.register.disk.clear = true;
+ }
+
+ //Attach Disk: Disk and Mirror virtual devices only
+ if (!pool.readonly && pool.status.config.tier.level == 1 && !pool.status.config.tier.cache && !pool.status.config.tier.spares && (/^mirror-/g.test(_value[0]) || pool.status.config.disk)) {
+ pool.status.config.actionsmenu.items.disk.push(`Attach Disk `);
+
+ pool.status.config.actionsmenu.register.disk.attach = true;
+ }
+
+ //Detach Disk: Disk and Mirror virtual devices only
+ if (!pool.readonly && (pool.status.config.tier.level == 2 && /^spare-/g.test(_value[0]) == false || pool.status.config.tier.level == 3) && /^mirror-/g.test(pool.status.config.tier.nametier1) && pool.status.config.disk) {
+ pool.status.config.actionsmenu.items.disk.push(`Detach Disk `);
+
+ pool.status.config.actionsmenu.register.disk.detach = true;
+ }
+
+ if (!pool.readonly && pool.status.config.tier.level > 0 && pool.status.config.disk) {
+ //Online Disk / Offline Disk
+ if (_value[1] == "OFFLINE" || _value[1] == "UNAVAIL" || _value[1] == "FAULTED") {
+ pool.status.config.actionsmenu.items.disk.push(`Online Disk `);
+
+ pool.status.config.actionsmenu.register.disk.online = true;
+ } else if ((_value[1] == "ONLINE" || _value[1] == "DEGRADED") && (pool.status.config.tier.level > 1 || pool.status.config.tier.level == 1 && (pool.status.config.tier.cache || pool.status.config.tier.logs))) { //Do not show offline disk if virtual device is Disk in Pool and Dedup
+ pool.status.config.actionsmenu.items.disk.push(`Offline Disk `);
+
+ pool.status.config.actionsmenu.register.disk.offline = true;
+ }
+
+ //Replace Disk
+ if (!pool.status.config.tier.spares) {
+ pool.status.config.actionsmenu.items.disk.push(`Replace Disk `);
+
+ pool.status.config.actionsmenu.register.disk.replace = true;
+ }
+
+ if (pool.status.disks.disk.ssd && !pool.status.disks.disk.trim.unsupported && !pool.status.config.tier.cache && !pool.status.config.tier.spares) {
+ //TRIM Disk
+ if (!pool.status.disks.disk.trim.started && !pool.status.disks.disk.trim.suspended) {
+ pool.status.config.actionsmenu.items.disk.push(`TRIM Disk `);
+
+ pool.status.config.actionsmenu.register.disk.trim.start = true;
+ }
+
+ //Resume Disk TRIM
+ if (pool.status.disks.disk.trim.suspended) {
+ pool.status.config.actionsmenu.items.disk.push(`Resume Disk TRIM `);
+
+ pool.status.config.actionsmenu.register.disk.trim.resume = true;
+ }
+
+ //Suspend Disk TRIM
+ if (pool.status.disks.disk.trim.started) {
+ pool.status.config.actionsmenu.items.disk.push(`Suspend Disk TRIM `);
+
+ pool.status.config.actionsmenu.register.disk.trim.suspend = true;
+ }
+
+ //Cancel Disk TRIM
+ if (pool.status.disks.disk.trim.started || pool.status.disks.disk.trim.suspended) {
+ pool.status.config.actionsmenu.items.disk.push(`Cancel Disk TRIM `);
+
+ pool.status.config.actionsmenu.register.disk.trim.cancel = true;
+ }
+ }
+ }
+
+ pool.status.config.output += `
`;
+ pool.status.config.output += ``;
+ pool.status.config.output += ` `;
+
+ $("#tbody-storagepool-status-config-" + pool.id).append(pool.status.config.output);
+
+ //Register status modals
+ if (pool.status.config.actionsmenu.register.disk.attach) {
+ FnModalStatusDiskAttach({ name: pool.name, id: pool.id, status: { config: { items: { index: _index }, tier: { name: pool.status.config.tier.nametier0, dedup: pool.status.config.tier.dedup, logs: pool.status.config.tier.logs, special: pool.status.config.tier.special } } } }, { id: _value[0], disk: pool.status.config.disk });
+ }
+ if (pool.status.config.actionsmenu.register.disk.clear) {
+ FnModalStatusDiskClear({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
+ }
+ if (pool.status.config.actionsmenu.register.disk.detach) {
+ FnModalStatusDiskDetach({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
+ }
+ if (pool.status.config.actionsmenu.register.disk.offline) {
+ FnModalStatusDiskOffline({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
+ }
+ if (pool.status.config.actionsmenu.register.disk.online) {
+ FnModalStatusDiskOnline({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
+ }
+ if (pool.status.config.actionsmenu.register.disk.replace) {
+ FnModalStatusDiskReplace({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.clear) {
+ FnModalStatusStoragePoolClear({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.regenerateguid) {
+ FnModalStatusStoragePoolRegenerateGuid({ name: pool.name, id: pool.id, guid: pool.guid, status: { config: { items: { index: _index } } } });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.resilver) {
+ FnModalStatusStoragePoolResilver({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } }, resilver: { started: pool.status.resilver.started } } });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.trim.start) {
+ FnModalStatusStoragePoolTrimStart({ name: pool.name, id: pool.id, autotrim: pool.autotrim, status: { config: { items: { index: _index } } } });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.upgrade) {
+ FnModalStatusStoragePoolUpgrade({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } }, version: pool.version });
+ }
+ if (pool.status.config.actionsmenu.register.virtualdevice.add) {
+ FnModalStatusVirtualDeviceAdd({ name: pool.name, id: pool.id, feature: { allocation_classes: pool.feature.allocation_classes }, status: { config: { items: { index: _index } } } });
+ }
+ if (pool.status.config.actionsmenu.register.virtualdevice.clear) {
+ FnModalStatusVirtualDeviceClear({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
+ }
+ if (pool.status.config.actionsmenu.register.virtualdevice.remove) {
+ FnModalStatusVirtualDeviceRemove({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0], disk: pool.status.config.disk });
+ }
+
+ //Register status dynamics
+ if (pool.status.config.actionsmenu.register.disk.trim.cancel) {
+ FnDynamicStatusDiskTrimCancel({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
+ }
+ if (pool.status.config.actionsmenu.register.disk.trim.resume) {
+ FnDynamicStatusDiskTrimResume({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
+ }
+ if (pool.status.config.actionsmenu.register.disk.trim.start) {
+ FnModalStatusDiskTrimStart({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
+ }
+ if (pool.status.config.actionsmenu.register.disk.trim.suspend) {
+ FnDynamicStatusDiskTrimSuspend({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } }, { id: _value[0] });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.scrub.pause) {
+ FnDynamicStatusStoragePoolScrubPause({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.scrub.resume) {
+ FnDynamicStatusStoragePoolScrubResume({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.scrub.start) {
+ FnDynamicStatusStoragePoolScrubStart({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.scrub.stop) {
+ FnDynamicStatusStoragePoolScrubStop({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.trim.cancel) {
+ FnDynamicStatusStoragePoolTrimCancel({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.trim.resume) {
+ FnDynamicStatusStoragePoolTrimResume({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
+ }
+ if (pool.status.config.actionsmenu.register.storagepool.trim.suspend) {
+ FnDynamicStatusStoragePoolTrimSuspend({ name: pool.name, id: pool.id, status: { config: { items: { index: _index } } } });
+ }
+ });
+
+ //Hide Storage Pool TRIM actions menu items if there is no SSD in the storage pool or all disks are TRIM unsupported
+ if (!pool.status.disks.ssd || pool.status.disks.trim.unsupportedcount == pool.status.disks.count) {
+ $("#btn-storagepool-status-trim-start-0-" + pool.id).addClass("hidden");
+ $("#btn-storagepool-status-trim-resume-0-" + pool.id).addClass("hidden");
+ $("#btn-storagepool-status-trim-suspend-0-" + pool.id).addClass("hidden");
+ $("#btn-storagepool-status-trim-cancel-0-" + pool.id).addClass("hidden");
+ }
+
+ //Hide Remove Virtual Device actions menu item is there is only one in the storage pool
+ if (pool.status.config.virtualdevice.count < 2) {
+ $("[id^=btn-storagepool-status-virtualdevice-remove-][id$='" + pool.id + "'].pool-virtualdevice").addClass("hidden");
+ $("[id^=divider-storagepool-status-][id$=" + pool.id + "].pool-virtualdevice").addClass("hidden");
+ }
+
+ $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-status", "true");
+
+ $("#spinner-storagepool-status-" + pool.id).addClass("hidden");
+ $("#paneltitle-storagepool-status-" + pool.id).removeClass("hidden").text(FnDateTime());
+ $("#btn-storagepool-status-refresh-" + pool.id).prop("disabled", false);
+ $("#btn-storagepool-status-refresh-auto-" + pool.id).prop("disabled", false);
+
+ FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
+ FnCockpitElementsUpdate();
+}
+
+function FnStatusGetFail(pool = { name, id, status: { empty: true } }) {
+ if (pool.status.empty) {
+ $("#tbody-storagepool-status-messages-" + pool.id).empty();
+ $("#tbody-storagepool-status-config-" + pool.id).empty();
+ $("#tbody-storagepool-status-messages-" + pool.id).append(`Status not available `);
+ $("#modals-storagepool-status-" + pool.id).remove();
+ $("#dynamics-storagepool-status-" + pool.id).remove();
+
+ $("#tr-storagepool-" + pool.id).attr("data-pool-refresh-status", "true");
+
+ $("#spinner-storagepool-status-" + pool.id).addClass("hidden");
+ $("#paneltitle-storagepool-status-" + pool.id).removeClass("hidden").text(FnDateTime());
+ $("#btn-storagepool-status-refresh-" + pool.id).prop("disabled", false);
+ $("#btn-storagepool-status-refresh-auto-" + pool.id).prop("disabled", false);
+ }
+
+ FnStoragePoolSpinnerHide({ name: pool.name, id: pool.id });
+ FnCockpitElementsUpdate();
+}
+
+//#endregion
+
+//#region System
+
+function FnSystemHostIdGet(modal = { name, id }) {
+ let process = {
+ command: ["/bin/sh", "-c", "/bin/cat /etc/hostid 2> /dev/null && echo response true || echo response false"]
+ };
+
+ FnConsole.log[2]("System, Host ID, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "System, Host ID, Get:" }));
+
+ data = data.replace(/\n+/g, "").replace(/^.+response /, "").replace("response ", "");
+
+ if (data == "false") {
+ if (modal.name) {
+ if ($("#switch-" + modal.name + "-multihost-" + modal.id + " input").prop("checked")) {
+ $("#btnspan-" + modal.name + "-hostid-" + modal.id).text("Use Lib C Generated Host ID").attr("data-field-value", "libc");
+ $("#dropdown-" + modal.name + "-hostid-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-hostid-" + modal.id + " li[value='libc']").addClass("active");
+
+ $("#controllabel-" + modal.name + "-hostid-" + modal.id).removeClass("hidden");
+ $("#validationwrapper-" + modal.name + "-hostid-" + modal.id).removeClass("hidden");
+ } else {
+ $("#btnspan-" + modal.name + "-hostid-" + modal.id).text("Use Lib C Generated Host ID").attr("data-field-value", "missing");
+ $("#dropdown-" + modal.name + "-hostid-" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-" + modal.name + "-hostid-" + modal.id + " li[value='libc']").addClass("active");
+ }
+ }
+
+ FnConsole.warn("System, Host ID, Get: Warning, Message: Host ID does not exist");
+ } else {
+ FnConsole.log[1]("System, Host ID, Get: Success");
+ }
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("System, Host ID, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnSystemHostIdSet(system = { hostid }) {
+ let process = {
+ command: ["/bin/sh", "-c", "[ -x /usr/" + (/Debian/.test(zfsmanager.system.operatingsystem) ? "s" : "") + "bin/zgenhostid ] && /usr/" + (/Debian/.test(zfsmanager.system.operatingsystem) ? "s" : "") + "bin/zgenhostid" + (system.hostid ? " " + system.hostid : "") + " || zgenhostid " + (system.hostid ? " " + system.hostid : "")]
+ };
+
+ FnConsole.log[2]("System, Host ID, Set: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "System Host ID successfully configured", description: null, breakword: false }, { name: "system-hostid-set", id: null, timeout: 4 });
+
+ FnConsole.log[1]("System, Host ID, Set: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("System, Host ID, Set: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnSystemNfsVersionGet(modal = { alert: { id } }) {
+ let process = {
+ command: ["/usr/sbin/nfsstat", "--version"]
+ };
+
+ FnConsole.log[2]("System, NFS, Version, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "System, NFS, Version, Get:" }));
+
+ modal.alert.id.addClass("hidden");
+
+ FnConsole.log[1]("System, NFS, Version, Get: Success");
+ })
+ .fail(function () {
+ modal.alert.id.removeClass("hidden");
+
+ FnConsole.warn("System, NFS, Version, Get: Failed, Message: NFS is not installed.");
+ });
+}
+
+function FnSystemOperatingSystemGet() {
+ let process = {
+ command: ["/bin/sh", "-c", "/usr/bin/hostnamectl status | /bin/grep 'Operating System'"]
+ };
+
+ FnConsole.log[2]("System, Operating System, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "System, Operating System, Get:" }));
+
+ data = data.replace(/\n+/g, "").replace(/^(?: +)Operating System: /, "");
+
+ if (data) {
+ zfsmanager.system.operatingsystem = data;
+ }
+
+ FnConsole.log[2]("System, Operating System, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("System, Operating System, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+//#endregion
+
+//#region Disks
+
+function FnDisksAvailableGet(modal = { name, id, default: true }) {
+ disks = {
+ attached: [],
+ id: {
+ device: [],
+ path: [],
+ vdev: []
+ },
+ importable: [],
+ importableconfig: [],
+ importableconfigok: false,
+ storagepools: [],
+ storagepoolsconfig: []
+
+ };
+ modal.id = (modal.id ? "-" + modal.id : "");
+
+ $("#listgroup-" + modal.name + modal.id).empty();
+ $("#listgroup-" + modal.name + modal.id).append(`
`);
+
+ FnDisksStoragePoolsAttachedGet({ name: null, id: null }, { id: { blockdevice: true } })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Disks, Storage Pools, Attached, Get:" }));
+
+ disks.storagepools = data.replace(/\n\t+/g, "[TAB1]").split(/\n/g).filter(v => v);
+
+ disks.storagepools.forEach((_value, _index) => {
+ if (/\[TAB1\]NAME/g.test(_value)) { //Config header row
+ _value = _value.split("upath").slice(1).join("."); //Remove config header row (and any previous text if exists)
+
+ if (new RegExp("^\\[TAB1\\]").test(_value)) { //Confirm config rows
+ _value.split("[TAB1]").filter(v => v && disks.storagepoolsconfig.push(v));
+ }
+ }
+ });
+
+ disks.storagepoolsconfig.forEach((_value, _index) => {
+ let config = {
+ disk: {
+ upath: ""
+ },
+ tier: {
+ level: (_value.match(/^\s*/g)[0].length / 2)
+ }
+ };
+
+ _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
+
+ if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[5])) { //upath
+ config.disk.upath = _value[5];
+ } else if (!$.isNumeric(_value[0]) && _value[5] != "was") { //upath appears after error messages and before trim messages
+ for (let i = 5; i < _value.length; i++) {
+ if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[i])) {
+ config.disk.upath = _value[i];
+ }
+ }
+ }
+
+ if (config.tier.level > 0) {
+ if (/^\/dev\/nvme|^\/dev\/sd/gi.test(config.disk.upath)) { //Block Device via upath
+ disks.attached.push(config.disk.upath.replace(/^\/dev\//gi, ""));
+ } else if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[0])) { //Block Device
+ if (/^\/dev\/nvme\d+n\d+p\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/p\d+$/, ""));
+ } else if (/^\/dev\/sd.*\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/\d+$/, ""));
+ } else {
+ disks.attached.push(_value[0]);
+ }
+ } else if (/^nvme-nvme/gi.test(_value[0]) || /^wwn-/gi.test(_value[0])) { //WWN
+ if (/^nvme-nvme.*-part\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/-part\d+$/, ""));
+ } else if (/^wwn-.*-part\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/-part\d+$/, ""));
+ } else {
+ disks.attached.push(_value[0]);
+ }
+ }
+ }
+ });
+
+ disks.attached.sort();
+
+ FnDisksStoragePoolsImportableAttachedGet()
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Disks, Storage Pools, Importable, Attached, Get:" }));
+
+ disks.importable = _data.replace(/\n\t+/g, "[TAB1]").split(/\n/g).filter(v => v);
+
+ disks.importable.forEach((_value, _index) => {
+ if (/config:/g.test(_value)) { //Config header row
+ disks.importableconfigok = true;
+ }
+
+ if (new RegExp("^\\[TAB1\\]").test(_value) && disks.importableconfigok) { //Confirm config rows
+ _value.split("[TAB1]").filter(v => v && disks.importableconfig.push(v));
+ }
+ });
+
+ disks.importableconfig.forEach((_value, _index) => {
+ let config = {
+ tier: {
+ level: (_value.match(/^\s*/g)[0].length / 2)
+ }
+ };
+
+ _value = _value.replace(/ +/g, "\u22C5").replace(/^\u22C5/, "").split("\u22C5").filter(v => v);
+
+ if (config.tier.level > 0) {
+ if (/^nvme|^sd/gi.test(_value[0])) { //Block Device
+ if (/^nvme\d+n\d+p\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/p\d+$/, ""));
+ } else if (/^sd.*\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/\d+$/, ""));
+ } else {
+ disks.attached.push(_value[0]);
+ }
+ } else if (/^\/dev\/nvme|^\/dev\/sd/gi.test(_value[0])) { //Block Device
+ if (/^\/dev\/nvme\d+n\d+p\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/p\d+$/, ""));
+ } else if (/^\/dev\/sd.*\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/^\/dev\//gi, "").replace(/\d+$/, ""));
+ } else {
+ disks.attached.push(_value[0]);
+ }
+ } else if (/^nvme-nvme/gi.test(_value[0]) || /^wwn-/gi.test(_value[0])) { //WWN
+ if (/^nvme-nvme.*-part\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/-part\d+$/, ""));
+ } else if (/^wwn-.*-part\d+$/gi.test(_value[0])) {
+ disks.attached.push(_value[0].replace(/-part\d+$/, ""));
+ } else {
+ disks.attached.push(_value[0]);
+ }
+ }
+ }
+ });
+
+ disks.attached.sort();
+
+ FnDisksLsblkGet({ sizeraw: true })
+ .done(function (__data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: __data, message: "Disks, Lsblk, Get:" }));
+
+ disks.lsblkjson = __data;
+
+ FnDisksBlkidGet()
+ .done(function (___data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: ___data, message: "Disks, Blkid, Get:" }));
+
+ let replacement = {
+ regexp: [
+ { pattern: /"/g, replacement: "" },
+ { pattern: /: LABEL=/g, replacement: ",LABEL=" },
+ { pattern: / UUID=/g, replacement: ",UUID=" },
+ { pattern: / UUID_SUB=/g, replacement: ",UUID_SUB=" },
+ { pattern: / TYPE=/g, replacement: ",TYPE=" },
+ { pattern: / PARTLABEL=/g, replacement: ",PARTLABEL=" },
+ { pattern: / PARTUUID=/g, replacement: ",PARTUUID=" }
+ ]
+ };
+
+ disks.blkid = replacement.regexp.reduce((d, r) => d.replace(r.pattern, r.replacement), ___data).split(/\n/g).filter(v => v);
+
+ FnDisksIdentifierDiskGet()
+ .done(function (____data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: ____data, message: "Disks, Identifier, Disk / WWN, Get:" }));
+
+ disks.id.device = ____data.replace(/\t+/g, "\u22C5").replace(/..\/..\//g, "").split(/\n/g).filter(v => v && v != "\u22C5");
+
+ FnDisksIdentifierHardwarePathGet()
+ .done(function (_____data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _____data, message: "Disks, Identifier, Hardware Path, Get:" }));
+
+ disks.id.path = _____data.replace(/\t+/g, "\u22C5").replace(/..\/..\//g, "").split(/\n/g).filter(v => v && v != "\u22C5");
+
+ FnDisksIdentifierVirtualDeviceMappingGet()
+ .done(function (______data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: ______data, message: "Disks, Identifier, Virtual Device Mapping, Get:" }));
+
+ disks.id.vdev = ______data.replace(/\t+/g, "\u22C5").replace(/..\/..\//g, "").split(/\n/g).filter(v => v && v != "\u22C5");
+
+ FnDisksAvailableGetCommand({ attached: disks.attached, blkid: disks.blkid, id: { device: disks.id.device, path: disks.id.path, vdev: disks.id.vdev }, lsblkjson: disks.lsblkjson }, { name: modal.name, id: modal.id, default: modal.default });
+ })
+ .fail(function (______message, ______data) {
+ FnConsole.warn("Disks, Available, Get: Failed, Message: " + (______data ? ______data : ______message));
+
+ FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: ______data, message: ______message });
+ });
+ })
+ .fail(function (_____message, _____data) {
+ FnConsole.warn("Disks, Available, Get: Failed, Message: " + (_____data ? _____data : _____message));
+
+ FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: _____data, message: _____message });
+ });
+ })
+ .fail(function (____message, ____data) {
+ FnConsole.warn("Disks, Available, Get: Failed, Message: " + (____data ? ____data : ____message));
+
+ FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: ____data, message: ____message });
+ });
+ })
+ .fail(function (___message, ___data) {
+ FnConsole.warn("Disks, Available, Get: Failed, Message: " + (___data ? ___data : ___message));
+
+ FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: ___data, message: ___message });
+ });
+ })
+ .fail(function (__message, __data) {
+ FnConsole.warn("Disks, Available, Get: Failed, Message: " + (__data ? __data : __message));
+
+ FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: __data, message: __message });
+ });
+ })
+ .fail(function (_message, _data) {
+ FnConsole.warn("Disks, Available, Get: Failed, Message: " + (_data ? _data : _message));
+
+ FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: _data, message: _message });
+ });
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Disks, Available, Get: Failed, Message: " + (data ? data : message));
+
+ FnDisksAvailableGetFail({ name: modal.name, id: modal.id }, { data: data, message: message });
+ });
+}
+
+function FnDisksAvailableGetCommand(disks = { attached: [], blkid: [], id: { device: [], path: [], vdev: [] }, lsblkjson }, modal = { name, id, default: true }) {
+ disks.lsblk = JSON.parse(disks.lsblkjson);
+ disks.regexp = {};
+
+ disks.lsblk.blockdevices.forEach((_value, _index) => {
+ if (_value.type == "disk") {
+ let disk = {
+ id: {
+ blockdevice: "",
+ disk: "",
+ path: "",
+ vdev: "",
+ wwn: ""
+ },
+ allow: true,
+ zfsmember: false,
+ warning: "",
+ warningicon: "",
+ };
+
+ disks.attached.forEach((__value, __index) => {
+ if (_value.name == __value || _value.wwn == __value || "nvme-" + _value.wwn == __value || "wwn-" + _value.wwn == __value) { //Do not allow if block device or WWN identifier match
+ disk.allow = false;
+ return;
+ }
+ });
+
+ if (_value.children && disk.allow) {
+ _value.children.forEach((__value, __index) => {
+ if (__value.mountpoint) { //Do not allow if partition of disk is mounted
+ disk.allow = false;
+ return;
+ }
+ });
+ }
+
+ if (disk.allow) {
+ disks.blkid.forEach((__value, __index) => {
+ disks.regexp.name = new RegExp("^\/dev\/" + _value.name, "gi");
+
+ if (disks.regexp.name.test(__value)) {
+ if (/,TYPE=zfs_member/gi.test(__value)) {
+ disk.zfsmember = true;
+ return;
+ }
+ }
+ });
+
+ if (disk.zfsmember) {
+ disk.warningicon = ` `;
+
+ $("#helpblock-" + modal.name + "-zfsmemberwarning" + modal.id).html("One or more disks used to be a member of a Storage Pool." + disk.warningicon);
+ }
+
+ disk.id.blockdevice = _value.name;
+
+ if (!_value.wwn) {
+ disk.id.wwn = "";
+ disk.warning = "One or more disks is missing a WWN identifier.";
+
+ $("#helpblock-" + modal.name + "-identifierwarning" + modal.id).removeClass("hidden").text(disk.warning);
+ } else {
+ if (/^nvme/gi.test(_value.wwn)) {
+ disk.id.wwn = "nvme-" + _value.wwn;
+ } else {
+ disk.id.wwn = "wwn-" + _value.wwn;
+ }
+ }
+
+ disks.id.device.forEach((_value, _index) => {
+ _value = _value.split("\u22C5");
+
+ if (_value[1] == disk.id.blockdevice) {
+ if (/^nvme-nvme|^wwn-/gi.test(_value[0])) {
+ return;
+ } else {
+ disk.id.disk = _value[0];
+ return;
+ }
+ }
+ });
+
+ disks.id.path.forEach((_value, _index) => {
+ _value = _value.split("\u22C5");
+
+ if (_value[1] == disk.id.blockdevice) {
+ disk.id.path = _value[0];
+
+ return;
+ }
+ });
+
+ disks.id.vdev.forEach((_value, _index) => {
+ _value = _value.split("\u22C5");
+
+ if (_value[1] == disk.id.blockdevice) {
+ disk.id.vdev = _value[0];
+
+ return;
+ }
+ });
+
+ disks.output = `
+
+
+
+
+ ` + FnFormatBytes({ base2: zfsmanager.configuration.disks.base2, decimals: 2, value: _value.size }) + " " + _value.model + (_value.serial ? " (" + _value.serial + ")" : "") + `
+ ` + (!disk.id.wwn ? "/dev/" + disk.id.blockdevice : disk.id.wwn) + `
+ Physical Sector Size: ` + FnFormatBytes({ base2: true, decimals: 0, value: _value["phy-sec"] }) + `
+
+ ` + disk.warningicon + `
+
+
+ `;
+
+ $("#listgroup-" + modal.name + modal.id).append(disks.output);
+ }
+ }
+ });
+
+ setTimeout(function () {
+ $("#spinner-" + modal.name + modal.id).remove();
+ $("#listgroup-" + modal.name + modal.id + " > li").removeClass("hidden");
+
+ if ($("#helpblock-" + modal.name + "-identifierwarning" + modal.id).text) {
+ $("#helpblock-" + modal.name + "-identifierwarning" + modal.id).removeClass("hidden");
+ }
+ if ($("#helpblock-" + modal.name + "-zfsmemberwarning" + modal.id).text()) {
+ $("#helpblock-" + modal.name + "-zfsmemberwarning" + modal.id).removeClass("hidden");
+ }
+
+ if ($("#listgroup-" + modal.name + modal.id + " > li").length == 1 && modal.default) { //Change Virtual Device dropdown to Disk if there is only 1 disk available
+ if (modal.name == "storagepools-create-disks") {
+ $("#btnspan-storagepools-create-virtualdevice").text("Disk").attr("data-field-value", "disk");
+ $("#dropdown-storagepools-create-virtualdevice li").siblings().removeClass("active");
+ $("#dropdown-storagepools-create-virtualdevice li[value='disk']").addClass("active");
+ } else if (modal.name == "storagepool-status-virtualdevice-add-disks") {
+ $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice" + modal.id).text("Disk").attr("data-field-value", "disk");
+ $("#dropdown-storagepool-status-virtualdevice-add-virtualdevice" + modal.id + " li").siblings().removeClass("active");
+ $("#dropdown-storagepool-status-virtualdevice-add-virtualdevice" + modal.id + " li[value='disk']").addClass("active");
+ }
+ }
+
+ if ($("#listgroup-" + modal.name + modal.id + " > li").length == 0) {
+ disks.output = `
+
+
+ No available disks found.
+
+
+ `;
+
+ $("#listgroup-" + modal.name + modal.id).append(disks.output);
+ }
+ }, 200);
+
+ FnConsole.log[1]("Disks, Available, Get: Success");
+}
+
+function FnDisksAvailableGetFail(modal = { name, id }, process = { data, message }) {
+ setTimeout(function () {
+ $("#spinner-" + modal.name + modal.id).remove();
+ $("#listgroup-" + modal.name + modal.id + " > li").removeClass("hidden");
+
+ if ($("#listgroup-" + modal.name + modal.id + " > li").length == 0) {
+ let disks = {
+ output: ""
+ };
+
+ disks.output = `
+
+
+ No available disks found.
+
+
+ `;
+
+ $("#listgroup-" + modal.name + modal.id).append(disks.output);
+ }
+ }, 200);
+}
+
+function FnDisksBlkidGet() {
+ let process = {
+ command: ["/bin/sh", "-c", "/sbin/blkid -o full | /bin/grep -E '/dev/nvme\|/dev/sd'"]
+ };
+
+ FnConsole.log[2]("Disks, Blkid, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[2]("Disks, Blkid, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Disks, Blkid, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnDisksIdentifierDiskGet() {
+ let process = {
+ command: ["/bin/sh", "-c", `ls -lF /dev/disk/by-id | awk '{ print $9"\t"$11 }'`]
+ };
+
+ FnConsole.log[2]("Disks, Identifier, Disk / WWN, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[2]("Disks, Identifier, Disk / WWN, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Disks, Identifier, Disk / WWN, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnDisksIdentifierHardwarePathGet() {
+ let process = {
+ command: ["/bin/sh", "-c", `ls -lF /dev/disk/by-path | awk '{ print $9"\t"$11 }'`]
+ };
+
+ FnConsole.log[2]("Disks, Identifier, Hardware Path, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[2]("Disks, Identifier, Hardware Path, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Disks, Identifier, Hardware Path, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnDisksIdentifierVirtualDeviceMappingGet() {
+ let process = {
+ command: ["/bin/sh", "-c", `[ -d /dev/disk/by-vdev ] && ls -lF /dev/disk/by-vdev | awk '{ print $9"\t"$11 }' || printf ""`]
+ };
+
+ FnConsole.log[2]("Disks, Identifier, Virtual Device Mapping, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[2]("Disks, Identifier, Virtual Device Mapping, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Disks, Identifier, Virtual Device Mapping, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnDisksLsblkGet(disks = { sizeraw: true }) {
+ let process = {
+ command: ["/bin/sh", "-c", "/bin/lsblk -o label,model,mountpoint,name,partuuid,phy-sec,rota,serial,size,type,uuid,vendor,wwn -J" + (disks.sizeraw ? " -b" : "")]
+ };
+
+ FnConsole.log[2]("Disks, Lsblk, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function () {
+ FnConsole.log[2]("Disks, Lsblk, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Disks, Lsblk, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnDisksStoragePoolsAttachedGet(pool = { name, id }, disks = { id: { blockdevice: true } }) {
+ let process = {
+ command: ["/bin/sh", "-c", ((zfsmanager.user.name == "root" || !zfsmanager.user.name) ? "ZPOOL_SCRIPTS_AS_ROOT=1 " : "") + "/sbin/zpool status -P " + (disks.id.blockdevice ? "-L " : "") + "-c upath" + (pool.name ? ` "` + pool.name + `"` : "")]
+ };
+
+ FnConsole.log[2]("Disks, Storage Pools, Attached, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function () {
+ FnConsole.log[2]("Disks, Storage Pools, Attached, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Disks, Storage Pools, Attached, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnDisksStoragePoolsImportableAttachedGet() {
+ let process = {
+ command: ["/sbin/zpool", "import", "-d", "/dev"]
+ };
+
+ FnConsole.log[2]("Disks, Storage Pools, Importable, Attached, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[2]("Disks, Storage Pools, Importable, Attached, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Disks, Storage Pools, Importable, Attached, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnDisksStoragePoolsImportableGet() {
+ let process = {
+ command: ["/bin/sh", "-c", "/sbin/zpool import | /bin/grep -E 'pool:\| id:' | tr '\\\n' ','"]
+ };
+
+ FnConsole.log[2]("Disks, Importable Storage Pools, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[2]("Disks, Importable Storage Pools, Get: Success");
+ })
+ .fail(function (message, data) {
+ if (/no pools available to import/gi.test(data) == false) {
+ FnConsole.warn("Disks, Importable Storage Pools, Get: Failed, Message: " + (data ? data : message));
+ }
+ });
+}
+
+//#endregion
+
+//#region Samba
+
+function FnSambaConfigurationReload() {
+ let process = {
+ command: ["/usr/bin/smbcontrol", "all", "reload-config"]
+ };
+
+ FnConsole.log[2]("Samba, Configuration, Reload: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Samba, Configuration, Reload: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, Configuration, Reload: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaConfigurationZfsSharesEnable() {
+ let process = {
+ command: ["/bin/sh", "-c", `[ -s /etc/samba/smb.conf ] && /usr/bin/awk -v k='\n\t# COCKPIT ZFS MANAGER\n\t# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION\n\tinclude = /etc/cockpit/zfs/shares.conf\n\tinclude = /run/cockpit/zfs/shares.conf\n' '($1=="[global]"||x&&/^\\[/)&&!(x=!x){print k} END{if(x)print k}1' /etc/samba/smb.conf > /etc/samba/smb.tmp && /bin/mv -f /etc/samba/smb.tmp /etc/samba/smb.conf \|\| { echo '/etc/samba/smb.conf file does not exist or is empty.' ; exit 1; }`]
+ };
+
+ FnConsole.log[2]("Samba, Configuration, ZFS Shares, Enable: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Samba, Configuration, ZFS Shares, Enable: Success");
+
+ FnSambaConfigurationReload();
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, Configuration, ZFS Shares, Enable: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaConfigurationZfsSharesGet() {
+ let process = {
+ command: ["/bin/sh", "-c", "/bin/grep -Pzoq '(?s)include = /etc/cockpit/zfs/shares.conf.*/run/cockpit/zfs/shares.conf' /etc/samba/smb.conf && echo true || echo false"]
+ };
+
+ FnConsole.log[2]("Samba, Configuration, ZFS Shares, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Configuration, ZFS Shares, Get:" }));
+
+ data = data.replace(/\n+/g, "");
+
+ if (data == "false") {
+ FnSambaConfigurationZfsSharesEnable();
+ } else if (data == "true") {
+ FnConsole.log[2]("Samba, Configuration, ZFS Shares, Get: Success");
+ } else {
+ FnConsole.warn("Samba, Configuration, ZFS Shares, Get: Failed, Message: " + (data ? data : message));
+ }
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, Configuration, ZFS Shares, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaManage() {
+ if (zfsmanager.user.admin) {
+ FnSambaConfigurationZfsSharesGet();
+ }
+}
+
+function FnSambaRestart() {
+ let process = {
+ command: ["/bin/systemctl", "restart"]
+ };
+
+ if (/Debian|Ubuntu/i.test(zfsmanager.system.operatingsystem)) {
+ process.command.splice(2, 0, "smbd");
+ } else {
+ process.command.splice(2, 0, "smb");
+ }
+
+ FnConsole.log[2]("Samba, Restart: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Samba, Restart: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, Restart: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaShareDestroy(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id }, samba = { restart: false }, display = { silent: false }) {
+ let process = {
+ promise: cockpit.defer()
+ };
+
+ FnSambaZfsShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id })
+ .done(function () {
+ FnSambaZfsSharesConfigurationReload()
+ .done(function () {
+ setTimeout(function () {
+ if (samba.restart) {
+ FnSambaRestart()
+ .finally(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba share successfully destroyed", description: filesystem.name, breakword: false }, { name: "samba-destroy", id: filesystem.id, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, Share, Destroy: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ process.promise.resolve();
+ });
+ } else {
+ FnSambaConfigurationReload()
+ .finally(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba share successfully destroyed", description: filesystem.name, breakword: false }, { name: "samba-destroy", id: filesystem.id, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, Share, Destroy: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ process.promise.resolve();
+ });
+ }
+ }, 500);
+ })
+ })
+ .fail(function () {
+ process.promise.resolve();
+ });
+
+ return process.promise.promise();
+}
+
+function FnSambaShareDisable(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id }, samba = { restart: false }, display = { modal: true, silent: false }) {
+ if (display.modal) {
+ $("#spinner-storagepool-filesystem-samba-disable-" + filesystem.id + " span").text("Disabling Samba share...");
+ }
+
+ if (!pool.readonly) {
+ FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id })
+ .done(function () {
+ FnSambaShareDisableCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: display.modal, silent: display.silent });
+ })
+ .fail(function (message, data) {
+ if (/property may be set/gi.test(data)) { //False error is generated when configuring filesystem
+ FnSambaShareDisableCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: display.modal, silent: display.silent });
+ } else {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "danger", title: "Samba share could not be disabled", description: filesystem.name, breakword: false }, { name: "samba-disable", id: filesystem.id, timeout: 4 });
+ }
+
+ if (display.modal) {
+ $("#modal-storagepool-filesystem-samba-disable-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
+ }, 200);
+ }
+ }
+ });
+ } else {
+ FnSambaShareDisableCommand({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id }, { restart: samba.restart }, { modal: display.modal, silent: display.silent });
+ }
+}
+
+function FnSambaShareDisableCommand(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id }, samba = { restart: false }, display = { modal: true, silent: false }) {
+ FnSambaZfsShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id })
+ .done(function () {
+ FnSambaZfsSharesConfigurationReload()
+ .done(function () {
+ setTimeout(function () {
+ if (samba.restart) {
+ FnSambaRestart()
+ .finally(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba share successfully disabled", description: filesystem.name, breakword: false }, { name: "samba-disable", id: filesystem.id, timeout: 4 });
+ }
+
+ if (display.modal) {
+ $("#modal-storagepool-filesystem-samba-disable-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
+ }, 200);
+ }
+ });
+ } else {
+ FnSambaConfigurationReload()
+ .finally(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba share successfully disabled", description: filesystem.name, breakword: false }, { name: "samba-diable", id: filesystem.id, timeout: 4 });
+ }
+
+ if (display.modal) {
+ $("#modal-storagepool-filesystem-samba-disable-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
+ }, 200);
+ }
+ });
+ }
+ }, 500);
+ })
+ .fail(function () {
+ FnFileSystemShareSmbEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ });
+ })
+ .fail(function () {
+ FnFileSystemShareSmbEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ });
+}
+
+function FnSambaShareEnable(pool = { name, id, readonly: false }, filesystem = { name, id, mounted: false, mountpoint }, samba = { share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }, display = { silent: false }) {
+ let modal = {
+ hide: true
+ };
+
+ $("#spinner-storagepool-filesystem-samba-enable-" + filesystem.id + " span").text("Enabling Samba share...");
+
+ FnSambaShareNamesGet({ zfsonly: false })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Share, Names, Get:" }));
+
+ samba.share.nameunique = true;
+ samba.share.errormessage = "Share name is already in use.";
+
+ if (data.replace(/\n/g, "") != "$empty") { //$empty response is received if share names list is empty
+ samba.shares = data.split(/\n/g).filter(v => v);
+
+ samba.shares.forEach((_value, _index) => {
+ if (_value.replace(/^\[/, "").replace(/\]$/, "").toLowerCase() == samba.share.name.toLowerCase() + (samba.share.administrative ? "$" : "")) {
+ samba.share.nameunique = false;
+
+ return;
+ }
+ });
+ }
+
+ if (/^global$|^homes$|^printers$/gi.test(samba.share.name)) {
+ samba.share.nameunique = false;
+ samba.share.errormessage = "Share name can not be a restricted name.";
+ }
+
+ if (!samba.share.nameunique) {
+ modal.hide = false;
+
+ $("#validationwrapper-storagepool-filesystem-samba-enable-name-" + filesystem.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystem-samba-enable-name-" + filesystem.id).addClass("has-error").removeClass("hidden").text(samba.share.errormessage);
+ $("#input-storagepool-filesystem-samba-enable-name-" + filesystem.id).focus();
+
+ if (!modal.hide) {
+ $("#spinner-storagepool-filesystem-samba-enable-" + filesystem.id).addClass("hidden");
+ $("#spinner-storagepool-filesystem-samba-enable-" + filesystem.id + " span").text("");
+ $("#btn-storagepool-filesystem-samba-enable-apply-" + filesystem.id).prop("disabled", false);
+
+ FnConsole.warn("Samba, Share, Enable: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + samba.share.errormessage);
+ }
+ } else {
+ FnSambaShareEnableCommand({ name: pool.name, id: pool.id, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: false, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: false }, { reload: true, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { refresh: true, silent: display.silent });
+
+ $("#modal-storagepool-filesystem-samba-enable-" + filesystem.id).modal("hide");
+ }
+ });
+}
+
+function FnSambaShareEnableAutoGenerateName(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, force: false, mounted: false, mountpoint, sharesmb: false }, samba = { reload: true }, display = { refresh: true, silent: false }) {
+ FnSambaShareNamesGet({ zfsonly: false })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Share, Names, Get:" }));
+
+ samba.share = {
+ name: "",
+ nameunique: true,
+ temporary: (pool.altroot || pool.readonly ? true : false)
+ };;
+
+ if (data.replace(/\n/g, "") != "$empty") { //$empty response is received if share names list is empty
+ samba.shares = data.split(/\n/g).filter(v => v);
+
+ samba.shares.forEach((_value, _index) => {
+ if (_value.replace(/^\[/, "").replace(/\]$/, "").toLowerCase() == filesystem.name.replace(/^.*\/(.*)$/, "$1").toLowerCase()) {
+ samba.share.nameunique = false;
+
+ return;
+ }
+ });
+ }
+
+ if (/^global$|^homes$|^printers$/gi.test(samba.share.name)) {
+ samba.share.nameunique = false;
+ }
+
+ if (!samba.share.nameunique) {
+ samba.share.name = FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.name });
+
+ if (filesystem.name == pool.name) {
+ samba.share.name = "StoragePool-" + samba.share.name;
+ }
+
+ FnSambaShareEnableCommand({ name: pool.name, id: pool.id, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: false, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: filesystem.sharesmb }, { reload: samba.reload, share: { additional: [], administrative: false, browseable: true, guestok: false, name: samba.share.name, comment: null, readonly: null, temporary: samba.share.temporary } }, { refresh: display.refresh, silent: display.silent });
+ } else {
+ FnSambaShareEnableCommand({ name: pool.name, id: pool.id, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: false, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: filesystem.sharesmb }, { reload: samba.reload, share: { additional: [], administrative: false, browseable: true, guestok: false, name: null, comment: null, readonly: null, temporary: samba.share.temporary } }, { refresh: display.refresh, silent: display.silent });
+ }
+ });
+}
+
+function FnSambaShareEnableCommand(pool = { name, id, readonly: false }, filesystem = { name, force: false, id, mounted: false, mountpoint, sharesmb: false }, samba = { reload: true, share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }, display = { refresh: true, silent: false }) {
+ if (!pool.readonly && (!filesystem.sharesmb || filesystem.sharesmb && filesystem.force)) { //Force to disable inheritance
+ FnFileSystemShareSmbEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id })
+ .done(function () {
+ FnSambaShareEnableCommandFinally({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint }, { reload: samba.reload, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { refresh: display.refresh, silent: display.silent });
+ })
+ .fail(function (message, data) {
+ if (/property may be set/gi.test(data)) { //False error is generated when configuring filesystem
+ FnSambaShareEnableCommandFinally({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { refresh: display.refresh, silent: display.silent });
+ } else {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "danger", title: "Samba share could not be enabled", description: filesystem.name, breakword: false }, { name: "samba-enable", id: filesystem.id, timeout: 4 });
+ }
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
+ }, 200);
+ }
+ });
+ } else {
+ FnSambaShareEnableCommandFinally({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint }, { reload: samba.reload, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { refresh: display.refresh, silent: display.silent });
+ }
+}
+
+function FnSambaShareEnableCommandFinally(pool = { name, id }, filesystem = { name, id, mounted: false, mountpoint }, samba = { reload: true, share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }, display = { refresh: true, silent: false }) {
+ FnSambaZfsShareEnable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } })
+ .done(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba share successfully enabled", description: filesystem.name, breakword: false }, { name: "samba-enable", id: filesystem.id, timeout: 4 });
+ }
+
+ if (samba.reload) {
+ FnSambaZfsSharesConfigurationReload()
+ .done(function () {
+ setTimeout(function () {
+ FnSambaConfigurationReload()
+ .finally(function () {
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
+ }, 200);
+ }
+ });
+ }, 500);
+ })
+ .fail(function () {
+ FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ });
+ } else {
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
+ }, 200);
+ }
+ }
+ })
+ .fail(function () {
+ FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ });
+}
+
+function FnSambaShareEnableMountpointGet(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false }, display = { silent: false }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "mounted,mountpoint", "-t", "filesystem", filesystem.name]
+ };
+
+ FnConsole.log[2]("File Systems, Mountpoint, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "File Systems, Mountpoint, Get:" }));
+
+ data = data.replace(/\n/g, "").replace(/\t/g, "\u22C5").split("\u22C5");
+
+ filesystem.mounted = data[0];
+ filesystem.mountpoint = data[1];
+
+ if (/^\//.test(filesystem.mountpoint)) {
+ FnConsole.log[1]("File Systems, Mountpoint, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ FnSambaShareEnableAutoGenerateName({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: false, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: filesystem.sharesmb }, { reload: true }, { refresh: true, silent: display.silent });
+ } else {
+ FnConsole.warn("File Systems, Mountpoint, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ }
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("File Systems, Mountpoint, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+
+ FnFileSystemShareSmbDisable({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id });
+ });
+}
+
+function FnSambaShareNamesGet(samba = { zfsonly: false }) {
+ let process = {
+ command: ["/bin/sh", "-c", `/bin/cat /etc/cockpit/zfs/shares/*.conf /run/cockpit/zfs/shares/*.conf ` + (!samba.zfsonly ? `/etc/samba/smb.conf ` : ``) + `2> /dev/null | /bin/grep "^\\\[.*\\\]$" || echo \\\$empty`]
+ };
+
+ FnConsole.log[2]("Samba, Share, Names, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function () {
+ FnConsole.log[1]("Samba, Share, Names, Get: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, Share, Names, Get: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaSharesDestroy(pool = { name, id, altroot: false, readonly: false }, filesystems = { id: [] }, samba = { restart: false }, display = { silent: true }) {
+ let process = {
+ promise: cockpit.defer()
+ };
+ let promise = Promise.resolve();
+
+ FnConsole.log[1]("Samba, Shares, Destroy: In Progress, Pool: " + pool.name);
+
+ if (filesystems.id.length > 0) {
+ filesystems.id.forEach((_value, _index) => {
+ let filesystem = {
+ properties: _value.split(/\t/g).filter(v => v)
+ };
+
+ filesystem.name = filesystem.properties[0];
+ filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0], attribute: true });
+ filesystem.mounted = filesystem.properties[1];
+ filesystem.mountpoint = filesystem.properties[2];
+ filesystem.sharesmb = filesystem.properties[3];
+
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ if (_index <= (filesystems.id.length - 1)) {
+ if (filesystem.sharesmb == "on") {
+ FnSambaZfsShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id });
+ }
+ }
+
+ if (_index == (filesystems.id.length - 1)) {
+ setTimeout(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba shares successfully destroyed", description: pool.name, breakword: false }, { name: "samba-destroy", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, Shares, Destroy: Success, Pool: " + pool.name);
+
+ FnSambaZfsSharesConfigurationReload()
+ .done(function () {
+ setTimeout(function () {
+ if (samba.restart) {
+ FnSambaRestart()
+ .finally(function () {
+ process.promise.resolve();
+ });
+ } else {
+ FnSambaConfigurationReload()
+ .finally(function () {
+ process.promise.resolve();
+ });
+ }
+ }, 300);
+ });
+ }, 500);
+ }
+
+ resolve();
+ }, 500)
+ ));
+ });
+ } else {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba shares successfully destroyed", description: pool.name, breakword: false }, { name: "samba-destroy", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, Shares, Destroy: Success, Pool: " + pool.name);
+
+ process.promise.resolve();
+ }
+
+ return process.promise.promise();
+}
+
+function FnSambaSharesDestroyAll(samba = { restart: false }, display = { silent: false }, modal = { name }) {
+ let process = {
+ command: ["/bin/sh", "-c", "echo '# COCKPIT ZFS MANAGER\n# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION' > /etc/cockpit/zfs/shares.conf && echo '# COCKPIT ZFS MANAGER\n# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION' > /run/cockpit/zfs/shares.conf && /bin/rm -rf /etc/cockpit/zfs/shares/*.conf && /bin/rm -rf /run/cockpit/zfs/shares/*.conf"],
+ promise: cockpit.defer()
+ };
+
+ FnConsole.log[1]("Samba, Shares, Destroy All: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ $("#spinner-" + modal.name + " span").text("Destroying Samba shares...");
+
+ cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba shares successfully destroyed", description: null, breakword: false }, { name: "samba-destroy-all", id: null, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, Shares, Destroy All: Success");
+
+ if (samba.restart) {
+ FnSambaRestart()
+ .finally(function () {
+ process.promise.resolve();
+ });
+ } else {
+ FnSambaConfigurationReload()
+ .finally(function () {
+ process.promise.resolve();
+ });
+ }
+ })
+ .fail(function (message, data) {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "danger", title: "Samba shares could not be destroyed", description: null, breakword: false }, { name: "samba-destroy-all", id: null, timeout: 4 });
+ }
+
+ FnConsole.warn("Samba, Shares, Destroy All: Failed, Message: " + (data ? data : message));
+
+ process.promise.resolve();
+ });
+
+ return process.promise.promise();
+}
+
+function FnSambaSharesEnable(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, force: false }, samba = { restart: false }, display = { refresh: false, silent: true }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name,mounted,mountpoint,sharesmb", "-r", "-t", "filesystem"],
+ promise: cockpit.defer()
+ };
+
+ if (filesystem.name) {
+ process.command.push(filesystem.name);
+ } else {
+ process.command.push(pool.name);
+ }
+
+ FnConsole.log[1]("Samba, Shares, Enable: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Shares, Enable:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+ let promise = Promise.resolve();
+
+ if (filesystems.id.length > 0) {
+ filesystems.id.forEach((_value, _index) => {
+ let filesystem = {
+ properties: _value.split(/\t/g).filter(v => v)
+ };
+
+ filesystem.name = filesystem.properties[0];
+ filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0], attribute: true });
+ filesystem.mounted = filesystem.properties[1];
+ filesystem.mountpoint = filesystem.properties[2];
+ filesystem.sharesmb = filesystem.properties[3];
+
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ if (_index <= (filesystems.id.length - 1)) {
+ if (filesystem.sharesmb == "on") {
+ FnSambaShareEnableAutoGenerateName({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: filesystem.force, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: true }, { reload: false }, { refresh: false, silent: true });
+ }
+ }
+
+ if (_index == (filesystems.id.length - 1)) {
+ setTimeout(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba shares successfully enabled", description: pool.name, breakword: false }, { name: "samba-enable", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, Shares, Enable: Success, Pool: " + pool.name);
+
+ FnSambaZfsSharesConfigurationReload()
+ .done(function () {
+ setTimeout(function () {
+ if (samba.restart) {
+ FnSambaRestart()
+ .finally(function () {
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ }
+
+ process.promise.resolve();
+ });
+ } else {
+ FnSambaConfigurationReload()
+ .finally(function () {
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ }
+
+ process.promise.resolve();
+ });
+ }
+ }, 300);
+ });
+ }, 500);
+ }
+
+ resolve();
+ }, 500)
+ ));
+ });
+ } else {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba shares successfully enabled", description: pool.name, breakword: false }, { name: "samba-enable", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, Shares, Enable: Success, Pool: " + pool.name);
+
+ process.promise.resolve();
+ }
+ })
+ .fail(function (message, data) {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "danger", title: "Samba shares could not enabled", description: pool.name, breakword: false }, { name: "samba-enable", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.warn("Samba, Shares, Enable: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ }
+
+ process.promise.resolve();
+ });
+
+ return process.promise.promise();
+}
+
+function FnSambaSharesEnableAll(samba = { restart: false }, display = { silent: false }, modal = { name }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name,mounted,mountpoint,sharesmb", "-r", "-t", "filesystem"],
+ promise: cockpit.defer()
+ };
+
+ FnConsole.log[1]("Samba, Shares, Enable All: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ FnStoragePoolsTemporaryGet()
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Storage Pools, Temporary, Get:" }));
+
+ $("#spinner-" + modal.name + " span").text("Disabling Samba share inheritance...");
+
+ FnFileSystemShareSmbInheritedDisable({ name: null, id: null, altroot: null }, { name: null }, { disable: false })
+ .finally(function () {
+ $("#spinner-" + modal.name + " span").text("Creating Samba shares...");
+
+ cockpit.spawn(process.command, { err: "out" })
+ .done(function (_data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: _data, message: "Samba, Shares, Enable All:" }));
+
+ let filesystems = {
+ id: _data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+ let promise = Promise.resolve();
+
+ if (filesystems.id.length > 0) {
+ filesystems.id.forEach((_value, _index) => {
+ let filesystem = {
+ properties: _value.split(/\t/g).filter(v => v)
+ };
+ let pool = {
+ name: filesystem.properties[0].replace(/\/.*$/, ""),
+ id: FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0].replace(/\/.*$/, ""), attribute: true })
+ };
+
+ filesystem.name = filesystem.properties[0];
+ filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0], attribute: true });
+ filesystem.mounted = filesystem.properties[1];
+ filesystem.mountpoint = filesystem.properties[2];
+ filesystem.sharesmb = filesystem.properties[3];
+
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ if (_index <= (filesystems.id.length - 1)) {
+ if (filesystem.sharesmb == "on") {
+
+ pool.properties = data.split(/\n/g).filter(v => v && new RegExp("^" + pool.name + "\t").test(v))[0].split(/\t/g).filter(v => v);
+
+ if (pool.properties[0] == pool.name) {
+ pool.altroot = (pool.properties[2] && pool.properties[2] != "-" ? true : false);
+ pool.readonly = (pool.properties[1].toLowerCase() == "on" ? true : false);
+
+ FnSambaShareEnableAutoGenerateName({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id, force: false, mounted: filesystem.mounted, mountpoint: filesystem.mountpoint, sharesmb: true }, { reload: false }, { refresh: false, silent: true });
+ }
+ }
+ }
+
+ if (_index == (filesystems.id.length - 1)) {
+ setTimeout(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba shares successfully enabled", description: null, breakword: false }, { name: "samba-enable-all", id: null, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, Shares, Enable All: Success");
+
+ FnSambaZfsSharesConfigurationReload()
+ .done(function () {
+ setTimeout(function () {
+ if (samba.restart) {
+ FnSambaRestart()
+ .finally(function () {
+ process.promise.resolve();
+ });
+ } else {
+ FnSambaConfigurationReload()
+ .finally(function () {
+ process.promise.resolve();
+ });
+ }
+ }, 300);
+ });
+ }, 500);
+ }
+
+ resolve();
+ }, 500)
+ ));
+ });
+ } else {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba shares successfully enabled", description: null, breakword: false }, { name: "samba-enable-all", id: null, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, Shares, Enable All: Success");
+
+ process.promise.resolve();
+ }
+ })
+ .fail(function (message, data) {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "danger", title: "Samba shares could not be enabled", description: null, breakword: false }, { name: "samba-enable-all", id: null, timeout: 4 });
+ }
+
+ FnConsole.warn("Samba, Shares, Enable All: Failed, Message: " + (data ? data : message));
+
+ process.promise.resolve();
+ });
+ });
+ })
+ .fail(function (message, data) {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "danger", title: "Samba shares could not be enabled", description: null, breakword: false }, { name: "samba-enable-all", id: null, timeout: 4 });
+ }
+
+ FnConsole.warn("Samba, Shares, Enable All: Failed, Message: " + (data ? data : message));
+
+ process.promise.resolve();
+ });
+
+ return process.promise.promise();
+}
+
+function FnSambaSharesGet(pool = { name, id }, filesystem = { name, clones: [] }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name,mounted,mountpoint,sharesmb", "-r", "-t", "filesystem"]
+ };
+
+ if (filesystem.name) {
+ process.command.push(filesystem.name);
+ } else if (filesystem.clones.length > 0) {
+ filesystem.clones.forEach(_value => _value && process.command.push(_value));
+ } else {
+ process.command.push(pool.name);
+ }
+
+ FnConsole.log[2]("Samba, Shares, Get: In Progress, Pool: " + pool.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function () {
+ FnConsole.log[1]("Samba, Shares, Get: Success, Pool: " + pool.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, Shares, Get: Failed, Pool: " + pool.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaSharesRename(pool = { name, id, altroot: false, readonly: false }, filesystems = { id: [], parent: { name, namenew } }, samba = { restart: false }, display = { silent: true }) {
+ let process = {
+ promise: cockpit.defer()
+ };
+ let promise = Promise.resolve();
+
+ FnConsole.log[1]("Samba, Shares, Rename: In Progress, Pool: " + pool.name);
+
+ if (filesystems.id.length > 0) {
+ filesystems.id.forEach((_value, _index) => {
+ let filesystem = {
+ properties: _value.split(/\t/g).filter(v => v)
+ };
+
+ filesystem.name = filesystem.properties[0];
+ filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0], attribute: true });
+ filesystem.mounted = filesystem.properties[1];
+ filesystem.mountpoint = filesystem.properties[2];
+ filesystem.sharesmb = filesystem.properties[3];
+
+ filesystem.namenew = filesystem.name.replace(new RegExp("^" + filesystems.parent.name), filesystems.parent.namenew);
+ filesystem.idnew = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.namenew, attribute: true });
+
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ if (_index <= (filesystems.id.length - 1)) {
+ if (filesystem.sharesmb == "on") {
+ FnFileSystemMountpointGet({ name: pool.name, id: pool.id }, { name: filesystem.namenew, id: filesystem.idnew })
+ .done(function (data) {
+ filesystem.mountpoint = data.replace(/\n$/, "");
+
+ FnSambaZfsShareConfigurationPathSet({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, namenew: filesystem.namenew, id: filesystem.id, mountpoint: filesystem.mountpoint })
+ .finally(function () {
+ FnSambaZfsShareDisable({ name: pool.name, id: pool.id, altroot: pool.altroot, readonly: pool.readonly }, { name: filesystem.name, id: filesystem.id });
+ });
+ });
+ }
+ }
+
+ if (_index == (filesystems.id.length - 1)) {
+ setTimeout(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba shares successfully renamed", description: pool.name, breakword: false }, { name: "samba-rename", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, Shares, Rename: Success, Pool: " + pool.name);
+
+ FnSambaZfsSharesConfigurationReload()
+ .done(function () {
+ setTimeout(function () {
+ if (samba.restart) {
+ FnSambaRestart()
+ .finally(function () {
+ process.promise.resolve();
+ });
+ } else {
+ FnSambaConfigurationReload()
+ .finally(function () {
+ process.promise.resolve();
+ });
+ }
+ }, 300);
+ });
+ }, 800);
+ }
+
+ resolve();
+ }, 800)
+ ));
+ });
+ } else {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba shares successfully renamed", description: pool.name, breakword: false }, { name: "samba-rename", id: pool.id, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, Shares, Rename: Success, Pool: " + pool.name);
+
+ process.promise.resolve();
+ }
+
+ return process.promise.promise();
+}
+
+function FnSambaStart() {
+ let process = {
+ command: ["/bin/systemctl", "start"]
+ };
+
+ if (/Debian|Ubuntu/i.test(zfsmanager.system.operatingsystem)) {
+ process.command.splice(2, 0, "smbd");
+ } else {
+ process.command.splice(2, 0, "smb");
+ }
+
+ FnConsole.log[2]("Samba, Start: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Samba, Start: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, Start: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaStop() {
+ let process = {
+ command: ["/bin/systemctl", "stop"]
+ };
+
+ if (/Debian|Ubuntu/i.test(zfsmanager.system.operatingsystem)) {
+ process.command.splice(2, 0, "smbd");
+ } else {
+ process.command.splice(2, 0, "smb");
+ }
+
+ FnConsole.log[2]("Samba, Stop: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Samba, Stop: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, Stop: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaUsersharesDirectoryCreate() {
+ let process = {
+ command: ["/bin/sh", "-c", `[ ! -d /var/lib/samba/usershares ] && /bin/mkdir -p /var/lib/samba/usershares || printf "Skipped"`]
+ };
+
+ FnConsole.log[2]("Samba, Usershares Directory, Create: In Progress")
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Usershares Directory, Create:" }));
+
+ if (data == "Skipped") {
+ FnConsole.log[2]("Samba, Usershares Directory, Create: Skipped");
+ } else {
+ FnConsole.log[1]("Samba, Usershares Directory, Create: Success");
+ }
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, Usershares Directory, Create: Failed, Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaVersionGet() {
+ let process = {
+ command: ["/usr/sbin/smbd", "-V"]
+ };
+ let samba = {
+ message: ""
+ };
+
+ FnConsole.log[2]("Samba, Version, Get: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data, message) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Version, Get:" }));
+
+ FnConsole.log[1]("Samba, Version, Get: Success, Version: " + (data ? data.replace(/^Version /i, "") : message.replace(/^Version /i, "")));
+
+ $("#alerts-requirements").empty().addClass("hidden");
+ $("#container").removeClass("hidden");
+ })
+ .fail(function (message, data) {
+ FnConsole.error("Samba, Version, Get: Failed, Message: " + (data ? data : message));
+
+ samba.message = `
+
+
+
+ This package requires Samba
+ Install Samba software via your package manager
+
+ Refresh
+
+ `;
+
+ $("#alerts-requirements").removeClass("hidden").html(samba.message);
+ $("#container").addClass("hidden");
+ });
+}
+
+function FnSambaZfsShareConfigurationGenerate(filesystem = { name, id, mountpoint }, samba = { enable: false, share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }) {
+ samba.share.conf = {
+ content: "",
+ path: "/" + (samba.share.temporary ? "run" : "etc") + "/cockpit/zfs/shares/" + FnGenerateShareFileName({ name: filesystem.name }) + ".conf"
+ }
+
+ if (!samba.share.name) {
+ samba.share.name = FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.name.replace(/^.*\/(.*)$/, "$1") });
+ }
+ if (samba.share.administrative) {
+ samba.share.name = samba.share.name + "$";
+ }
+ if (!samba.share.comment && samba.enable) {
+ samba.share.comment = "ZFS: " + filesystem.name;
+ }
+
+ samba.share.additional = samba.share.additional.reduce((a, v) => {
+ let allow = true;
+
+ if (/[\[\]]/g.test(v)) { //Do not allow section names
+ allow = false;
+ }
+ if (/^[#]/.test(v) == false && /[=]/.test(v)) { //Do not allow modal configurable properties
+ if (/(path|comment|browseable|read only|guest ok).*=/gi.test(v)) {
+ allow = false;
+ }
+ }
+
+ if (allow) {
+ v = v.replace(/\\/g, "\\\\\\");
+
+ a.push((/^[#]/.test(v) == false && /[=]/.test(v) ? "\\t" + v : v));
+ }
+
+ return a;
+ }, []);
+
+ samba.share.conf.content = "\"# COCKPIT ZFS MANAGER\n# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION\\n\[" + samba.share.name + "\]\\n\\tpath \= " + filesystem.mountpoint + "\\n\\tcomment \= " + samba.share.comment + "\\n\\tbrowseable = " + (samba.share.browseable ? "yes" : "no") + "\\n\\tread only = " + (samba.share.readonly ? "yes" : "no") + "\\n\\tguest ok = " + (samba.share.guestok ? "yes" : "no") + "\\n\\n# ADD ADDITIONAL CONFIGURATION HERE\\n" + samba.share.additional.join("\\n") + "\\n\" > \"" + samba.share.conf.path + "\"";
+
+ return samba.share.conf.content;
+}
+
+function FnSambaZfsShareConfigurationGet(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id }, modal = { name, id }) {
+ let process = {
+ command: ["/bin/cat", "/" + (pool.altroot || pool.readonly ? "run" : "etc") + "/cockpit/zfs/shares/" + FnGenerateShareFileName({ name: filesystem.name }) + ".conf"]
+ };
+ let samba = {
+ share: {
+ name: "",
+ path: "",
+ comment: "",
+ administrative: false,
+ browseable: true,
+ guestok: false,
+ readonly: false,
+ additional: []
+ }
+ };
+
+ FnConsole.log[2]("Samba, ZFS Share Configuration, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, ZFS Share Configuration, Get:" }));
+
+ samba.share.conf = data.split(/\n/g).filter(v => v);
+
+ samba.share.conf.forEach((_value, _index) => {
+ _value = _value.replace(/\t/g, "");
+
+ //2=name, 3=path, 4=comment, 5=browseable, 6=read only, 7=guest ok
+
+ switch (_index) {
+ case 2: //2=name
+ if (/^\[.*\]$/g.test(_value)) {
+ samba.share.name = _value.replace(/\[/g, "").replace(/\]/g, "");
+
+ if (/[$]$/.test(samba.share.name)) {
+ samba.share.administrative = true;
+ samba.share.name = samba.share.name.replace(/[$]$/, "");
+ }
+ }
+
+ break;
+ case 3: //3=path
+ if (/path \=/gi.test(_value)) {
+ samba.share.path = _value.replace("path = ", "").replace(/["]/g, "");
+ }
+
+ break;
+ case 4: //4=comment
+ if (/comment \=/gi.test(_value)) {
+ samba.share.comment = _value.replace("comment = ", "").replace(/["]/g, "");
+ }
+
+ break;
+ case 5: //5=browseable
+ if (/browseable \=/gi.test(_value)) {
+ samba.share.browseable = (_value.replace("browseable = ", "").replace(/["]/g, "") == "yes" ? true : false);
+ }
+
+ break;
+ case 6: //6=read only
+ if (/read only \=/gi.test(_value)) {
+ samba.share.readonly = (_value.replace("read only = ", "").replace(/["]/g, "") == "yes" ? true : false);
+ }
+
+ break;
+ case 7: //7=guest ok
+ if (/guest ok \=/gi.test(_value)) {
+ samba.share.guestok = (_value.replace("guest ok = ", "").replace(/["]/g, "") == "yes" ? true : false);
+ }
+
+ break;
+ }
+ });
+
+ samba.share.additional = samba.share.conf.filter((v, i) => i > 8).map(v => v.replace(/^\s+/, ""));
+
+ FnConsole.log[1]("Samba, ZFS Share Configuration, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, ZFS Share Configuration, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#input-" + modal.name + "-name-" + modal.id).val(samba.share.name).attr("data-field-value", samba.share.name);
+ $("#input-" + modal.name + "-comment-" + modal.id).val(samba.share.comment);
+ $("#textarea-" + modal.name + "-additional-" + modal.id).val(samba.share.additional.join("\n"));
+
+ if (samba.share.administrative && !$("#switch-" + modal.name + "-administrative-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-administrative-" + modal.id + " input").click();
+ }
+ if (!samba.share.browseable && $("#switch-" + modal.name + "-browseable-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-browseable-" + modal.id + " input").click();
+ }
+ if (samba.share.guestok && !$("#switch-" + modal.name + "-guestok-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-guestok-" + modal.id + " input").click();
+ }
+ if (samba.share.readonly && !$("#switch-" + modal.name + "-readonly-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-readonly-" + modal.id + " input").click();
+ }
+
+ if (!samba.share.name) {
+ $("#alert-" + modal.name + "-configurationmissing-" + modal.id).removeClass("hidden");
+
+ $("#input-" + modal.name + "-name-" + modal.id).val(FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.name.replace(/^.*\/(.*)$/, "$1") })).focus();
+ if (!samba.share.comment) {
+ $("#input-" + modal.name + "-comment-" + modal.id).val("ZFS: " + filesystem.name);
+ }
+ }
+ if (samba.share.additional.length > 0 && !$("#switch-" + modal.name + "-additional-" + modal.id + " input").prop("checked")) {
+ $("#switch-" + modal.name + "-additional-" + modal.id + " input").click();
+ }
+ });
+}
+
+function FnSambaZfsShareConfigurationPathSet(pool = { name, id, altroot: false }, filesystem = { name, namenew, id, mountpoint }, display = { silent: true }) {
+ let process = {
+ command: ["/bin/cat", "/" + (pool.altroot ? "run" : "etc") + "/cockpit/zfs/shares/" + FnGenerateShareFileName({ name: filesystem.name }) + ".conf"],
+ promise: cockpit.defer()
+ };
+ let samba = {
+ share: {
+ name: "",
+ path: "",
+ comment: "",
+ administrative: false,
+ browseable: true,
+ guestok: false,
+ readonly: false,
+ temporary: (pool.altroot ? true : false),
+ additional: []
+ }
+ };
+
+ FnConsole.log[2]("Samba, ZFS Share Configuration, Get: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, ZFS Share Configuration, Get:" }));
+
+ samba.share.conf = data.split(/\n/g).filter(v => v);
+
+ samba.share.conf.forEach((_value, _index) => {
+ _value = _value.replace(/\t/g, "");
+
+ //2=name, 3=path, 4=comment, 5=browseable, 6=read only, 7=guest ok
+
+ switch (_index) {
+ case 2: //2=name
+ if (/^\[.*\]$/g.test(_value)) {
+ samba.share.name = _value.replace(/\[/g, "").replace(/\]/g, "");
+
+ if (/[$]$/.test(samba.share.name)) {
+ samba.share.administrative = true;
+ samba.share.name = samba.share.name.replace(/[$]$/, "");
+ }
+ }
+
+ break;
+ case 3: //3=path
+ if (/path \=/gi.test(_value)) {
+ samba.share.path = _value.replace("path = ", "").replace(/["]/g, "");
+ }
+
+ break;
+ case 4: //4=comment
+ if (/comment \=/gi.test(_value)) {
+ samba.share.comment = _value.replace("comment = ", "").replace(/["]/g, "");
+ }
+
+ break;
+ case 5: //5=browseable
+ if (/browseable \=/gi.test(_value)) {
+ samba.share.browseable = (_value.replace("browseable = ", "").replace(/["]/g, "") == "yes" ? true : false);
+ }
+
+ break;
+ case 6: //6=read only
+ if (/read only \=/gi.test(_value)) {
+ samba.share.readonly = (_value.replace("read only = ", "").replace(/["]/g, "") == "yes" ? true : false);
+ }
+
+ break;
+ case 7: //7=guest ok
+ if (/guest ok \=/gi.test(_value)) {
+ samba.share.guestok = (_value.replace("guest ok = ", "").replace(/["]/g, "") == "yes" ? true : false);
+ }
+
+ break;
+ }
+ });
+
+ samba.share.additional = samba.share.conf.filter((v, i) => i > 8).map(v => v.replace(/^\s+/, ""));
+
+ FnConsole.log[1]("Samba, ZFS Share Configuration, Get: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ if (filesystem.mountpoint != samba.share.path || filesystem.namenew) {
+ if (filesystem.namenew) {
+ if ((filesystem.name.replace(/^.*\/(.*)$/, "$1") != filesystem.namenew.replace(/^.*\/(.*)$/, "$1") && samba.share.name.toLowerCase() == FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.name.replace(/^.*\/(.*)$/, "$1") }).toLowerCase()) || samba.share.name.toLowerCase() == FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.name }).toLowerCase()) {
+ samba.share.nameunique = true;
+
+ FnSambaShareNamesGet({ zfsonly: false })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Share, Names, Get:" }));
+
+ if (data.replace(/\n/g, "") != "$empty") { //$empty response is received if share names list is empty
+ samba.shares = data.split(/\n/g).filter(v => v);
+
+ samba.shares.forEach((_value, _index) => {
+ if (_value.replace(/^\[/, "").replace(/\]$/, "").toLowerCase() == filesystem.namenew.replace(/^.*\/(.*)$/, "$1").toLowerCase() + (samba.share.administrative ? "$" : "")) {
+ samba.share.nameunique = false;
+
+ return;
+ }
+ });
+ }
+
+ if (/^global$|^homes$|^printers$/gi.test(samba.share.name)) {
+ samba.share.nameunique = false;
+ }
+
+ if (!samba.share.nameunique) {
+ samba.share.name = FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.namenew });
+ } else {
+ samba.share.name = FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.namenew.replace(/^.*\/(.*)$/, "$1") });
+ }
+
+ filesystem.name = filesystem.namenew;
+ samba.share.comment = "ZFS: " + filesystem.namenew;
+
+ FnSambaZfsShareConfigurationPathSetCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { silent: display.silent })
+ .finally(function () {
+ process.promise.resolve();
+ });
+ })
+ .fail(function () {
+ filesystem.name = filesystem.namenew;
+ samba.share.comment = "ZFS: " + filesystem.namenew;
+ samba.share.name = FnGenerateShareName({ at: false, colon: false, period: false, whitespace: false }, { name: filesystem.namenew });
+
+ FnSambaZfsShareConfigurationPathSetCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { silent: display.silent })
+ .finally(function () {
+ process.promise.resolve();
+ });
+ });
+ } else {
+ filesystem.name = filesystem.namenew;
+ samba.share.comment = "ZFS: " + filesystem.namenew;
+
+ FnSambaZfsShareConfigurationPathSetCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { silent: display.silent })
+ .finally(function () {
+ process.promise.resolve();
+ });
+ }
+ } else {
+ FnSambaZfsShareConfigurationPathSetCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } }, { silent: display.silent })
+ .finally(function () {
+ process.promise.resolve();
+ });
+ }
+ } else {
+ process.promise.resolve();
+ }
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, ZFS Share Configuration, Get: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+
+ process.promise.resolve();
+ });
+
+ return process.promise.promise();
+}
+
+function FnSambaZfsShareConfigurationPathSetCommand(pool = { name, id }, filesystem = { name, id, mountpoint }, samba = { share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }, display = { silent: true }) {
+ let process = {
+ command: ["/bin/sh", "-c", "printf " + FnSambaZfsShareConfigurationGenerate({ name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { enable: false, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } })]
+ };
+
+ FnConsole.log[2]("Samba, ZFS Share Configuration, Path, Set: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "success", title: "Samba share configuration successfully updated", description: filesystem.name, breakword: false }, { name: "samba-configure-share", id: filesystem.id, timeout: 4 });
+ }
+
+ FnConsole.log[1]("Samba, ZFS Share Configuration, Path, Set: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ if (!display.silent) {
+ FnDisplayAlert({ status: "danger", title: "Samba share configuration could not be updated", description: filesystem.name, breakword: false }, { name: "samba-configure-share", id: filesystem.id, timeout: 4 });
+ }
+
+ FnConsole.warn("Samba, ZFS Share Configuration, Path, Set: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaZfsShareConfigurationPathsSet(pool = { name, id, altroot: false }, filesystem = { name }, samba = { restart: false }, display = { refresh: false, silent: true }) {
+ let process = {
+ command: ["/sbin/zfs", "list", "-H", "-o", "name,mounted,mountpoint,sharesmb", "-r", "-t", "filesystem", filesystem.name],
+ promise: cockpit.defer()
+ };
+
+ FnConsole.log[2]("Samba, ZFS Share Configuration, Paths, Set: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ cockpit.spawn(process.command, { err: "out" })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, ZFS Share Configuration, Paths, Set:" }));
+
+ let filesystems = {
+ id: data.split(/\n/g).filter(v => v && /\ton$/i.test(v))
+ };
+ let promise = Promise.resolve();
+
+ if (filesystems.id.length > 0) {
+ filesystems.id.forEach((_value, _index) => {
+ let filesystem = {
+ properties: _value.split(/\t/g).filter(v => v)
+ };
+
+ filesystem.name = filesystem.properties[0];
+ filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.properties[0], attribute: true });
+ filesystem.mounted = filesystem.properties[1];
+ filesystem.mountpoint = filesystem.properties[2];
+ filesystem.sharesmb = filesystem.properties[3];
+
+ promise = promise.then(_ => new Promise(resolve =>
+ setTimeout(function () {
+ if (_index <= (filesystems.id.length - 1)) {
+ if (filesystem.sharesmb == "on") {
+ FnSambaZfsShareConfigurationPathSet({ name: pool.name, id: pool.id, altroot: pool.altroot }, { name: filesystem.name, namenew: null, id: filesystem.id, mountpoint: filesystem.mountpoint })
+ }
+ }
+
+ if (_index == (filesystems.id.length - 1)) {
+ setTimeout(function () {
+ FnDisplayAlert({ status: "success", title: "Samba share configurations successfully updated", description: pool.name, breakword: false }, { name: "samba-configure-share", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Samba, ZFS Share Configuration, Paths, Set: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ FnSambaZfsSharesConfigurationReload()
+ .done(function () {
+ setTimeout(function () {
+ if (samba.restart) {
+ FnSambaRestart()
+ .finally(function () {
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ }
+
+ process.promise.resolve();
+ });
+ } else {
+ FnSambaConfigurationReload()
+ .finally(function () {
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ }
+
+ process.promise.resolve();
+ });
+ }
+ }, 300);
+ });
+ }, 500);
+ }
+
+ resolve();
+ }, 500)
+ ));
+ });
+ } else {
+ FnDisplayAlert({ status: "success", title: "Samba share configurations successfully updated", description: pool.name, breakword: false }, { name: "samba-configure-share", id: pool.id, timeout: 4 });
+
+ FnConsole.log[1]("Samba, ZFS Share Configuration, Paths, Set: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ process.promise.resolve();
+ }
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Samba share configurations could not updated", description: pool.name, breakword: false }, { name: "samba-configure-share", id: pool.id, timeout: 4 });
+
+ FnConsole.warn("Samba, ZFS Share Configuration, Paths, Set: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+
+ if (display.refresh) {
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: true, status: false });
+ }, 500);
+ }
+
+ process.promise.resolve();
+ });
+
+ return process.promise.promise();
+}
+
+function FnSambaZfsShareConfigure(pool = { name, id }, filesystem = { name, id, mountpoint }, samba = { share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, nameexisting, readonly: false, temporary: false }, restart: false }) {
+ $("#spinner-storagepool-filesystem-samba-configure-" + filesystem.id + " span").text("Configuring Samba share...");
+
+ FnSambaShareNamesGet({ zfsonly: false })
+ .done(function (data) {
+ FnConsole.log[4](FnConsoleVerbose({ data: data, message: "Samba, Share, Names, Get:" }));
+
+ samba.share.nameunique = true;
+ samba.share.errormessage = "Share name is already in use.";
+
+ if (data.replace(/\n/g, "") != "$empty") { //$empty response is received if share names list is empty
+ samba.shares = data.split(/\n/g).filter(v => v);
+
+ samba.shares.forEach((_value, _index) => {
+ if (_value.replace(/^\[/, "").replace(/\]$/, "").toLowerCase() == samba.share.name.toLowerCase() + (samba.share.administrative ? "$" : "")) {
+ if (samba.share.name != samba.share.nameexisting) { //Allow the name since the share is already enabled with this name
+ samba.share.nameunique = false;
+
+ return;
+ }
+ }
+ });
+ }
+
+ if (/^global$|^homes$|^printers$/gi.test(samba.share.name)) {
+ samba.share.nameunique = false;
+ samba.share.errormessage = "Share name can not be a restricted name.";
+ }
+
+ if (!samba.share.nameunique) {
+ $("#validationwrapper-storagepool-filesystem-samba-configure-name-" + filesystem.id).addClass("has-error");
+ $("#helpblock-storagepool-filesystem-samba-configure-name-" + filesystem.id).addClass("has-error").removeClass("hidden").text(samba.share.errormessage);
+ $("#input-storagepool-filesystem-samba-configure-name-" + filesystem.id).focus();
+
+ $("#spinner-storagepool-filesystem-samba-configure-" + filesystem.id).addClass("hidden");
+ $("#spinner-storagepool-filesystem-samba-configure-" + filesystem.id + " span").text("");
+ $("#btn-storagepool-filesystem-samba-configure-apply-" + filesystem.id).prop("disabled", false);
+
+ FnConsole.warn("Samba, ZFS Share Configuration, Update: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + samba.share.errormessage);
+ } else {
+ FnSambaZfsShareConfigureCommand({ name: pool.name, id: pool.id }, { name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary }, restart: samba.restart });
+ }
+ });
+}
+
+function FnSambaZfsShareConfigureCommand(pool = { name, id }, filesystem = { name, id, mountpoint }, samba = { share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false }, restart: false }) {
+ let process = {
+ command: ["/bin/sh", "-c", "printf " + FnSambaZfsShareConfigurationGenerate({ name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { enable: false, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } })]
+ };
+
+ FnConsole.log[2]("Samba, ZFS Share Configuration, Update: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnDisplayAlert({ status: "success", title: "Samba share configuration successfully updated", description: filesystem.name, breakword: false }, { name: "samba-configure-share", id: filesystem.id, timeout: 4 });
+
+ FnConsole.log[1]("Samba, ZFS Share Configuration, Update: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+
+ if (samba.restart) {
+ FnSambaRestart();
+ } else {
+ FnSambaConfigurationReload();
+ }
+ })
+ .fail(function (message, data) {
+ FnDisplayAlert({ status: "danger", title: "Samba share configuration could not be updated", description: filesystem.name, breakword: false }, { name: "samba-configure-share", id: filesystem.id, timeout: 4 });
+
+ FnConsole.warn("Samba, ZFS Share Configuration, Update: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ })
+ .finally(function () {
+ $("#modal-storagepool-filesystem-samba-configure-" + filesystem.id).modal("hide");
+
+ setTimeout(function () {
+ FnStoragePoolRefresh({ name: pool.name, id: pool.id }, { storagepool: true, filesystems: true, snapshots: false, status: false });
+ }, 200);
+ });
+}
+
+function FnSambaZfsShareDisable(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id }) {
+ let process = {
+ command: ["/bin/rm", "-f", "/" + (pool.altroot || pool.readonly ? "run" : "etc") + "/cockpit/zfs/shares/" + FnGenerateShareFileName({ name: filesystem.name }) + ".conf"]
+ };
+
+ FnConsole.log[2]("Samba, Share, Disable: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Samba, Share, Disable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, Share, Disable: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaZfsShareEnable(pool = { name, id }, filesystem = { name, id, mountpoint }, samba = { share: { additional: [], administrative: false, browseable: true, guestok: false, name, comment, readonly: false, temporary: false } }) {
+ let process = {
+ command: ["/bin/sh", "-c", "printf " + FnSambaZfsShareConfigurationGenerate({ name: filesystem.name, id: filesystem.id, mountpoint: filesystem.mountpoint }, { enable: true, share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: samba.share.temporary } })]
+ };
+
+ FnConsole.log[2]("Samba, Share, Enable: In Progress, Pool: " + pool.name + ", File System: " + filesystem.name);
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Samba, Share, Enable: Success, Pool: " + pool.name + ", File System: " + filesystem.name);
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, Share, Enable: Failed, Pool: " + pool.name + ", File System: " + filesystem.name + ", Message: " + (data ? data : message));
+ });
+}
+
+function FnSambaZfsSharesConfigurationReload() {
+ let process = {
+ command: ["/bin/sh", "-c", "echo '# COCKPIT ZFS MANAGER\n# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION' > /etc/cockpit/zfs/shares.conf && /bin/ls /etc/cockpit/zfs/shares/*.conf 2> /dev/null | /bin/sed -e 's/^/include = /' >> /etc/cockpit/zfs/shares.conf && echo '# COCKPIT ZFS MANAGER\n# WARNING: DO NOT EDIT, AUTO-GENERATED CONFIGURATION' > /run/cockpit/zfs/shares.conf && /bin/ls /run/cockpit/zfs/shares/*.conf 2> /dev/null | /bin/sed -e 's/^/include = /' >> /run/cockpit/zfs/shares.conf"]
+ };
+
+ FnConsole.log[2]("Samba, ZFS Shares Configuration, Reload: In Progress");
+ FnConsole.log[3](FnConsoleCommand({ command: process.command }));
+
+ return cockpit.spawn(process.command, { err: "out", superuser: "require" })
+ .done(function () {
+ FnConsole.log[1]("Samba, ZFS Shares Configuration, Reload: Success");
+ })
+ .fail(function (message, data) {
+ FnConsole.warn("Samba, ZFS Shares Configuration, Reload: Failed, Message: " + (data ? data : message));
+ });
+}
+
+//#endregion
+
+//#region Dynamic Content Click Actions
+
+function FnDynamicStatusDiskTrimCancel(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
+ let dynamic = {
+ script: ""
+ };
+
+ dynamic.script = `
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-trim-cancel-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolTrimCancel({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `" });
+ });
+ \x3C/script>
+ `;
+
+ $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
+}
+
+function FnDynamicStatusDiskTrimResume(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
+ let dynamic = {
+ script: ""
+ };
+
+ dynamic.script = `
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-trim-resume-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolTrimStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `" }, { resume: true, secure: false }, { name: null, id: null });
+ });
+ \x3C/script>
+ `;
+
+ $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
+}
+
+function FnDynamicStatusDiskTrimSuspend(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
+ let dynamic = {
+ script: ""
+ };
+
+ dynamic.script = `
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-trim-suspend-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolTrimSuspend({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `" });
+ });
+ \x3C/script>
+ `;
+
+ $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
+}
+
+function FnDynamicStatusStoragePoolScrubPause(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
+ let dynamic = {
+ script: ""
+ };
+
+ dynamic.script = `
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-scrub-pause-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolScrubPause({ name: "` + pool.name + `", id: "` + pool.id + `" }, { refresh: true });
+ });
+ \x3C/script>
+ `;
+
+ $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
+}
+
+function FnDynamicStatusStoragePoolScrubResume(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
+ let dynamic = {
+ script: ""
+ };
+
+ dynamic.script = `
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-scrub-resume-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolScrubStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { resume: true }), { refresh: true };
+ });
+ \x3C/script>
+ `;
+
+ $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
+}
+
+function FnDynamicStatusStoragePoolScrubStart(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
+ let dynamic = {
+ script: ""
+ };
+
+ dynamic.script = `
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-scrub-start-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolScrubStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { resume: false }, { refresh: true });
+ });
+ \x3C/script>
+ `;
+
+ $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
+}
+
+function FnDynamicStatusStoragePoolScrubStop(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
+ let dynamic = {
+ script: ""
+ };
+
+ dynamic.script = `
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-scrub-stop-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolScrubStop({ name: "` + pool.name + `", id: "` + pool.id + `" }, { refresh: true });
+ });
+ \x3C/script>
+ `;
+
+ $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
+}
+
+function FnDynamicStatusStoragePoolTrimCancel(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
+ let dynamic = {
+ script: ""
+ };
+
+ dynamic.script = `
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-trim-cancel-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolTrimCancel({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: null });
+ });
+ \x3C/script>
+ `;
+
+ $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
+}
+
+function FnDynamicStatusStoragePoolTrimResume(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
+ let dynamic = {
+ script: ""
+ };
+
+ dynamic.script = `
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-trim-resume-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolTrimStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: null }, { resume: true, secure: false }, { name: null, id: null });
+ });
+ \x3C/script>
+ `;
+
+ $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
+}
+
+function FnDynamicStatusStoragePoolTrimSuspend(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
+ let dynamic = {
+ script: ""
+ };
+
+ dynamic.script = `
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-trim-suspend-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolTrimSuspend({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: null });
+ });
+ \x3C/script>
+ `;
+
+ $("#dynamics-storagepool-status-" + pool.id).append(dynamic.script);
+}
+
+//#endregion
+
+//#region Modals Register
+
+function FnModalsRegister() {
+ $("#modals").append(`
`);
+ $("#modals").append(`
`);
+
+ FnModalAbout();
+ FnModalConfigure();
+ FnModalUpdate();
+ FnModalWelcome();
+ FnModalStoragePoolsCreate();
+ FnModalStoragePoolsImport();
+ FnModalFileSystemsUnlock();
+}
+
+//#endregion
+
+//#region Modal Cockpit ZFS Manager
+
+function FnModalAbout() {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+
+
+
+
Cockpit ZFS Manager is an interactive ZFS on Linux admin package for Cockpit.
+ ` + FnDisplayInlineAlert({ status: "info", title: "A new version of Cockpit ZFS Manager is now available", description: `
` }, { name: "about-update", id: null, hidden: true }) + `
+
Version: ` + zfsmanager.version + `
+
Copyright © 2019-2020 OPTIMANS Pty Ltd.
+
+
+
+
+
+
+
+ `;
+
+ $("#modals").append(modal.window);
+}
+
+function FnModalConfigure() {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-configure").on("click", function () {
+ FnModalConfigureContent({ id: $("#modal-configure") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals").append(modal.window);
+}
+
+function FnModalConfigureContent(modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-configure-samba-manage input").on("click", function () {
+ if (!$(this).prop("checked")) {
+ $("#switch-configure-samba-windowscompatibility input").prop("disabled", true);
+ $("#switch-configure-samba-windowscompatibility").parent().addClass("hidden");
+ } else {
+ $("#switch-configure-samba-windowscompatibility input").removeClass("hidden").prop("disabled", false);
+ $("#switch-configure-samba-windowscompatibility").parent().removeClass("hidden");
+ }
+ });
+
+ $("#switch-configure-zfs-storagepool-boot input").on("click", function () {
+ if (!$(this).prop("checked")) {
+ $("#switch-configure-zfs-storagepool-bootlockdown input").prop("disabled", true);
+ $("#switch-configure-zfs-storagepool-bootlockdown").parent().addClass("hidden");
+ } else {
+ $("#switch-configure-zfs-storagepool-bootlockdown input").prop("disabled", false);
+ $("#switch-configure-zfs-storagepool-bootlockdown").parent().removeClass("hidden");
+ }
+ });
+
+ $("#btn-configure-apply").on("click", function () {
+ $("#spinner-configure").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let user = {
+ cockpit: {
+ manage: $("#switch-configure-cockpit-manage input").prop("checked")
+ },
+ disks: {
+ base2: $("#switch-configure-disks-base2 input").prop("checked"),
+ },
+ loglevel: $("#btnspan-configure-zfs-storagepool-loglevel").attr("data-field-value"),
+ samba: {
+ manage: $("#switch-configure-samba-manage input").prop("checked"),
+ windowscompatibility: $("#switch-configure-samba-windowscompatibility input").prop("checked")
+ },
+ updates: {
+ check: $("#switch-configure-updates-check input").prop("checked")
+ },
+ zfs: {
+ filesystem: {
+ cloneorigin: $("#switch-configure-zfs-filesystem-cloneorigin input").prop("checked"),
+ quotarestrict: $("#switch-configure-zfs-filesystem-quotarestrict input").prop("checked"),
+ readonlylockdown: $("#switch-configure-zfs-filesystem-readonlylockdown input").prop("checked"),
+ snapshotactions: $("#switch-configure-zfs-filesystem-snapshotactions input").prop("checked")
+ },
+ snapshot: {
+ filesystemlist: $("#switch-configure-zfs-snapshot-filesystemlist input").prop("checked")
+ },
+ status: {
+ errorcolors: $("#switch-configure-zfs-status-errorcolors input").prop("checked"),
+ trimunsupported: $("#switch-configure-zfs-status-trimunsupported input").prop("checked")
+ },
+ storagepool: {
+ activetab: $("#btnspan-configure-zfs-storagepool-activetab").attr("data-field-value"),
+ boot: $("#switch-configure-zfs-storagepool-boot input").prop("checked"),
+ bootlockdown: $("#switch-configure-zfs-storagepool-bootlockdown input").prop("checked"),
+ count: $("#switch-configure-zfs-storagepool-count input").prop("checked"),
+ refreshall: $("#switch-configure-zfs-storagepool-refreshall input").prop("checked"),
+ root: $("#switch-configure-zfs-storagepool-root input").prop("checked")
+ }
+ }
+ };
+
+ FnConfigure({ cockpit: { manage: user.cockpit.manage }, disks: { base2: user.disks.base2 }, loglevel: user.loglevel, samba: { manage: user.samba.manage, windowscompatibility: user.samba.windowscompatibility }, updates: { check: user.updates.check }, zfs: { filesystem: { cloneorigin: user.zfs.filesystem.cloneorigin, quotarestrict: user.zfs.filesystem.quotarestrict, readonlylockdown: user.zfs.filesystem.readonlylockdown, snapshotactions: user.zfs.filesystem.snapshotactions }, snapshot: { filesystemlist: user.zfs.snapshot.filesystemlist }, status: { errorcolors: user.zfs.status.errorcolors, trimunsupported: user.zfs.status.trimunsupported }, storagepool: { activetab: user.zfs.storagepool.activetab, boot: user.zfs.storagepool.boot, bootlockdown: user.zfs.storagepool.bootlockdown, count: user.zfs.storagepool.count, refreshall: user.zfs.storagepool.refreshall, root: user.zfs.storagepool.root } } }, { name: "configure", welcome: false })
+ });
+
+ $("#dropdown-configure-zfs-storagepool-activetab").on("click", "li a", function () {
+ $("#btnspan-configure-zfs-storagepool-activetab").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-configure-zfs-storagepool-loglevel").on("click", "li a", function () {
+ $("#btnspan-configure-zfs-storagepool-loglevel").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalUpdate() {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+ `;
+
+ $("#modals").append(modal.window);
+}
+
+function FnModalUpdateContent(modal = { id }) {
+ modal.content = `
+
+ `;
+
+ modal.id.empty().append(modal.content);
+
+ $("#progressbar-update .progress-bar").css("width", "100%");
+}
+
+function FnModalWelcome() {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+ `;
+
+ $("#modals").append(modal.window);
+}
+
+function FnModalWelcomeContent(modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-welcome-samba-manage input").on("click", function () {
+ if (!$(this).prop("checked")) {
+ $("#switch-welcome-samba-windowscompatibility input").prop("disabled", true);
+ $("#switch-welcome-samba-windowscompatibility").parent().addClass("hidden");
+ } else {
+ $("#switch-welcome-samba-windowscompatibility input").removeClass("hidden").prop("disabled", false);
+ $("#switch-welcome-samba-windowscompatibility").parent().removeClass("hidden");
+ }
+ });
+
+ $("#switch-welcome-zfs-storagepool-boot input").on("click", function () {
+ if (!$(this).prop("checked")) {
+ $("#switch-welcome-zfs-storagepool-bootlockdown input").prop("disabled", true);
+ $("#switch-welcome-zfs-storagepool-bootlockdown").parent().addClass("hidden");
+ } else {
+ $("#switch-welcome-zfs-storagepool-bootlockdown input").prop("disabled", false);
+ $("#switch-welcome-zfs-storagepool-bootlockdown").parent().removeClass("hidden");
+ }
+ });
+
+ $("#btn-welcome-apply").on("click", function () {
+ $("#spinner-welcome").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let user = {
+ cockpit: {
+ manage: $("#switch-welcome-cockpit-manage input").prop("checked")
+ },
+ loglevel: $("#btnspan-welcome-zfs-storagepool-loglevel").attr("data-field-value"),
+ samba: {
+ manage: $("#switch-welcome-samba-manage input").prop("checked"),
+ windowscompatibility: $("#switch-welcome-samba-windowscompatibility input").prop("checked")
+ },
+ updates: {
+ check: $("#switch-welcome-updates-check input").prop("checked")
+ },
+ zfs: {
+ storagepool: {
+ boot: $("#switch-welcome-zfs-storagepool-boot input").prop("checked"),
+ bootlockdown: $("#switch-welcome-zfs-storagepool-bootlockdown input").prop("checked"),
+ root: $("#switch-welcome-zfs-storagepool-root input").prop("checked")
+ }
+ }
+ };
+
+ FnConfigure({ cockpit: { manage: user.cockpit.manage }, disks: { base2: ` + zfsmanager.configuration.disks.base2 + ` }, loglevel: user.loglevel, samba: { manage: user.samba.manage, windowscompatibility: user.samba.windowscompatibility }, updates: { check: user.updates.check }, zfs: { filesystem: { cloneorigin: ` + zfsmanager.configuration.zfs.filesystem.cloneorigin + `, quotarestrict: ` + zfsmanager.configuration.zfs.filesystem.quotarestrict + `, readonlylockdown: ` + zfsmanager.configuration.zfs.filesystem.readonlylockdown + `, snapshotactions: ` + zfsmanager.configuration.zfs.filesystem.snapshotactions + ` }, snapshot: { filesystemlist: ` + zfsmanager.configuration.zfs.snapshot.filesystemlist + ` }, status: { errorcolors: ` + zfsmanager.configuration.zfs.status.errorcolors + `, trimunsupported: ` + zfsmanager.configuration.zfs.status.trimunsupported + ` }, storagepool: { activetab: ` + zfsmanager.configuration.zfs.storagepool.activetab + `, boot: user.zfs.storagepool.boot, bootlockdown: user.zfs.storagepool.bootlockdown, count: ` + zfsmanager.configuration.zfs.storagepool.count + `, refreshall: ` + zfsmanager.configuration.zfs.storagepool.refreshall + `, root: user.zfs.storagepool.root } } }, { name: "welcome", welcome: true })
+ });
+
+ $("#dropdown-welcome-zfs-storagepool-activetab").on("click", "li a", function () {
+ $("#btnspan-welcome-zfs-storagepool-activetab").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-welcome-zfs-storagepool-loglevel").on("click", "li a", function () {
+ $("#btnspan-welcome-zfs-storagepool-loglevel").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+//#endregion
+
+//#region Modal Storage Pools
+
+function FnModalStoragePoolsCreate() {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepools-create").on("click", function () {
+ FnModalStoragePoolsCreateContent({ id: $("#modal-storagepools-create") });
+ FnDisksAvailableGet({ name: "storagepools-create-disks", id: null, default: true });
+
+ $("#input-storagepools-create-refreservation").val("10");
+ $("#validationwrapper-storagepools-create-refreservation .min-slider-handle").attr("tabindex", "1003");
+ setTimeout(function() {
+ $("#input-storagepools-create-name").focus();
+ }, 600);
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepools").append(modal.window);
+}
+
+function FnModalStoragePoolsCreateContent(modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#input-storagepools-create-refreservation").tooltip({ trigger: "manual" })
+ .on("keyup", function (element) {
+ let $this = $(this);
+ let sd = $this.siblings("[data-provide=slider]").slider();
+
+ if ($this.val().trim() && !$.isNumeric(this.value)) {
+ this.value = sd.slider("getValue");
+ }
+ })
+ .on("keypress blur", function (element) {
+ if (element.which == 13 || element.type === "blur") {
+ element.preventDefault();
+
+ let $this = $(this);
+ let sd = $this.siblings("[data-provide=slider]").slider();
+ let max = sd.slider("getAttribute", "max");
+ let min = sd.slider("getAttribute", "min");
+
+ if (!$.isNumeric(this.value) || (this.value > max || this.value < min)) {
+ let warningInfo = $.isNumeric(this.value) ? "Valid value should be between " + min + " and " + max : "Valid value should be number";
+ $this.attr("data-original-title", warningInfo).tooltip("show").addClass("warning");
+ this.value = sd.slider("getValue");
+ setTimeout(function () {
+ $this.tooltip("hide");
+ }, 3000);
+ } else {
+ if ($this.is(".warning")) {
+ $this.tooltip("hide");
+ }
+
+ this.value = $this.val().trim();
+ sd.slider("setValue", this.value);
+ }
+ }
+ })
+ .siblings("[data-provide=slider]").each(function () {
+ $("#input-storagepools-create-refreservation").val(this.value);
+ $(this).slider().on("change", function (element) {
+ $("#input-storagepools-create-refreservation").val(element.value.newValue);
+ });
+ });
+
+ $("#input-storagepools-create-refreservation").on("change textInput input", function (element) {
+ if ($(this).val() > 20) { //Force reset to maximum allowed value
+ $(this).val(20);
+ } else if ($(this).val() < 0) { //Force reset to minimum allowed value
+ $(this).val(0);
+ }
+
+ if ($.isNumeric($(this).val())) {
+ $("#slider-storagepools-create-refreservation").slider("setValue", $(this).val());
+ }
+ });
+
+ $("#switch-storagepools-create-disks-wwn input").on("click", function () {
+ $("#btnspan-storagepools-create-disks-identifier").text("Block Device");
+ $("#dropdown-storagepools-create-disks-identifier li").siblings().removeClass("active");
+ $("#dropdown-storagepools-create-disks-identifier li[value='blockdevice']").addClass("active");
+ $("#helpblock-storagepools-create-disks-identifierwarning").addClass("hidden").text("");
+ ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepools-create-disks-identifierwarningzfs").addClass("hidden");` : ``) + `
+
+ let disk = {
+ identifier: ($(this).prop("checked") ? "wwn" : "blockdevice"),
+ identifiertext: ($(this).prop("checked") ? "WWN" : "Block Device")
+ };
+
+ if ($(this).prop("checked")) {
+ $("#controllabel-storagepools-create-disks-identifier").addClass("hidden");
+ $("#validationwrapper-storagepools-create-disks-identifier").addClass("hidden");
+ } else {
+ $("#controllabel-storagepools-create-disks-identifier").removeClass("hidden");
+ $("#validationwrapper-storagepools-create-disks-identifier").removeClass("hidden");
+ }
+
+ $("#listgroup-storagepools-create-disks input[name='checkbox-storagepools-create-disks']").map(function () {
+ if ($(this).attr("data-disk-id-" + disk.identifier)) {
+ $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
+ } else {
+ $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
+ $("#helpblock-storagepools-create-disks-identifierwarning").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
+ }
+ });
+ });
+
+ $("#btn-storagepools-create-apply").on("click", function () {
+ $("#spinner-storagepools-create").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let disks = {
+ id: []
+ };
+ let filesystem = {
+ compression: "",
+ dedup: "off",
+ recordsize: "131072",
+ refreservationpercent: 0,
+ selinux: false
+ };
+ let pool = {
+ ashift: 0,
+ autoexpand: "",
+ autoreplace: "",
+ autotrim: "",
+ force: false,
+ name: "",
+ virtualdevice: ""
+ }
+ let validation = {
+ disks: false,
+ name: false
+ };
+
+ $("#listgroup-storagepools-create-disks input[name='checkbox-storagepools-create-disks']:checked").map(function () {
+ disks.id.push($(this).attr("data-disk-name"));
+ });
+
+ if ($("#input-storagepools-create-name").val().length == 0) {
+ $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
+
+ validation.name = false;
+ } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepools-create-name").val()) == false) {
+ $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
+
+ validation.name = false;
+ } else if (/^[0-9]/.test($("#input-storagepools-create-name").val())) {
+ $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with numerical characters.");
+
+ validation.name = false;
+ } else if (/^[.]/.test($("#input-storagepools-create-name").val())) {
+ $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
+
+ validation.name = false;
+ } else if (/^[_]/.test($("#input-storagepools-create-name").val())) {
+ $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
+
+ validation.name = false;
+ } else if (/^[-]/.test($("#input-storagepools-create-name").val())) {
+ $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
+
+ validation.name = false;
+ } else if (/^[:]/.test($("#input-storagepools-create-name").val())) {
+ $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
+
+ validation.name = false;
+ } else if (/^[ ]/.test($("#input-storagepools-create-name").val())) {
+ $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
+
+ validation.name = false;
+ } else if (/[ ]$/.test($("#input-storagepools-create-name").val())) {
+ $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
+
+ validation.name = false;
+ } else if (/^c[0-9]|^log|^mirror|^raidz|^raidz1|^raidz2|^raidz3|^spare/.test($("#input-storagepools-create-name").val())) {
+ $("#helpblock-storagepools-create-name").addClass("has-error").removeClass("hidden").text("Name can not begin with a reserved name.");
+
+ validation.name = false;
+ } else {
+ $("#validationwrapper-storagepools-create-name").removeClass("has-error");
+ $("#helpblock-storagepools-create-name").addClass("hidden").text("");
+
+ validation.name = true;
+ }
+ if (disks.id.length < 1 && $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "disk") {
+ $("#helpblock-storagepools-create-disks").removeClass("hidden").text("One or more disks is needed for Disk.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 2 && $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "mirror") {
+ $("#helpblock-storagepools-create-disks").removeClass("hidden").text("Two or more disks is needed for Mirror.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 2 && $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "raidz1") {
+ $("#helpblock-storagepools-create-disks").removeClass("hidden").text("Two or more disks is needed for RaidZ1.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 3 && $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "raidz2") {
+ $("#helpblock-storagepools-create-disks").removeClass("hidden").text("Three or more disks is needed for RaidZ2.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 4 && $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "raidz3") {
+ $("#helpblock-storagepools-create-disks").removeClass("hidden").text("Four or more disks is needed for RaidZ3.");
+
+ validation.disks = false;
+ } else {
+ $("#validationwrapper-storagepools-create-disks").removeClass("has-error");
+ $("#helpblock-storagepools-create-disks").removeClass("hidden").text("");
+
+ validation.disks = true;
+ }
+
+ if (!validation.name || !validation.disks) {
+ if (!validation.name) {
+ $("#validationwrapper-storagepools-create-name").addClass("has-error");
+ $("#input-storagepools-create-name").focus();
+ }
+ if (!validation.disks) {
+ $("#validationwrapper-storagepools-create-disks").addClass("has-error");
+ }
+
+ $("#spinner-storagepools-create").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.name && validation.disks) {
+ filesystem.compression = ($("#switch-storagepools-create-compression input").prop("checked") ? "lz4" : "off");
+ filesystem.dedup = $("#btnspan-storagepools-create-dedup").attr("data-field-value");
+ filesystem.recordsize = $("#btnspan-storagepools-create-recordsize").attr("data-field-value");
+ filesystem.refreservationpercent = ($("#input-storagepools-create-refreservation").val() != "0" ? $("#input-storagepools-create-refreservation").val() : "0");
+ filesystem.selinux = $("#switch-storagepools-create-selinux input").prop("checked");
+
+ pool.ashift = $("#btnspan-storagepools-create-ashift").attr("data-field-value");
+ pool.autoexpand = ($("#switch-storagepools-create-autoexpand input").prop("checked") ? "on" : "off");
+ pool.autoreplace = ($("#switch-storagepools-create-autoreplace input").prop("checked") ? "on" : "off");
+ pool.autotrim = ($("#switch-storagepools-create-autotrim input").prop("checked") ? "on" : "off");
+ pool.force = $("#switch-storagepools-create-force input").prop("checked");
+ pool.name = $("#input-storagepools-create-name").val();
+ pool.virtualdevice = ($("#btnspan-storagepools-create-virtualdevice").attr("data-field-value") == "disk" ? "" : $("#btnspan-storagepools-create-virtualdevice").attr("data-field-value"));
+
+ FnStoragePoolCreate({ name: pool.name, ashift: pool.ashift, autoexpand: pool.autoexpand, autoreplace: pool.autoreplace, autotrim: pool.autotrim, force: pool.force, virtualdevice: pool.virtualdevice }, { compression: filesystem.compression, dedup: filesystem.dedup, recordsize: filesystem.recordsize, refreservationpercent: filesystem.refreservationpercent, selinux: filesystem.selinux }, { id: disks.id });
+ }
+ });
+
+ $("#dropdown-storagepools-create-virtualdevice").on("click", "li a", function () {
+ $("#btnspan-storagepools-create-virtualdevice").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepools-create-ashift").on("click", "li a", function () {
+ $("#btnspan-storagepools-create-ashift").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepools-create-disks-identifier").on("click", "li a", function () {
+ $("#btnspan-storagepools-create-disks-identifier").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+
+ $("#helpblock-storagepools-create-disks-identifierwarning").addClass("hidden").text("");
+ ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepools-create-disks-identifierwarningzfs").addClass("hidden");` : ``) + `
+
+ let disk = {
+ identifier: $(this).parent().attr("value"),
+ identifiertext: $(this).parent().text()
+ };
+
+ $("#listgroup-storagepools-create-disks input[name='checkbox-storagepools-create-disks']").map(function () {
+ if ($(this).attr("data-disk-id-" + disk.identifier)) {
+ $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
+ } else {
+ $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
+ $("#helpblock-storagepools-create-disks-identifierwarning").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
+
+ ` + (zfsmanager.zfs.warnings.nvmevdev ? `
+ if (disk.identifier == "vdev" && /^nvme/gi.test($(this).attr("data-disk-id-blockdevice"))) {
+ $("#helpblock-storagepools-create-disks-identifierwarningzfs").removeClass("hidden");
+ }
+ ` : ``) + `
+ }
+ });
+ });
+
+ $("#dropdown-storagepools-create-dedup").on("click", "li a", function () {
+ $("#btnspan-storagepools-create-dedup").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepools-create-recordsize").on("click", "li a", function () {
+ $("#btnspan-storagepools-create-recordsize").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStoragePoolsImport() {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepools-import").on("click", function () {
+ FnModalStoragePoolsImportContent({ id: $("#modal-storagepools-import") });
+ FnStoragePoolsImportableGet({ destroyed: false });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepools").append(modal.window);
+}
+
+function FnModalStoragePoolsImportContent(modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepools-import-destroyed input").on("click", function () {
+ $("#helpblock-storagepools-import-storagepools").addClass("hidden").text("");
+ $("#helpblock-storagepools-import-storagepools-warning").addClass("hidden").text("");
+
+ FnStoragePoolsImportableGet({ destroyed: ($(this).prop("checked") ? true : false) });
+ });
+
+ $("#switch-storagepools-import-rename input").on("click", function () {
+ if ($(this).prop("checked")) {
+ $("#controllabel-storagepools-import-namenew").removeClass("hidden");
+ $("#validationwrapper-storagepools-import-namenew").removeClass("hidden");
+ $("#input-storagepools-import-namenew").focus();
+ } else {
+ $("#controllabel-storagepools-import-namenew").addClass("hidden");
+ $("#validationwrapper-storagepools-import-namenew").addClass("hidden");
+ $("#validationwrapper-storagepools-import-namenew").removeClass("has-error");
+ $("#helpblock-storagepools-import-namenew").removeClass("has-error").addClass("hidden").text("");
+ $("#input-storagepools-import-namenew").val("");
+ }
+ });
+
+ $("#switch-storagepools-import-selinux input").on("click", function () {
+ if ($(this).prop("checked") && $("#switch-storagepools-import-readonly input").prop("checked")) {
+ $("#switch-storagepools-import-readonly input").click();
+ }
+ });
+
+ $("#switch-storagepools-import-readonly input").on("click", function () {
+ if ($(this).prop("checked") && $("#switch-storagepools-import-selinux input").prop("checked")) {
+ $("#switch-storagepools-import-selinux input").click();
+ }
+ });
+
+ $("#btn-storagepools-import-apply").on("click", function () {
+ $("#spinner-storagepools-import").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let disks = {
+ id: {
+ blockdevice: true,
+ disk: false,
+ path: false,
+ vdev: false
+ },
+ identifier: ""
+ };
+
+ let filesystem = {
+ mount: true,
+ selinux: true
+ };
+
+ let pool = {
+ altroot: "",
+ name: [],
+ namenew: "",
+ guid: [],
+ destroyed: false,
+ force: false,
+ ignoremissinglog: false,
+ readonly: false,
+ recoverymode: false
+ };
+
+ let validation = {
+ altroot: false,
+ name: false,
+ namenew: false,
+ storagepools: false
+ };
+
+ $("#listgroup-storagepools-import-storagepools input[name='checkbox-storagepools-import-storagepools']:checked").map(function () {
+ pool.guid.push($(this).attr("data-pool-import-guid"));
+ pool.name.push($(this).attr("data-pool-import-name"));
+
+ disks.id.disk = ($(this).attr("data-pool-import-id-disk") == "true" ? true : false);
+ disks.id.path = ($(this).attr("data-pool-import-id-path") == "true" ? true : false);
+ disks.id.vdev = ($(this).attr("data-pool-import-id-vdev") == "true" ? true : false);
+ });
+
+ if (pool.guid.length != 1) {
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("One storage pool is needed for import.");
+
+ validation.storagepools = false;
+ } else {
+ $("#validationwrapper-storagepools-import-storagepools").removeClass("has-error");
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("");
+
+ validation.storagepools = true;
+
+ pool.guid = pool.guid.join(" ");
+ pool.name = pool.name.join(" ");
+ }
+
+ if (validation.storagepools && !$("#switch-storagepools-import-rename input").prop("checked")) {
+ if (pool.name.length == 0) {
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not be empty. New name is needed.");
+
+ validation.name = false;
+ } else if (/^[a-zA-Z0-9-_.: ]*$/.test(pool.name) == false) {
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name contains invalid characters. New name is needed.");
+
+ validation.name = false;
+ } else if (/^[0-9]/.test(pool.name)) {
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with numerical characters. New name is needed.");
+
+ validation.name = false;
+ } else if (/^[.]/.test(pool.name)) {
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with a period (.). New name is needed.");
+
+ validation.name = false;
+ } else if (/^[_]/.test(pool.name)) {
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with an underscore (_). New name is needed.");
+
+ validation.name = false;
+ } else if (/^[-]/.test(pool.name)) {
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with a hypen (-). New name is needed.");
+
+ validation.name = false;
+ } else if (/^[:]/.test(pool.name)) {
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with an colon (:). New name is needed.");
+
+ validation.name = false;
+ } else if (/^[ ]/.test(pool.name)) {
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with whitespace ( ). New name is needed.");
+
+ validation.name = false;
+ } else if (/[ ]$/.test(pool.name)) {
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not end with whitespace ( ). New name is needed.");
+
+ validation.name = false;
+ } else if (/^c[0-9]|^log|^mirror|^raidz|^raidz1|^raidz2|^raidz3|^spare/.test(pool.name)) {
+ $("#helpblock-storagepools-import-storagepools").removeClass("hidden").text("Storage pool name can not begin with a reserved name. New name is needed.");
+
+ validation.name = false;
+ } else {
+ validation.name = true;
+ }
+
+ if (!validation.name && !$("#switch-storagepools-import-rename input").prop("checked")) {
+ $("#switch-storagepools-import-rename input").click();
+ $("#input-storagepools-import-namenew").focus();
+ }
+ }
+
+ if (validation.storagepools && !validation.name && $("#switch-storagepools-import-rename input").prop("checked") && $("#input-storagepools-import-namenew").val().length >= 2) {
+ validation.name = true;
+ }
+
+ if ($("#switch-storagepools-import-rename input").prop("checked")) {
+ if ($("#input-storagepools-import-namenew").val().length == 0) {
+ $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not be empty.");
+
+ validation.namenew = false;
+ } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepools-import-namenew").val()) == false) {
+ $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name contains invalid characters.");
+
+ validation.namenew = false;
+ } else if (/^[0-9]/.test($("#input-storagepools-import-namenew").val())) {
+ $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with numerical characters.");
+
+ validation.namenew = false;
+ } else if (/^[.]/.test($("#input-storagepools-import-namenew").val())) {
+ $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with a period (.).");
+
+ validation.namenew = false;
+ } else if (/^[_]/.test($("#input-storagepools-import-namenew").val())) {
+ $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with an underscore (_).");
+
+ validation.namenew = false;
+ } else if (/^[-]/.test($("#input-storagepools-import-namenew").val())) {
+ $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with a hypen (-).");
+
+ validation.namenew = false;
+ } else if (/^[:]/.test($("#input-storagepools-import-namenew").val())) {
+ $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with an colon (:).");
+
+ validation.namenew = false;
+ } else if (/^[ ]/.test($("#input-storagepools-import-namenew").val())) {
+ $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with whitespace ( ).");
+
+ validation.namenew = false;
+ } else if (/[ ]$/.test($("#input-storagepools-import-namenew").val())) {
+ $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not end with whitespace ( ).");
+
+ validation.namenew = false;
+ } else if (/^c[0-9]|^log|^mirror|^raidz|^raidz1|^raidz2|^raidz3|^spare/.test($("#input-storagepools-import-namenew").val())) {
+ $("#helpblock-storagepools-import-namenew").addClass("has-error").removeClass("hidden").text("New name can not begin with a reserved name.");
+
+ validation.namenew = false;
+ } else {
+ $("#validationwrapper-storagepools-import-namenew").removeClass("has-error");
+ $("#helpblock-storagepools-import-namenew").addClass("hidden").text("");
+
+ validation.namenew = true;
+ }
+ } else {
+ $("#validationwrapper-storagepools-import-namenew").removeClass("has-error");
+ $("#helpblock-storagepools-import-namenew").removeClass("has-error").addClass("hidden").text("");
+
+ validation.namenew = true;
+ }
+
+ if (/^[a-zA-Z0-9-_.:/ ]*$/.test($("#input-storagepools-import-altroot").val()) == false) {
+ $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root contains invalid characters.");
+
+ validation.altroot = false;
+ } else if ($("#input-storagepools-import-altroot").val() && /^[/]/.test($("#input-storagepools-import-altroot").val()) == false) {
+ $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root is an absolute path and must begin with a forward slash (/).");
+
+ validation.altroot = false;
+ } else if (/^[.]/.test($("#input-storagepools-import-altroot").val())) {
+ $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not begin with a period (.).");
+
+ validation.altroot = false;
+ } else if (/[.]$/.test($("#input-storagepools-import-altroot").val())) {
+ $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not end with a period (.).");
+
+ validation.altroot = false;
+ } else if (/[/][.][/]/g.test($("#input-storagepools-import-altroot").val())) {
+ $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not contain a period as a sub directory (/./).");
+
+ validation.altroot = false;
+ } else if (/[/][.][.][/]/g.test($("#input-storagepools-import-altroot").val())) {
+ $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not contain a double period as a sub directory (/../).");
+
+ validation.altroot = false;
+ } else if (/[/][/]/g.test($("#input-storagepools-import-altroot").val())) {
+ $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not contain double forward slashes (//).");
+
+ validation.altroot = false;
+ } else if (/[.][.]/g.test($("#input-storagepools-import-altroot").val())) {
+ $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not contain a double period (..).");
+
+ validation.altroot = false;
+ } else if (/^[ ]/.test($("#input-storagepools-import-altroot").val())) {
+ $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not begin with whitespace ( ).");
+
+ validation.altroot = false;
+ } else if (/[ ]$/.test($("#input-storagepools-import-altroot").val())) {
+ $("#helpblock-storagepools-import-altroot").addClass("has-error").removeClass("hidden").text("Alt Root can not end with whitespace ( ).");
+
+ validation.altroot = false;
+ } else {
+ $("#validationwrapper-storagepools-import-altroot").removeClass("has-error");
+ $("#helpblock-storagepools-import-altroot").addClass("hidden").text("");
+
+ validation.altroot = true;
+ }
+
+ if (!validation.altroot || !validation.name || !validation.namenew || !validation.storagepools) {
+ if (!validation.name || !validation.storagepools) {
+ $("#validationwrapper-storagepools-import-storagepools").addClass("has-error");
+ }
+ if (!validation.namenew) {
+ $("#validationwrapper-storagepools-import-namenew").addClass("has-error");
+ $("#input-storagepools-import-namenew").focus();
+ }
+ if (!validation.altroot) {
+ $("#validationwrapper-storagepools-import-altroot").addClass("has-error");
+ $("#input-storagepools-import-altroot").focus();
+ }
+
+ $("#spinner-storagepools-import").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.altroot && validation.name && validation.namenew && validation.storagepools) {
+ disks.identifier = $("#btnspan-storagepools-import-disks-identifier").attr("data-field-value");
+
+ filesystem.mount = $("#switch-storagepools-import-mount input").prop("checked");
+ filesystem.selinux = $("#switch-storagepools-import-selinux input").prop("checked");
+
+ pool.altroot = $("#input-storagepools-import-altroot").val();
+ pool.destroyed = $("#switch-storagepools-import-destroyed input").prop("checked");
+ pool.force = $("#switch-storagepools-import-force input").prop("checked");
+ pool.ignoremissinglog = $("#switch-storagepools-import-ignoremissinglog input").prop("checked");
+ pool.namenew = ($("#switch-storagepools-import-rename input").prop("checked") ? $("#input-storagepools-import-namenew").val() : "");
+ pool.readonly = $("#switch-storagepools-import-readonly input").prop("checked");
+ pool.recoverymode = $("#switch-storagepools-import-recoverymode input").prop("checked");
+
+ FnStoragePoolImport({ name: pool.name, altroot: pool.altroot, destroyed: pool.destroyed, force: pool.force, guid: pool.guid, ignoremissinglog: pool.ignoremissinglog, namenew: pool.namenew, readonly: pool.readonly, recoverymode: pool.recoverymode }, { mount: filesystem.mount, selinux: filesystem.selinux }, { id: { blockdevice: disks.id.blockdevice, disk: disks.id.disk, path: disks.id.path, vdev: disks.id.vdev }, identifier: disks.identifier });
+ }
+ });
+
+ $("#dropdown-storagepools-import-disks-identifier").on("click", "li a", function () {
+ $("#btnspan-storagepools-import-disks-identifier").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+//#endregion
+
+//#region Modal Storage Pool
+
+function FnModalStoragePoolConfigure(pool = { name, id, boot: false, guid, readonly: false, root: false }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-configure-` + pool.id + `").on("click", function () {
+ FnModalStoragePoolConfigureContent({ name: "` + pool.name + `", id: "` + pool.id + `", guid: "` + pool.guid + `", readonly: ` + pool.readonly + ` }, { id: $("#modal-storagepool-configure-` + pool.id + `") });
+ FnStoragePoolConfigurationGet({ name: "` + pool.name + `", id: "` + pool.id + `", boot: ` + pool.boot + `, root: ` + pool.root + ` }, { name: "storagepool-configure", id: "` + pool.id + `" });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-" + pool.id).append(modal.window);
+}
+
+function FnModalStoragePoolConfigureContent(pool = { name, id, guid, readonly: false }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-configure-multihost-` + pool.id + ` input").on("click", function () {
+ FnSystemHostIdGet({ name: "storagepool-configure", id: "` + pool.id + `" });
+
+ if (!$(this).prop("checked")) {
+ $("#controllabel-storagepool-configure-hostid-` + pool.id + `").addClass("hidden");
+ $("#validationwrapper-storagepool-configure-hostid-` + pool.id + `").addClass("hidden");
+ }
+ });
+
+ $("#btn-storagepool-configure-apply-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-configure-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let modal = {
+ id: ""
+ };
+ let pool = {
+ ashift: 0,
+ autoexpand: "",
+ autoreplace: "",
+ autotrim: "",
+ comment: "",
+ delegation: "",
+ failmode: "",
+ listsnapshots: "",
+ multihost: ""
+ };
+ let system = {
+ hostid: false
+ };
+ let validation = {
+ comment: false
+ };
+
+ if ($("#input-storagepool-configure-comment-` + pool.id + `").val().length > 32) {
+ $("#helpblock-storagepool-configure-comment-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Comment can not be longer than 32 characters.");
+
+ validation.comment = false;
+ } else if (/^[ -~]*$/.test($("#input-storagepool-configure-comment-` + pool.id + `").val()) == false) {
+ $("#helpblock-storagepool-configure-comment-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Comment contains invalid characters.");
+
+ validation.comment = false;
+ } else {
+ $("#validationwrapper-storagepool-configure-comment-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-configure-comment-` + pool.id + `").addClass("hidden").text("");
+
+ validation.comment = true;
+ }
+
+ if (!validation.comment) {
+ $("#validationwrapper-storagepool-configure-comment-` + pool.id + `").addClass("has-error");
+ $("#input-storagepool-configure-comment-` + pool.id + `").focus();
+
+ $("#spinner-storagepool-configure-` + pool.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.comment) {
+ modal.id = $("#modal-storagepool-configure-` + pool.id + `");
+
+ pool.ashift = ($("#btnspan-storagepool-configure-ashift-` + pool.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-configure-ashift-` + pool.id + `").attr("data-field-value-new") : null);
+ pool.autoexpand = ($("#switch-storagepool-configure-autoexpand-` + pool.id + ` input").prop("checked") ? "on" : "off");
+ pool.autoreplace = ($("#switch-storagepool-configure-autoreplace-` + pool.id + ` input").prop("checked") ? "on" : "off");
+ pool.autotrim = ($("#switch-storagepool-configure-autotrim-` + pool.id + ` input").prop("checked") ? "on" : "off");
+ pool.comment = $("#input-storagepool-configure-comment-` + pool.id + `").val();
+ pool.delegation = ($("#switch-storagepool-configure-delegation-` + pool.id + ` input").prop("checked") ? "on" : "off");
+ pool.failmode = ($("#btnspan-storagepool-configure-failmode-` + pool.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-configure-failmode-` + pool.id + `").attr("data-field-value-new") : null);
+ pool.listsnapshots = ($("#switch-storagepool-configure-listsnapshots-` + pool.id + ` input").prop("checked") ? "on" : "off");
+ pool.multihost = ($("#switch-storagepool-configure-multihost-` + pool.id + ` input").prop("checked") ? "on" : "off");
+
+ if (!$("#validationwrapper-storagepool-configure-hostid-` + pool.id + `").hasClass("hidden")) {
+ system.hostid = $("#btnspan-storagepool-configure-hostid-` + pool.id + `").attr("data-field-value");
+ } else {
+ if ($("#btnspan-storagepool-configure-hostid-` + pool.id + `").attr("data-field-value") == "missing") { //Host ID is missing - Generate Host ID before disabling multihost property to avoid error
+ system.hostid = "libc";
+ }
+ }
+
+ //Set values to null if unchanged, so that they are skipped in the configure function
+ if (pool.ashift == $("#btnspan-storagepool-configure-ashift-` + pool.id + `").attr("data-field-value")) {
+ pool.ashift = null;
+ }
+ if (pool.autoexpand == $("#switch-storagepool-configure-autoexpand-` + pool.id + `").attr("data-field-value")) {
+ pool.autoexpand = null;
+ }
+ if (pool.autoreplace == $("#switch-storagepool-configure-autoreplace-` + pool.id + `").attr("data-field-value")) {
+ pool.autoreplace = null;
+ }
+ if (pool.autotrim == $("#switch-storagepool-configure-autotrim-` + pool.id + `").attr("data-field-value")) {
+ pool.autotrim = null;
+ }
+ if (pool.comment == $("#input-storagepool-configure-comment-` + pool.id + `").attr("data-field-value")) {
+ pool.comment = null;
+ } else if (pool.comment != $("#input-storagepool-configure-comment-` + pool.id + `").attr("data-field-value") && !pool.comment) {
+ pool.comment = "$empty";
+ }
+ if (pool.failmode == $("#btnspan-storagepool-configure-failmode-` + pool.id + `").attr("data-field-value")) {
+ pool.failmode = null;
+ }
+ if (pool.delegation == $("#switch-storagepool-configure-delegation-` + pool.id + `").attr("data-field-value")) {
+ pool.delegation = null;
+ }
+ if (pool.listsnapshots == $("#switch-storagepool-configure-listsnapshots-` + pool.id + `").attr("data-field-value")) {
+ pool.listsnapshots = null;
+ }
+ if (pool.multihost == $("#switch-storagepool-configure-multihost-` + pool.id + `").attr("data-field-value")) {
+ pool.multihost = null;
+ }
+
+ FnStoragePoolConfigure({ name: "` + pool.name + `", id: "` + pool.id + `", ashift: pool.ashift, autoexpand: pool.autoexpand, autoreplace: pool.autoreplace, autotrim: pool.autotrim, comment: pool.comment, delegation: pool.delegation, failmode: pool.failmode, listsnapshots: pool.listsnapshots, multihost: pool.multihost, readonly: ` + pool.readonly + ` }, { hostid: system.hostid }, { id: modal.id });
+ }
+ });
+
+ $("#dropdown-storagepool-configure-ashift-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-configure-ashift-` + pool.id + `").text($(this).text()).attr("data-field-value-new", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-configure-failmode-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-configure-failmode-` + pool.id + `").text($(this).text()).attr("data-field-value-new", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-configure-hostid-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-configure-hostid-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStoragePoolConfigureFeatures(pool = { name, id, boot: false, readonly: false }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-configure-features-` + pool.id + `").on("click", function () {
+ FnModalStoragePoolConfigureFeaturesContent({ name: "` + pool.name + `", id: "` + pool.id + `", boot: ` + pool.boot + `, readonly: ` + pool.readonly + ` }, { id: $("#modal-storagepool-configure-features-` + pool.id + `") });
+ FnStoragePoolConfigurationFeaturesGet({ name: "` + pool.name + `", id: "` + pool.id + `", boot: ` + pool.boot + ` }, { name: "storagepool-configure-features", id: "` + pool.id + `" });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-" + pool.id).append(modal.window);
+}
+
+function FnModalStoragePoolConfigureFeaturesContent(pool = { name, id, boot: false, readonly: false }, modal = { id }) {
+ pool.version = $("#tr-storagepool-" + pool.id).attr("data-pool-version");
+
+ modal.content = `
+
+
+
+
+
Pool: ` + pool.name + `
+ ` + (pool.boot ? FnDisplayInlineAlert({ status: "danger", title: "Changes to the boot storage pool may cause an unbootable system.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
+ ` + FnDisplayInlineAlert({ status: ($.isNumeric(pool.version) ? "danger" : "warning"), title: ($.isNumeric(pool.version) ? "The storage pool will no longer be accessible on software that does not support feature flags." : "Once a feature is enabled the pool may become incompatible with software that does not support the feature.") + " Features can not be disabled once they have been enabled.", description: null }, { name: "storagepool-configure-features-compatibility", id: pool.id, hidden: true }) + `
+
+ Allocation Classes
+
+
+
+ Asynchronous Destroy
+
+
+
+ Bookmarks
+
+
+
+ Bookmarks Version 2
+
+
+
+ Checkpoint
+
+
+
+ Device Removal
+
+
+
+ Edon-R
+
+
+
+ Embedded Data
+
+
+
+ Empty Block Pointer Objects
+
+
+
+ Encryption
+
+
+
+ Extensible Dataset
+
+
+
+ File System Limits
+
+
+
+ Hole Birth
+
+
+
+ Large Blocks
+
+
+
+ Large DNode
+
+
+
+ LZ4 Compression
+
+
+
+ Multi Virtual Device Crash Dump
+
+
+
+ Obsolete Counts
+
+
+
+ Project Quota
+
+
+
+ Resilver Defer
+
+
+
+ SHA-512
+
+
+
+ Skein
+
+
+
+ Space Map Histogram
+
+
+
+ Space Map Version 2
+
+
+
+ Transaction Group Accounting
+
+
+
+ User Object Accounting
+
+
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("[id^=switch-storagepool-configure-features-][id$='-` + pool.id + `'] input").on("click", function () {
+ if ($(this).prop("checked") && $(this).parent().attr("data-field-value") == "disabled") {
+ $("#alert-storagepool-configure-features-compatibility-` + pool.id + `").removeClass("hidden");
+ }
+
+ FnModalStoragePoolConfigureFeaturesDependencies({ name: "` + pool.name + `", id: "` + pool.id + `" }, { switch: { id: $(this) } });
+ });
+
+ $("#btn-storagepool-configure-features-apply-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-configure-features-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let modal = {
+ id: ""
+ };
+
+ let pool = {
+ feature: {
+ allocation_classes: ($("#switch-storagepool-configure-features-allocation_classes-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-allocation_classes-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ async_destroy: ($("#switch-storagepool-configure-features-async_destroy-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-async_destroy-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ bookmark_v2: ($("#switch-storagepool-configure-features-bookmark_v2-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-bookmark_v2-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ bookmarks: ($("#switch-storagepool-configure-features-bookmarks-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-bookmarks-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ device_removal: ($("#switch-storagepool-configure-features-device_removal-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-device_removal-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ edonr: ($("#switch-storagepool-configure-features-edonr-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-edonr-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ embedded_data: ($("#switch-storagepool-configure-features-embedded_data-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-embedded_data-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ empty_bpobj: ($("#switch-storagepool-configure-features-empty_bpobj-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-empty_bpobj-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ enabled_txg: ($("#switch-storagepool-configure-features-enabled_txg-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-enabled_txg-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ encryption: ($("#switch-storagepool-configure-features-encryption-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-encryption-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ extensible_dataset: ($("#switch-storagepool-configure-features-extensible_dataset-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ filesystem_limits: ($("#switch-storagepool-configure-features-filesystem_limits-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-filesystem_limits-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ hole_birth: ($("#switch-storagepool-configure-features-hole_birth-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-hole_birth-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ large_blocks: ($("#switch-storagepool-configure-features-large_blocks-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-large_blocks-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ large_dnode: ($("#switch-storagepool-configure-features-large_dnode-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-large_dnode-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ lz4_compress: ($("#switch-storagepool-configure-features-lz4_compress-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-lz4_compress-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ multi_vdev_crash_dump: ($("#switch-storagepool-configure-features-multi_vdev_crash_dump-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-multi_vdev_crash_dump-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ obsolete_counts: ($("#switch-storagepool-configure-features-obsolete_counts-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-obsolete_counts-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ project_quota: ($("#switch-storagepool-configure-features-project_quota-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-project_quota-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ resilver_defer: ($("#switch-storagepool-configure-features-resilver_defer-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-resilver_defer-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ sha512: ($("#switch-storagepool-configure-features-sha512-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-sha512-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ skein: ($("#switch-storagepool-configure-features-skein-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-skein-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ spacemap_histogram: ($("#switch-storagepool-configure-features-spacemap_histogram-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-spacemap_histogram-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ spacemap_v2: ($("#switch-storagepool-configure-features-spacemap_v2-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-spacemap_v2-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ userobj_accounting: ($("#switch-storagepool-configure-features-userobj_accounting-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-userobj_accounting-` + pool.id + ` input").prop("disabled") ? "enabled" : null),
+ zpool_checkpoint: ($("#switch-storagepool-configure-features-zpool_checkpoint-` + pool.id + ` input").prop("checked") && !$("#switch-storagepool-configure-features-zpool_checkpoint-` + pool.id + ` input").prop("disabled") ? "enabled" : null)
+ }
+ };
+
+ FnStoragePoolConfigureFeatures({ name: "` + pool.name + `", id: "` + pool.id + `", feature: { allocation_classes: pool.feature.allocation_classes, async_destroy: pool.feature.async_destroy, bookmark_v2: pool.feature.bookmark_v2, bookmarks: pool.feature.bookmarks, device_removal: pool.feature.device_removal, edonr: pool.feature.edonr, embedded_data: pool.feature.embedded_data, empty_bpobj: pool.feature.empty_bpobj, enabled_txg: pool.feature.enabled_txg, encryption: pool.feature.encryption, extensible_dataset: pool.feature.extensible_dataset, filesystem_limits: pool.feature.filesystem_limits, hole_birth: pool.feature.hole_birth, large_blocks: pool.feature.large_blocks, large_dnode: pool.feature.large_dnode, lz4_compress: pool.feature.lz4_compress, multi_vdev_crash_dump: pool.feature.multi_vdev_crash_dump, obsolete_counts: pool.feature.obsolete_counts, project_quota: pool.feature.project_quota, resilver_defer: pool.feature.resilver_defer, sha512: pool.feature.sha512, skein: pool.feature.skein, spacemap_histogram: pool.feature.spacemap_histogram, spacemap_v2: pool.feature.spacemap_v2, userobj_accounting: pool.feature.userobj_accounting, zpool_checkpoint: pool.feature.zpool_checkpoint }, readonly: ` + pool.readonly + ` }, { id: $("#modal-storagepool-configure-features-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStoragePoolConfigureFeaturesDependencies(pool = { name, id }, modal = { switch: { id } }) {
+ if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-bookmarks-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
+ }
+ } else {
+ if ($("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").click();
+ }
+ if ($("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-encryption-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-bookmark_v2-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").click();
+ }
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
+ }
+ } else {
+ if ($("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-encryption-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-device_removal-" + pool.id) {
+ if (!$("#switch-storagepool-configure-features-device_removal-" + pool.id + " input").prop("checked")) {
+ if ($("#switch-storagepool-configure-features-obsolete_counts-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-obsolete_counts-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-obsolete_counts-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-edonr-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-edonr-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-enabled_txg-" + pool.id) {
+ if (!$("#switch-storagepool-configure-features-enabled_txg-" + pool.id + " input").prop("checked")) {
+ if ($("#switch-storagepool-configure-features-hole_birth-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-hole_birth-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-hole_birth-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-encryption-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").click();
+ }
+ if (!$("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").click();
+ }
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-extensible_dataset-" + pool.id) {
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked")) {
+ if ($("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-bookmarks-" + pool.id + " input").click();
+ }
+ if ($("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-bookmark_v2-" + pool.id + " input").click();
+ }
+ if ($("#switch-storagepool-configure-features-edonr-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-edonr-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-edonr-" + pool.id + " input").click();
+ }
+ if ($("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-encryption-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-encryption-" + pool.id + " input").click();
+ }
+ if ($("#switch-storagepool-configure-features-filesystem_limits-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-filesystem_limits-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-filesystem_limits-" + pool.id + " input").click();
+ }
+ if ($("#switch-storagepool-configure-features-large_blocks-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-large_blocks-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-large_blocks-" + pool.id + " input").click();
+ }
+ if ($("#switch-storagepool-configure-features-large_dnode-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-large_dnode-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-large_dnode-" + pool.id + " input").click();
+ }
+ if ($("#switch-storagepool-configure-features-project_quota-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-project_quota-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-project_quota-" + pool.id + " input").click();
+ }
+ if ($("#switch-storagepool-configure-features-sha512-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-sha512-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-sha512-" + pool.id + " input").click();
+ }
+ if ($("#switch-storagepool-configure-features-skein-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-skein-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-skein-" + pool.id + " input").click();
+ }
+ if ($("#switch-storagepool-configure-features-userobj_accounting-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-userobj_accounting-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-userobj_accounting-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-filesystem_limits-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-filesystem_limits-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-hole_birth-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-hole_birth-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-enabled_txg-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-enabled_txg-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-enabled_txg-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-large_blocks-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-large_blocks-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-large_dnode-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-large_dnode-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-obsolete_counts-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-obsolete_counts-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-device_removal-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-device_removal-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-device_removal-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-project_quota-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-project_quota-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-sha512-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-sha512-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-skein-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-skein-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
+ }
+ }
+ } else if (modal.switch.id.parent().attr("id") == "switch-storagepool-configure-features-userobj_accounting-" + pool.id) {
+ if ($("#switch-storagepool-configure-features-userobj_accounting-" + pool.id + " input").prop("checked")) {
+ if (!$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("checked") && !$("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").prop("disabled")) {
+ $("#switch-storagepool-configure-features-extensible_dataset-" + pool.id + " input").click();
+ }
+ }
+ }
+}
+
+function FnModalStoragePoolDestroy(pool = { name, id, altroot: false }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-destroy-` + pool.id + `").on("click", function () {
+ FnModalStoragePoolDestroyContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { id: $("#modal-storagepool-destroy-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-" + pool.id).append(modal.window);
+}
+
+function FnModalStoragePoolDestroyContent(pool = { name, id, altroot: false }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-destroy-apply-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-destroy-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let pool = {
+ force: $("#switch-storagepool-destroy-force-` + pool.id + ` input").prop("checked"),
+ labelclear: $("#switch-storagepool-destroy-labelclear-` + pool.id + ` input").prop("checked")
+ };
+ let samba = {
+ restart: $("#switch-storagepool-destroy-samba-restart-` + pool.id + ` input").prop("checked")
+ };
+
+ FnStoragePoolDestroy({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, force: pool.force, labelclear: pool.labelclear }, { restart: samba.restart });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStoragePoolExport(pool = { name, id, altroot: false, readonly: false }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-export-` + pool.id + `").on("click", function () {
+ FnModalStoragePoolExportContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { id: $("#modal-storagepool-export-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-" + pool.id).append(modal.window);
+}
+
+function FnModalStoragePoolExportContent(pool = { name, id, altroot: false, readonly: false }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to export storage pool: ` + pool.name + ` ?
+
+ Options
+
+ Forcefully unmount all file systems
+
+
+ Restart Samba service
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-export-apply-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-export-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let pool = {
+ force: $("#switch-storagepool-export-force-` + pool.id + ` input").prop("checked")
+ };
+ let samba = {
+ restart: $("#switch-storagepool-export-samba-restart-` + pool.id + ` input").prop("checked")
+ };
+
+ FnStoragePoolExport({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, force: pool.force, readonly: ` + pool.readonly + ` }, { restart: samba.restart });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+//#endregion
+
+//#region Modal File Systems
+
+function FnModalFileSystemsCreate(pool = { name, id, altroot: false, feature: { allocation_classes: true, edonr: true, encryption: true, large_blocks: true, large_dnode: true, lz4_compress: true, sha512: true, skein: true } }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystems-create-` + pool.id + `").on("click", function () {
+ FnModalFileSystemsCreateContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, feature: { allocation_classes: ` + pool.feature.allocation_classes + `, edonr: ` + pool.feature.edonr + `, encryption: ` + pool.feature.encryption + `, large_blocks: ` + pool.feature.large_blocks + `, large_dnode: ` + pool.feature.large_dnode + `, lz4_compress: ` + pool.feature.lz4_compress + `, sha512: ` + pool.feature.sha512 + `, skein: ` + pool.feature.skein + ` } }, { id: $("#modal-storagepool-filesystems-create-` + pool.id + `") });
+ FnFileSystemsNamesGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { existing: { name: null, clone: false, encryption: false, encryptionroot: null, origin: null}, override: true }, { dropdown: { id: $("#dropdown-storagepool-filesystems-create-parentfilesystem-` + pool.id + `"), selected: "` + pool.name + `" } });
+ FnFileSystemConfigurationInheritedGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + pool.name + `" }, { name: "storagepool-filesystems-create", id: "` + pool.id + `" });
+
+ $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val("0");
+ $("#validationwrapper-storagepool-filesystems-create-quota-` + pool.id + ` .min-slider-handle").attr("tabindex", "15");
+ setTimeout(function() {
+ $("#input-storagepool-filesystems-create-name-` + pool.id + `").focus();
+ }, 600);
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystems-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemsCreateContent(pool = { name, id, altroot: false, feature: { allocation_classes: true, edonr: true, encryption: true, large_blocks: true, large_dnode: true, lz4_compress: true, sha512: true, skein: true } }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
+ Parent File System
+
+ Name
+
+
+
+
+ Encryption
+
+
+
+ Passphrase
+
+ ` + (!pool.feature.encryption ? FnDisplayInlineAlert({ status: "warning", title: "Encryption feature flag is not enabled on storage pool.", description: null }, { name: "storagepool-filesystems-create-encryption", id: pool.id, hidden: false }) : ``) + `
+
+
+
+ Confirm Passphrase
+
+
+
+
+ Cipher
+
+ Access Time
+
+ Case Sensitivity
+
+ Compression
+
+ Deduplication
+
+ DNode Size
+
+ Extended Attributes
+
+ NFS Share
+
+
+
+ NFS Options
+
+ ` + FnDisplayInlineAlert({ status: "warning", title: "NFS is not installed.", description: null }, { name: "storagepool-filesystems-create-sharenfs-options", id: pool.id, hidden: true }) + `
+
+
+
+ Quota
+
+ Record Size
+
+ Special Small Blocks
+
+ ` + FnDisplayInlineAlert({ status: "warning", title: "Allocation Classes feature flag is not enabled on storage pool.", description: null }, { name: "storagepool-filesystems-create-special_small_blocks", id: pool.id, hidden: true }) + `
+
+
+ Options
+
+ SELinux contexts for Samba
+
+
+ Enable Samba share
+
+
+ Read only
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#input-storagepool-filesystems-create-quota-` + pool.id + `").tooltip({ trigger: "manual" })
+ .on("keyup", function (element) {
+ let $this = $(this);
+ let sd = $this.siblings("[data-provide=slider]").slider();
+
+ if ($this.val().trim() && !$.isNumeric(this.value)) {
+ this.value = sd.slider("getValue");
+ }
+ })
+ .on("keypress blur", function (element) {
+ if (element.which == 13 || element.type === "blur") {
+ element.preventDefault();
+
+ let $this = $(this);
+ let sd = $this.siblings("[data-provide=slider]").slider();
+ let max = sd.slider("getAttribute", "max");
+ let min = sd.slider("getAttribute", "min");
+
+ if (!$.isNumeric(this.value) || (this.value > max || this.value < min)) {
+ let warningInfo = $.isNumeric(this.value) ? "Valid value should be between " + min + " and " + max : "Valid value should be number";
+ $this.attr("data-original-title", warningInfo).tooltip("show").addClass("warning");
+ this.value = sd.slider("getValue");
+ setTimeout(function () {
+ $this.tooltip("hide");
+ }, 3000);
+ } else {
+ if ($this.is(".warning")) {
+ $this.tooltip("hide");
+ }
+
+ this.value = $this.val().trim();
+ sd.slider("setValue", this.value);
+ }
+ }
+ })
+ .siblings("[data-provide=slider]").each(function () {
+ $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val(this.value);
+ $(this).slider().on("change", function (element) {
+ $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val(element.value.newValue);
+ });
+ });
+
+ $("#input-storagepool-filesystems-create-quota-` + pool.id + `").on("change textInput input", function (element) {
+ if ($(this).val() > 1000) { //Force reset to maximum allowed value
+ $(this).val(1000);
+ } else if ($(this).val() < 0) { //Force reset to minimum allowed value
+ $(this).val(0);
+ }
+
+ if ($.isNumeric($(this).val())) {
+ $("#slider-storagepool-filesystems-create-quota-` + pool.id + `").slider("setValue", $(this).val());
+ }
+ });
+
+ $("#switch-storagepool-filesystems-create-encryption-` + pool.id + ` input").on("click", function () {
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ if ($(this).prop("checked")) {
+ $("#controllabel-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("hidden");
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("hidden");
+ $("#controllabel-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("hidden");
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("hidden");
+ $("#controllabel-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").removeClass("hidden");
+ $("#validationwrapper-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").removeClass("hidden");
+ } else {
+ $("#controllabel-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("hidden");
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("hidden");
+ $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val("");
+ $("#controllabel-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").addClass("hidden");
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").addClass("hidden");
+ $("#input-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").val("");
+ $("#controllabel-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").addClass("hidden");
+ $("#validationwrapper-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").addClass("hidden");
+ }
+ });
+
+ $("#switch-storagepool-filesystems-create-sharenfs-` + pool.id + ` input").on("click", function () {
+ $("#validationwrapper-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ if ($(this).prop("checked")) {
+ $("#controllabel-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").removeClass("hidden");
+ $("#validationwrapper-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").removeClass("hidden");
+
+ FnSystemNfsVersionGet({ alert: { id: $("#alert-storagepool-filesystems-create-sharenfs-options-` + pool.id + `") } });
+ } else {
+ $("#validationwrapper-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").addClass("hidden");
+ $("#controllabel-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").addClass("hidden");
+ }
+ });
+
+ $("#btn-storagepool-filesystems-create-apply-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystems-create-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let filesystem = {
+ name: "",
+ id: "",
+ atime: "",
+ casesensitivity: "",
+ cipher: "",
+ compression: "",
+ dedup: "",
+ dnodesize: "",
+ encryption: "",
+ passphrase: "",
+ quota: "none",
+ readonly: "",
+ recordsize: "",
+ selinux: "",
+ sharesmb: "",
+ special_small_blocks: "",
+ xattr: ""
+ };
+ let validation = {
+ encryption: false,
+ name: false,
+ sharenfs: false
+ };
+
+ if ($("#input-storagepool-filesystems-create-name-` + pool.id + `").val().length == 0) {
+ $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
+
+ validation.name = false;
+ } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val()) == false) {
+ $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
+
+ validation.name = false;
+ } else if (/^[.]/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
+
+ validation.name = false;
+ } else if (/^[_]/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
+
+ validation.name = false;
+ } else if (/^[-]/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
+
+ validation.name = false;
+ } else if (/^[:]/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
+
+ validation.name = false;
+ } else if (/^[ ]/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
+
+ validation.name = false;
+ } else if (/[ ]$/.test($("#input-storagepool-filesystems-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
+
+ validation.name = false;
+ } else {
+ $("#validationwrapper-storagepool-filesystems-create-name-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-name-` + pool.id + `").addClass("hidden").text("");
+
+ validation.name = true;
+ }
+ if ($("#switch-storagepool-filesystems-create-encryption-` + pool.id + ` input").prop("checked")) {
+ if ($("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val().length == 0 && $("#switch-storagepool-filesystems-create-encryption-` + pool.id + ` input").prop("disabled")) {
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ validation.encryption = true;
+ } else if ($("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val().length == 0) {
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Passphrase can not be empty.");
+ $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").focus();
+
+ validation.encryption = false;
+ } else if ($("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val().length < 8) {
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
+ $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").focus();
+
+ validation.encryption = false;
+ } else if (/^[a-zA-Z0-9-_. \`~!@#$%^\(\)+\\[\\]{}:',/?]*$/.test($("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val()) == false) {
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Passphrase contains invalid characters.");
+ $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").focus();
+
+ validation.encryption = false;
+ } else if ($("#input-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").val().length < 8 || $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val() != $("#input-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").val()) {
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error").removeClass("hidden").text("");
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").addClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Passphrase does not match");
+ $("#input-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").focus();
+
+ validation.encryption = false;
+ } else {
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
+ $("#validationwrapper-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-encryption-passphrase-confirm-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ validation.encryption = true;
+ }
+ } else {
+ validation.encryption = true;
+ }
+
+ if ($("#switch-storagepool-filesystems-create-sharenfs-` + pool.id + ` input").prop("checked")) {
+ if (/^[a-zA-Z0-9-_.:/@#+=!&*(), ]*$/.test($("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").val()) == false) {
+ $("#validationwrapper-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").addClass("has-error");
+ $("#helpblock-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").addClass("has-error").removeClass("hidden").text("NFS Share options contain invalid characters.");
+ $("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").focus();
+
+ validation.sharenfs = false;
+ } else {
+ validation.sharenfs = true;
+ }
+ } else {
+ validation.sharenfs = true;
+ }
+
+ if (!validation.name || !validation.encryption || !validation.sharenfs) {
+ if (!validation.name) {
+ $("#validationwrapper-storagepool-filesystems-create-name-` + pool.id + `").addClass("has-error");
+ $("#input-storagepool-filesystems-create-name-` + pool.id + `").focus();
+ }
+
+ $("#spinner-storagepool-filesystems-create-` + pool.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.name && validation.encryption && validation.sharenfs) {
+ filesystem.atime = $("#btnspan-storagepool-filesystems-create-atime-` + pool.id + `").attr("data-field-value");
+ filesystem.casesensitivity = $("#btnspan-storagepool-filesystems-create-casesensitivity-` + pool.id + `").attr("data-field-value");
+ filesystem.cipher = $("#btnspan-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").attr("data-field-value");
+ filesystem.compression = $("#btnspan-storagepool-filesystems-create-compression-` + pool.id + `").attr("data-field-value");
+ filesystem.dedup = $("#btnspan-storagepool-filesystems-create-dedup-` + pool.id + `").attr("data-field-value");
+ filesystem.dnodesize = $("#btnspan-storagepool-filesystems-create-dnodesize-` + pool.id + `").attr("data-field-value");
+ filesystem.encryption = $("#switch-storagepool-filesystems-create-encryption-` + pool.id + ` input").prop("checked");
+ filesystem.name = $("#btnspan-storagepool-filesystems-create-parentfilesystem-` + pool.id + `").attr("data-field-value") + "/" + $("#input-storagepool-filesystems-create-name-` + pool.id + `").val();
+ filesystem.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: filesystem.name, attribute: true });
+ filesystem.passphrase = $("#input-storagepool-filesystems-create-encryption-passphrase-` + pool.id + `").val();
+ filesystem.readonly = ($("#switch-storagepool-filesystems-create-readonly-` + pool.id + ` input").prop("checked") ? "on" : "off");
+ filesystem.recordsize = $("#btnspan-storagepool-filesystems-create-recordsize-` + pool.id + `").attr("data-field-value");
+ filesystem.selinux = ($("#switch-storagepool-filesystems-create-selinux-` + pool.id + ` input").prop("checked") ? "on" : "off");
+ filesystem.sharesmb = ($("#switch-storagepool-filesystems-create-samba-share-` + pool.id + ` input").prop("checked") ? "on" : "off");
+ filesystem.special_small_blocks = $("#btnspan-storagepool-filesystems-create-special_small_blocks-` + pool.id + `").attr("data-field-value");
+ filesystem.xattr = $("#btnspan-storagepool-filesystems-create-xattr-` + pool.id + `").attr("data-field-value");
+
+ if ($("#switch-storagepool-filesystems-create-sharenfs-` + pool.id + ` input").prop("checked")) {
+ if ($("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").val().toLowerCase() == "on" || $("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").val() == "sec=sys,rw,crossmnt,no_subtree_check,no_root_squash" || !$("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").val()) {
+ filesystem.sharenfs = "on";
+ } else {
+ filesystem.sharenfs = $("#input-storagepool-filesystems-create-sharenfs-options-` + pool.id + `").val();
+ }
+ } else {
+ filesystem.sharenfs = "off";
+ }
+
+ if ($("#input-storagepool-filesystems-create-quota-` + pool.id + `").val() > 0) { //Remove friendly text so final value is sent
+ filesystem.quota = $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val() + $("#btnspan-storagepool-filesystems-create-quota-` + pool.id + `").attr("data-field-value").replace(/iB$/g, "");
+ } else {
+ filesystem.quota = "none";
+ }
+
+ FnFileSystemCreate({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { name: filesystem.name, id: filesystem.id, atime: filesystem.atime, casesensitivity: filesystem.casesensitivity, cipher: filesystem.cipher, compression: filesystem.compression, dedup: filesystem.dedup, dnodesize: filesystem.dnodesize, encryption: filesystem.encryption, passphrase: filesystem.passphrase, quota: filesystem.quota, readonly: filesystem.readonly, recordsize: filesystem.recordsize, selinux: filesystem.selinux, sharenfs: filesystem.sharenfs, sharesmb: filesystem.sharesmb, special_small_blocks: filesystem.special_small_blocks, xattr: filesystem.xattr });
+ }
+ });
+
+ $("#dropdown-storagepool-filesystems-create-parentfilesystem-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystems-create-parentfilesystem-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+
+ FnFileSystemConfigurationInheritedGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: $(this).text() }, { name: "storagepool-filesystems-create", id: "` + pool.id + `" });
+ });
+
+ $("#dropdown-storagepool-filesystems-create-atime-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystems-create-atime-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystems-create-casesensitivity-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystems-create-casesensitivity-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystems-create-compression-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystems-create-compression-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystems-create-dedup-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystems-create-dedup-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystems-create-dnodesize-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystems-create-dnodesize-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystems-create-encryption-cipher-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystems-create-quota-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystems-create-quota-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).text());
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+
+ let size = {
+ slider: {
+ value: $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val(),
+ valuemax: $("#input-storagepool-filesystems-create-quota-` + pool.id + `").attr("data-filesystem-quota-max-" + $(this).text().toLowerCase())
+ }
+ };
+
+ $("#slider-storagepool-filesystems-create-quota-` + pool.id + `").data("slider").options.max = size.slider.valuemax;
+ $("#slider-storagepool-filesystems-create-quota-` + pool.id + `").data("slider").options.step = (size.slider.valuemax < 10 ? "0.1" : "1");
+ $("#slider-storagepool-filesystems-create-quota-` + pool.id + `").slider("setValue", 0); //Force display update
+ $("#slider-storagepool-filesystems-create-quota-` + pool.id + `").slider("setValue", size.slider.value);
+ $("#input-storagepool-filesystems-create-quota-` + pool.id + `").val($("#slider-storagepool-filesystems-create-quota-` + pool.id + `").data("slider").getValue());
+ });
+
+ $("#dropdown-storagepool-filesystems-create-recordsize-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystems-create-recordsize-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystems-create-special_small_blocks-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystems-create-special_small_blocks-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystems-create-xattr-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystems-create-xattr-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemsUnlock() {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepools-filesystems-unlock").on("click", function () {
+ FnModalFileSystemsUnlockContent({ id: $("#modal-storagepools-filesystems-unlock") });
+ FnFileSystemsLockedGet();
+
+ setTimeout(function() {
+ $("#input-storagepools-filesystems-unlock-passphrase").focus();
+ }, 600);
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepools-filesystems").append(modal.window);
+}
+
+function FnModalFileSystemsUnlockContent(modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepools-filesystems-unlock-mount input").on("click", function () {
+ if ($(this).prop("checked")) {
+ $("#switch-storagepools-filesystems-unlock-overlay").parent().removeClass("hidden");
+ } else {
+ $("#switch-storagepools-filesystems-unlock-overlay").parent().addClass("hidden");
+ }
+ });
+
+ $("#btn-storagepools-filesystems-unlock-apply").on("click", function () {
+ $("#spinner-storagepools-filesystems-unlock").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let filesystem = {
+ mount: true,
+ passphrase: ""
+ };
+ let filesystems = {
+ id: []
+ };
+ let modal = {
+ name: "storagepools-filesystems-unlock",
+ id: ""
+ };
+ let samba = {
+ enable: false
+ };
+ let validation = {
+ filesystems: false,
+ passphrase: false
+ };
+
+ $("#listgroup-storagepools-filesystems-unlock-filesystems input[name='checkbox-storagepools-filesystems-unlock-filesystems']:checked").map(function () {
+ filesystems.id.push($(this).attr("data-filesystem-name"));
+ });
+
+ if (filesystems.id.length == 0) {
+ $("#validationwrapper-storagepools-filesystems-unlock-filesystems").addClass("has-error");
+ $("#helpblock-storagepools-filesystems-unlock-filesystems").removeClass("hidden").text("One or more file systems is needed for unlock.");
+
+ validation.filesystems = false;
+ } else {
+ $("#validationwrapper-storagepools-filesystems-unlock-filesystems").removeClass("has-error");
+ $("#helpblock-storagepools-filesystems-unlock-filesystems").removeClass("hidden").text("");
+
+ validation.filesystems = true;
+ }
+
+ if ($("#input-storagepools-filesystems-unlock-passphrase").val().length == 0) {
+ $("#helpblock-storagepools-filesystems-unlock-passphrase").addClass("has-error").removeClass("hidden").text("Passphrase can not be empty.");
+
+ validation.passphrase = false;
+ } else if ($("#input-storagepools-filesystems-unlock-passphrase").val().length < 8) {
+ $("#helpblock-storagepools-filesystems-unlock-passphrase").addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
+
+ validation.passphrase = false;
+ } else if (/^[a-zA-Z0-9-_. \`~!@#$%^\(\)+\\[\\]{}:',/?]*$/.test($("#input-storagepools-filesystems-unlock-passphrase").val()) == false) {
+ $("#helpblock-storagepools-filesystems-unlock-passphrase").addClass("has-error").removeClass("hidden").text("Passphrase contains invalid characters.");
+
+ validation.passphrase = false;
+ } else {
+ $("#validationwrapper-storagepools-filesystems-unlock-passphrase").removeClass("has-error");
+ $("#helpblock-storagepools-filesystems-unlock-passphrase").removeClass("has-error").addClass("hidden").text("");
+
+ validation.passphrase = true;
+ }
+
+ if (!validation.filesystems || !validation.passphrase) {
+ if (!validation.passphrase) {
+ $("#validationwrapper-storagepools-filesystems-unlock-passphrase").addClass("has-error");
+ $("#input-storagepools-filesystems-unlock-passphrase").focus();
+ }
+
+ $("#spinner-storagepools-filesystems-unlock").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.filesystems && validation.passphrase) {
+ filesystem.mount = $("#switch-storagepools-filesystems-unlock-mount input").prop("checked");
+ filesystem.overlay = $("#switch-storagepools-filesystems-unlock-overlay input").prop("checked");
+ filesystem.passphrase = $("#input-storagepools-filesystems-unlock-passphrase").val();
+
+ FnFileSystemsUnlock({ id: filesystems.id }, { mount: filesystem.mount, overlay: filesystem.overlay, passphrase: filesystem.passphrase }, { name: modal.name, id: modal.id });
+ }
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+//#endregion
+
+//#region Modal File System
+
+function FnModalFileSystemChangePassphrase(pool = { name, id }, filesystem = { name, id }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-changepassphrase-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemChangePassphraseContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { id: $("#modal-storagepool-filesystem-changepassphrase-` + filesystem.id + `") });
+
+ setTimeout(function() {
+ $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").focus();
+ }, 600);
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemChangePassphraseContent(pool = { name, id }, filesystem = { name, id }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-changepassphrase-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-changepassphrase-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let filesystem = {
+ passphrase: ""
+ };
+ let validation = {
+ passphrase: false
+ };
+
+ if ($("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").val().length == 0) {
+ $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error");
+ $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase can not be empty.");
+ $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").focus();
+
+ validation.passphrase = false;
+ } else if ($("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").val().length < 8) {
+ $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error");
+ $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
+ $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").focus();
+
+ validation.passphrase = false;
+ } else if (/^[a-zA-Z0-9-_. \`~!@#$%^\(\)+\\[\\]{}:',/?]*$/.test($("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").val()) == false) {
+ $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error");
+ $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase contains invalid characters.");
+ $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").focus();
+
+ validation.passphrase = false;
+ } else if ($("#input-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").val().length < 8 || $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").val() != $("#input-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").val()) {
+ $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").removeClass("has-error").removeClass("hidden").text("");
+ $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").addClass("has-error");
+ $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase does not match.");
+ $("#input-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").focus();
+
+ validation.passphrase = false;
+ } else {
+ $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").removeClass("has-error").removeClass("hidden").text("");
+ $("#validationwrapper-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-changepassphrase-passphrase-confirm-` + filesystem.id + `").removeClass("has-error").removeClass("hidden").text("");
+
+ validation.passphrase = true;
+ }
+
+ if (!validation.passphrase) {
+ $("#spinner-storagepool-filesystem-changepassphrase-` + filesystem.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.passphrase) {
+ $("#validationwrapper-storagepool-filesystem-changepassphrase-filesystem-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-changepassphrase-filesystem-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ filesystem.passphrase = $("#input-storagepool-filesystem-changepassphrase-passphrase-` + filesystem.id + `").val();
+
+ FnFileSystemChangePassphrase({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", passphrase: filesystem.passphrase });
+ }
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemConfigure(pool = { name, id, altroot: false, feature: { allocation_classes: true, edonr: true, large_blocks: true, large_dnode: true, lz4_compress: true, sha512: true, skein: true }, readonly: false }, filesystem = { name, id, origin, type }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-configure-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemConfigureContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, feature: { allocation_classes: ` + pool.feature.allocation_classes + `, edonr: ` + pool.feature.edonr + `, large_blocks: ` + pool.feature.large_blocks + `, large_dnode: ` + pool.feature.large_dnode + `, lz4_compress: ` + pool.feature.lz4_compress + `, sha512: ` + pool.feature.sha512 + `, skein: ` + pool.feature.skein + ` }, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", origin: "` + filesystem.origin + `", type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-configure-` + filesystem.id + `") });
+ FnFileSystemConfigurationGet({ name: "` + pool.name + `", id: "` + pool.id + `", readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { name: "storagepool-filesystem-configure", id: "` + filesystem.id + `" });
+ ` + (pool.altroot ? `FnStoragePoolAlternativeRootGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "storagepool-filesystem-configure", id: "` + filesystem.id + `" });` : ``) + `
+
+ $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val("0");
+ $("#validationwrapper-storagepool-filesystem-configure-quota-` + filesystem.id + ` .min-slider-handle").attr("tabindex", "14");
+ $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val("0");
+ $("#validationwrapper-storagepool-filesystem-configure-refreservation-` + filesystem.id + ` .min-slider-handle").attr("tabindex", "18");
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemConfigureContent(pool = { name, id, altroot: false, feature: { allocation_classes: true, edonr: true, large_blocks: true, large_dnode: true, lz4_compress: true, sha512: true, skein: true }, readonly: false }, filesystem = { name, id, origin, type }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").tooltip({ trigger: "manual" })
+ .on("keyup", function (element) {
+ let $this = $(this);
+ let sd = $this.siblings("[data-provide=slider]").slider();
+
+ if ($this.val().trim() && !$.isNumeric(this.value)) {
+ this.value = sd.slider("getValue");
+ }
+ })
+ .on("keypress blur", function (element) {
+ if (element.which == 13 || element.type === "blur") {
+ element.preventDefault();
+
+ let $this = $(this);
+ let sd = $this.siblings("[data-provide=slider]").slider();
+ let max = sd.slider("getAttribute", "max");
+ let min = sd.slider("getAttribute", "min");
+
+ if (!$.isNumeric(this.value) || (this.value > max || this.value < min)) {
+ let warningInfo = $.isNumeric(this.value) ? "Valid value should be between " + min + " and " + max : "Valid value should be number";
+ $this.attr("data-original-title", warningInfo).tooltip("show").addClass("warning");
+ this.value = sd.slider("getValue");
+ setTimeout(function () {
+ $this.tooltip("hide");
+ }, 3000);
+ } else {
+ if ($this.is(".warning")) {
+ $this.tooltip("hide");
+ }
+
+ this.value = $this.val().trim();
+ sd.slider("setValue", this.value);
+ }
+ }
+ })
+ .siblings("[data-provide=slider]").each(function () {
+ $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val(this.value);
+ $(this).slider().on("change", function (element) {
+ $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val(element.value.newValue);
+ });
+ });
+
+ $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").on("change textInput input", function (element) {
+ if ($(this).val() > 1000) { //Force reset to maximum allowed value
+ $(this).val(1000);
+ } else if ($(this).val() < 0) { //Force reset to minimum allowed value
+ $(this).val(0);
+ }
+
+ if ($.isNumeric($(this).val())) {
+ $("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").slider("setValue", $(this).val());
+ }
+ });
+
+ $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").tooltip({ trigger: "manual" })
+ .on("keyup", function (element) {
+ let $this = $(this);
+ let sd = $this.siblings("[data-provide=slider]").slider();
+
+ if ($this.val().trim() && !$.isNumeric(this.value)) {
+ this.value = sd.slider("getValue");
+ }
+ })
+ .on("keypress blur", function (element) {
+ if (element.which == 13 || element.type === "blur") {
+ element.preventDefault();
+
+ let $this = $(this);
+ let sd = $this.siblings("[data-provide=slider]").slider();
+ let max = sd.slider("getAttribute", "max");
+ let min = sd.slider("getAttribute", "min");
+
+ if (!$.isNumeric(this.value) || (this.value > max || this.value < min)) {
+ let warningInfo = $.isNumeric(this.value) ? "Valid value should be between " + min + " and " + max : "Valid value should be number";
+ $this.attr("data-original-title", warningInfo).tooltip("show").addClass("warning");
+ this.value = sd.slider("getValue");
+ setTimeout(function () {
+ $this.tooltip("hide");
+ }, 3000);
+ } else {
+ if ($this.is(".warning")) {
+ $this.tooltip("hide");
+ }
+
+ this.value = $this.val().trim();
+ sd.slider("setValue", this.value);
+ }
+ }
+ })
+ .siblings("[data-provide=slider]").each(function () {
+ $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val(this.value);
+ $(this).slider().on("change", function (element) {
+ $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val(element.value.newValue);
+ });
+ });
+
+ $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").on("change textInput input", function (element) {
+ if ($(this).val() > 1000) { //Force reset to maximum allowed value
+ $(this).val(1000);
+ } else if ($(this).val() < 0) { //Force reset to minimum allowed value
+ $(this).val(0);
+ }
+
+ if ($.isNumeric($(this).val())) {
+ $("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").slider("setValue", $(this).val());
+ }
+ });
+
+ $("#switch-storagepool-filesystem-configure-sharenfs-` + filesystem.id + ` input").on("click", function () {
+ $("#validationwrapper-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ if ($(this).prop("checked")) {
+ $("#controllabel-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").removeClass("hidden");
+ $("#validationwrapper-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").removeClass("hidden");
+
+ FnSystemNfsVersionGet({ alert: { id: $("#alert-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `") } });
+ } else {
+ $("#validationwrapper-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").addClass("hidden");
+ $("#controllabel-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").addClass("hidden");
+ }
+ });
+
+ $("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").on("input", function (element) {
+ if ($("#switch-storagepool-filesystem-configure-sharesmb-` + filesystem.id + `").attr("data-field-value") == "on") {
+ if ($(this).val() != $(this).attr("data-field-value")) {
+ $("#switch-storagepool-filesystem-configure-samba-restart-` + filesystem.id + `").parent().removeClass("hidden");
+ } else {
+ $("#switch-storagepool-filesystem-configure-samba-restart-` + filesystem.id + `").parent().addClass("hidden");
+ }
+ }
+ });
+
+ $("#btn-storagepool-filesystem-configure-apply-` + filesystem.id + `").on("click",function () {
+ $("#spinner-storagepool-filesystem-configure-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let filesystem = {
+ aclinherit: "",
+ acltype: "",
+ atime: "",
+ canmount: "",
+ checksum: "",
+ compression: "",
+ context: "",
+ dedup: "",
+ dnodesize: "",
+ defcontext: "",
+ fscontext: "",
+ mountpoint: "",
+ quota: "none",
+ readonly: "",
+ recordsize: "",
+ refreservation: "0B",
+ rootcontext: "",
+ selinux: "",
+ sharenfs: "",
+ sharesmb: "",
+ special_small_blocks: "0B",
+ xattr: ""
+ };
+ let modal = {
+ id: $("#modal-storagepool-filesystem-configure-` + filesystem.id + `")
+ };
+ let samba = {
+ restart: false
+ };
+ let validation = {
+ mountpoint: false,
+ sharenfs: false
+ };
+
+ if ($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val().length == 0) {
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not be empty.");
+
+ validation.mountpoint = false;
+ } else if (/^[a-zA-Z0-9-_.:/ ]*$/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val()) == false) {
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint contains invalid characters.");
+
+ validation.mountpoint = false;
+ } else if ($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val() && /^[/]/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val()) == false) {
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint is an absolute path and must begin with a forward slash (/).");
+
+ validation.mountpoint = false;
+ } else if (/^[.]/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not begin with a period (.).");
+
+ validation.mountpoint = false;
+ } else if (/[.]$/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not end with a period (.).");
+
+ validation.mountpoint = false;
+ } else if (/[/][.][/]/g.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not contain a period as a sub directory (/./).");
+
+ validation.mountpoint = false;
+ } else if (/[/][.][.][/]/g.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not contain a double period as a sub directory (/../).");
+
+ validation.mountpoint = false;
+ } else if (/[/][/]/g.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not contain double forward slashes (//).");
+
+ validation.mountpoint = false;
+ } else if (/[.][.]/g.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not contain a double period (..).");
+
+ validation.mountpoint = false;
+ } else if (/^[ ]/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not begin with whitespace ( ).");
+
+ validation.mountpoint = false;
+ } else if (/[ ]$/.test($("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Mountpoint can not end with whitespace ( ).");
+
+ validation.mountpoint = false;
+ } else {
+ $("#validationwrapper-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("hidden").text("");
+
+ validation.mountpoint = true;
+ }
+
+ if ($("#switch-storagepool-filesystem-configure-sharenfs-` + filesystem.id + ` input").prop("checked")) {
+ if (/^[a-zA-Z0-9-_.:/@#+=!&*(), ]*$/.test($("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").val()) == false) {
+ $("#validationwrapper-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").addClass("has-error");
+ $("#helpblock-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("NFS Share options contain invalid characters.");
+ $("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").focus();
+
+ validation.sharenfs = false;
+ } else {
+ validation.sharenfs = true;
+ }
+ } else {
+ validation.sharenfs = true;
+ }
+
+ if (!validation.mountpoint || !validation.sharenfs) {
+ if (!validation.mountpoint) {
+ $("#validationwrapper-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").addClass("has-error");
+ $("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").focus();
+ }
+
+ $("#spinner-storagepool-filesystem-configure-` + filesystem.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.mountpoint && validation.sharenfs) {
+ filesystem.aclinherit = ($("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-value-new") : null);
+ filesystem.acltype = ($("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-value-new") : null);
+ filesystem.atime = ($("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-value-new") : null);
+ filesystem.canmount = ($("#btnspan-storagepool-filesystem-configure-canmount-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-canmount-` + filesystem.id + `").attr("data-field-value-new") : null);
+ filesystem.checksum = ($("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-value-new") : null);
+ filesystem.compression = ($("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-value-new") : null);
+ filesystem.context = ($("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + ` input").prop("checked") ? "system_u:object_r:samba_share_t:s0" : "none");
+ filesystem.dedup = ($("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-value-new") : null);
+ filesystem.dnodesize = ($("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-value-new") : null);
+ filesystem.defcontext = ($("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + ` input").prop("checked") ? "system_u:object_r:samba_share_t:s0" : "none");
+ filesystem.fscontext = ($("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + ` input").prop("checked") ? "system_u:object_r:samba_share_t:s0" : "none");
+ filesystem.mountpoint = $("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").val();
+ filesystem.readonly = ($("#switch-storagepool-filesystem-configure-readonly-` + filesystem.id + ` input").prop("checked") ? "on" : "off");
+ filesystem.recordsize = ($("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-value-new") : null);
+ filesystem.rootcontext = ($("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + ` input").prop("checked") ? "system_u:object_r:samba_share_t:s0" : "none");
+ filesystem.selinux = $("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + ` input").prop("checked");
+ filesystem.sharesmb = ` + (zfsmanager.configuration.samba.manage ? `$("#switch-storagepool-filesystem-configure-sharesmb-` + filesystem.id + `").attr("data-field-value");` : `($("#switch-storagepool-filesystem-configure-sharesmb-` + filesystem.id + ` input").prop("checked") ? "on" : "off");`) + `
+ filesystem.special_small_blocks = ($("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-value-new") : null);
+ filesystem.xattr = ($("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-value-new") != "" ? $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-value-new") : null);
+
+ if ($("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val() > 0) { //Remove friendly text so final value is sent
+ filesystem.quota = $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val() + $("#btnspan-storagepool-filesystem-configure-quota-` + filesystem.id + `").attr("data-field-value").replace(/iB$/g, "");
+ } else {
+ filesystem.quota = "none";
+ }
+
+ if ($("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val() > 0) { //Remove friendly text so final value is sent
+ filesystem.refreservation = $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val() + $("#btnspan-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").attr("data-field-value").replace(/iB$/g, "");
+ } else {
+ filesystem.refreservation = "0B";
+ }
+
+ if ($("#switch-storagepool-filesystem-configure-sharenfs-` + filesystem.id + ` input").prop("checked")) {
+ if ($("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").val().toLowerCase() == "on" || $("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").val() == "sec=sys,rw,crossmnt,no_subtree_check,no_root_squash" || !$("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").val()) {
+ filesystem.sharenfs = "on";
+ } else {
+ filesystem.sharenfs = $("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").val();
+ }
+ } else {
+ filesystem.sharenfs = "off";
+ }
+
+ //Set values to null if unchanged, so that they are skipped in the configure function
+ if (/^Inherited/.test(filesystem.aclinherit) && $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-source") == "inherited") {
+ filesystem.aclinherit = null;
+ } else if (/^Default/.test(filesystem.aclinherit) && $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-source") == "default") {
+ filesystem.aclinherit = null;
+ } else if (filesystem.aclinherit == $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").attr("data-field-source") == "local") {
+ filesystem.aclinherit = null;
+ }
+
+ if (/^Inherited/.test(filesystem.acltype) && $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-source") == "inherited") {
+ filesystem.acltype = null;
+ } else if (/^Default/.test(filesystem.acltype) && $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-source") == "default") {
+ filesystem.acltype = null;
+ } else if (filesystem.acltype == $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").attr("data-field-source") == "local") {
+ filesystem.acltype = null;
+ }
+
+ if (/^Inherited/.test(filesystem.atime) && $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-source") == "inherited") {
+ filesystem.atime = null;
+ } else if (/^Default/.test(filesystem.atime) && $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-source") == "default") {
+ filesystem.atime = null;
+ } else if (filesystem.atime == $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").attr("data-field-source") == "local") {
+ filesystem.atime = null;
+ }
+
+ if (filesystem.canmount == $("#btnspan-storagepool-filesystem-configure-canmount-` + filesystem.id + `").attr("data-field-value")) {
+ filesystem.canmount = null;
+ }
+
+ if (/^Inherited/.test(filesystem.checksum) && $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-source") == "inherited") {
+ filesystem.checksum = null;
+ } else if (/^Default/.test(filesystem.checksum) && $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-source") == "default") {
+ filesystem.checksum = null;
+ } else if (filesystem.checksum == $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").attr("data-field-source") == "local") {
+ filesystem.checksum = null;
+ }
+
+ if (/^Inherited/.test(filesystem.compression) && $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-source") == "inherited") {
+ filesystem.compression = null;
+ } else if (/^Default/.test(filesystem.compression) && $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-source") == "default") {
+ filesystem.compression = null;
+ } else if (filesystem.compression == $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").attr("data-field-source") == "local") {
+ filesystem.compression = null;
+ }
+
+
+ if (/^Inherited/.test(filesystem.dedup) && $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-source") == "inherited") {
+ filesystem.dedup = null;
+ } else if (/^Default/.test(filesystem.dedup) && $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-source") == "default") {
+ filesystem.dedup = null;
+ } else if (filesystem.dedup == $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").attr("data-field-source") == "local") {
+ filesystem.dedup = null;
+ }
+
+ if (/^Inherited/.test(filesystem.dnodesize) && $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-source") == "inherited") {
+ filesystem.dnodesize = null;
+ } else if (/^Default/.test(filesystem.dnodesize) && $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-source") == "default") {
+ filesystem.dnodesize = null;
+ } else if (filesystem.dnodesize == $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").attr("data-field-source") == "local") {
+ filesystem.dnodesize = null;
+ }
+
+ if (filesystem.mountpoint == $("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").attr("data-field-value")) {
+ filesystem.mountpoint = null;
+ } else {
+ ` + (pool.altroot ? `filesystem.mountpoint = filesystem.mountpoint.replace(new RegExp("^" + $("#input-storagepool-filesystem-configure-mountpoint-` + filesystem.id + `").attr("data-field-altroot")), "");` : ``) + `
+
+ samba.restart = $("#switch-storagepool-filesystem-configure-samba-restart-` + filesystem.id + ` input").prop("checked");
+ }
+
+ if (filesystem.quota == $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").attr("data-field-value")) {
+ filesystem.quota = null;
+ }
+
+ if (filesystem.readonly == $("#switch-storagepool-filesystem-configure-readonly-` + filesystem.id + `").attr("data-field-value")) {
+ filesystem.readonly = null;
+ }
+
+ if (/^Inherited/.test(filesystem.recordsize) && $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-source") == "inherited") {
+ filesystem.recordsize = null;
+ } else if (/^Default/.test(filesystem.recordsize) && $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-source") == "default") {
+ filesystem.recordsize = null;
+ } else if (filesystem.recordsize == $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").attr("data-field-source") == "local") {
+ filesystem.recordsize = null;
+ }
+
+ if (filesystem.refreservation == $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").attr("data-field-value")) {
+ filesystem.refreservation = null;
+ }
+
+ if (filesystem.selinux == $("#switch-storagepool-filesystem-configure-selinux-` + filesystem.id + `").attr("data-field-value")) {
+ filesystem.context = null;
+ filesystem.defcontext = null;
+ filesystem.fscontext = null;
+ filesystem.rootcontext = null;
+ filesystem.selinux = null;
+ }
+
+ if (filesystem.sharenfs == $("#input-storagepool-filesystem-configure-sharenfs-options-` + filesystem.id + `").attr("data-field-value")) {
+ filesystem.sharenfs = null;
+ }
+
+ if (/^Inherited/.test(filesystem.special_small_blocks) && $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-source") == "inherited") {
+ filesystem.special_small_blocks = null;
+ } else if (/^Default/.test(filesystem.special_small_blocks) && $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-source") == "default") {
+ filesystem.special_small_blocks = null;
+ } else if (filesystem.special_small_blocks == $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").attr("data-field-source") == "local") {
+ filesystem.special_small_blocks = null;
+ }
+
+ if (/^Inherited/.test(filesystem.xattr) && $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-source") == "inherited") {
+ filesystem.xattr = null;
+ } else if (/^Default/.test(filesystem.xattr) && $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-source") == "default") {
+ filesystem.xattr = null;
+ } else if (filesystem.xattr == $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-value") && $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").attr("data-field-source") == "local") {
+ filesystem.xattr = null;
+ }
+
+ FnFileSystemConfigure({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", aclinherit: filesystem.aclinherit, acltype: filesystem.acltype, atime: filesystem.atime, canmount: filesystem.canmount, checksum: filesystem.checksum, compression: filesystem.compression, context: filesystem.context, dedup: filesystem.dedup, dnodesize: filesystem.dnodesize, defcontext: filesystem.defcontext, fscontext: filesystem.fscontext, mountpoint: filesystem.mountpoint, quota: filesystem.quota, readonly: filesystem.readonly, recordsize: filesystem.recordsize, refreservation: filesystem.refreservation, rootcontext: filesystem.rootcontext, sharenfs: filesystem.sharenfs, sharesmb: filesystem.sharesmb, special_small_blocks: filesystem.special_small_blocks, type: "` + filesystem.type + `", xattr: filesystem.xattr }, { restart: samba.restart }, { id: modal.id });
+ }
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-aclinherit-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-acltype-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-acltype-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-atime-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-atime-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-canmount-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-canmount-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-checksum-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-checksum-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-compression-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-compression-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-dedup-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-dedup-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-dnodesize-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-quota-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-quota-` + filesystem.id + `").text($(this).text()).attr("data-field-value", $(this).text());
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+
+ let size = {
+ slider: {
+ value: $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val(),
+ valuemax: $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").attr("data-filesystem-quota-max-" + $(this).text().toLowerCase())
+ }
+ };
+
+ $("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").data("slider").options.max = size.slider.valuemax;
+ $("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").data("slider").options.step = (size.slider.valuemax < 10 ? "0.1" : "1");
+ $("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").slider("setValue", 0); //Force display update
+ $("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").slider("setValue", size.slider.value);
+ $("#input-storagepool-filesystem-configure-quota-` + filesystem.id + `").val($("#slider-storagepool-filesystem-configure-quota-` + filesystem.id + `").data("slider").getValue());
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-recordsize-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").text($(this).text()).attr("data-field-value", $(this).text());
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+
+ let size = {
+ slider: {
+ value: $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val(),
+ valuemax: $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").attr("data-filesystem-refreservation-max-" + $(this).text().toLowerCase())
+ }
+ };
+
+ $("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").data("slider").options.max = size.slider.valuemax;
+ $("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").data("slider").options.step = (size.slider.valuemax < 10 ? "0.1" : "1");
+ $("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").slider("setValue", 0); //Force display update
+ $("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").slider("setValue", size.slider.value);
+ $("#input-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").val($("#slider-storagepool-filesystem-configure-refreservation-` + filesystem.id + `").data("slider").getValue());
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-special_small_blocks-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+
+ $("#dropdown-storagepool-filesystem-configure-xattr-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-configure-xattr-` + filesystem.id + `").text($(this).text()).attr("data-field-value-new", (/^Default/.test($(this).text()) ? "Default" : $(this).parent().attr("value")));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemDestroy(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-destroy-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemDestroyContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-destroy-` + filesystem.id + `") });
+ FnFileSystemChildDatasetsGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", clones: true }, { name: "storagepool-filesystem-destroy", id: "` + filesystem.id + `" });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemDestroyContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-filesystem-destroy-recursive-` + filesystem.id + ` input").on("click", function () {
+ if ($(this).prop("checked") && $("#switch-storagepool-filesystem-destroy-recursiveall-` + filesystem.id + ` input").prop("checked")) {
+ $("#switch-storagepool-filesystem-destroy-recursiveall-` + filesystem.id + ` input").click();
+ }
+
+ $("#panel-storagepool-filesystem-destroy-child-filesystemswithclones-` + filesystem.id + `").addClass("hidden");
+ $("#panel-storagepool-filesystem-destroy-child-filesystemswithclones-` + filesystem.id + ` .collapse").collapse("hide");
+ $("#panel-storagepool-filesystem-destroy-child-snapshotswithclones-` + filesystem.id + `").addClass("hidden");
+ $("#panel-storagepool-filesystem-destroy-child-snapshotswithclones-` + filesystem.id + ` .collapse").collapse("hide");
+
+ if ($(this).prop("checked") && $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-filesystems") > 0) {
+ $("#panel-storagepool-filesystem-destroy-child-filesystems-` + filesystem.id + `").removeClass("hidden");
+ } else {
+ $("#panel-storagepool-filesystem-destroy-child-filesystems-` + filesystem.id + `").addClass("hidden");
+ $("#panel-storagepool-filesystem-destroy-child-filesystems-` + filesystem.id + ` .collapse").collapse("hide");
+ }
+ if ($(this).prop("checked") && $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-snapshots") > 0) {
+ $("#panel-storagepool-filesystem-destroy-child-snapshots-` + filesystem.id + `").removeClass("hidden");
+ } else {
+ $("#panel-storagepool-filesystem-destroy-child-snapshots-` + filesystem.id + `").addClass("hidden");
+ $("#panel-storagepool-filesystem-destroy-child-snapshots-` + filesystem.id + ` .collapse").collapse("hide");
+ }
+ if ($(this).prop("checked") && ($("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-filesystems") > 0 || $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-snapshots") > 0)) {
+ $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").addClass("modal-ct-bodytext-1");
+ } else {
+ $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").removeClass("modal-ct-bodytext-1");
+ }
+ });
+
+ $("#switch-storagepool-filesystem-destroy-recursiveall-` + filesystem.id + ` input").on("click", function () {
+ if ($(this).prop("checked") && $("#switch-storagepool-filesystem-destroy-recursive-` + filesystem.id + ` input").prop("checked")) {
+ $("#switch-storagepool-filesystem-destroy-recursive-` + filesystem.id + ` input").click();
+ }
+
+ $("#panel-storagepool-filesystem-destroy-child-filesystems-` + filesystem.id + `").addClass("hidden");
+ $("#panel-storagepool-filesystem-destroy-child-filesystems-` + filesystem.id + ` .collapse").collapse("hide");
+ $("#panel-storagepool-filesystem-destroy-child-snapshots-` + filesystem.id + `").addClass("hidden");
+ $("#panel-storagepool-filesystem-destroy-child-snapshots-` + filesystem.id + ` .collapse").collapse("hide");
+
+ if ($(this).prop("checked") && $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-filesystemswithclones") > 0) {
+ $("#panel-storagepool-filesystem-destroy-child-filesystemswithclones-` + filesystem.id + `").removeClass("hidden");
+ } else {
+ $("#panel-storagepool-filesystem-destroy-child-filesystemswithclones-` + filesystem.id + `").addClass("hidden");
+ $("#panel-storagepool-filesystem-destroy-child-filesystemswithclones-` + filesystem.id + ` .collapse").collapse("hide");
+ }
+ if ($(this).prop("checked") && $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-snapshotswithclones") > 0) {
+ $("#panel-storagepool-filesystem-destroy-child-snapshotswithclones-` + filesystem.id + `").removeClass("hidden");
+ } else {
+ $("#panel-storagepool-filesystem-destroy-child-snapshotswithclones-` + filesystem.id + `").addClass("hidden");
+ $("#panel-storagepool-filesystem-destroy-child-snapshotswithclones-` + filesystem.id + ` .collapse").collapse("hide");
+ }
+ if ($(this).prop("checked") && ($("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-filesystemswithclones") > 0 || $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").attr("data-filesystem-child-snapshotswithclones") > 0)) {
+ $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").addClass("modal-ct-bodytext-1");
+ } else {
+ $("#panelgroup-storagepool-filesystem-destroy-` + filesystem.id + `").removeClass("modal-ct-bodytext-1");
+ }
+ });
+
+ $("#btn-storagepool-filesystem-destroy-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-destroy-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let filesystem = {
+ force: $("#switch-storagepool-filesystem-destroy-force-` + filesystem.id + ` input").prop("checked"),
+ recursive: $("#switch-storagepool-filesystem-destroy-recursive-` + filesystem.id + ` input").prop("checked"),
+ recursiveall: $("#switch-storagepool-filesystem-destroy-recursiveall-` + filesystem.id + ` input").prop("checked")
+ };
+ let samba = {
+ restart: $("#switch-storagepool-filesystem-destroy-samba-restart-` + filesystem.id + ` input").prop("checked")
+ };
+
+ FnFileSystemDestroy({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", force: filesystem.force, recursive: filesystem.recursive, recursiveall: filesystem.recursiveall, sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { restart: samba.restart });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemLock(pool = { name, id }, filesystem = { name, id, type }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-lock-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemLockContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-lock-` + filesystem.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemLockContent(pool = { name, id }, filesystem = { name, id, type }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to lock ` + filesystem.type.toLowerCase() + `: ` + filesystem.name + ` ?
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-lock-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-lock-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ FnFileSystemLock({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", type: "` + filesystem.type + `" }, { refresh: true });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemMount(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-mount-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemMountContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-mount-` + filesystem.id + `") });
+ FnFileSystemsMountedGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { alert: { id: $("#div-storagepool-filesystem-mount-warning-` + filesystem.id + `"), mount: true } });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemMountContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to mount ` + filesystem.type.toLowerCase() + `: ` + filesystem.name + ` ?
+
+ ` + FnDisplayInlineAlert({ status: "warning", title: "Enabling Samba share on the root file system will expose all child file systems regardless of their share status.", description: null }, { name: "storagepool-filesystem-samba-warning", id: filesystem.id, hidden: true }) + `
+
+ Options
+
+ Forcefully mount file system if directory is not empty
+
+
+ Enable Samba share
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-filesystem-mount-samba-enable-` + filesystem.id + ` input").on("click", function () {
+ if ($(this).prop("checked")) {
+ ` + (filesystem.name == pool.name ? `$("#alert-storagepool-filesystem-samba-warning-` + filesystem.id + `").removeClass("hidden");` : ``) + `
+ } else {
+ ` + (filesystem.name == pool.name ? `$("#alert-storagepool-filesystem-samba-warning-` + filesystem.id + `").addClass("hidden");` : ``) + `
+ }
+ });
+
+ $("#btn-storagepool-filesystem-mount-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-mount-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let filesystem = {
+ overlay: $("#switch-storagepool-filesystem-mount-overlay-` + filesystem.id + ` input").prop("checked")
+ };
+ let samba = {
+ enable: ` + ((pool.readonly || filesystem.sharesmb) ? false : `$("#switch-storagepool-filesystem-mount-samba-enable-` + filesystem.id + ` input").prop("checked")`) + `
+ };
+
+ FnFileSystemMount({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", overlay: filesystem.overlay, type: "` + filesystem.type + `" }, { enable: samba.enable }, { refresh: true });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemPromote(pool = { name, id }, filesystem = { name, id, origin, type }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-promote-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemPromoteContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", origin: "` + filesystem.origin + `", type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-promote-` + filesystem.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemPromoteContent(pool = { name, id }, filesystem = { name, id, origin, type }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to promote ` + filesystem.type.toLowerCase() + `: ` + filesystem.name + ` ?
+
Origin: ` + filesystem.origin + `
+ ` + FnDisplayInlineAlert({ status: "info", title: "Origin file system: " + filesystem.origin.replace(/^(.*)\@.*$/, "$1") + " will be promoted to a clone file system.", description: null }, { name: null, id: null, hidden: false }) + `
+ ` + (new RegExp("^" + filesystem.origin.replace(/^(.*)\@.*$/, "$1") + "/").test(filesystem.name) ? FnDisplayInlineAlert({ status: "warning", title: "Clone file system is a child of origin file system, which may create recursive dependency errors. It is recommended to rename this clone file system to a name that is not a child file system of the origin file system before promoting.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-promote-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-promote-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ FnFileSystemPromote({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", type: "` + filesystem.type + `" });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemRename(pool = { name, id, altroot: false }, filesystem = { name, id, clone: false, encryption: false, encryptionroot, origin, sharesmb: false, type }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-rename-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemRenameContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", clone: ` + filesystem.clone + `, encryption: ` + filesystem.encryption + `, origin: "` + filesystem.origin + `", sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-rename-` + filesystem.id + `") });
+ FnFileSystemsNamesGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { existing: { name: "` + filesystem.name + `", clone: ` + filesystem.clone + `, encryption: ` + filesystem.encryption + `, encryptionroot: "` + filesystem.encryptionroot + `", origin: "` + filesystem.origin + `" }, override: false }, { dropdown: { id: $("#dropdown-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `"), selected: "` + filesystem.name.replace(/\/[^\/]+$/, "") + `" } });
+
+ setTimeout(function() {
+ $("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").focus();
+ }, 600);
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemRenameContent(pool = { name, id, altroot: false }, filesystem = { name, id, clone: false, encryption: false, origin, sharesmb: false, type }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-rename-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-rename-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let filesystem = {
+ createnonexistparents: false,
+ force: false,
+ namenew: "",
+ parent: ""
+ };
+ let samba = {
+ restart: false
+ };
+ let validation = {
+ name: false
+ };
+
+ if ($("#btnspan-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").attr("data-field-value") + "/" + $("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val() == "` + filesystem.name + `") {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name or parent file system must be different.");
+
+ validation.name = false;
+ } else if (new RegExp("^" + "` + filesystem.name + `/").test($("#btnspan-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").attr("data-field-value") + "/" + $("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not be a descendant of current file system.");
+
+ validation.name = false;
+ } else if ($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val().length == 0) {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
+
+ validation.name = false;
+ } else if (/^[a-zA-Z0-9-_.:/ ]*$/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val()) == false) {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
+
+ validation.name = false;
+ } else if (/^[.]/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
+
+ validation.name = false;
+ } else if (/^[_]/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
+
+ validation.name = false;
+ } else if (/^[-]/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
+
+ validation.name = false;
+ } else if (/^[:]/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
+
+ validation.name = false;
+ } else if (/^[/]/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a forward slash (/).");
+
+ validation.name = false;
+ } else if (/[/]$/.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with a forward slash (/).");
+
+ validation.name = false;
+ } else if (/^ |\\/ /.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
+
+ validation.name = false;
+ } else if (/ $| \\//.test($("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
+
+ validation.name = false;
+ } else {
+ $("#validationwrapper-storagepool-filesystem-rename-name-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("hidden").text("");
+
+ validation.name = true;
+ }
+
+ if (!validation.name) {
+ $("#validationwrapper-storagepool-filesystem-rename-name-` + filesystem.id + `").addClass("has-error");
+ $("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").focus();
+
+ $("#spinner-storagepool-filesystem-rename-` + filesystem.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.name) {
+ filesystem.createnonexistparents = $("#switch-storagepool-filesystem-rename-createnonexistparents-` + filesystem.id + ` input").prop("checked");
+ filesystem.force = $("#switch-storagepool-filesystem-rename-force-` + filesystem.id + ` input").prop("checked");
+ filesystem.namenew = $("#btnspan-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").attr("data-field-value") + "/" + $("#input-storagepool-filesystem-rename-name-` + filesystem.id + `").val();
+ filesystem.parent = $("#btnspan-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").attr("data-field-value");
+
+ samba.restart = $("#switch-storagepool-filesystem-rename-samba-restart-` + filesystem.id + ` input").prop("checked")
+
+ FnFileSystemRename({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", createnonexistparents: filesystem.createnonexistparents, force: filesystem.force, namenew: filesystem.namenew, parent: filesystem.parent, sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { restart: samba.restart });
+ }
+ });
+
+ $("#dropdown-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-filesystem-rename-parentfilesystem-` + filesystem.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemSambaConfigure(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mountpoint }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-samba-configure-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemSambaConfigureContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", mountpoint: "` + filesystem.mountpoint + `" }, { id: $("#modal-storagepool-filesystem-samba-configure-` + filesystem.id + `") });
+ FnSambaZfsShareConfigurationGet({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { name: "storagepool-filesystem-samba-configure", id: "` + filesystem.id + `" });
+
+ setTimeout(function() {
+ $("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").focus();
+ }, 600);
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemSambaConfigureContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mountpoint }, modal = { id }) {
+ modal.content = `
+
+
+
+
+ ` + (filesystem.name == pool.name ? FnDisplayInlineAlert({ status: "warning", title: "Samba share on the root file system exposes all child file systems regardless of their share status.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
+ ` + FnDisplayInlineAlert({ status: "warning", title: "Share configuration does not exist. Configure to save a new share configuration.", description: null }, { name: "storagepool-filesystem-samba-configure-configurationmissing", id: filesystem.id, hidden: true }) + `
+
+ Share Name
+
+
+
+
+ Comment
+
+ Additional
+
+
+
+
+ Options
+
+
+ Anonymous access
+
+
+ Browseable
+
+
+ Read only
+
+
+ Restart Samba service
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-filesystem-samba-configure-additional-` + filesystem.id + ` input").on("click", function () {
+ $("#validationwrapper-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ if ($("#switch-storagepool-filesystem-samba-configure-additional-` + filesystem.id + ` input").prop("checked")) {
+ $("#validationwrapper-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").removeClass("hidden");
+ } else {
+ $("#validationwrapper-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").addClass("hidden");
+ }
+ });
+
+ $("#btn-storagepool-filesystem-samba-configure-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-samba-configure-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let samba = {
+ share: {
+ additional: ($("#switch-storagepool-filesystem-samba-configure-additional-` + filesystem.id + ` input").prop("checked") ? $("#textarea-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").val().split("\\n").filter(v => v) : []),
+ administrative: false,
+ browseable: true,
+ comment: "",
+ guestok: false,
+ name: "",
+ nameexisting: "",
+ readonly: false
+ }
+ };
+ let validation = {
+ comment: false,
+ name: false,
+ additional: false
+ };
+
+ if ($("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").val().length == 0) {
+ $("#helpblock-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not be empty.");
+
+ validation.name = false;
+ } else if (/^[a-zA-Z0-9-_.@%+!#$^,(){}~ ]*$/.test($("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").val()) == false) {
+ $("#helpblock-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name contains invalid characters.");
+
+ validation.name = false;
+ } else if (/^[ ]/.test($("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not begin with whitespace ( ).");
+
+ validation.name = false;
+ } else if (/[ ]$/.test($("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not end with whitespace ( ).");
+
+ validation.name = false;
+ } else {
+ $("#validationwrapper-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("hidden").text("");
+
+ validation.name = true;
+ }
+
+ if (/^[ -~]*$/.test($("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").val()) == false) {
+ $("#helpblock-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment contains invalid characters.");
+
+ validation.comment = false;
+ } else if (/^[.]/.test($("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment can not begin with a period (.).");
+
+ validation.comment = false;
+ } else if (/^[ ]/.test($("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment can not begin with whitespace ( ).");
+
+ validation.comment = false;
+ } else if (/[ ]$/.test($("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment can not end with whitespace ( ).");
+
+ validation.comment = false;
+ } else {
+ $("#validationwrapper-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("hidden").text("");
+
+ validation.comment = true;
+ }
+
+ if (samba.share.additional.length > 0) {
+ samba.share.additional.forEach((_value, _index) => {
+ if (/[\\[\\]]/g.test(_value)) { //Do not allow section names
+ $("#helpblock-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must not contain brackets. Line: " + (_index + 1));
+
+ validation.additional = false;
+ return;
+ } else if (/^[#]/.test(_value) == false && /[=]/.test(_value) && /(path|comment|browseable|read only|guest ok).*=/gi.test(_value)) {
+ $("#helpblock-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must not contain duplicate properties. Line: " + (_index + 1));
+
+ validation.additional = false;
+ return;
+ } else if (/[#=]/.test(_value) == false) {
+ $("#helpblock-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must contain comments or properties only. Line: " + (_index + 1));
+
+ validation.additional = false;
+ return;
+ } else if (_index == (samba.share.additional.length -1)) {
+ $("#validationwrapper-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ validation.additional = true;
+ }
+ });
+ } else {
+ validation.additional = true;
+ }
+
+ if (!validation.name || !validation.comment || !validation.additional) {
+ if (!validation.name) {
+ $("#validationwrapper-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").addClass("has-error");
+ $("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").focus();
+ }
+ if (!validation.comment) {
+ $("#validationwrapper-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").addClass("has-error");
+ $("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").focus();
+ }
+ if (!validation.additional) {
+ $("#validationwrapper-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").addClass("has-error");
+ $("#textarea-storagepool-filesystem-samba-configure-additional-` + filesystem.id + `").focus();
+ }
+
+ $("#spinner-storagepool-filesystem-samba-configure-` + filesystem.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.name && validation.comment && validation.additional) {
+ samba.restart = $("#switch-storagepool-filesystem-samba-configure-restart-` + filesystem.id + ` input").prop("checked");
+ samba.share.administrative = $("#switch-storagepool-filesystem-samba-configure-administrative-` + filesystem.id + ` input").prop("checked");
+ samba.share.browseable = $("#switch-storagepool-filesystem-samba-configure-browseable-` + filesystem.id + ` input").prop("checked");
+ samba.share.comment = $("#input-storagepool-filesystem-samba-configure-comment-` + filesystem.id + `").val();
+ samba.share.guestok = $("#switch-storagepool-filesystem-samba-configure-guestok-` + filesystem.id + ` input").prop("checked");
+ samba.share.name = $("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").val();
+ samba.share.nameexisting = $("#input-storagepool-filesystem-samba-configure-name-` + filesystem.id + `").attr("data-field-value");
+ samba.share.readonly = $("#switch-storagepool-filesystem-samba-configure-readonly-` + filesystem.id + ` input").prop("checked");
+
+ FnSambaZfsShareConfigure({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", mountpoint: "` + filesystem.mountpoint + `" }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, nameexisting: samba.share.nameexisting, readonly: samba.share.readonly, temporary: ` + (pool.altroot || pool.readonly ? true : false) + ` }, restart: samba.restart });
+ }
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemSambaDisable(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, type }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-samba-disable-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemSambaDisableContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-samba-disable-` + filesystem.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemSambaDisableContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, type }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to disable Samba share for ` + filesystem.type.toLowerCase() + `: ` + filesystem.name + ` ?
+
+ Options
+
+ Restart Samba service
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-samba-disable-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-samba-disable-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let samba = {
+ restart: $("#switch-storagepool-filesystem-samba-disable-restart-` + filesystem.id + ` input").prop("checked")
+ };
+
+ FnSambaShareDisable({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { restart: samba.restart }, { modal: true, silent: false });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemSambaEnable(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mounted: false, mountpoint }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-samba-enable-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemSambaEnableContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", mounted: ` + filesystem.mounted + `, mountpoint: "` + filesystem.mountpoint + `" }, { id: $("#modal-storagepool-filesystem-samba-enable-` + filesystem.id + `") });
+
+ setTimeout(function() {
+ $("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").focus();
+ }, 600);
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemSambaEnableContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, mounted: false, mountpoint }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-filesystem-samba-enable-additional-` + filesystem.id + ` input").on("click", function () {
+ $("#validationwrapper-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ if ($(this).prop("checked")) {
+ $("#validationwrapper-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").removeClass("hidden");
+ } else {
+ $("#validationwrapper-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").addClass("hidden");
+ }
+ });
+
+ $("#btn-storagepool-filesystem-samba-enable-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-samba-enable-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let samba = {
+ share: {
+ additional: ($("#switch-storagepool-filesystem-samba-enable-additional-` + filesystem.id + ` input").prop("checked") ? $("#textarea-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").val().split("\\n").filter(v => v) : []),
+ administrative: false,
+ browseable: true,
+ comment: "",
+ guestok: false,
+ name: "",
+ readonly: false
+ }
+ };
+ let validation = {
+ comment: false,
+ name: false,
+ additional: false
+ };
+
+ if ($("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").val().length == 0) {
+ $("#helpblock-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not be empty.");
+
+ validation.name = false;
+ } else if (/^[a-zA-Z0-9-_.@%+!#$^,(){}~ ]*$/.test($("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").val()) == false) {
+ $("#helpblock-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name contains invalid characters.");
+
+ validation.name = false;
+ } else if (/^[ ]/.test($("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not begin with whitespace ( ).");
+
+ validation.name = false;
+ } else if (/[ ]$/.test($("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Share name can not end with whitespace ( ).");
+
+ validation.name = false;
+ } else {
+ $("#validationwrapper-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("hidden").text("");
+
+ validation.name = true;
+ }
+
+ if (/^[ -~]*$/.test($("#input-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").val()) == false) {
+ $("#helpblock-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment contains invalid characters.");
+
+ validation.comment = false;
+ } else if (/^[ ]/.test($("#input-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment can not begin with whitespace ( ).");
+
+ validation.comment = false;
+ } else if (/[ ]$/.test($("#input-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Comment can not end with whitespace ( ).");
+
+ validation.comment = false;
+ } else {
+ $("#validationwrapper-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").addClass("hidden").text("");
+
+ validation.comment = true;
+ }
+
+ if (samba.share.additional.length > 0) {
+ samba.share.additional.forEach((_value, _index) => {
+ if (/[\\[\\]]/g.test(_value)) { //Do not allow section names
+ $("#helpblock-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must not contain brackets. Line: " + (_index + 1));
+
+ validation.additional = false;
+ return;
+ } else if (/^[#]/.test(_value) == false && /[=]/.test(_value) && /(path|comment|browseable|read only|guest ok).*=/gi.test(_value)) {
+ $("#helpblock-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must not contain duplicate properties. Line: " + (_index + 1));
+
+ validation.additional = false;
+ return;
+ } else if (/[#=]/.test(_value) == false) {
+ $("#helpblock-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Additional must contain comments or properties only. Line: " + (_index + 1));
+
+ validation.additional = false;
+ return;
+ } else if (_index == (samba.share.additional.length -1)) {
+ $("#validationwrapper-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ validation.additional = true;
+ }
+ });
+ } else {
+ validation.additional = true;
+ }
+
+ if (!validation.name || !validation.comment || !validation.additional) {
+ if (!validation.name) {
+ $("#validationwrapper-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").addClass("has-error");
+ $("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").focus();
+ }
+ if (!validation.comment) {
+ $("#validationwrapper-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").addClass("has-error");
+ $("#input-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").focus();
+ }
+ if (!validation.additional) {
+ $("#validationwrapper-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").addClass("has-error");
+ $("#textarea-storagepool-filesystem-samba-enable-additional-` + filesystem.id + `").focus();
+ }
+
+ $("#spinner-storagepool-filesystem-samba-enable-` + filesystem.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.name && validation.comment && validation.additional) {
+ samba.share.administrative = $("#switch-storagepool-filesystem-samba-enable-administrative-` + filesystem.id + ` input").prop("checked");
+ samba.share.browseable = $("#switch-storagepool-filesystem-samba-enable-browseable-` + filesystem.id + ` input").prop("checked");
+ samba.share.comment = $("#input-storagepool-filesystem-samba-enable-comment-` + filesystem.id + `").val();
+ samba.share.guestok = $("#switch-storagepool-filesystem-samba-enable-guestok-` + filesystem.id + ` input").prop("checked");
+ samba.share.name = $("#input-storagepool-filesystem-samba-enable-name-` + filesystem.id + `").val();
+ samba.share.readonly = $("#switch-storagepool-filesystem-samba-enable-readonly-` + filesystem.id + ` input").prop("checked");
+
+ FnSambaShareEnable({ name: "` + pool.name + `", id: "` + pool.id + `", readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", mounted: ` + filesystem.mounted + `, mountpoint: "` + filesystem.mountpoint + `" }, { share: { additional: samba.share.additional, administrative: samba.share.administrative, browseable: samba.share.browseable, guestok: samba.share.guestok, name: samba.share.name, comment: samba.share.comment, readonly: samba.share.readonly, temporary: ` + (pool.altroot || pool.readonly ? true : false) + ` } }, { silent: false });
+ }
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemSnapshotCreate(pool = { name, id }, filesystem = { name, id }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-snapshot-create-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemSnapshotCreateContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { id: $("#modal-storagepool-filesystem-snapshot-create-` + filesystem.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemSnapshotCreateContent(pool = { name, id }, filesystem = { name, id }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-filesystem-snapshot-create-customname-` + filesystem.id + ` input").on("click", function () {
+ $("#validationwrapper-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ if ($(this).prop("checked")) {
+ $("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val("").prop("readonly", false).focus();
+ } else {
+ $("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val("YYYY.MM.DD-HH.MM.SS").prop("readonly", true);;
+ }
+ });
+
+ $("#btn-storagepool-filesystem-snapshot-create-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-snapshot-create-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let snapshot = {
+ name: "",
+ id: "",
+ recursive: false
+ };
+ let validation = {
+ name: false
+ };
+
+ if ($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val().length == 0) {
+ $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
+
+ validation.name = false;
+ } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val()) == false) {
+ $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
+
+ validation.name = false;
+ } else if (/^[.]/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
+
+ validation.name = false;
+ } else if (/^[_]/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
+
+ validation.name = false;
+ } else if (/^[-]/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
+
+ validation.name = false;
+ } else if (/^[:]/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
+
+ validation.name = false;
+ } else if (/^[ ]/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
+
+ validation.name = false;
+ } else if (/[ ]$/.test($("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val())) {
+ $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
+
+ validation.name = false;
+ } else {
+ $("#validationwrapper-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("hidden").text("");
+
+ validation.name = true;
+ }
+
+ if (!validation.name) {
+ $("#validationwrapper-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").addClass("has-error");
+ $("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").focus();
+
+ $("#spinner-storagepool-filesystem-snapshot-create-` + filesystem.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.name) {
+ snapshot.name = "` + filesystem.name + `" + "@" + $("#input-storagepool-filesystem-snapshot-create-name-` + filesystem.id + `").val();
+ snapshot.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: snapshot.name, attribute: true });
+ snapshot.recursive = $("#switch-storagepool-filesystem-snapshot-create-recursive-` + filesystem.id + ` input").prop("checked");
+
+ if ($("#switch-storagepool-filesystem-snapshot-create-customname-` + filesystem.id + ` input").prop("checked")) {
+ FnSnapshotCreate({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive }, { name: "storagepool-filesystem-snapshot-create", id: "` + filesystem.id + `"});
+ } else {
+ FnSnapshotCreateDateGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive }, { name: "storagepool-filesystem-snapshot-create", id: "` + filesystem.id + `"});
+ }
+ }
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemUnlock(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-unlock-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemUnlockContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-unlock-` + filesystem.id + `") });
+
+ setTimeout(function() {
+ $("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").focus();
+ }, 600);
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemUnlockContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, sharesmb: false, type }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-filesystem-unlock-mount-` + filesystem.id + ` input").on("click", function () {
+ if ($(this).prop("checked")) {
+ $("#switch-storagepool-filesystem-unlock-overlay-` + filesystem.id + `").parent().removeClass("hidden");
+ } else {
+ $("#switch-storagepool-filesystem-unlock-overlay-` + filesystem.id + `").parent().addClass("hidden");
+ }
+ });
+
+ $("#btn-storagepool-filesystem-unlock-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-unlock-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let filesystem = {
+ mount: true,
+ passphrase: ""
+ };
+ let samba = {
+ enable: false
+ };
+ let validation = {
+ passphrase: false
+ };
+
+ if ($("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").val().length == 0) {
+ $("#helpblock-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase can not be empty.");
+
+ validation.passphrase = false;
+ } else if ($("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").val().length < 8) {
+ $("#helpblock-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase requires a minimum of 8 characters.");
+
+ validation.passphrase = false;
+ } else if (/^[a-zA-Z0-9-_. \`~!@#$%^\(\)+\\[\\]{}:',/?]*$/.test($("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").val()) == false) {
+ $("#helpblock-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").addClass("has-error").removeClass("hidden").text("Passphrase contains invalid characters.");
+
+ validation.passphrase = false;
+ } else {
+ $("#validationwrapper-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ validation.passphrase = true;
+ }
+
+ if (!validation.passphrase) {
+ $("#validationwrapper-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").addClass("has-error");
+ $("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").focus();
+
+ $("#spinner-storagepool-filesystem-unlock-` + filesystem.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.passphrase) {
+ filesystem.mount = $("#switch-storagepool-filesystem-unlock-mount-` + filesystem.id + ` input").prop("checked");
+ filesystem.overlay = $("#switch-storagepool-filesystem-unlock-overlay-` + filesystem.id + ` input").prop("checked");
+ filesystem.passphrase = $("#input-storagepool-filesystem-unlock-passphrase-` + filesystem.id + `").val();
+
+ samba.enable = ` + ((pool.readonly || filesystem.sharesmb) ? false : `$("#switch-storagepool-filesystem-unlock-samba-enable-` + filesystem.id + ` input").prop("checked")`) + `;
+
+ FnFileSystemUnlock({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", mount: filesystem.mount, overlay: filesystem.overlay, passphrase: filesystem.passphrase, type: "` + filesystem.type + `" }, { enable: samba.enable }, { name: "storagepool-filesystem-unlock", id: "` + filesystem.id + `" }, { refresh: true });
+ }
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalFileSystemUnmount(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, encryptionroot, keystatus, sharesmb: false, type }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-unmount-` + filesystem.id + `").on("click", function () {
+ FnModalFileSystemUnmountContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", encryptionroot: "` + filesystem.encryptionroot + `", keystatus: "` + filesystem.keystatus + `", sharesmb: ` + filesystem.sharesmb + `, type: "` + filesystem.type + `" }, { id: $("#modal-storagepool-filesystem-unmount-` + filesystem.id + `") });
+ FnFileSystemsMountedGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `" }, { alert: { id: $("#div-storagepool-filesystem-unmount-warning-` + filesystem.id + `"), mount: false } });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-filesystem-" + pool.id).append(modal.window);
+}
+
+function FnModalFileSystemUnmountContent(pool = { name, id, altroot: false, readonly: false }, filesystem = { name, id, encryptionroot, keystatus, sharesmb: false, type }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-filesystem-unmount-apply-` + filesystem.id + `").on("click", function () {
+ $("#spinner-storagepool-filesystem-unmount-` + filesystem.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let filesystem = {
+ force: $("#switch-storagepool-filesystem-unmount-force-` + filesystem.id + ` input").prop("checked"),
+ lock: ` + (filesystem.keystatus == "available" && filesystem.encryptionroot == filesystem.name ? `$("#switch-storagepool-filesystem-unmount-lock-` + filesystem.id + ` input").prop("checked")` : false) + `
+ };
+ let samba = {
+ disable: ` + ((!pool.readonly && filesystem.sharesmb) ? `$("#switch-storagepool-filesystem-unmount-samba-disable-` + filesystem.id + ` input").prop("checked")` : false) + `,
+ restart: $("#switch-storagepool-filesystem-unmount-samba-restart-` + filesystem.id + ` input").prop("checked")
+ };
+
+ FnFileSystemUnmount({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + filesystem.name + `", id: "` + filesystem.id + `", force: filesystem.force, lock: filesystem.lock, type: "` + filesystem.type + `" }, { disable: samba.disable, restart: samba.restart });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+//#endregion
+
+//#region Modal Snapshots
+
+function FnModalSnaphshotsCreate(pool = { name, id }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-snapshots-create-` + pool.id + `").on("click", function () {
+ FnModalSnaphshotsCreateContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: $("#modal-storagepool-snapshots-create-` + pool.id + `") });
+ FnFileSystemsNamesGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { existing: { name: null, clone: false, encryption: false, encryptionroot: null, origin: null }, override: true }, { dropdown: { id: $("#dropdown-storagepool-snapshots-create-filesystem-` + pool.id + `"), selected: "` + pool.name + `" } });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-snapshots-" + pool.id).append(modal.window);
+}
+
+function FnModalSnaphshotsCreateContent(pool = { name, id }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-snapshots-create-customname-` + pool.id + ` input").on("click", function () {
+ $("#validationwrapper-storagepool-snapshots-create-name-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ if ($(this).prop("checked")) {
+ $("#input-storagepool-snapshots-create-name-` + pool.id + `").val("").prop("readonly", false).focus();
+ } else {
+ $("#input-storagepool-snapshots-create-name-` + pool.id + `").val("YYYY.MM.DD-HH.MM.SS").prop("readonly", true);;
+ }
+ });
+
+ $("#btn-storagepool-snapshots-create-apply-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-snapshots-create-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let snapshot = {
+ name: "",
+ id: "",
+ recursive: false
+ };
+ let validation = {
+ name: false
+ };
+
+ if ($("#input-storagepool-snapshots-create-name-` + pool.id + `").val().length == 0) {
+ $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
+
+ validation.name = false;
+ } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val()) == false) {
+ $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
+
+ validation.name = false;
+ } else if (/^[.]/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
+
+ validation.name = false;
+ } else if (/^[_]/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
+
+ validation.name = false;
+ } else if (/^[-]/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
+
+ validation.name = false;
+ } else if (/^[:]/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
+
+ validation.name = false;
+ } else if (/^[ ]/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
+
+ validation.name = false;
+ } else if (/[ ]$/.test($("#input-storagepool-snapshots-create-name-` + pool.id + `").val())) {
+ $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
+
+ validation.name = false;
+ } else {
+ $("#validationwrapper-storagepool-snapshots-create-name-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-snapshots-create-name-` + pool.id + `").addClass("hidden").text("");
+
+ validation.name = true;
+ }
+
+ if (!validation.name) {
+ $("#validationwrapper-storagepool-snapshots-create-name-` + pool.id + `").addClass("has-error");
+ $("#input-storagepool-snapshots-create-name-` + pool.id + `").focus();
+
+ $("#spinner-storagepool-snapshots-create-` + pool.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.name) {
+ snapshot.name = $("#btnspan-storagepool-snapshots-create-filesystem-` + pool.id + `").attr("data-field-value") + "@" + $("#input-storagepool-snapshots-create-name-` + pool.id + `").val();
+ snapshot.id = FnGenerateId({ at: true, colon: true, forwardslash: true, period: true, underscore: true, whitespace: true }, { name: snapshot.name, attribute: true });
+ snapshot.recursive = $("#switch-storagepool-snapshots-create-recursive-` + pool.id + ` input").prop("checked");
+
+ if ($("#switch-storagepool-snapshots-create-customname-` + pool.id + ` input").prop("checked")) {
+ FnSnapshotCreate({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive }, { name: "storagepool-snapshots-create", id: "` + pool.id + `"});
+ } else {
+ FnSnapshotCreateDateGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: snapshot.name, id: snapshot.id, recursive: snapshot.recursive }, { name: "storagepool-snapshots-create", id: "` + pool.id + `"});
+ }
+ }
+ });
+
+ $("#dropdown-storagepool-snapshots-create-filesystem-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-snapshots-create-filesystem-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+//#endregion
+
+//#region Modal Snapshot
+
+function FnModalSnapshotClone(pool = { name, id, altroot: false }, snapshot = { name, id, encryption: false, encryptionroot }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-snapshot-clone-` + snapshot.id + `").on("click", function () {
+ FnModalSnapshotCloneContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", encryption: ` + snapshot.encryption + ` }, { id: $("#modal-storagepool-snapshot-clone-` + snapshot.id + `") });
+ FnFileSystemsNamesGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { existing: { name: null, clone: false, encryption: ` + snapshot.encryption + `, encryptionroot: "` + snapshot.encryptionroot + `", origin: null }, override: false }, { dropdown: { id: $("#dropdown-storagepool-snapshot-clone-parentfilesystem-` + snapshot.id + `"), selected: "` + snapshot.name.replace(/^(.*)\@.*$/, "$1") + `" } });
+
+ setTimeout(function() {
+ $("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").focus();
+ }, 600);
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-snapshot-" + pool.id).append(modal.window);
+}
+
+function FnModalSnapshotCloneContent(pool = { name, id, altroot: false }, snapshot = { name, id, encryption: false }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-snapshot-clone-apply-` + snapshot.id + `").on("click", function () {
+ $("#spinner-storagepool-snapshot-clone-` + snapshot.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let snapshot = {
+ clone: {
+ createnonexistparents: false,
+ name: "",
+ parent: ""
+ }
+ };
+ let validation = {
+ name: false
+ };
+
+ if ($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val().length == 0) {
+ $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
+
+ validation.name = false;
+ } else if (/^[a-zA-Z0-9-_.:/ ]*$/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val()) == false) {
+ $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
+
+ validation.name = false;
+ } else if (/^[.]/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
+
+ validation.name = false;
+ } else if (/^[_]/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
+
+ validation.name = false;
+ } else if (/^[-]/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
+
+ validation.name = false;
+ } else if (/^[:]/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
+
+ validation.name = false;
+ } else if (/^[/]/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a forward slash (/).");
+
+ validation.name = false;
+ } else if (/[/]$/.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with a forward slash (/).");
+
+ validation.name = false;
+ } else if (/^ |\\/ /.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
+
+ validation.name = false;
+ } else if (/ $| \\//.test($("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
+
+ validation.name = false;
+ } else {
+ $("#validationwrapper-storagepool-snapshot-clone-name-` + snapshot.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-snapshot-clone-name-` + snapshot.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ validation.name = true;
+ }
+
+ if (!validation.name) {
+ $("#validationwrapper-storagepool-snapshot-clone-name-` + snapshot.id + `").addClass("has-error");
+ $("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").focus();
+
+ $("#spinner-storagepool-snapshot-clone-` + snapshot.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.name) {
+ snapshot.clone.createnonexistparents = $("#switch-storagepool-snapshot-clone-createnonexistparents-` + snapshot.id + ` input").prop("checked");
+ snapshot.clone.name = $("#btnspan-storagepool-snapshot-clone-parentfilesystem-` + snapshot.id + `").attr("data-field-value") + "/" + $("#input-storagepool-snapshot-clone-name-` + snapshot.id + `").val();
+ snapshot.clone.parent = $("#btnspan-storagepool-snapshot-clone-parentfilesystem-` + snapshot.id + `").attr("data-field-value");
+
+ FnSnapshotClone({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", clone: { name: snapshot.clone.name, createnonexistparents: snapshot.clone.createnonexistparents, parent: snapshot.clone.parent } });
+ }
+ });
+
+ $("#dropdown-storagepool-snapshot-clone-parentfilesystem-` + snapshot.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-snapshot-clone-parentfilesystem-` + snapshot.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalSnapshotDestroy(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, clones: [] }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-snapshot-destroy-` + snapshot.id + `").on("click", function () {
+ FnModalSnapshotDestroyContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", clones: [` + (snapshot.clones.length > 0 ? `"` + snapshot.clones.join(`","`) + `"` : ``) + `] }, { id: $("#modal-storagepool-snapshot-destroy-` + snapshot.id + `") });
+ ` + (snapshot.clones.length > 0 ? `FnSnapshotChildFileSystemsGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `" }, { id: ` + (snapshot.clones.length > 0 ? `["` + snapshot.clones.join(`", "`) + `"]` : `[]`) + ` }, { name: "storagepool-snapshot-destroy", id: "` + snapshot.id + `" });` : ``) + `
+ FnSnapshotChildSnapshotsGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", exclude: false }, { id: ` + (snapshot.clones.length > 0 ? `["` + snapshot.clones.join(`", "`) + `"]` : `[]`) + ` }, { name: "storagepool-snapshot-destroy", id: "` + snapshot.id + `" });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-snapshot-" + pool.id).append(modal.window);
+}
+
+function FnModalSnapshotDestroyContent(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, clones: [] }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-snapshot-destroy-recursive-` + snapshot.id + ` input").on("click", function () {
+ if ($(this).prop("checked") && $("#switch-storagepool-snapshot-destroy-recursiveall-` + snapshot.id + ` input").prop("checked")) {
+ $("#switch-storagepool-snapshot-destroy-recursiveall-` + snapshot.id + ` input").click();
+ }
+
+ $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
+ $("#panel-storagepool-snapshot-destroy-child-snapshotswithclones-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-destroy-child-snapshotswithclones-` + snapshot.id + ` .collapse").collapse("hide");
+
+ if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-snapshots") > 0) {
+ $("#panel-storagepool-snapshot-destroy-child-snapshots-` + snapshot.id + `").removeClass("hidden");
+ } else {
+ $("#panel-storagepool-snapshot-destroy-child-snapshots-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-destroy-child-snapshots-` + snapshot.id + ` .collapse").collapse("hide");
+ }
+ if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-snapshots") > 0) {
+ $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").addClass("modal-ct-bodytext-1");
+ } else {
+ $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").removeClass("modal-ct-bodytext-1");
+ }
+ });
+
+ $("#switch-storagepool-snapshot-destroy-recursiveall-` + snapshot.id + ` input").on("click", function () {
+ if ($(this).prop("checked") && $("#switch-storagepool-snapshot-destroy-recursive-` + snapshot.id + ` input").prop("checked")) {
+ $("#switch-storagepool-snapshot-destroy-recursive-` + snapshot.id + ` input").click();
+ }
+
+ $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
+ $("#panel-storagepool-snapshot-destroy-child-snapshots-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-destroy-child-snapshots-` + snapshot.id + ` .collapse").collapse("hide");
+
+ if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-filesystems") > 0) {
+ $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + `").removeClass("hidden");
+ } else {
+ $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-destroy-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
+ }
+ if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-snapshotswithclones") > 0) {
+ $("#panel-storagepool-snapshot-destroy-child-snapshotswithclones-` + snapshot.id + `").removeClass("hidden");
+ } else {
+ $("#panel-storagepool-snapshot-destroy-child-snapshotswithclones-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-destroy-child-snapshotswithclones-` + snapshot.id + ` .collapse").collapse("hide");
+ }
+ if ($(this).prop("checked") && ($("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-snapshotswithclones") > 0 || $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").attr("data-snapshot-child-snapshotswithclones") > 0)) {
+ $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").addClass("modal-ct-bodytext-1");
+ } else {
+ $("#panelgroup-storagepool-snapshot-destroy-` + snapshot.id + `").removeClass("modal-ct-bodytext-1");
+ }
+ });
+
+ $("#btn-storagepool-snapshot-destroy-apply-` + snapshot.id + `").on("click", function () {
+ $("#spinner-storagepool-snapshot-destroy-` + snapshot.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let snapshot = {
+ recursive: $("#switch-storagepool-snapshot-destroy-recursive-` + snapshot.id + ` input").prop("checked"),
+ recursiveall: $("#switch-storagepool-snapshot-destroy-recursiveall-` + snapshot.id + ` input").prop("checked")
+ };
+ let samba = {
+ restart: $("#switch-storagepool-snapshot-destroy-samba-restart-` + snapshot.id + ` input").prop("checked")
+ };
+
+ FnSnapshotDestroy({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", clones: ` + (snapshot.clones.length > 0 ? `["` + snapshot.clones.join(`", "`) + `"]` : `[]`) + `, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { restart: samba.restart });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalSnapshotRename(pool = { name, id }, snapshot = { name, id, creation }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-snapshot-rename-` + snapshot.id + `").on("click", function () {
+ FnModalSnapshotRenameContent({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", creation: "` + snapshot.creation + `" }, { id: $("#modal-storagepool-snapshot-rename-` + snapshot.id + `") });
+
+ setTimeout(function() {
+ $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").focus();
+ }, 600);
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-snapshot-" + pool.id).append(modal.window);
+}
+
+function FnModalSnapshotRenameContent(pool = { name, id }, snapshot = { name, id, creation }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-snapshot-rename-creationdate-` + snapshot.id + ` input").on("click", function () {
+ if ($(this).prop("checked")) {
+ $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val("` + FnDateTimeSnapshot({ date: new Date(snapshot.creation * 1000) }) + `").prop("readonly", true);
+ } else {
+ $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val("` + snapshot.name.replace(/^.*\@(.*)$/, "$1") + `").prop("readonly", false).focus();
+ }
+ });
+
+ $("#btn-storagepool-snapshot-rename-apply-` + snapshot.id + `").on("click", function () {
+ $("#spinner-storagepool-snapshot-rename-` + snapshot.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let snapshot = {
+ namenew: "",
+ recursive: false
+ };
+ let validation = {
+ name: false
+ };
+
+ if ("` + snapshot.name.replace(/^(.*)\@.*$/, "$1") + `" + "@" + $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val() == "` + snapshot.name + `") {
+ $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name must be different.");
+
+ validation.name = false;
+ } else if ($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val().length == 0) {
+ $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not be empty.");
+
+ validation.name = false;
+ } else if (/^[a-zA-Z0-9-_.: ]*$/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val()) == false) {
+ $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name contains invalid characters.");
+
+ validation.name = false;
+ } else if (/^[.]/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a period (.).");
+
+ validation.name = false;
+ } else if (/^[_]/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an underscore (_).");
+
+ validation.name = false;
+ } else if (/^[-]/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with a hypen (-).");
+
+ validation.name = false;
+ } else if (/^[:]/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with an colon (:).");
+
+ validation.name = false;
+ } else if (/^[ ]/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not begin with whitespace ( ).");
+
+ validation.name = false;
+ } else if (/[ ]$/.test($("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val())) {
+ $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error").removeClass("hidden").text("Name can not end with whitespace ( ).");
+
+ validation.name = false;
+ } else {
+ $("#validationwrapper-storagepool-snapshot-rename-name-` + snapshot.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-snapshot-rename-name-` + snapshot.id + `").removeClass("has-error").addClass("hidden").text("");
+
+ validation.name = true;
+ }
+
+ if (!validation.name) {
+ $("#validationwrapper-storagepool-snapshot-rename-name-` + snapshot.id + `").addClass("has-error");
+ $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").focus();
+
+ $("#spinner-storagepool-snapshot-rename-` + snapshot.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.name) {
+ snapshot.namenew = "` + snapshot.name.replace(/^(.*)\@.*$/, "$1") + `" + "@" + $("#input-storagepool-snapshot-rename-name-` + snapshot.id + `").val();
+ snapshot.recursive = $("#switch-storagepool-snapshot-rename-recursive-` + snapshot.id + ` input").prop("checked");
+
+ FnSnapshotRename({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", namenew: snapshot.namenew, recursive: snapshot.recursive });
+ }
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalSnapshotRollBack(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, creation }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-snapshot-rollback-` + snapshot.id + `").on("click", function () {
+ FnModalSnapshotRollBackContent({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", creation: "` + snapshot.creation + `" }, { id: $("#modal-storagepool-snapshot-rollback-` + snapshot.id + `") });
+ FnSnapshotRollBackSnapshotsGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", creation: "` + snapshot.creation + `" }, { name: "storagepool-snapshot-rollback", id: "` + snapshot.id + `" });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-snapshot-" + pool.id).append(modal.window);
+}
+
+function FnModalSnapshotRollBackContent(pool = { name, id, altroot: false, readonly: false }, snapshot = { name, id, creation }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-snapshot-rollback-recursive-` + snapshot.id + ` input").on("click", function () {
+ if ($(this).prop("checked") && $("#switch-storagepool-snapshot-rollback-recursiveall-` + snapshot.id + ` input").prop("checked")) {
+ $("#switch-storagepool-snapshot-rollback-recursiveall-` + snapshot.id + ` input").click();
+ }
+
+ $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
+ $("#panel-storagepool-snapshot-rollback-child-snapshotswithclones-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-rollback-child-snapshotswithclones-` + snapshot.id + ` .collapse").collapse("hide");
+
+ if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-rollback-` + snapshot.id + `").attr("data-snapshot-snapshots") > 0) {
+ $("#panel-storagepool-snapshot-rollback-snapshots-` + snapshot.id + `").removeClass("hidden");
+ } else {
+ $("#panel-storagepool-snapshot-rollback-snapshots-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-rollback-snapshots-` + snapshot.id + ` .collapse").collapse("hide");
+ }
+ });
+
+ $("#switch-storagepool-snapshot-rollback-recursiveall-` + snapshot.id + ` input").on("click", function () {
+ if ($(this).prop("checked") && $("#switch-storagepool-snapshot-rollback-recursive-` + snapshot.id + ` input").prop("checked")) {
+ $("#switch-storagepool-snapshot-rollback-recursive-` + snapshot.id + ` input").click();
+ }
+
+ if ($(this).prop("checked")) {
+ $("#switch-storagepool-snapshot-rollback-force-` + snapshot.id + `").parent().removeClass("hidden");
+ } else {
+ $("#switch-storagepool-snapshot-rollback-force-` + snapshot.id + `").parent().addClass("hidden");
+
+ if ($("#switch-storagepool-snapshot-rollback-force-` + snapshot.id + ` input").prop("checked")) {
+ $("#switch-storagepool-snapshot-rollback-force-` + snapshot.id + ` input").click();
+ }
+ }
+
+ $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
+ $("#panel-storagepool-snapshot-rollback-snapshots-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-rollback-snapshots-` + snapshot.id + ` .collapse").collapse("hide");
+
+ if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-rollback-` + snapshot.id + `").attr("data-snapshot-child-filesystems") > 0) {
+ $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + `").removeClass("hidden");
+ } else {
+ $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-rollback-child-filesystems-` + snapshot.id + ` .collapse").collapse("hide");
+ }
+ if ($(this).prop("checked") && $("#panelgroup-storagepool-snapshot-rollback-` + snapshot.id + `").attr("data-snapshot-child-snapshotswithclones") > 0) {
+ $("#panel-storagepool-snapshot-rollback-child-snapshotswithclones-` + snapshot.id + `").removeClass("hidden");
+ } else {
+ $("#panel-storagepool-snapshot-rollback-child-snapshotswithclones-` + snapshot.id + `").addClass("hidden");
+ $("#panel-storagepool-snapshot-rollback-child-snapshotswithclones-` + snapshot.id + ` .collapse").collapse("hide");
+ }
+ });
+
+ $("#btn-storagepool-snapshot-rollback-apply-` + snapshot.id + `").on("click", function () {
+ $("#spinner-storagepool-snapshot-rollback-` + snapshot.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let snapshot = {
+ force: ($("#switch-storagepool-snapshot-rollback-recursiveall-` + snapshot.id + ` input").prop("checked") ? $("#switch-storagepool-snapshot-rollback-force-` + snapshot.id + ` input").prop("checked") : false),
+ recursive: $("#switch-storagepool-snapshot-rollback-recursive-` + snapshot.id + ` input").prop("checked"),
+ recursiveall: $("#switch-storagepool-snapshot-rollback-recursiveall-` + snapshot.id + ` input").prop("checked")
+ };
+ let samba = {
+ restart: $("#switch-storagepool-snapshot-rollback-samba-restart-` + snapshot.id + ` input").prop("checked")
+ };
+
+ FnSnapshotRollBack({ name: "` + pool.name + `", id: "` + pool.id + `", altroot: ` + pool.altroot + `, readonly: ` + pool.readonly + ` }, { name: "` + snapshot.name + `", id: "` + snapshot.id + `", creation: "` + snapshot.creation + `", force: snapshot.force, recursive: snapshot.recursive, recursiveall: snapshot.recursiveall }, { restart: samba.restart });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+//#endregion
+
+//#region Modal Status
+
+function FnModalStatusDiskAttach(pool = { name, id, status: { config: { items: { index: 0 }, tier: { name, dedup: false, logs: false, special: false } } } }, virtualdevice = { id, disk: true }) {
+ let modal = {
+ tiername: (pool.status.config.tier.dedup ? "Dedup" : (pool.status.config.tier.logs ? "Log" : (pool.status.config.tier.special ? "Special" : pool.status.config.tier.name))),
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-attach-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusDiskAttachContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + virtualdevice.id + `" , disk: ` + virtualdevice.disk + ` }, { id: $("#modal-storagepool-status-disk-attach-` + pool.status.config.items.index + `-` + pool.id + `"), tiername: "` + modal.tiername + `" });
+ FnDisksAvailableGet({ name: "storagepool-status-disk-attach-disks", id: "` + pool.status.config.items.index + `-` + pool.id + `", default: true });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusDiskAttachContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, virtualdevice = { id, disk: true }, modal = { id, tiername }) {
+ modal.content = `
+
+
+
+
+ ` + (virtualdevice.disk ? FnDisplayInlineAlert({ status: "info", title: "Attaching a disk will convert the virtual device from Disk to Mirror.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
+
+ Virtual Device
+
+
` + virtualdevice.id + ` (` + modal.tiername + `)
+
+ Disks WWN
+
+
+
+ Disks Identifier
+
+ Disks
+
+
+
+ ` + (zfsmanager.zfs.warnings.nvmevdev ? `
Virtual Device Mapping identifiers for NVMe devices may not have been created due to a bug in the ZFS software . Update ZFS to 0.8.3 for fix. ` : ``) + `
+
+
+
+ Options
+
+ Forcefully attach disk
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-status-disk-attach-disks-wwn-` + pool.status.config.items.index + `-` + pool.id + ` input").on("click", function () {
+ $("#btnspan-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text("Block Device");
+ $("#dropdown-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li").siblings().removeClass("active");
+ $("#dropdown-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li[value='blockdevice']").addClass("active");
+ $("#helpblock-storagepool-status-disk-attach-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
+ ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-disk-attach-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
+
+ let disk = {
+ identifier: ($(this).prop("checked") ? "wwn" : "blockdevice"),
+ identifiertext: ($(this).prop("checked") ? "WWN" : "Block Device")
+ };
+
+ if ($(this).prop("checked")) {
+ $("#controllabel-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ $("#validationwrapper-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ } else {
+ $("#controllabel-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $("#validationwrapper-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ }
+
+ $("#listgroup-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
+ if ($(this).attr("data-disk-id-" + disk.identifier)) {
+ $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
+ } else {
+ $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
+ $("#helpblock-storagepool-status-disk-attach-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
+ }
+ });
+ });
+
+ $("#btn-storagepool-status-disk-attach-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-disk-attach-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let disk = {
+ idnew: []
+ };
+ let modal = {
+ name: "",
+ id: ""
+ };
+ let pool = {
+ force: false
+ };
+ let validation = {
+ disks: false
+ };
+
+ $("#listgroup-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `']:checked").map(function () {
+ disk.idnew.push($(this).attr("data-disk-name"));
+ });
+
+ if (disk.idnew.length != 1) {
+ $("#helpblock-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One disk is needed.");
+
+ validation.disks = false;
+ } else {
+ $("#validationwrapper-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("");
+
+ validation.disks = true;
+ }
+
+ if (!validation.disks) {
+ $("#validationwrapper-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `").addClass("has-error");
+
+ $("#spinner-storagepool-status-disk-attach-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.disks) {
+ modal.name = "storagepool-status-disk-attach";
+ modal.id = "` + pool.status.config.items.index + `-` + pool.id + `";
+
+ pool.force = $("#switch-storagepool-status-disk-attach-force-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked");
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolDiskAttach({ name: "` + pool.name + `", id: "` + pool.id + `", force: pool.force }, { id: "` + virtualdevice.id + `", disk: ` + virtualdevice.disk + ` }, { idnew: disk.idnew }, { name: modal.name, id: modal.id });
+ }
+ });
+
+ $("#dropdown-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-status-disk-attach-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+
+ $("#helpblock-storagepool-status-disk-attach-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
+ ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-disk-attach-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
+
+ let disk = {
+ identifier: $(this).parent().attr("value"),
+ identifiertext: $(this).parent().text()
+ };
+
+ $("#listgroup-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-attach-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
+ if ($(this).attr("data-disk-id-" + disk.identifier)) {
+ $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
+ } else {
+ $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
+ $("#helpblock-storagepool-status-disk-attach-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
+
` + (zfsmanager.zfs.warnings.nvmevdev ? `
if (disk.identifier == "vdev" && /^nvme/gi.test($(this).attr("data-disk-id-blockdevice"))) {
$("#helpblock-storagepool-status-disk-attach-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
}
- ` : ``) + `
- }
- });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusDiskClear(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-clear-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusDiskClearContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-clear-` + pool.status.config.items.index + `-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusDiskClearContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to clear errors for disk: ` + disk.id + ` ?
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-clear-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-disk-clear-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let modal = {
- name: "storagepool-status-disk-clear",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolDiskClear({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `" }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusDiskDetach(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-detach-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusDiskDetachContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-detach-` + pool.status.config.items.index + `-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusDiskDetachContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to detach disk: ` + disk.id + ` ?
-
- Options
-
- Clear the label information on the disk
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-detach-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-disk-detach-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let disk = {
- labelclear: $("#switch-storagepool-status-disk-detach-labelclear-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
- };
- let modal = {
- name: "storagepool-status-disk-detach",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolDiskDetach({ name: "` + pool.name + `", id: "` + pool.id + `"}, { id: "` + disk.id + `", labelclear: disk.labelclear }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusDiskOffline(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-offline-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusDiskOfflineContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-offline-` + pool.status.config.items.index + `-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusDiskOfflineContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to offline disk: ` + disk.id + ` ?
-
- Options
-
- Forcefully offline the disk
-
-
- Temporarily offline the disk until next reboot
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-offline-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-disk-offline-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let disk = {
- force: $("#switch-storagepool-status-disk-offline-force-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked"),
- temporary: $("#switch-storagepool-status-disk-offline-temporary-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
- };
- let modal = {
- name: "storagepool-status-disk-offline",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolDiskOffline({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `", force: disk.force, temporary: disk.temporary }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusDiskOnline(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-online-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusDiskOnlineContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-online-` + pool.status.config.items.index + `-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-
-}
-
-function FnModalStatusDiskOnlineContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to online disk: ` + disk.id + ` ?
-
- Options
-
- Expand the device to use all available space
-
-
- Scrub the storage pool after disk is set online
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-online-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-disk-online-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let disk = {
- expand: $("#switch-storagepool-status-disk-online-expand-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
- };
- let modal = {
- name: "storagepool-status-disk-online",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
- let pool = {
- scrub: $("#switch-storagepool-status-disk-online-scrub-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolDiskOnline({ name: "` + pool.name + `", id: "` + pool.id + `", scrub: pool.scrub }, { id: "` + disk.id + `", expand: disk.expand }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusDiskReplace(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-replace-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusDiskReplaceContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-replace-` + pool.status.config.items.index + `-` + pool.id + `") });
- FnDisksAvailableGet({ name: "storagepool-status-disk-replace-disks", id: "` + pool.status.config.items.index + `-` + pool.id + `", default: true });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusDiskReplaceContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
- modal.content = `
-
-
-
-
-
- Disk
-
- Disks WWN
-
-
-
- Disks Identifier
-
- Disks
-
-
-
- ` + (zfsmanager.zfs.warnings.nvmevdev ? `
Virtual Device Mapping identifiers for NVMe devices may not have been created due to a bug in the ZFS software . Update ZFS to 0.8.3 for fix. ` : ``) + `
-
-
-
- Options
-
- Forcefully replace disk
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-status-disk-replace-disks-wwn-` + pool.status.config.items.index + `-` + pool.id + ` input").on("click", function () {
- $("#btnspan-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text("Block Device");
- $("#dropdown-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li").siblings().removeClass("active");
- $("#dropdown-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li[value='blockdevice']").addClass("active");
- $("#helpblock-storagepool-status-disk-replace-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
- ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-disk-replace-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
-
- let disk = {
- identifier: ($(this).prop("checked") ? "wwn" : "blockdevice"),
- identifiertext: ($(this).prop("checked") ? "WWN" : "Block Device")
- };
-
- if ($(this).prop("checked")) {
- $("#controllabel-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- $("#validationwrapper-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- } else {
- $("#controllabel-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $("#validationwrapper-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- }
-
- $("#listgroup-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
- if ($(this).attr("data-disk-id-" + disk.identifier)) {
- $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
- } else {
- $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
- $("#helpblock-storagepool-status-disk-replace-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
- }
- });
- });
-
- $("#btn-storagepool-status-disk-replace-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-disk-replace-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let disk = {
- idnew: []
- };
- let modal = {
- name: "",
- id: ""
- };
- let pool = {
- force: false
- };
- let validation = {
- disks: false
- };
-
- $("#listgroup-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `']:checked").map(function () {
- disk.idnew.push($(this).attr("data-disk-name"));
- });
-
- if (disk.idnew.length != 1) {
- $("#helpblock-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One disk is needed.");
-
- validation.disks = false;
- } else {
- $("#validationwrapper-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("");
-
- validation.disks = true;
- }
-
- if (!validation.disks) {
- $("#validationwrapper-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `").addClass("has-error");
-
- $("#spinner-storagepool-status-disk-replace-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.disks) {
- modal.name = "storagepool-status-disk-replace";
- modal.id = "` + pool.status.config.items.index + `-` + pool.id + `";
-
- pool.force = $("#switch-storagepool-status-disk-replace-force-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked");
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolDiskReplace({ name: "` + pool.name + `", id: "` + pool.id + `", force: pool.force }, { id: "` + disk.id + `", idnew: disk.idnew }, { name: modal.name, id: modal.id });
- }
- });
-
- $("#dropdown-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
-
- $("#helpblock-storagepool-status-disk-replace-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
- ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-disk-replace-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
-
- let disk = {
- identifier: $(this).parent().attr("value"),
- identifiertext: $(this).parent().text()
- };
-
- $("#listgroup-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
- if ($(this).attr("data-disk-id-" + disk.identifier)) {
- $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
- } else {
- $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
- $("#helpblock-storagepool-status-disk-replace-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
-
+ ` : ``) + `
+ }
+ });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusDiskClear(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-clear-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusDiskClearContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-clear-` + pool.status.config.items.index + `-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusDiskClearContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to clear errors for disk: ` + disk.id + ` ?
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-clear-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-disk-clear-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let modal = {
+ name: "storagepool-status-disk-clear",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolDiskClear({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `" }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusDiskDetach(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-detach-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusDiskDetachContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-detach-` + pool.status.config.items.index + `-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusDiskDetachContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to detach disk: ` + disk.id + ` ?
+
+ Options
+
+ Clear the label information on the disk
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-detach-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-disk-detach-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let disk = {
+ labelclear: $("#switch-storagepool-status-disk-detach-labelclear-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
+ };
+ let modal = {
+ name: "storagepool-status-disk-detach",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolDiskDetach({ name: "` + pool.name + `", id: "` + pool.id + `"}, { id: "` + disk.id + `", labelclear: disk.labelclear }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusDiskOffline(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-offline-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusDiskOfflineContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-offline-` + pool.status.config.items.index + `-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusDiskOfflineContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to offline disk: ` + disk.id + ` ?
+
+ Options
+
+ Forcefully offline the disk
+
+
+ Temporarily offline the disk until next reboot
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-offline-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-disk-offline-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let disk = {
+ force: $("#switch-storagepool-status-disk-offline-force-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked"),
+ temporary: $("#switch-storagepool-status-disk-offline-temporary-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
+ };
+ let modal = {
+ name: "storagepool-status-disk-offline",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolDiskOffline({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `", force: disk.force, temporary: disk.temporary }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusDiskOnline(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-online-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusDiskOnlineContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-online-` + pool.status.config.items.index + `-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+
+}
+
+function FnModalStatusDiskOnlineContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to online disk: ` + disk.id + ` ?
+
+ Options
+
+ Expand the device to use all available space
+
+
+ Scrub the storage pool after disk is set online
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-online-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-disk-online-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let disk = {
+ expand: $("#switch-storagepool-status-disk-online-expand-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
+ };
+ let modal = {
+ name: "storagepool-status-disk-online",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+ let pool = {
+ scrub: $("#switch-storagepool-status-disk-online-scrub-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolDiskOnline({ name: "` + pool.name + `", id: "` + pool.id + `", scrub: pool.scrub }, { id: "` + disk.id + `", expand: disk.expand }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusDiskReplace(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-replace-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusDiskReplaceContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-replace-` + pool.status.config.items.index + `-` + pool.id + `") });
+ FnDisksAvailableGet({ name: "storagepool-status-disk-replace-disks", id: "` + pool.status.config.items.index + `-` + pool.id + `", default: true });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusDiskReplaceContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
+ Disk
+
+ Disks WWN
+
+
+
+ Disks Identifier
+
+ Disks
+
+
+
+ ` + (zfsmanager.zfs.warnings.nvmevdev ? `
Virtual Device Mapping identifiers for NVMe devices may not have been created due to a bug in the ZFS software . Update ZFS to 0.8.3 for fix. ` : ``) + `
+
+
+
+ Options
+
+ Forcefully replace disk
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-status-disk-replace-disks-wwn-` + pool.status.config.items.index + `-` + pool.id + ` input").on("click", function () {
+ $("#btnspan-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text("Block Device");
+ $("#dropdown-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li").siblings().removeClass("active");
+ $("#dropdown-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li[value='blockdevice']").addClass("active");
+ $("#helpblock-storagepool-status-disk-replace-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
+ ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-disk-replace-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
+
+ let disk = {
+ identifier: ($(this).prop("checked") ? "wwn" : "blockdevice"),
+ identifiertext: ($(this).prop("checked") ? "WWN" : "Block Device")
+ };
+
+ if ($(this).prop("checked")) {
+ $("#controllabel-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ $("#validationwrapper-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ } else {
+ $("#controllabel-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $("#validationwrapper-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ }
+
+ $("#listgroup-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
+ if ($(this).attr("data-disk-id-" + disk.identifier)) {
+ $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
+ } else {
+ $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
+ $("#helpblock-storagepool-status-disk-replace-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
+ }
+ });
+ });
+
+ $("#btn-storagepool-status-disk-replace-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-disk-replace-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let disk = {
+ idnew: []
+ };
+ let modal = {
+ name: "",
+ id: ""
+ };
+ let pool = {
+ force: false
+ };
+ let validation = {
+ disks: false
+ };
+
+ $("#listgroup-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `']:checked").map(function () {
+ disk.idnew.push($(this).attr("data-disk-name"));
+ });
+
+ if (disk.idnew.length != 1) {
+ $("#helpblock-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One disk is needed.");
+
+ validation.disks = false;
+ } else {
+ $("#validationwrapper-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("");
+
+ validation.disks = true;
+ }
+
+ if (!validation.disks) {
+ $("#validationwrapper-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `").addClass("has-error");
+
+ $("#spinner-storagepool-status-disk-replace-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.disks) {
+ modal.name = "storagepool-status-disk-replace";
+ modal.id = "` + pool.status.config.items.index + `-` + pool.id + `";
+
+ pool.force = $("#switch-storagepool-status-disk-replace-force-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked");
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolDiskReplace({ name: "` + pool.name + `", id: "` + pool.id + `", force: pool.force }, { id: "` + disk.id + `", idnew: disk.idnew }, { name: modal.name, id: modal.id });
+ }
+ });
+
+ $("#dropdown-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-status-disk-replace-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+
+ $("#helpblock-storagepool-status-disk-replace-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
+ ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-disk-replace-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
+
+ let disk = {
+ identifier: $(this).parent().attr("value"),
+ identifiertext: $(this).parent().text()
+ };
+
+ $("#listgroup-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-disk-replace-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
+ if ($(this).attr("data-disk-id-" + disk.identifier)) {
+ $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
+ } else {
+ $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
+ $("#helpblock-storagepool-status-disk-replace-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
+
` + (zfsmanager.zfs.warnings.nvmevdev ? `
if (disk.identifier == "vdev" && /^nvme/gi.test($(this).attr("data-disk-id-blockdevice"))) {
$("#helpblock-storagepool-status-disk-replace-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
}
- ` : ``) + `
- }
- });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusDiskTrimStart(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-trim-start-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusDiskTrimStartContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-trim-start-` + pool.status.config.items.index + `-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusDiskTrimStartContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to start TRIM for disk: ` + disk.id + ` ?
-
- Options
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-disk-trim-start-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-disk-trim-start-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let modal = {
- name: "storagepool-status-disk-trim-start",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
- let trim = {
- secure: $("#switch-storagepool-status-disk-trim-start-secure-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolTrimStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `" }, { resume: false, secure: trim.secure }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusStoragePoolClear(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-clear-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusStoragePoolClearContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: $("#modal-storagepool-status-clear-` + pool.status.config.items.index + `-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusStoragePoolClearContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to clear errors for storage pool: ` + pool.name + ` ?
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-clear-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-clear-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let modal = {
- name: "storagepool-status-clear",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolClear({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusStoragePoolRegenerateGuid(pool = { name, id, guid, status: { config: { items: { index: 0 } } } }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-regenerateguid-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusStoragePoolRegenerateGuidContent({ name: "` + pool.name + `", id: "` + pool.id + `", guid: "` + pool.guid + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: $("#modal-storagepool-status-regenerateguid-` + pool.status.config.items.index + `-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusStoragePoolRegenerateGuidContent(pool = { name, id, guid, status: { config: { items: { index: 0 } } } }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to regenerate the GUID for storage pool: ` + pool.name + ` ?
-
GUID: ` + pool.guid + `
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-regenerateguid-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-regenerateguid-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let modal = {
- name: "storagepool-status-regenerateguid",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolRegenerateGuid({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusStoragePoolResilver(pool = { name, id, status: { config: { items: { index: 0 } }, resilver: { started: false } } }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-resilver-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusStoragePoolResilverContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } }, resilver: { started: ` + pool.status.resilver.started + ` } } }, { id: $("#modal-storagepool-status-resilver-` + pool.status.config.items.index + `-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusStoragePoolResilverContent(pool = { name, id, status: { config: { items: { index: 0 } }, resilver: { started: false } } }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to start resilver for storage pool: ` + pool.name + ` ?
- ` + (pool.status.resilver.started ? FnDisplayInlineAlert({ status: "warning", title: "A resilver is currently in progress and will be restarted.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-resilver-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-resilver-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let modal = {
- name: "storagepool-status-resilver",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolResilver({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusStoragePoolTrimStart(pool = { name, id, autotrim: false, status: { config: { items: { index: 0 } } } }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-trim-start-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusStoragePoolTrimStartContent({ name: "` + pool.name + `", id: "` + pool.id + `", autotrim: ` + pool.autotrim + `, status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: $("#modal-storagepool-status-trim-start-` + pool.status.config.items.index + `-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusStoragePoolTrimStartContent(pool = { name, id, autotrim: false, status: { config: { items: { index: 0 } } } }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to start TRIM for storage pool: ` + pool.name + ` ?
- ` + (pool.autotrim ? FnDisplayInlineAlert({ status: "info", title: "Automatic TRIM is currently enabled for this storage pool.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
-
- Options
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-trim-start-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-trim-start-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let modal = {
- name: "storagepool-status-trim-start",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
- let trim = {
- secure: $("#switch-storagepool-status-trim-start-secure-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolTrimStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: null }, { resume: false, secure: trim.secure }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusStoragePoolUpgrade(pool = { name, id, status: { config: { items: { index: 0 } } }, version }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-upgrade-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusStoragePoolUpgradeContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } }, version: "` + pool.version + `" }, { id: $("#modal-storagepool-status-upgrade-` + pool.status.config.items.index + `-` + pool.id + `") });
- FnStoragePoolConfigurationFeaturesDisabledGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "storagepool-status-upgrade", id: "` + pool.status.config.items.index + `-` + pool.id + `" });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusStoragePoolUpgradeContent(pool = { name, id, status: { config: { items: { index: 0 } } }, version }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to upgrade storage pool: ` + pool.name + ` ?
- ` + ($.isNumeric(pool.version) ? `
Legacy Version: ` + pool.version + `
` : ``) + `
- ` + FnDisplayInlineAlert({ status: ($.isNumeric(pool.version) ? "danger" : "warning"), title: ($.isNumeric(pool.version) ? "The storage pool will no longer be accessible on software that does not support feature flags." : "Once a feature is enabled the pool may become incompatible with software that does not support the feature."), description: null }, { name: null, id: null, hidden: false }) + `
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-upgrade-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-upgrade-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let modal = {
- name: "storagepool-status-upgrade",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolUpgrade({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusVirtualDeviceAdd(pool = { name, id, feature: { allocation_classes: true }, status: { config: { items: { index: 0 } } } }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-virtualdevice-add-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusVirtualDeviceAddContent({ name: "` + pool.name + `", id: "` + pool.id + `", feature: { allocation_classes: ` + pool.feature.allocation_classes + ` }, status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: $("#modal-storagepool-status-virtualdevice-add-` + pool.status.config.items.index + `-` + pool.id + `") });
- FnDisksAvailableGet({ name: "storagepool-status-virtualdevice-add-disks", id: "` + pool.status.config.items.index + `-` + pool.id + `", default: true });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusVirtualDeviceAddContent(pool = { name, id, feature: { allocation_classes: true }, status: { config: { items: { index: 0 } } } }, modal = { id }) {
- modal.content = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#switch-storagepool-status-virtualdevice-add-disks-wwn-` + pool.status.config.items.index + `-` + pool.id + ` input").on("click", function () {
- $("#btnspan-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text("Block Device");
- $("#dropdown-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li").siblings().removeClass("active");
- $("#dropdown-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li[value='blockdevice']").addClass("active");
- $("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
- ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
-
- let disk = {
- identifier: ($(this).prop("checked") ? "wwn" : "blockdevice"),
- identifiertext: ($(this).prop("checked") ? "WWN" : "Block Device")
- };
-
- if ($(this).prop("checked")) {
- $("#controllabel-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- $("#validationwrapper-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- } else {
- $("#controllabel-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $("#validationwrapper-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- }
-
- $("#listgroup-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
- if ($(this).attr("data-disk-id-" + disk.identifier)) {
- $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
- } else {
- $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
- $("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
- }
- });
- });
-
- $("#btn-storagepool-status-virtualdevice-add-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-virtualdevice-add-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let disks = {
- id: []
- };
- let pool = {
- force: false,
- virtualdevice: ""
- };
- let modal = {
- name: "",
- id: ""
- };
- let validation = {
- disks: false
- };
-
- $("#listgroup-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `']:checked").map(function () {
- disks.id.push($(this).attr("data-disk-name"));
- });
-
- if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "cache") {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Cache.");
-
- validation.disks = false;
- } else if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "dedup" && !$("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Dedup.");
-
- validation.disks = false;
- } else if (disks.id.length < 2 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "dedup" && $("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Two or more disks is needed for Dedup (Mirror).");
-
- validation.disks = false;
- } else if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "disk") {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Disk.");
-
- validation.disks = false;
- } else if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "log" && !$("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Log.");
-
- validation.disks = false;
- } else if (disks.id.length < 2 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "log" && $("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Two or more disks is needed for Log (Mirror).");
-
- validation.disks = false;
- } else if (disks.id.length < 2 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "mirror") {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Two or more disks is needed for Mirror.");
-
- validation.disks = false;
- } else if (disks.id.length < 2 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "raidz1") {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Two or more disks is needed for RaidZ1.");
-
- validation.disks = false;
- } else if (disks.id.length < 3 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "raidz2") {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Three or more disks is needed for RaidZ2.");
-
- validation.disks = false;
- } else if (disks.id.length < 4 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "raidz3") {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Four or more disks is needed for RaidZ3.");
-
- validation.disks = false;
- } else if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "spare") {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Spare.");
-
- validation.disks = false;
- } else if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "special" && !$("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Special.");
-
- validation.disks = false;
- } else if (disks.id.length < 2 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "special" && $("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Two or more disks is needed for Special (Mirror).");
-
- validation.disks = false;
- } else {
- $("#validationwrapper-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("has-error");
- $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("");
-
- validation.disks = true;
- }
-
- if (!validation.disks) {
- $("#validationwrapper-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").addClass("has-error");
-
- $("#spinner-storagepool-status-virtualdevice-add-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- $(this).prop("disabled", false);
- }
-
- if (validation.disks) {
- modal.name = "storagepool-status-virtualdevice-add";
- modal.id = "` + pool.status.config.items.index + `-` + pool.id + `";
-
- pool.force = $("#switch-storagepool-status-virtualdevice-add-force-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked");
- pool.virtualdevice = ($("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") != "disk" ? $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") : "");
-
- if ($("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "dedup" && $("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- pool.virtualdevice = "dedup mirror";
- } else if ($("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "log" && $("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- pool.virtualdevice = "log mirror";
- } else if ($("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "special" && $("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- pool.virtualdevice = "special mirror";
- }
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolVirtualDeviceAdd({ name: "` + pool.name + `", id: "` + pool.id + `", force: pool.force, virtualdevice: pool.virtualdevice }, { id: disks.id }, { name: modal.name, id: modal.id });
- }
- });
-
- $("#dropdown-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
-
- $("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
- ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
-
- let disk = {
- identifier: $(this).parent().attr("value"),
- identifiertext: $(this).parent().text()
- };
-
- $("#listgroup-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
- if ($(this).attr("data-disk-id-" + disk.identifier)) {
- $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
- } else {
- $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
- $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
- $("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
-
+ ` : ``) + `
+ }
+ });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusDiskTrimStart(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-trim-start-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusDiskTrimStartContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + disk.id + `" }, { id: $("#modal-storagepool-status-disk-trim-start-` + pool.status.config.items.index + `-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusDiskTrimStartContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, disk = { id }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to start TRIM for disk: ` + disk.id + ` ?
+
+ Options
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-disk-trim-start-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-disk-trim-start-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let modal = {
+ name: "storagepool-status-disk-trim-start",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+ let trim = {
+ secure: $("#switch-storagepool-status-disk-trim-start-secure-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolTrimStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + disk.id + `" }, { resume: false, secure: trim.secure }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusStoragePoolClear(pool = { name, id, status: { config: { items: { index: 0 } } } }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-clear-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusStoragePoolClearContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: $("#modal-storagepool-status-clear-` + pool.status.config.items.index + `-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusStoragePoolClearContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to clear errors for storage pool: ` + pool.name + ` ?
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-clear-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-clear-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let modal = {
+ name: "storagepool-status-clear",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolClear({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusStoragePoolRegenerateGuid(pool = { name, id, guid, status: { config: { items: { index: 0 } } } }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-regenerateguid-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusStoragePoolRegenerateGuidContent({ name: "` + pool.name + `", id: "` + pool.id + `", guid: "` + pool.guid + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: $("#modal-storagepool-status-regenerateguid-` + pool.status.config.items.index + `-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusStoragePoolRegenerateGuidContent(pool = { name, id, guid, status: { config: { items: { index: 0 } } } }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to regenerate the GUID for storage pool: ` + pool.name + ` ?
+
GUID: ` + pool.guid + `
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-regenerateguid-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-regenerateguid-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let modal = {
+ name: "storagepool-status-regenerateguid",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolRegenerateGuid({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusStoragePoolResilver(pool = { name, id, status: { config: { items: { index: 0 } }, resilver: { started: false } } }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-resilver-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusStoragePoolResilverContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } }, resilver: { started: ` + pool.status.resilver.started + ` } } }, { id: $("#modal-storagepool-status-resilver-` + pool.status.config.items.index + `-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusStoragePoolResilverContent(pool = { name, id, status: { config: { items: { index: 0 } }, resilver: { started: false } } }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to start resilver for storage pool: ` + pool.name + ` ?
+ ` + (pool.status.resilver.started ? FnDisplayInlineAlert({ status: "warning", title: "A resilver is currently in progress and will be restarted.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-resilver-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-resilver-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let modal = {
+ name: "storagepool-status-resilver",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolResilver({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusStoragePoolTrimStart(pool = { name, id, autotrim: false, status: { config: { items: { index: 0 } } } }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-trim-start-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusStoragePoolTrimStartContent({ name: "` + pool.name + `", id: "` + pool.id + `", autotrim: ` + pool.autotrim + `, status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: $("#modal-storagepool-status-trim-start-` + pool.status.config.items.index + `-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusStoragePoolTrimStartContent(pool = { name, id, autotrim: false, status: { config: { items: { index: 0 } } } }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to start TRIM for storage pool: ` + pool.name + ` ?
+ ` + (pool.autotrim ? FnDisplayInlineAlert({ status: "info", title: "Automatic TRIM is currently enabled for this storage pool.", description: null }, { name: null, id: null, hidden: false }) : ``) + `
+
+ Options
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-trim-start-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-trim-start-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let modal = {
+ name: "storagepool-status-trim-start",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+ let trim = {
+ secure: $("#switch-storagepool-status-trim-start-secure-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolTrimStart({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: null }, { resume: false, secure: trim.secure }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusStoragePoolUpgrade(pool = { name, id, status: { config: { items: { index: 0 } } }, version }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-upgrade-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusStoragePoolUpgradeContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } }, version: "` + pool.version + `" }, { id: $("#modal-storagepool-status-upgrade-` + pool.status.config.items.index + `-` + pool.id + `") });
+ FnStoragePoolConfigurationFeaturesDisabledGet({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: "storagepool-status-upgrade", id: "` + pool.status.config.items.index + `-` + pool.id + `" });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusStoragePoolUpgradeContent(pool = { name, id, status: { config: { items: { index: 0 } } }, version }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to upgrade storage pool: ` + pool.name + ` ?
+ ` + ($.isNumeric(pool.version) ? `
Legacy Version: ` + pool.version + `
` : ``) + `
+ ` + FnDisplayInlineAlert({ status: ($.isNumeric(pool.version) ? "danger" : "warning"), title: ($.isNumeric(pool.version) ? "The storage pool will no longer be accessible on software that does not support feature flags." : "Once a feature is enabled the pool may become incompatible with software that does not support the feature."), description: null }, { name: null, id: null, hidden: false }) + `
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-upgrade-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-upgrade-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let modal = {
+ name: "storagepool-status-upgrade",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolUpgrade({ name: "` + pool.name + `", id: "` + pool.id + `" }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusVirtualDeviceAdd(pool = { name, id, feature: { allocation_classes: true }, status: { config: { items: { index: 0 } } } }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-virtualdevice-add-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusVirtualDeviceAddContent({ name: "` + pool.name + `", id: "` + pool.id + `", feature: { allocation_classes: ` + pool.feature.allocation_classes + ` }, status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: $("#modal-storagepool-status-virtualdevice-add-` + pool.status.config.items.index + `-` + pool.id + `") });
+ FnDisksAvailableGet({ name: "storagepool-status-virtualdevice-add-disks", id: "` + pool.status.config.items.index + `-` + pool.id + `", default: true });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusVirtualDeviceAddContent(pool = { name, id, feature: { allocation_classes: true }, status: { config: { items: { index: 0 } } } }, modal = { id }) {
+ modal.content = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#switch-storagepool-status-virtualdevice-add-disks-wwn-` + pool.status.config.items.index + `-` + pool.id + ` input").on("click", function () {
+ $("#btnspan-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text("Block Device");
+ $("#dropdown-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li").siblings().removeClass("active");
+ $("#dropdown-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + ` li[value='blockdevice']").addClass("active");
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
+ ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
+
+ let disk = {
+ identifier: ($(this).prop("checked") ? "wwn" : "blockdevice"),
+ identifiertext: ($(this).prop("checked") ? "WWN" : "Block Device")
+ };
+
+ if ($(this).prop("checked")) {
+ $("#controllabel-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ $("#validationwrapper-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ } else {
+ $("#controllabel-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $("#validationwrapper-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ }
+
+ $("#listgroup-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
+ if ($(this).attr("data-disk-id-" + disk.identifier)) {
+ $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
+ } else {
+ $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
+ }
+ });
+ });
+
+ $("#btn-storagepool-status-virtualdevice-add-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-virtualdevice-add-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let disks = {
+ id: []
+ };
+ let pool = {
+ force: false,
+ virtualdevice: ""
+ };
+ let modal = {
+ name: "",
+ id: ""
+ };
+ let validation = {
+ disks: false
+ };
+
+ $("#listgroup-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `']:checked").map(function () {
+ disks.id.push($(this).attr("data-disk-name"));
+ });
+
+ if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "cache") {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Cache.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "dedup" && !$("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Dedup.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 2 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "dedup" && $("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Two or more disks is needed for Dedup (Mirror).");
+
+ validation.disks = false;
+ } else if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "disk") {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Disk.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "log" && !$("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Log.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 2 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "log" && $("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Two or more disks is needed for Log (Mirror).");
+
+ validation.disks = false;
+ } else if (disks.id.length < 2 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "mirror") {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Two or more disks is needed for Mirror.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 2 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "raidz1") {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Two or more disks is needed for RaidZ1.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 3 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "raidz2") {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Three or more disks is needed for RaidZ2.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 4 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "raidz3") {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Four or more disks is needed for RaidZ3.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "spare") {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Spare.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 1 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "special" && !$("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is needed for Special.");
+
+ validation.disks = false;
+ } else if (disks.id.length < 2 && $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "special" && $("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("Two or more disks is needed for Special (Mirror).");
+
+ validation.disks = false;
+ } else {
+ $("#validationwrapper-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("has-error");
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("");
+
+ validation.disks = true;
+ }
+
+ if (!validation.disks) {
+ $("#validationwrapper-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `").addClass("has-error");
+
+ $("#spinner-storagepool-status-virtualdevice-add-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ $(this).prop("disabled", false);
+ }
+
+ if (validation.disks) {
+ modal.name = "storagepool-status-virtualdevice-add";
+ modal.id = "` + pool.status.config.items.index + `-` + pool.id + `";
+
+ pool.force = $("#switch-storagepool-status-virtualdevice-add-force-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked");
+ pool.virtualdevice = ($("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") != "disk" ? $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") : "");
+
+ if ($("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "dedup" && $("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ pool.virtualdevice = "dedup mirror";
+ } else if ($("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "log" && $("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ pool.virtualdevice = "log mirror";
+ } else if ($("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").attr("data-field-value") == "special" && $("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ pool.virtualdevice = "special mirror";
+ }
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolVirtualDeviceAdd({ name: "` + pool.name + `", id: "` + pool.id + `", force: pool.force, virtualdevice: pool.virtualdevice }, { id: disks.id }, { name: modal.name, id: modal.id });
+ }
+ });
+
+ $("#dropdown-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-status-virtualdevice-add-disks-identifier-` + pool.status.config.items.index + `-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden").text("");
+ ` + (zfsmanager.zfs.warnings.nvmevdev ? `$("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");` : ``) + `
+
+ let disk = {
+ identifier: $(this).parent().attr("value"),
+ identifiertext: $(this).parent().text()
+ };
+
+ $("#listgroup-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + ` input[name='checkbox-storagepool-status-virtualdevice-add-disks-` + pool.status.config.items.index + `-` + pool.id + `']").map(function () {
+ if ($(this).attr("data-disk-id-" + disk.identifier)) {
+ $(this).next().find(".select-ct-disk-row-id").text((disk.identifier == "blockdevice" ? "/dev/" : "") + $(this).attr("data-disk-id-" + disk.identifier));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-" + disk.identifier));
+ } else {
+ $(this).next().find(".select-ct-disk-row-id").text("/dev/" + $(this).attr("data-disk-id-blockdevice"));
+ $(this).attr("data-disk-name", $(this).attr("data-disk-id-blockdevice"));
+ $("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarning-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden").text("One or more disks is missing a " + disk.identifiertext + " identifier.");
+
` + (zfsmanager.zfs.warnings.nvmevdev ? `
if (disk.identifier == "vdev" && /^nvme/gi.test($(this).attr("data-disk-id-blockdevice"))) {
$("#helpblock-storagepool-status-virtualdevice-add-disks-identifierwarningzfs-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
}
- ` : ``) + `
- }
- });
- });
-
- $("#dropdown-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").on("click", "li a", function () {
- $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
- $(this).parent().siblings().removeClass("active");
- $(this).parent().addClass("active");
-
- if ($(this).text() == "Dedup") {
- $("#controllabel-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().removeClass("hidden");
- } else {
- $("#controllabel-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- $("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().addClass("hidden");
- if ($("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- $("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").click();
- }
- }
-
- if ($(this).text() == "Log") {
- $("#controllabel-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().removeClass("hidden");
- } else {
- $("#controllabel-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- $("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().addClass("hidden");
- if ($("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- $("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").click();
- }
- }
-
- if ($(this).text() == "Special") {
- $("#controllabel-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().removeClass("hidden");
- } else {
- $("#controllabel-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
- $("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().addClass("hidden");
- if ($("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
- $("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").click();
- }
- }
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusVirtualDeviceClear(pool = { name, id, status: { config: { items: { index: 0 } } } }, virtualdevice = { id }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-virtualdevice-clear-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusVirtualDeviceClearContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + virtualdevice.id + `" }, { id: $("#modal-storagepool-status-virtualdevice-clear-` + pool.status.config.items.index + `-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusVirtualDeviceClearContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, virtualdevice = { id }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to clear errors for virtual device: ` + virtualdevice.id + ` ?
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-virtualdevice-clear-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-virtualdevice-clear-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let modal = {
- name: "storagepool-status-virtualdevice-clear",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolVirtualDeviceClear({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + virtualdevice.id + `" }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
-function FnModalStatusVirtualDeviceRemove(pool = { name, id, status: { config: { items: { index: 0 } } } }, virtualdevice = { id, disk: false }) {
- let modal = {
- window: ""
- };
-
- modal.window = `
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-virtualdevice-remove-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
- FnModalStatusVirtualDeviceRemoveContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + virtualdevice.id + `", disk: ` + virtualdevice.disk + ` }, { id: $("#modal-storagepool-status-virtualdevice-remove-` + pool.status.config.items.index + `-` + pool.id + `") });
- });
- \x3C/script>
- `;
-
- $("#modals-storagepool-status-" + pool.id).append(modal.window);
-}
-
-function FnModalStatusVirtualDeviceRemoveContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, virtualdevice = { id, disk: false }, modal = { id }) {
- modal.content = `
-
-
-
-
-
Are you sure you want to remove virtual device: ` + virtualdevice.id + ` ?
-
- Options
-
- Clear the label information on the disk
-
-
-
-
-
-
-
- \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
- $("#btn-storagepool-status-virtualdevice-remove-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
- $("#spinner-storagepool-status-virtualdevice-remove-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
- $(this).prop("disabled", true);
-
- let virtualdevice = {
- labelclear: ` + (virtualdevice.disk ? `$("#switch-storagepool-status-virtualdevice-remove-labelclear-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")` : false) + `
- };
- let modal = {
- name: "storagepool-status-virtualdevice-remove",
- id: "` + pool.status.config.items.index + `-` + pool.id + `"
- };
-
- $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
- $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
-
- FnStoragePoolVirtualDeviceRemove({ name: "` + pool.name + `", id: "` + pool.id + `"} , { id: "` + virtualdevice.id + `", labelclear: virtualdevice.labelclear }, { name: modal.name, id: modal.id });
- });
- \x3C/script>
- `;
-
- modal.id.empty().append(modal.content);
-}
-
+ ` : ``) + `
+ }
+ });
+ });
+
+ $("#dropdown-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").on("click", "li a", function () {
+ $("#btnspan-storagepool-status-virtualdevice-add-virtualdevice-` + pool.status.config.items.index + `-` + pool.id + `").text($(this).text()).attr("data-field-value", $(this).parent().attr("value"));
+ $(this).parent().siblings().removeClass("active");
+ $(this).parent().addClass("active");
+
+ if ($(this).text() == "Dedup") {
+ $("#controllabel-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().removeClass("hidden");
+ } else {
+ $("#controllabel-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ $("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().addClass("hidden");
+ if ($("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ $("#switch-storagepool-status-virtualdevice-add-dedup-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").click();
+ }
+ }
+
+ if ($(this).text() == "Log") {
+ $("#controllabel-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().removeClass("hidden");
+ } else {
+ $("#controllabel-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ $("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().addClass("hidden");
+ if ($("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ $("#switch-storagepool-status-virtualdevice-add-log-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").click();
+ }
+ }
+
+ if ($(this).text() == "Special") {
+ $("#controllabel-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().removeClass("hidden");
+ } else {
+ $("#controllabel-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + `").addClass("hidden");
+ $("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + `").parent().addClass("hidden");
+ if ($("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")) {
+ $("#switch-storagepool-status-virtualdevice-add-special-mirror-` + pool.status.config.items.index + `-` + pool.id + ` input").click();
+ }
+ }
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusVirtualDeviceClear(pool = { name, id, status: { config: { items: { index: 0 } } } }, virtualdevice = { id }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-virtualdevice-clear-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusVirtualDeviceClearContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + virtualdevice.id + `" }, { id: $("#modal-storagepool-status-virtualdevice-clear-` + pool.status.config.items.index + `-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusVirtualDeviceClearContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, virtualdevice = { id }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to clear errors for virtual device: ` + virtualdevice.id + ` ?
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-virtualdevice-clear-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-virtualdevice-clear-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let modal = {
+ name: "storagepool-status-virtualdevice-clear",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolVirtualDeviceClear({ name: "` + pool.name + `", id: "` + pool.id + `" }, { id: "` + virtualdevice.id + `" }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
+function FnModalStatusVirtualDeviceRemove(pool = { name, id, status: { config: { items: { index: 0 } } } }, virtualdevice = { id, disk: false }) {
+ let modal = {
+ window: ""
+ };
+
+ modal.window = `
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-virtualdevice-remove-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ FnStoragePoolRefreshAutoDisable({ name: "` + pool.name + `", id: "` + pool.id + `" });
+ FnModalStatusVirtualDeviceRemoveContent({ name: "` + pool.name + `", id: "` + pool.id + `", status: { config: { items: { index: ` + pool.status.config.items.index + ` } } } }, { id: "` + virtualdevice.id + `", disk: ` + virtualdevice.disk + ` }, { id: $("#modal-storagepool-status-virtualdevice-remove-` + pool.status.config.items.index + `-` + pool.id + `") });
+ });
+ \x3C/script>
+ `;
+
+ $("#modals-storagepool-status-" + pool.id).append(modal.window);
+}
+
+function FnModalStatusVirtualDeviceRemoveContent(pool = { name, id, status: { config: { items: { index: 0 } } } }, virtualdevice = { id, disk: false }, modal = { id }) {
+ modal.content = `
+
+
+
+
+
Are you sure you want to remove virtual device: ` + virtualdevice.id + ` ?
+
+ Options
+
+ Clear the label information on the disk
+
+
+
+
+
+
+
+ \x3Cscript nonce="1t55lZ7tzuKTreHVNwE66Ox32Mc=">
+ $("#btn-storagepool-status-virtualdevice-remove-apply-` + pool.status.config.items.index + `-` + pool.id + `").on("click", function () {
+ $("#spinner-storagepool-status-virtualdevice-remove-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+ $(this).prop("disabled", true);
+
+ let virtualdevice = {
+ labelclear: ` + (virtualdevice.disk ? `$("#switch-storagepool-status-virtualdevice-remove-labelclear-` + pool.status.config.items.index + `-` + pool.id + ` input").prop("checked")` : false) + `
+ };
+ let modal = {
+ name: "storagepool-status-virtualdevice-remove",
+ id: "` + pool.status.config.items.index + `-` + pool.id + `"
+ };
+
+ $("[id^=btn-storagepool-status-dropdown-][id$=` + pool.id + `]").addClass("disabled");
+ $("#spinner-storagepool-status-` + pool.status.config.items.index + `-` + pool.id + `").removeClass("hidden");
+
+ FnStoragePoolVirtualDeviceRemove({ name: "` + pool.name + `", id: "` + pool.id + `"} , { id: "` + virtualdevice.id + `", labelclear: virtualdevice.labelclear }, { name: modal.name, id: modal.id });
+ });
+ \x3C/script>
+ `;
+
+ modal.id.empty().append(modal.content);
+}
+
//#endregion
\ No newline at end of file