- new version 276.1

- login: Use valid selectors when testing for :is() / :where() support.
  - stability and performance improvements
  - previous changes https://cockpit-project.org/blog/cockpit-275.html
- css-overrides.patch, hide-docs.patch, remove-pwscore.patch: refreshed
- kdump-close.patch, kdump-refactor.patch, kdump-suse.patch: upstreamed
  and removed

OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:cockpit/cockpit?expand=0&rev=113
This commit is contained in:
Adam Majer 2022-09-20 09:33:51 +00:00 committed by Git OBS Bridge
parent 2613237f81
commit 52b2fb4499
15 changed files with 6748 additions and 8002 deletions

View File

@ -13,7 +13,7 @@
<param name="versionformat">@PARENT_TAG@</param> <param name="versionformat">@PARENT_TAG@</param>
<param name="url">http://github.com/cockpit-project/cockpit.git</param> <param name="url">http://github.com/cockpit-project/cockpit.git</param>
<param name="scm">git</param> <param name="scm">git</param>
<param name="revision">271</param> <param name="revision">276.1</param>
<param name="submodules">disable</param> <param name="submodules">disable</param>
</service> </service>
<service name="node_modules" mode="manual"> <service name="node_modules" mode="manual">

BIN
cockpit-271.obscpio (Stored with Git LFS)

Binary file not shown.

BIN
cockpit-276.1.obscpio (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1,3 +1,14 @@
-------------------------------------------------------------------
Tue Sep 20 08:20:16 UTC 2022 - Adam Majer <adam.majer@suse.de>
- new version 276.1
- login: Use valid selectors when testing for :is() / :where() support.
- stability and performance improvements
- previous changes https://cockpit-project.org/blog/cockpit-275.html
- css-overrides.patch, hide-docs.patch, remove-pwscore.patch: refreshed
- kdump-close.patch, kdump-refactor.patch, kdump-suse.patch: upstreamed
and removed
------------------------------------------------------------------- -------------------------------------------------------------------
Tue Sep 13 09:46:17 UTC 2022 - Adam Majer <adam.majer@suse.de> Tue Sep 13 09:46:17 UTC 2022 - Adam Majer <adam.majer@suse.de>

View File

@ -1,4 +1,4 @@
name: cockpit name: cockpit
version: 271 version: 276.1
mtime: 1654679280 mtime: 1662983171
commit: d2d8bc30bc5279b2acc3628616cfb9c4e18c7edd commit: 33f16d10c3505aceeac7541e01553ea44e10678d

View File

@ -25,9 +25,9 @@
# Check first cockpit-devel@lists.fedorahosted.org # Check first cockpit-devel@lists.fedorahosted.org
# #
# earliest base that the subpackages work on; the instances of this get computed/updated # earliest base that the subpackages work on; this is still required as long as
# by tools/gen-spec-dependencies during "make dist", but keep a hardcoded fallback # we maintain the basic/optional split, then it can be replaced with just %{version}.
%define required_base 122 %define required_base 266
# we generally want CentOS packages to be like RHEL; special cases need to check %{centos} explicitly # we generally want CentOS packages to be like RHEL; special cases need to check %{centos} explicitly
%if 0%{?centos} %if 0%{?centos}
@ -50,7 +50,7 @@ Summary: Web Console for Linux servers
License: LGPL-2.1-or-later License: LGPL-2.1-or-later
URL: https://cockpit-project.org/ URL: https://cockpit-project.org/
Version: 271 Version: 276.1
Release: 0 Release: 0
Source0: cockpit-%{version}.tar Source0: cockpit-%{version}.tar
Source1: cockpit.pam Source1: cockpit.pam
@ -65,20 +65,18 @@ Patch2: hide-docs.patch
Patch3: suse-microos-branding.patch Patch3: suse-microos-branding.patch
Patch4: css-overrides.patch Patch4: css-overrides.patch
Patch5: storage-btrfs.patch Patch5: storage-btrfs.patch
Patch6: kdump-close.patch
Patch7: kdump-refactor.patch
Patch8: kdump-suse.patch
# SLE Micro specific patches # SLE Micro specific patches
Patch100: remove-pwscore.patch Patch100: remove-pwscore.patch
Patch101: hide-pcp.patch Patch101: hide-pcp.patch
Patch102: css-overrides.patch
# in RHEL 8 the source package is duplicated: cockpit (building basic packages like cockpit-{bridge,system}) # in RHEL 8 the source package is duplicated: cockpit (building basic packages like cockpit-{bridge,system})
# and cockpit-appstream (building optional packages like cockpit-{pcp}) # and cockpit-appstream (building optional packages like cockpit-{pcp})
# This split does not apply to EPEL/COPR. # This split does not apply to EPEL/COPR nor packit c8s builds, only to our own
# image-prepare rhel-8-Y builds (which will disable build_all).
# In Fedora ELN/RHEL 9+ there is just one source package, which ships rpms in both BaseOS and AppStream # In Fedora ELN/RHEL 9+ there is just one source package, which ships rpms in both BaseOS and AppStream
# We also provide an override mechanism if you want to build all packages. %define build_all 1
%define build_all 0 %if 0%{?rhel} == 8 && 0%{?epel} == 0 && !0%{?build_all}
%if 0%{?rhel} == 8 && 0%{?epel} == 0 && !%{build_all}
%if "%{name}" == "cockpit" %if "%{name}" == "cockpit"
%define build_basic 1 %define build_basic 1
@ -189,9 +187,6 @@ Requires: subscription-manager-cockpit
%patch3 -p1 %patch3 -p1
%patch4 -p1 %patch4 -p1
%patch5 -p1 %patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%if 0%{?sle_version} %if 0%{?sle_version}
%patch100 -p1 %patch100 -p1
@ -244,23 +239,10 @@ cp src/fonts.css %{buildroot}%{_datadir}/cockpit/branding/suse
cp -a src/fonts %{buildroot}%{_datadir}/cockpit/branding/suse cp -a src/fonts %{buildroot}%{_datadir}/cockpit/branding/suse
popd popd
# only ship deprecated PatternFly API for stable releases
%if 0%{?rhel} == 8
if [ -f %{buildroot}/%{_datadir}/cockpit/base1/cockpit.css.gz ]; then
ln -s cockpit.css.gz %{buildroot}/%{_datadir}/cockpit/base1/patternfly.css.gz
elif [ -f %{buildroot}/%{_datadir}/cockpit/base1/cockpit.css ]; then
ln -s cockpit.css %{buildroot}/%{_datadir}/cockpit/base1/patternfly.css
else
echo >&2 Neither cockpit.css.gz nor cockpit.css exists.
exit 1
fi
%endif
# Build the package lists for resource packages # Build the package lists for resource packages
# cockpit-bridge is the basic dependency for all cockpit-* packages, so centrally own the page directory # cockpit-bridge is the basic dependency for all cockpit-* packages, so centrally own the page directory
echo '%dir %{_datadir}/cockpit' > base.list echo '%dir %{_datadir}/cockpit' > base.list
echo '%dir %{_datadir}/cockpit/base1' >> base.list echo '%dir %{_datadir}/cockpit/base1' >> base.list
echo '%dir %{_datadir}/cockpit/base1/fonts' >> base.list
find %{buildroot}%{_datadir}/cockpit/base1 -type f -o -type l >> base.list find %{buildroot}%{_datadir}/cockpit/base1 -type f -o -type l >> base.list
echo '%{_sysconfdir}/cockpit/machines.d' >> base.list echo '%{_sysconfdir}/cockpit/machines.d' >> base.list
echo %{buildroot}%{_datadir}/polkit-1/actions/org.cockpit-project.cockpit-bridge.policy >> base.list echo %{buildroot}%{_datadir}/polkit-1/actions/org.cockpit-project.cockpit-bridge.policy >> base.list
@ -479,8 +461,6 @@ Provides: cockpit-sosreport = %{version}-%{release}
%if 0%{?fedora} %if 0%{?fedora}
Recommends: (reportd if abrt) Recommends: (reportd if abrt)
%endif %endif
# NPM modules which are also available as packages
Provides: bundled(xstatic-patternfly-common) = 3.59.5
%description system %description system
This package contains the Cockpit shell and system configuration interfaces. This package contains the Cockpit shell and system configuration interfaces.
@ -629,8 +609,8 @@ fi
%package kdump %package kdump
Summary: Cockpit user interface for kernel crash dumping Summary: Cockpit user interface for kernel crash dumping
Requires: cockpit-bridge >= 130 Requires: cockpit-bridge >= %{required_base}
Requires: cockpit-shell >= 130 Requires: cockpit-shell >= %{required_base}
Requires: kexec-tools Requires: kexec-tools
BuildArch: noarch BuildArch: noarch
@ -643,8 +623,8 @@ The Cockpit component for configuring kernel crash dumping.
%if !0%{?suse_version} %if !0%{?suse_version}
%package sosreport %package sosreport
Summary: Cockpit user interface for diagnostic reports Summary: Cockpit user interface for diagnostic reports
Requires: cockpit-bridge >= 122 Requires: cockpit-bridge >= %{required_base}
Requires: cockpit-shell >= 122 Requires: cockpit-shell >= %{required_base}
Requires: sos Requires: sos
BuildArch: noarch BuildArch: noarch
@ -659,8 +639,8 @@ sosreport tool.
%package networkmanager %package networkmanager
Summary: Cockpit user interface for networking, using NetworkManager Summary: Cockpit user interface for networking, using NetworkManager
Requires: cockpit-bridge >= 186 Requires: cockpit-bridge >= %{required_base}
Requires: cockpit-shell >= 186 Requires: cockpit-shell >= %{required_base}
Requires: NetworkManager >= 1.6 Requires: NetworkManager >= 1.6
Conflicts: cockpit-wicked Conflicts: cockpit-wicked
# Optional components # Optional components
@ -678,8 +658,8 @@ The Cockpit component for managing networking. This package uses NetworkManager
%package selinux %package selinux
Summary: Cockpit SELinux package Summary: Cockpit SELinux package
Requires: cockpit-bridge >= 122 Requires: cockpit-bridge >= %{required_base}
Requires: cockpit-shell >= 122 Requires: cockpit-shell >= %{required_base}
Requires: setroubleshoot-server >= 3.3.3 Requires: setroubleshoot-server >= 3.3.3
BuildArch: noarch BuildArch: noarch
@ -709,7 +689,7 @@ Dummy package from building optional packages only; never install or publish me.
%package -n cockpit-storaged %package -n cockpit-storaged
Summary: Cockpit user interface for storage, using udisks Summary: Cockpit user interface for storage, using udisks
Requires: cockpit-shell >= 266 Requires: cockpit-shell >= %{required_base}
Requires: udisks2 >= 2.9 Requires: udisks2 >= 2.9
Requires: %{__python3} Requires: %{__python3}
%if 0%{?suse_version} %if 0%{?suse_version}
@ -757,7 +737,7 @@ This package contains files used to develop cockpit modules
%package -n cockpit-pcp %package -n cockpit-pcp
Summary: Cockpit PCP integration Summary: Cockpit PCP integration
Requires: cockpit-bridge >= 238.1.1 Requires: cockpit-bridge >= %{required_base}
Requires: pcp Requires: pcp
%description -n cockpit-pcp %description -n cockpit-pcp
@ -773,7 +753,7 @@ systemctl reload-or-try-restart pmlogger
%package -n cockpit-packagekit %package -n cockpit-packagekit
Summary: Cockpit user interface for packages Summary: Cockpit user interface for packages
BuildArch: noarch BuildArch: noarch
Requires: cockpit-bridge >= 186 Requires: cockpit-bridge >= %{required_base}
Requires: PackageKit Requires: PackageKit
Recommends: python3-tracer Recommends: python3-tracer
# HACK: https://bugzilla.redhat.com/show_bug.cgi?id=1800468 # HACK: https://bugzilla.redhat.com/show_bug.cgi?id=1800468

View File

@ -42,11 +42,11 @@ now, it fulfills the requirements of [3].
25 files changed, 36 insertions(+) 25 files changed, 36 insertions(+)
create mode 100644 src/branding/default/css-overrides.css create mode 100644 src/branding/default/css-overrides.css
diff --git a/pkg/apps/index.html b/pkg/apps/index.html Index: cockpit/pkg/apps/index.html
index 176f2eb01..b77cfd6d9 100644 ===================================================================
--- a/pkg/apps/index.html --- cockpit.orig/pkg/apps/index.html
+++ b/pkg/apps/index.html +++ cockpit/pkg/apps/index.html
@@ -23,6 +23,7 @@ along with Cockpit; If not, see <http://www.gnu.org/licenses/>. @@ -23,6 +23,7 @@ along with Cockpit; If not, see <http://
<title translate="yes">Applications</title> <title translate="yes">Applications</title>
<meta charset="utf-8"> <meta charset="utf-8">
<link href="apps.css" type="text/css" rel="stylesheet"> <link href="apps.css" type="text/css" rel="stylesheet">
@ -54,23 +54,23 @@ index 176f2eb01..b77cfd6d9 100644
<script type="text/javascript" src="../base1/cockpit.js"></script> <script type="text/javascript" src="../base1/cockpit.js"></script>
<script type="text/javascript" src="../base1/po.js"></script> <script type="text/javascript" src="../base1/po.js"></script>
<script type="text/javascript" src="po.js"></script> <script type="text/javascript" src="po.js"></script>
diff --git a/pkg/kdump/index.html b/pkg/kdump/index.html Index: cockpit/pkg/kdump/index.html
index 6c5228ccb..87ca05d74 100644 ===================================================================
--- a/pkg/kdump/index.html --- cockpit.orig/pkg/kdump/index.html
+++ b/pkg/kdump/index.html +++ cockpit/pkg/kdump/index.html
@@ -25,6 +25,7 @@ along with Cockpit; If not, see <http://www.gnu.org/licenses/>. @@ -25,6 +25,7 @@ along with Cockpit; If not, see <http://
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="kdump.css"> <link rel="stylesheet" href="kdump.css">
+ <link href="../../static/css-overrides.css" type="text/css" rel="stylesheet"> + <link href="../../static/css-overrides.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="kdump.js"></script> <script type="text/javascript" src="kdump.js"></script>
<script type="text/javascript" src="../base/po.js"></script> <script type="text/javascript" src="../base1/po.js"></script>
diff --git a/pkg/metrics/index.html b/pkg/metrics/index.html Index: cockpit/pkg/metrics/index.html
index a62d780b5..9d5d104a5 100644 ===================================================================
--- a/pkg/metrics/index.html --- cockpit.orig/pkg/metrics/index.html
+++ b/pkg/metrics/index.html +++ cockpit/pkg/metrics/index.html
@@ -23,6 +23,7 @@ along with this package; If not, see <http://www.gnu.org/licenses/>. @@ -23,6 +23,7 @@ along with this package; If not, see <ht
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="index.css"> <link rel="stylesheet" href="index.css">
@ -78,11 +78,11 @@ index a62d780b5..9d5d104a5 100644
<script type="text/javascript" src="../base1/cockpit.js"></script> <script type="text/javascript" src="../base1/cockpit.js"></script>
<script type="text/javascript" src="../manifests.js"></script> <script type="text/javascript" src="../manifests.js"></script>
diff --git a/pkg/networkmanager/firewall.html b/pkg/networkmanager/firewall.html Index: cockpit/pkg/networkmanager/firewall.html
index 016650651..da60cb121 100644 ===================================================================
--- a/pkg/networkmanager/firewall.html --- cockpit.orig/pkg/networkmanager/firewall.html
+++ b/pkg/networkmanager/firewall.html +++ cockpit/pkg/networkmanager/firewall.html
@@ -23,6 +23,7 @@ along with Cockpit; If not, see <http://www.gnu.org/licenses/>. @@ -23,6 +23,7 @@ along with Cockpit; If not, see <http://
<meta charset="utf-8"> <meta charset="utf-8">
<link href="firewall.css" type="text/css" rel="stylesheet"> <link href="firewall.css" type="text/css" rel="stylesheet">
@ -90,10 +90,10 @@ index 016650651..da60cb121 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="../base1/po.js"></script> <script src="../base1/po.js"></script>
diff --git a/pkg/networkmanager/index.html b/pkg/networkmanager/index.html Index: cockpit/pkg/networkmanager/index.html
index ada48b1f1..e44e7cdd1 100644 ===================================================================
--- a/pkg/networkmanager/index.html --- cockpit.orig/pkg/networkmanager/index.html
+++ b/pkg/networkmanager/index.html +++ cockpit/pkg/networkmanager/index.html
@@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -102,11 +102,11 @@ index ada48b1f1..e44e7cdd1 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="../manifests.js"></script> <script src="../manifests.js"></script>
<script src="../base1/po.js"></script> <script src="../base1/po.js"></script>
diff --git a/pkg/packagekit/index.html b/pkg/packagekit/index.html Index: cockpit/pkg/packagekit/index.html
index 9489fe9c4..eafa63726 100644 ===================================================================
--- a/pkg/packagekit/index.html --- cockpit.orig/pkg/packagekit/index.html
+++ b/pkg/packagekit/index.html +++ cockpit/pkg/packagekit/index.html
@@ -24,6 +24,7 @@ along with Cockpit; If not, see <http://www.gnu.org/licenses/>. @@ -24,6 +24,7 @@ along with Cockpit; If not, see <http://
<meta charset="utf-8"> <meta charset="utf-8">
<link href="updates.css" rel="stylesheet"> <link href="updates.css" rel="stylesheet">
@ -114,10 +114,10 @@ index 9489fe9c4..eafa63726 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="../base1/po.js"></script> <script src="../base1/po.js"></script>
diff --git a/pkg/playground/index.html b/pkg/playground/index.html Index: cockpit/pkg/playground/index.html
index bfa507064..f8419f572 100644 ===================================================================
--- a/pkg/playground/index.html --- cockpit.orig/pkg/playground/index.html
+++ b/pkg/playground/index.html +++ cockpit/pkg/playground/index.html
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<title>Cockpit Development Playground</title> <title>Cockpit Development Playground</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -126,10 +126,10 @@ index bfa507064..f8419f572 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="../manifests.js"></script> <script src="../manifests.js"></script>
<script src="index.js"></script> <script src="index.js"></script>
diff --git a/pkg/playground/journal.html b/pkg/playground/journal.html Index: cockpit/pkg/playground/journal.html
index df2743a75..61ce3cd46 100644 ===================================================================
--- a/pkg/playground/journal.html --- cockpit.orig/pkg/playground/journal.html
+++ b/pkg/playground/journal.html +++ cockpit/pkg/playground/journal.html
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<title>Cockpit Journal Box</title> <title>Cockpit Journal Box</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -138,10 +138,10 @@ index df2743a75..61ce3cd46 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="journal.js"></script> <script src="journal.js"></script>
</head> </head>
diff --git a/pkg/playground/metrics.html b/pkg/playground/metrics.html Index: cockpit/pkg/playground/metrics.html
index c16c619c4..7987d0cf5 100644 ===================================================================
--- a/pkg/playground/metrics.html --- cockpit.orig/pkg/playground/metrics.html
+++ b/pkg/playground/metrics.html +++ cockpit/pkg/playground/metrics.html
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<title>Cockpit Monitoring</title> <title>Cockpit Monitoring</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -150,10 +150,10 @@ index c16c619c4..7987d0cf5 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="metrics.js"></script> <script src="metrics.js"></script>
</head> </head>
diff --git a/pkg/playground/plot.html b/pkg/playground/plot.html Index: cockpit/pkg/playground/plot.html
index f451bef1a..06dad225d 100644 ===================================================================
--- a/pkg/playground/plot.html --- cockpit.orig/pkg/playground/plot.html
+++ b/pkg/playground/plot.html +++ cockpit/pkg/playground/plot.html
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<title>Cockpit Plots</title> <title>Cockpit Plots</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -162,10 +162,10 @@ index f451bef1a..06dad225d 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="plot.js"></script> <script src="plot.js"></script>
</head> </head>
diff --git a/pkg/playground/react-patterns.html b/pkg/playground/react-patterns.html Index: cockpit/pkg/playground/react-patterns.html
index 0bf888664..3db9e08a2 100644 ===================================================================
--- a/pkg/playground/react-patterns.html --- cockpit.orig/pkg/playground/react-patterns.html
+++ b/pkg/playground/react-patterns.html +++ cockpit/pkg/playground/react-patterns.html
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<title>Cockpit React Patterns Usage</title> <title>Cockpit React Patterns Usage</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -174,10 +174,10 @@ index 0bf888664..3db9e08a2 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="react-patterns.js"></script> <script src="react-patterns.js"></script>
</head> </head>
diff --git a/pkg/playground/speed.html b/pkg/playground/speed.html Index: cockpit/pkg/playground/speed.html
index 86a8cd7a6..0920be9dc 100644 ===================================================================
--- a/pkg/playground/speed.html --- cockpit.orig/pkg/playground/speed.html
+++ b/pkg/playground/speed.html +++ cockpit/pkg/playground/speed.html
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<title>Cockpit Speed Tests</title> <title>Cockpit Speed Tests</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -186,10 +186,10 @@ index 86a8cd7a6..0920be9dc 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="speed.js"></script> <script src="speed.js"></script>
</head> </head>
diff --git a/pkg/playground/test.html b/pkg/playground/test.html Index: cockpit/pkg/playground/test.html
index 61220e5df..34cd6d738 100644 ===================================================================
--- a/pkg/playground/test.html --- cockpit.orig/pkg/playground/test.html
+++ b/pkg/playground/test.html +++ cockpit/pkg/playground/test.html
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<title>Cockpit playground</title> <title>Cockpit playground</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -198,11 +198,11 @@ index 61220e5df..34cd6d738 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="test.js"></script> <script src="test.js"></script>
</head> </head>
diff --git a/pkg/selinux/setroubleshoot.html b/pkg/selinux/setroubleshoot.html Index: cockpit/pkg/selinux/setroubleshoot.html
index d412acf4a..981dc30bc 100644 ===================================================================
--- a/pkg/selinux/setroubleshoot.html --- cockpit.orig/pkg/selinux/setroubleshoot.html
+++ b/pkg/selinux/setroubleshoot.html +++ cockpit/pkg/selinux/setroubleshoot.html
@@ -25,6 +25,7 @@ along with Cockpit; If not, see <http://www.gnu.org/licenses/>. @@ -25,6 +25,7 @@ along with Cockpit; If not, see <http://
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="selinux.css"> <link rel="stylesheet" href="selinux.css">
@ -210,10 +210,10 @@ index d412acf4a..981dc30bc 100644
<script type="text/javascript" src="../base1/cockpit.js"></script> <script type="text/javascript" src="../base1/cockpit.js"></script>
<script type="text/javascript" src="../base1/po.js"></script> <script type="text/javascript" src="../base1/po.js"></script>
diff --git a/pkg/shell/index.html b/pkg/shell/index.html Index: cockpit/pkg/shell/index.html
index 4e7204f48..6c85e2faf 100644 ===================================================================
--- a/pkg/shell/index.html --- cockpit.orig/pkg/shell/index.html
+++ b/pkg/shell/index.html +++ cockpit/pkg/shell/index.html
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="index.css" rel="stylesheet"> <link href="index.css" rel="stylesheet">
@ -222,10 +222,10 @@ index 4e7204f48..6c85e2faf 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="../manifests.js"></script> <script src="../manifests.js"></script>
<script src="../*/po.js"></script> <script src="../*/po.js"></script>
diff --git a/pkg/shell/shell.html b/pkg/shell/shell.html Index: cockpit/pkg/shell/shell.html
index 5c7bcd121..edc8edd99 100644 ===================================================================
--- a/pkg/shell/shell.html --- cockpit.orig/pkg/shell/shell.html
+++ b/pkg/shell/shell.html +++ cockpit/pkg/shell/shell.html
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -234,11 +234,11 @@ index 5c7bcd121..edc8edd99 100644
</head> </head>
<body class="pf-m-redhat-font"> <body class="pf-m-redhat-font">
<div class="curtains-ct"> <div class="curtains-ct">
diff --git a/pkg/sosreport/index.html b/pkg/sosreport/index.html Index: cockpit/pkg/sosreport/index.html
index 37c26f81d..7273c108e 100644 ===================================================================
--- a/pkg/sosreport/index.html --- cockpit.orig/pkg/sosreport/index.html
+++ b/pkg/sosreport/index.html +++ cockpit/pkg/sosreport/index.html
@@ -22,6 +22,7 @@ along with Cockpit; If not, see <http://www.gnu.org/licenses/>. @@ -22,6 +22,7 @@ along with Cockpit; If not, see <http://
<title translate="yes">Diagnostic reports</title> <title translate="yes">Diagnostic reports</title>
<meta charset="utf-8"> <meta charset="utf-8">
<link href="sosreport.css" rel="stylesheet"> <link href="sosreport.css" rel="stylesheet">
@ -246,10 +246,10 @@ index 37c26f81d..7273c108e 100644
<script type="text/javascript" src="../base1/cockpit.js"></script> <script type="text/javascript" src="../base1/cockpit.js"></script>
<script type="text/javascript" src="../base1/po.js"></script> <script type="text/javascript" src="../base1/po.js"></script>
<script type="text/javascript" src="po.js"></script> <script type="text/javascript" src="po.js"></script>
diff --git a/pkg/storaged/index.html b/pkg/storaged/index.html Index: cockpit/pkg/storaged/index.html
index d56fcb7b5..36953f0d9 100644 ===================================================================
--- a/pkg/storaged/index.html --- cockpit.orig/pkg/storaged/index.html
+++ b/pkg/storaged/index.html +++ cockpit/pkg/storaged/index.html
@@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -258,10 +258,10 @@ index d56fcb7b5..36953f0d9 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="../base1/po.js"></script> <script src="../base1/po.js"></script>
<script src="../manifests.js"></script> <script src="../manifests.js"></script>
diff --git a/pkg/systemd/hwinfo.html b/pkg/systemd/hwinfo.html Index: cockpit/pkg/systemd/hwinfo.html
index ef0fa560d..fb649d358 100644 ===================================================================
--- a/pkg/systemd/hwinfo.html --- cockpit.orig/pkg/systemd/hwinfo.html
+++ b/pkg/systemd/hwinfo.html +++ cockpit/pkg/systemd/hwinfo.html
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
<title translate="yes">Hardware information</title> <title translate="yes">Hardware information</title>
<meta charset="utf-8"> <meta charset="utf-8">
@ -270,10 +270,10 @@ index ef0fa560d..fb649d358 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="../base1/po.js"></script> <script src="../base1/po.js"></script>
<script src="po.js"></script> <script src="po.js"></script>
diff --git a/pkg/systemd/index.html b/pkg/systemd/index.html Index: cockpit/pkg/systemd/index.html
index bea228152..f4a6983bd 100644 ===================================================================
--- a/pkg/systemd/index.html --- cockpit.orig/pkg/systemd/index.html
+++ b/pkg/systemd/index.html +++ cockpit/pkg/systemd/index.html
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
@ -282,11 +282,11 @@ index bea228152..f4a6983bd 100644
<script type="text/javascript" src="../base1/cockpit.js"></script> <script type="text/javascript" src="../base1/cockpit.js"></script>
<script type="text/javascript" src="../base1/po.js"></script> <script type="text/javascript" src="../base1/po.js"></script>
diff --git a/pkg/systemd/logs.html b/pkg/systemd/logs.html Index: cockpit/pkg/systemd/logs.html
index 1475a96ec..7cd64312b 100644 ===================================================================
--- a/pkg/systemd/logs.html --- cockpit.orig/pkg/systemd/logs.html
+++ b/pkg/systemd/logs.html +++ cockpit/pkg/systemd/logs.html
@@ -23,6 +23,7 @@ along with Cockpit; If not, see <http://www.gnu.org/licenses/>. @@ -23,6 +23,7 @@ along with Cockpit; If not, see <http://
<title translate>Journal</title> <title translate>Journal</title>
<meta charset="utf-8"> <meta charset="utf-8">
<link href="logs.css" rel="stylesheet"> <link href="logs.css" rel="stylesheet">
@ -294,10 +294,10 @@ index 1475a96ec..7cd64312b 100644
<script type="text/javascript" src="../base1/cockpit.js"></script> <script type="text/javascript" src="../base1/cockpit.js"></script>
<script src="../base1/po.js"></script> <script src="../base1/po.js"></script>
<script src="po.js"></script> <script src="po.js"></script>
diff --git a/pkg/systemd/services.html b/pkg/systemd/services.html Index: cockpit/pkg/systemd/services.html
index 038680dcd..c665da6cf 100644 ===================================================================
--- a/pkg/systemd/services.html --- cockpit.orig/pkg/systemd/services.html
+++ b/pkg/systemd/services.html +++ cockpit/pkg/systemd/services.html
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -306,10 +306,10 @@ index 038680dcd..c665da6cf 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="../base1/po.js"></script> <script src="../base1/po.js"></script>
<script src="services.js"></script> <script src="services.js"></script>
diff --git a/pkg/systemd/terminal.html b/pkg/systemd/terminal.html Index: cockpit/pkg/systemd/terminal.html
index 536ae4eed..ff5a592d6 100644 ===================================================================
--- a/pkg/systemd/terminal.html --- cockpit.orig/pkg/systemd/terminal.html
+++ b/pkg/systemd/terminal.html +++ cockpit/pkg/systemd/terminal.html
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -318,10 +318,10 @@ index 536ae4eed..ff5a592d6 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="../base1/po.js"></script> <script src="../base1/po.js"></script>
<script src="po.js"></script> <script src="po.js"></script>
diff --git a/pkg/users/index.html b/pkg/users/index.html Index: cockpit/pkg/users/index.html
index 6b945a3a9..7060e88fd 100644 ===================================================================
--- a/pkg/users/index.html --- cockpit.orig/pkg/users/index.html
+++ b/pkg/users/index.html +++ cockpit/pkg/users/index.html
@@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -330,11 +330,10 @@ index 6b945a3a9..7060e88fd 100644
<script src="../base1/cockpit.js"></script> <script src="../base1/cockpit.js"></script>
<script src="../base1/po.js"></script> <script src="../base1/po.js"></script>
<script src="po.js"></script> <script src="po.js"></script>
diff --git a/pkg/static/css-overrides.css b/pkg/static/css-overrides.css Index: cockpit/pkg/static/css-overrides.css
new file mode 100644 ===================================================================
index 000000000..f489352af
--- /dev/null --- /dev/null
+++ b/pkg/static/css-overrides.css +++ cockpit/pkg/static/css-overrides.css
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
+/** +/**
+ * PLEASE, DO NOT CHANGE THIS FILE. + * PLEASE, DO NOT CHANGE THIS FILE.
@ -348,6 +347,3 @@ index 000000000..f489352af
+ * - https://github.com/cockpit-project/cockpit/pull/17437 + * - https://github.com/cockpit-project/cockpit/pull/17437
+ * - https://github.com/cockpit-project/cockpit/issues/16359 + * - https://github.com/cockpit-project/cockpit/issues/16359
+ */ + */
--
2.36.1

View File

@ -20,7 +20,7 @@ Index: cockpit/pkg/kdump/manifest.json
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
"tools": { "tools": {
"index": { "index": {
"label": "Kernel Dump", "label": "Kernel dump",
- "docs": [ - "docs": [
+ "docs-rh": [ + "docs-rh": [
{ {
@ -46,7 +46,7 @@ Index: cockpit/pkg/packagekit/manifest.json
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
"tools": { "tools": {
"index": { "index": {
"label": "Software Updates", "label": "Software updates",
- "docs": [ - "docs": [
+ "docs-rh": [ + "docs-rh": [
{ {
@ -113,7 +113,7 @@ Index: cockpit/pkg/shell/topnav.jsx
=================================================================== ===================================================================
--- cockpit.orig/pkg/shell/topnav.jsx --- cockpit.orig/pkg/shell/topnav.jsx
+++ cockpit/pkg/shell/topnav.jsx +++ cockpit/pkg/shell/topnav.jsx
@@ -121,9 +121,9 @@ export class TopNav extends React.Compon @@ -119,9 +119,9 @@ export class TopNav extends React.Compon
{cockpit.format(_("$0 documentation"), this.state.osRelease.NAME)} {cockpit.format(_("$0 documentation"), this.state.osRelease.NAME)}
</DropdownItem>); </DropdownItem>);

View File

@ -1,23 +0,0 @@
From 9be51b563c98744053e4a7412e5030fa2ab3e061 Mon Sep 17 00:00:00 2001
From: Marius Vollmer <mvollmer@redhat.com>
Date: Mon, 8 Aug 2022 14:50:51 +0300
Subject: [PATCH] kdump: Use close with cockpit.file, not remove
There is no remove, and the intention is to close the watch channel.
---
pkg/kdump/config-client.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/kdump/config-client.js b/pkg/kdump/config-client.js
index 9b95b9a0c65..c58cb85fd99 100644
--- a/pkg/kdump/config-client.js
+++ b/pkg/kdump/config-client.js
@@ -47,7 +47,7 @@ export class ConfigFile {
close() {
if (this._fileHandle) {
- this._fileHandle.remove();
+ this._fileHandle.close();
this._fileHandle = undefined;
}
}

View File

@ -1,712 +0,0 @@
From b61b273451987a283825a585a4f40901be12b11c Mon Sep 17 00:00:00 2001
From: Jacek Tomasiak <jacek.tomasiak@gmail.com>
Date: Tue, 12 Jul 2022 01:38:04 +0200
Subject: [PATCH 1/4] kdump: Refactor config handling
Config handling was modified to decouple UI from config file format.
All of the platform-specific code was moved to config-client.js and
"abstract" settings model was added as an interface.
In addition, NFS UI page was modified to not require NFS mounts in
specific format but as separate "server" and "export" fields.
---
pkg/kdump/config-client.js | 186 +++++++++++++++++++++++++++++++++++--
pkg/kdump/kdump-client.js | 87 ++++-------------
pkg/kdump/kdump-view.jsx | 125 ++++++++-----------------
3 files changed, 237 insertions(+), 161 deletions(-)
diff --git a/pkg/kdump/config-client.js b/pkg/kdump/config-client.js
index 39913bb6c86..d292bd9bebd 100644
--- a/pkg/kdump/config-client.js
+++ b/pkg/kdump/config-client.js
@@ -19,6 +19,12 @@
import cockpit from 'cockpit';
+const deprecatedKeys = ["net", "options", "link_delay", "disk_timeout", "debug_mem_level", "blacklist"];
+const knownKeys = [
+ "raw", "nfs", "ssh", "sshkey", "path", "core_collector", "kdump_post", "kdump_pre", "extra_bins", "extra_modules",
+ "default", "force_rebuild", "override_resettable", "dracut_args", "fence_kdump_args", "fence_kdump_nodes"
+];
+
/* Parse an ini-style config file
* and monitor it for changes
*/
@@ -82,7 +88,12 @@ export class ConfigFile {
// parse the config file
this._lines = rawContent.split(/\r?\n/);
- this.settings = { };
+ // this is the format expected by the UI
+ this.settings = {
+ _internal: {},
+ targets: {},
+ compression: { enabled: false, allowed: false, },
+ };
this._lines.forEach((line, index) => {
const trimmed = line.trim();
// if the line is empty or only a comment, skip
@@ -103,7 +114,7 @@ export class ConfigFile {
comment = value.substring(commentIndex).trim();
value = value.substring(0, commentIndex).trim();
}
- this.settings[key] = {
+ this.settings._internal[key] = {
index: index,
value: value,
origLine: line,
@@ -113,21 +124,182 @@ export class ConfigFile {
// make sure we copy the original keys so we overwrite the correct lines when saving
this._originalSettings = { };
- Object.keys(this.settings).forEach((key) => {
- this._originalSettings[key] = { ...this.settings[key] };
+ Object.keys(this.settings._internal).forEach((key) => {
+ this._originalSettings[key] = { ...this.settings._internal[key] };
});
+
+ this._extractSettings();
+
if (!skipNotify)
this.dispatchEvent("kdumpConfigChanged", this.settings);
}
+ /* extract settings managed by cockpit from _internal into platform independent model
+ */
+ _extractSettings() {
+ // "path" applies to all targets
+ const path = this.settings._internal.path || { value: "" };
+
+ Object.keys(this.settings._internal).forEach((key) => {
+ if (key === "nfs") {
+ // split nfs line into server and export parts
+ const parts = this.settings._internal.nfs.value.match(/^([^[][^:]+|\[[^\]]+\]):(.*)$/);
+ if (!parts)
+ return;
+ this.settings.targets.nfs = {
+ type: key,
+ path: path.value,
+ server: parts[1],
+ export: parts[2],
+ };
+ } else if (key === "ssh") {
+ this.settings.targets.ssh = {
+ type: key,
+ path: path.value,
+ server: this.settings._internal.ssh.value,
+ };
+ if ("sshkey" in this.settings._internal)
+ this.settings.targets.ssh.sshkey = this.settings._internal.sshkey.value;
+ } else if (key === "raw") {
+ this.settings.targets.raw = {
+ type: key,
+ partition: this.settings._internal.raw.value
+ };
+ } else {
+ // probably local, but we might also have a mount
+ // check against known keys, the ones left over may be a mount target
+ // if the key is empty or known, we don't care about it here
+ if (!key || key in knownKeys || key in deprecatedKeys)
+ return;
+ // if we have a UUID, LABEL or /dev in the value, we can be pretty sure it's a mount option
+ const value = JSON.stringify(this.settings._internal[key]).toLowerCase();
+ if (value.indexOf("uuid") > -1 || value.indexOf("label") > -1 || value.indexOf("/dev") > -1) {
+ this.settings.targets.mount = {
+ type: "mount",
+ path: path.value,
+ fsType: key,
+ partition: this.settings._internal[key].value,
+ };
+ } else {
+ // TODO: check for know filesystem types here
+ }
+ }
+ });
+
+ // default to local if no target configured
+ if (Object.keys(this.settings.targets).length === 0)
+ this.settings.targets.local = { type: "local", path: path.value };
+
+ // only allow compression if there is no core collector set or it's set to makedumpfile
+ this.settings.compression.allowed = (
+ !("core_collector" in this.settings._internal) ||
+ (this.settings._internal.core_collector.value.trim().indexOf("makedumpfile") === 0)
+ );
+ // compression is enabled if we have a core_collector command with the "-c" parameter
+ this.settings.compression.enabled = (
+ ("core_collector" in this.settings._internal) &&
+ this.settings._internal.core_collector.value &&
+ (this.settings._internal.core_collector.value.split(" ").indexOf("-c") != -1)
+ );
+ }
+
+ /* update single _internal setting to given value
+ * make sure setting exists if value is not empty
+ */
+ _updateSetting(settings, key, value) {
+ if (key in settings._internal) {
+ if (value)
+ settings._internal[key].value = value;
+ else
+ delete settings._internal[key];
+ } else {
+ if (value)
+ settings._internal[key] = { value: value };
+ }
+ }
+
+ /* transform settings from model back to _internal format
+ * this.settings = current state from file
+ * settings = in-memory state from UI
+ */
+ _persistSettings(settings) {
+ // target
+ if (Object.keys(settings.targets).length > 0) {
+ const target = Object.values(settings.targets)[0];
+ this._updateSetting(settings, "path", target.path);
+
+ // wipe old target settings
+ for (const key in this.settings.targets) {
+ const oldTarget = this.settings.targets[key];
+ if (oldTarget.type == "mount") {
+ delete settings._internal[oldTarget.fsType];
+ } else {
+ delete settings._internal[key];
+ }
+ }
+
+ if (target.type === "nfs") {
+ this._updateSetting(settings, "nfs", [target.server, target.export].join(":"));
+ } else if (target.type === "ssh") {
+ this._updateSetting(settings, "ssh", target.server);
+ if ("sshkey" in target)
+ this._updateSetting(settings, "sshkey", target.sshkey);
+ } else if (target.type === "raw") {
+ this._updateSetting(settings, "raw", target.partition);
+ } else if (target.type === "mount") {
+ this._updateSetting(settings, target.fsType, target.partition);
+ }
+
+ /* ssh target needs a flattened vmcore for transport */
+ if ("core_collector" in settings._internal &&
+ settings._internal.core_collector.value.includes("makedumpfile")) {
+ if (target.type === "ssh" && !settings._internal.core_collector.value.includes("-F"))
+ settings._internal.core_collector.value += " -F";
+ else if (settings._internal.core_collector.value.includes("-F"))
+ settings._internal.core_collector.value =
+ settings._internal.core_collector.value
+ .split(" ")
+ .filter(e => e != "-F")
+ .join(" ");
+ }
+ }
+ // compression
+ if (this.settings.compression.enabled != settings.compression.enabled) {
+ if (settings.compression.enabled) {
+ // enable compression
+ if ("core_collector" in settings._internal)
+ settings._internal.core_collector.value = settings._internal.core_collector.value + " -c";
+ else
+ settings._internal.core_collector = { value: "makedumpfile -c" };
+ } else {
+ // disable compression
+ if ("core_collector" in this.settings._internal) {
+ // just remove all "-c" parameters
+ settings._internal.core_collector.value =
+ settings._internal.core_collector.value
+ .split(" ")
+ .filter((e) => { return (e != "-c") })
+ .join(" ");
+ } else {
+ // if we don't have anything on this in the original settings,
+ // we can get rid of the entry altogether
+ delete settings._internal.core_collector;
+ }
+ }
+ }
+ return settings;
+ }
+
/* generate the config file from raw text and settings
*/
_generateConfig(settings) {
+ settings = this._persistSettings(settings);
+
const lines = this._lines.slice(0);
const linesToDelete = [];
// first find the settings lines that have been disabled/deleted
Object.keys(this._originalSettings).forEach((key) => {
- if (!(key in settings) || !(key in settings && settings[key].value)) {
+ if (!(key in settings._internal) || !(key in settings._internal && settings._internal[key].value)) {
const origEntry = this._originalSettings[key];
// if the line had a comment, keep it, otherwise delete
if (origEntry.comment !== undefined)
@@ -138,8 +310,8 @@ export class ConfigFile {
});
// we take the lines from our last read operation and modify them with the new settings
- Object.keys(settings).forEach((key) => {
- const entry = settings[key];
+ Object.keys(settings._internal).forEach((key) => {
+ const entry = settings._internal[key];
let line = key + " " + entry.value;
if (entry.comment)
line = line + " " + entry.comment;
diff --git a/pkg/kdump/kdump-client.js b/pkg/kdump/kdump-client.js
index a161fc25214..d001ebb0b5a 100644
--- a/pkg/kdump/kdump-client.js
+++ b/pkg/kdump/kdump-client.js
@@ -25,12 +25,6 @@ import crashKernelScript from 'raw-loader!./crashkernel.sh';
import testWritableScript from 'raw-loader!./testwritable.sh';
const _ = cockpit.gettext;
-const deprecatedKeys = ["net", "options", "link_delay", "disk_timeout", "debug_mem_level", "blacklist"];
-const knownKeys = [
- "raw", "nfs", "ssh", "sshkey", "path", "core_collector", "kdump_post", "kdump_pre", "extra_bins", "extra_modules",
- "default", "force_rebuild", "override_resettable", "dracut_args", "fence_kdump_args", "fence_kdump_nodes"
-];
-
/* initializes the kdump status
* emits "kdumpStatusChanged" when the status changes, along with a status object:
* {
@@ -40,7 +34,7 @@ const knownKeys = [
* config: settings from kdump.conf
* target: dump target info, content depends on dump type
* always contains the keys:
- * target value in ["local", "nfs", "ssh", "raw", "mount", "unknown"]
+ * type value in ["local", "nfs", "ssh", "raw", "mount", "unknown"]
* multipleTargets true if the config file has more than one target defined, false otherwise
* }
*
@@ -106,19 +100,24 @@ export class KdumpClient {
path = "/var/crash";
return new Promise((resolve, reject) => {
- if (target.target === "local") {
+ if (target.type === "local") {
// local path, try to see if we can write
cockpit.script(testWritableScript, [path], { superuser: "try" })
.then(resolve)
.catch(() => reject(cockpit.format(_("Directory $0 isn't writable or doesn't exist."), path)));
return;
- } else if (target.target === "nfs") {
- if (!target.nfs.value.match("\\S+:/.+"))
- reject(_("nfs dump target isn't formatted as server:path"));
- } else if (target.target === "ssh") {
- if (!target.ssh.value.trim())
+ } else if (target.type === "nfs") {
+ if (!target.server || !target.server.trim())
+ reject(_("nfs server is empty"));
+ // IPv6 must be enclosed in square brackets
+ if (target.server.trim().match(/^\[.*[^\]]$/))
+ reject(_("nfs server is not valid IPv6"));
+ if (!target.export || !target.export.trim())
+ reject(_("nfs export is empty"));
+ } else if (target.type === "ssh") {
+ if (!target.server || !target.server.trim())
reject(_("ssh server is empty"));
- if (target.sshkey && !target.sshkey.value.match("/.+"))
+ if (target.sshkey && !target.sshkey.match("/.+"))
reject(_("ssh key isn't a path"));
}
@@ -149,67 +148,17 @@ export class KdumpClient {
}
targetFromSettings(settings) {
- // since local target is the default and can be used even without "path", we need to
- // check for the presence of all known targets
- // we have the additional difficulty that partitions don't have a good config key, since their
- // lines begin with the fs_type
const target = {
- target: "unknown",
+ type: "unknown",
multipleTargets: false,
};
- if (!settings)
+ if (!settings || Object.keys(settings.targets).length === 0)
return target;
- if ("nfs" in settings) {
- if (target.target != "unknown")
- target.multipleTargets = true;
- target.target = "nfs";
- target.nfs = settings.nfs;
- if ("path" in settings)
- target.path = settings.path;
- } else if ("ssh" in settings) {
- if (target.target != "unknown")
- target.multipleTargets = true;
- target.target = "ssh";
- target.ssh = settings.ssh;
- target.sshkey = settings.sshkey;
- } else if ("raw" in settings) {
- if (target.target != "unknown")
- target.multipleTargets = true;
- target.target = "raw";
- target.raw = settings.raw;
- } else {
- // probably local, but we might also have a mount
- // check all keys against known keys, the ones left over may be a mount target
- Object.keys(settings).forEach((key) => {
- // if the key is empty or known, we don't care about it here
- if (!key || key in knownKeys || key in deprecatedKeys)
- return;
- // if we have a UUID, LABEL or /dev in the value, we can be pretty sure it's a mount option
- const value = JSON.stringify(settings[key]).toLowerCase();
- if (value.indexOf("uuid") > -1 || value.indexOf("label") > -1 || value.indexOf("/dev") > -1) {
- if (target.target != "unknown")
- target.multipleTargets = true;
- target.target = "mount";
- target.fsType = key;
- target.partition = settings[key].value;
- } else {
- // TODO: check for know filesystem types here
- }
- });
- }
-
- // if no target matches, then we use the local filesystem
- if (target.target == "unknown")
- target.target = "local";
-
- // "path" applies to all targets
- // default to "/var/crash for "
- if ("path" in settings)
- target.path = settings.path.value;
- else if (["local", "ssh", "nfs", "mount"].indexOf(target.target) !== -1)
- target.path = "/var/crash";
+ // copy first target
+ cockpit.extend(target, Object.values(settings.targets)[0]);
+ target.multipleTargets = Object.keys(settings.targets).length > 1;
return target;
}
}
diff --git a/pkg/kdump/kdump-view.jsx b/pkg/kdump/kdump-view.jsx
index 718d8c43bc9..956811d7826 100644
--- a/pkg/kdump/kdump-view.jsx
+++ b/pkg/kdump/kdump-view.jsx
@@ -57,7 +57,7 @@ class KdumpTargetBody extends React.Component {
constructor(props) {
super(props);
this.state = {
- storeDest: this.props.initialTarget.target, // dialog mode, depends on location
+ storeDest: this.props.initialTarget.type, // dialog mode, depends on location
};
this.changeLocation = this.changeLocation.bind(this);
}
@@ -71,15 +71,10 @@ class KdumpTargetBody extends React.Component {
render() {
let detailRows;
- // only allow compression if there is no core collector set or it's set to makedumpfile
- const compressionPossible = (
- !this.props.settings ||
- !("core_collector" in this.props.settings) ||
- (this.props.settings.core_collector.value.trim().indexOf("makedumpfile") === 0)
- );
+ const compressionPossible = !this.props.settings || this.props.settings.compression.allowed;
let directory = "";
- if (this.props.settings && "path" in this.props.settings)
- directory = this.props.settings.path.value;
+ if (this.props.settings && "path" in this.props.settings.targets[this.state.storeDest])
+ directory = this.props.settings.targets[this.state.storeDest].path;
if (this.state.storeDest == "local") {
detailRows = (
@@ -91,15 +86,22 @@ class KdumpTargetBody extends React.Component {
</FormGroup>
);
} else if (this.state.storeDest == "nfs") {
- let nfs = "";
- if (this.props.settings && "nfs" in this.props.settings)
- nfs = this.props.settings.nfs.value;
+ let nfs = {};
+ if (this.props.settings && "nfs" in this.props.settings.targets)
+ nfs = this.props.settings.targets.nfs;
+ const server = nfs.server || "";
+ const exportpath = nfs.export || "";
detailRows = (
<>
- <FormGroup fieldId="kdump-settings-nfs-mount" label={_("Mount")}>
- <TextInput id="kdump-settings-nfs-mount" key="mount"
- placeholder="penguin.example.com:/export/cores" value={nfs}
- onChange={value => this.props.onChange("nfs", value)} />
+ <FormGroup fieldId="kdump-settings-nfs-server" label={_("Server")}>
+ <TextInput id="kdump-settings-nfs-server" key="server"
+ placeholder="penguin.example.com" value={server}
+ onChange={value => this.props.onChange("server", value)} />
+ </FormGroup>
+ <FormGroup fieldId="kdump-settings-nfs-export" label={_("Export")}>
+ <TextInput id="kdump-settings-nfs-export" key="export"
+ placeholder="/export/cores" value={exportpath}
+ onChange={value => this.props.onChange("export", value)} />
</FormGroup>
<FormGroup fieldId="kdump-settings-nfs-directory" label={_("Directory")}>
<TextInput id="kdump-settings-nfs-directory" key="directory"
@@ -110,18 +112,17 @@ class KdumpTargetBody extends React.Component {
</>
);
} else if (this.state.storeDest == "ssh") {
- let ssh = "";
- if (this.props.settings && "ssh" in this.props.settings)
- ssh = this.props.settings.ssh.value;
- let sshkey = "";
- if (this.props.settings && "sshkey" in this.props.settings)
- sshkey = this.props.settings.sshkey.value;
+ let ssh = {};
+ if (this.props.settings && "ssh" in this.props.settings.targets)
+ ssh = this.props.settings.targets.ssh;
+ const server = ssh.server || "";
+ const sshkey = ssh.sshkey || "";
detailRows = (
<>
<FormGroup fieldId="kdump-settings-ssh-server" label={_("Server")}>
<TextInput id="kdump-settings-ssh-server" key="server"
- placeholder="user@server.com" value={ssh}
- onChange={value => this.props.onChange("ssh", value)} />
+ placeholder="user@server.com" value={server}
+ onChange={value => this.props.onChange("server", value)} />
</FormGroup>
<FormGroup fieldId="kdump-settings-ssh-key" label={_("ssh key")}>
@@ -201,78 +202,32 @@ export class KdumpPage extends React.Component {
}
compressionStatus(settings) {
- // compression is enabled if we have a core_collector command with the "-c" parameter
- return (
- settings &&
- ("core_collector" in settings) &&
- settings.core_collector.value &&
- (settings.core_collector.value.split(" ").indexOf("-c") != -1)
- );
+ return settings && settings.compression.enabled;
}
changeSetting(key, value) {
let settings = this.state.dialogSettings;
- // a few special cases, otherwise write to config directly
+ // a few special cases, otherwise write to config target directly
if (key == "compression") {
- if (value) {
- // enable compression
- if ("core_collector" in settings)
- settings.core_collector.value = settings.core_collector.value + " -c";
- else
- settings.core_collector = { value: "makedumpfile -c" };
- } else {
- // disable compression
- if ("core_collector" in this.props.kdumpStatus.config) {
- // just remove all "-c" parameters
- settings.core_collector.value =
- settings.core_collector.value
- .split(" ")
- .filter((e) => { return (e != "-c") })
- .join(" ");
- } else {
- // if we don't have anything on this in the original settings,
- // we can get rid of the entry altogether
- delete settings.core_collector;
- }
- }
+ settings.compression.enabled = value;
} else if (key === "target") {
/* target changed, restore settings and wipe all settings associated
* with a target so no conflicting settings remain */
settings = {};
+ // TODO: do we need a deep copy here?
Object.keys(this.props.kdumpStatus.config).forEach((key) => {
settings[key] = { ...this.props.kdumpStatus.config[key] };
});
- Object.keys(this.props.kdumpStatus.target).forEach((key) => {
- if (settings[key])
- delete settings[key];
- });
- if (value === "ssh")
- settings.ssh = { value: "" };
- else if (value === "nfs")
- settings.nfs = { value: "" };
-
- if ("core_collector" in settings &&
- settings.core_collector.value.includes("makedumpfile")) {
- /* ssh target needs a flattened vmcore for transport */
- if (value === "ssh" && !settings.core_collector.value.includes("-F"))
- settings.core_collector.value += " -F";
- else if (settings.core_collector.value.includes("-F"))
- settings.core_collector.value =
- settings.core_collector.value
- .split(" ")
- .filter(e => e != "-F")
- .join(" ");
- }
+ settings.targets = {};
+ settings.targets[value] = { type: value };
} else if (key !== undefined) {
+ const type = Object.keys(settings.targets)[0];
if (!value) {
- if (settings[key])
- delete settings[key];
+ if (settings.targets[type][key])
+ delete settings.targets[type][key];
} else {
- if (key in settings)
- settings[key].value = value;
- else
- settings[key] = { value: value };
+ settings.targets[type][key] = value;
}
}
this.setState({ dialogSettings: settings });
@@ -391,21 +346,21 @@ export class KdumpPage extends React.Component {
if (target.multipleTargets) {
kdumpLocation = _("invalid: multiple targets defined");
} else {
- if (target.target == "local") {
+ if (target.type == "local") {
if (target.path)
kdumpLocation = cockpit.format(_("locally in $0"), target.path);
else
kdumpLocation = cockpit.format(_("locally in $0"), "/var/crash");
targetCanChange = true;
- } else if (target.target == "ssh") {
+ } else if (target.type == "ssh") {
kdumpLocation = _("Remote over SSH");
targetCanChange = true;
- } else if (target.target == "nfs") {
+ } else if (target.type == "nfs") {
kdumpLocation = _("Remote over NFS");
targetCanChange = true;
- } else if (target.target == "raw") {
+ } else if (target.type == "raw") {
kdumpLocation = _("Raw to a device");
- } else if (target.target == "mount") {
+ } else if (target.type == "mount") {
/* mount targets outside of nfs are too complex for the
* current target dialog */
kdumpLocation = _("On a mounted device");
From 2d045f916a9cff40e38411f8c07487d0b0f65b48 Mon Sep 17 00:00:00 2001
From: Jacek Tomasiak <jacek.tomasiak@gmail.com>
Date: Tue, 12 Jul 2022 12:03:28 +0200
Subject: [PATCH 2/4] kdump: Update config-client test
---
pkg/kdump/test-config-client.js | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/pkg/kdump/test-config-client.js b/pkg/kdump/test-config-client.js
index 61b10a57cb4..6eb84592d26 100644
--- a/pkg/kdump/test-config-client.js
+++ b/pkg/kdump/test-config-client.js
@@ -49,10 +49,10 @@ QUnit.test("config_update", function (assert) {
const dataWasChanged = new Promise(resolve => { this.dataWasChangedResolve = resolve });
let config;
const configChanged = (event, settings) => {
- assert.equal(settings.foo.value, "moo", "value changed correctly");
- assert.equal("key" in settings, false, "setting with comment deleted correctly");
- assert.equal("will" in settings, false, "setting without comment deleted correctly");
- assert.equal(settings.hooray.value, "value", "value added correctly");
+ assert.equal(settings._internal.foo.value, "moo", "value changed correctly");
+ assert.equal("key" in settings._internal, false, "setting with comment deleted correctly");
+ assert.equal("will" in settings._internal, false, "setting without comment deleted correctly");
+ assert.equal(settings._internal.hooray.value, "value", "value added correctly");
assert.equal(config._rawContent, changedConfig, "raw text for changed config is correct");
this.dataWasChangedResolve();
};
@@ -65,10 +65,10 @@ QUnit.test("config_update", function (assert) {
assert.equal(configFile.path, filename, "file has correct path");
config = new kdump.ConfigFile(filename);
config.wait().then(() => {
- config.settings.foo.value = "moo";
- delete config.settings.key;
- delete config.settings.will;
- config.settings.hooray = { value: "value" };
+ config.settings._internal.foo.value = "moo";
+ delete config.settings._internal.key;
+ delete config.settings._internal.will;
+ config.settings._internal.hooray = { value: "value" };
config.addEventListener('kdumpConfigChanged', configChanged);
config.write(config.settings)
.then(() => dataWasChanged.then(done));
From f94cf930e138681feeda272edef8172a5504cfb9 Mon Sep 17 00:00:00 2001
From: Jacek Tomasiak <jacek.tomasiak@gmail.com>
Date: Tue, 12 Jul 2022 12:21:59 +0200
Subject: [PATCH 3/4] kdump: Update kdump tests
---
test/verify/check-kdump | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/test/verify/check-kdump b/test/verify/check-kdump
index 5ef7108062c..107c6730dfa 100755
--- a/test/verify/check-kdump
+++ b/test/verify/check-kdump
@@ -109,15 +109,15 @@ class TestKdump(KdumpHelpers):
b.click("#kdump-change-target")
b.wait_visible("#kdump-settings-dialog")
b.set_val("#kdump-settings-location", "nfs")
- mountInput = "#kdump-settings-nfs-mount"
- b.set_input_text(mountInput, ":/var/crash")
+ serverInput = "#kdump-settings-nfs-server"
+ b.set_input_text(serverInput, "")
b.click(f"#kdump-settings-dialog button{self.primary_btn_class}")
- b.wait_in_text("#kdump-settings-dialog h4.pf-c-alert__title", "Unable to save settings: nfs dump target isn't formatted as server:path")
+ b.wait_in_text("#kdump-settings-dialog h4.pf-c-alert__title", "Unable to save settings: nfs server is empty")
# no further details/journal
self.assertFalse(b.is_present("#kdump-settings-dialog .pf-c-code-block__code"))
- b.set_input_text(mountInput, "localhost:")
+ b.set_input_text(serverInput, "localhost")
b.click(f"#kdump-settings-dialog button{self.primary_btn_class}")
- b.wait_in_text("#kdump-settings-dialog h4.pf-c-alert__title", "Unable to save settings: nfs dump target isn't formatted as server:path")
+ b.wait_in_text("#kdump-settings-dialog h4.pf-c-alert__title", "Unable to save settings: nfs export is empty")
b.click("#kdump-settings-dialog button.cancel")
b.wait_not_present("#kdump-settings-dialog")
@@ -207,7 +207,8 @@ class TestKdump(KdumpHelpers):
b.click("#kdump-change-target")
b.wait_visible("#kdump-settings-dialog")
b.set_val("#kdump-settings-location", "nfs")
- b.set_input_text("#kdump-settings-nfs-mount", "someserver:/srv")
+ b.set_input_text("#kdump-settings-nfs-server", "someserver")
+ b.set_input_text("#kdump-settings-nfs-export", "/srv")
b.click("button:contains('Save')")
b.wait_not_present("#kdump-settings-dialog")
conf = m.execute("cat /etc/kdump.conf")
@@ -277,7 +278,8 @@ class TestKdumpNFS(KdumpHelpers):
b.click("#kdump-change-target")
b.wait_visible("#kdump-settings-dialog")
b.set_val("#kdump-settings-location", "nfs")
- b.set_input_text("#kdump-settings-nfs-mount", "10.111.113.2:/srv/kdump")
+ b.set_input_text("#kdump-settings-nfs-server", "10.111.113.2")
+ b.set_input_text("#kdump-settings-nfs-export", "/srv/kdump")
b.click(f"#kdump-settings-dialog button{self.primary_btn_class}")
# rebuilding initrd might take a while on busy CI machines
with b.wait_timeout(300):
From 7a0d578063a1f4e25697eb13a9331f37d277857d Mon Sep 17 00:00:00 2001
From: Jacek Tomasiak <jacek.tomasiak@gmail.com>
Date: Tue, 19 Jul 2022 15:58:03 +0200
Subject: [PATCH 4/4] kdump: Fix ssh settings wiping
Leftover sshkey setting confused kdump on Fedora-35.
---
pkg/kdump/config-client.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/pkg/kdump/config-client.js b/pkg/kdump/config-client.js
index d292bd9bebd..9b95b9a0c65 100644
--- a/pkg/kdump/config-client.js
+++ b/pkg/kdump/config-client.js
@@ -233,6 +233,9 @@ export class ConfigFile {
const oldTarget = this.settings.targets[key];
if (oldTarget.type == "mount") {
delete settings._internal[oldTarget.fsType];
+ } else if (oldTarget.type == "ssh") {
+ delete settings._internal.ssh;
+ delete settings._internal.sshkey;
} else {
delete settings._internal[key];
}

View File

@ -1,491 +0,0 @@
From d95850239f81a65c90743f20a0bc0450cb61823a Mon Sep 17 00:00:00 2001
From: Jacek Tomasiak <jacek.tomasiak@gmail.com>
Date: Fri, 2 Sep 2022 16:51:02 +0200
Subject: [PATCH] kdump: Add SUSE kdump config support
If parsing /etc/kdump.conf doesn't return usable settings, try
/etc/sysconfig/kdump which is used by SUSE distributions as the main
kdump config.
The file is in dotenv format and currently only KDUMP_SAVEDIR,
KDUMP_DUMPFORMAT and KDUMP_SSH_IDENTITY entries
are used by Cockpit.
SUSE supports additional dump target types (ftp, sftp, cifs) but doesn't
support others (raw, mount). The target dialog currently supports the
common types (nfs, ssh, local).
---
pkg/kdump/config-client-suse.js | 265 ++++++++++++++++++++++++++++++++
pkg/kdump/kdump-client.js | 14 ++
pkg/kdump/kdump-view.jsx | 8 +-
test/verify/check-kdump | 127 +++++++++++++++
4 files changed, 413 insertions(+), 1 deletion(-)
create mode 100644 pkg/kdump/config-client-suse.js
diff --git a/pkg/kdump/config-client-suse.js b/pkg/kdump/config-client-suse.js
new file mode 100644
index 00000000000..074d9e406ca
--- /dev/null
+++ b/pkg/kdump/config-client-suse.js
@@ -0,0 +1,265 @@
+/*
+ * This file is part of Cockpit.
+ *
+ * Copyright (C) 2022 SUSE LLC
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+import { ConfigFile } from './config-client.js';
+
+/* Parse an dotenv-style config file
+ * and monitor it for changes
+ */
+export class ConfigFileSUSE extends ConfigFile {
+ /* parse lines of the config file
+ * if a line has a valid key=value format, use the key in _internal structure
+ * and also store original line, line index, value and optional line suffix / comment
+ * if value was quoted it will be stripped of quotes in `value` and `quoted` flag will
+ * be used when writing the file to keep original formatting
+ * e.g. for line 'someKey="foo" # comment'
+ * outputObject._internal["someKey"] = {
+ * index: 0,
+ * value: "foo",
+ * quoted: true,
+ * origLine: 'someKey="foo" # comment',
+ * suffix: "# comment"
+ * }
+ * skipNotify: Don't notify about changes, e.g.to avoid multiple updates when writing a file
+ */
+ _parseText(rawContent, skipNotify = false) {
+ this._dataAvailableResolve();
+
+ // clear settings if file is empty/missing
+ if (!rawContent) {
+ this._originalSettings = null;
+ this.settings = null;
+ if (!skipNotify)
+ this.dispatchEvent("kdumpConfigChanged", this.settings);
+ return;
+ }
+
+ // if nothing changed, don't bother parsing the content
+ if (rawContent == this._rawContent)
+ return;
+
+ this._rawContent = rawContent;
+
+ // this is the format expected by the UI
+ this.settings = {
+ _internal: {},
+ targets: {},
+ compression: { enabled: false, allowed: true },
+ };
+
+ this._lines = rawContent.split(/\r?\n/);
+ this._lines.forEach((line, index) => {
+ const trimmed = line.trim();
+ // if the line is empty or only a comment, skip
+ if (trimmed.indexOf("#") === 0 || trimmed.length === 0)
+ return;
+
+ // parse KEY=value or KEY="value" line
+ let parts = trimmed.match(/^([A-Z_]+)\s*=\s*(.*)$/);
+ if (parts === null) {
+ console.warn("Malformed kdump config line:", trimmed, "in", this.filename);
+ return;
+ }
+ const key = parts[1];
+ let value = parts[2];
+
+ // value might be quoted
+ let quoted = false;
+ if (value.startsWith('"')) {
+ quoted = true;
+ parts = value.match(/^"([^"]*)"\s*(.*)$/);
+ // malformed line, no ending quote?
+ if (parts === null) {
+ console.warn("Incorrectly quoted value in kdump config line:", line, "in", this.filename);
+ return;
+ }
+ } else {
+ // not quoted should be simple value but grab everything and quote on write
+ parts = value.match(/^([^#]+?)\s*(#.*)?$/);
+ if (parts === null)
+ parts = ["", ""];
+ }
+ value = parts[1];
+ const suffix = (parts[2] || "").trim();
+
+ this.settings._internal[key] = {
+ index: index,
+ value: value,
+ origLine: line,
+ quoted: quoted,
+ suffix: suffix
+ };
+ });
+
+ // make sure we copy the original keys so we overwrite the correct lines when saving
+ this._originalSettings = { };
+ Object.keys(this.settings._internal).forEach((key) => {
+ this._originalSettings[key] = { ...this.settings._internal[key] };
+ });
+
+ this._extractSettings();
+
+ if (!skipNotify)
+ this.dispatchEvent("kdumpConfigChanged", this.settings);
+ }
+
+ /* extract settings managed by cockpit from _internal into platform independent model
+ */
+ _extractSettings() {
+ // generate target(s) from KDUMP_SAVEDIR
+ if ("KDUMP_SAVEDIR" in this.settings._internal && this.settings._internal.KDUMP_SAVEDIR.value) {
+ let savedir = this.settings._internal.KDUMP_SAVEDIR.value;
+ // handle legacy "file" without prefix
+ if (savedir.startsWith("/"))
+ savedir = "file://" + savedir;
+ // server includes "username:password@" and can be empty for file://
+ const parts = savedir.match(/^(.*):\/\/([^/]*)(\/.*)$/);
+ // malformed KDUMP_SAVEDIR
+ if (parts === null) {
+ console.warn("Malformed KDUMP_SAVEDIR entry:", savedir, "in", this.filename);
+ return;
+ }
+ const [, scheme, server, path] = parts;
+ if (scheme === "file") {
+ this.settings.targets.local = {
+ type: "local",
+ path: path,
+ };
+ } else if (scheme === "nfs") {
+ this.settings.targets.nfs = {
+ type: scheme,
+ // on read full path is used as export
+ export: path,
+ server: server,
+ };
+ } else {
+ this.settings.targets[scheme] = {
+ type: scheme,
+ path: path,
+ server: server,
+ };
+ // sshkey is used by ssh and sftp/scp
+ if ("KDUMP_SSH_IDENTITY" in this.settings._internal) {
+ this.settings.targets[scheme].sshkey =
+ this.settings._internal.KDUMP_SSH_IDENTITY.value;
+ }
+ }
+ }
+
+ // default to local if no target configured
+ if (Object.keys(this.settings.targets).length === 0)
+ this.settings.targets.local = { type: "local" };
+
+ this.settings.compression.enabled = (
+ !("KDUMP_DUMPFORMAT" in this.settings._internal) ||
+ // TODO: what about other compression formats (lzo, snappy)?
+ this.settings._internal.KDUMP_DUMPFORMAT.value === "compressed"
+ );
+ }
+
+ /* update single _internal setting to given value
+ * make sure setting exists if value is not empty
+ * don't delete existing settings
+ */
+ _updateSetting(settings, key, value) {
+ if (key in settings._internal) {
+ settings._internal[key].value = value;
+ } else {
+ if (value)
+ settings._internal[key] = { value: value };
+ }
+ }
+
+ /* transform settings from model back to _internal format
+ * this.settings = current state from file
+ * settings = in-memory state from UI
+ */
+ _persistSettings(settings) {
+ // target
+ if (Object.keys(settings.targets).length > 0) {
+ const target = Object.values(settings.targets)[0];
+
+ if ("sshkey" in target)
+ this._updateSetting(settings, "KDUMP_SSH_IDENTITY", target.sshkey);
+
+ let savedir;
+ // default for empty path (except nfs, see below)
+ let path = target.path || "/var/crash";
+ if (path && !path.startsWith("/"))
+ path = "/" + path;
+ if (target.type === "local") {
+ savedir = "file://" + path;
+ } else if (target.type === "nfs") {
+ // override empty path default as nfs path is merged into export on read
+ if (!target.path)
+ path = "";
+ let exprt = target.export;
+ if (!exprt.startsWith("/"))
+ exprt = "/" + exprt;
+ savedir = "nfs://" + target.server + exprt + path;
+ } else {
+ savedir = target.type + "://" + target.server + path;
+ }
+ this._updateSetting(settings, "KDUMP_SAVEDIR", savedir);
+ }
+ // compression
+ if (this.settings.compression.enabled != settings.compression.enabled) {
+ if (settings.compression.enabled) {
+ this._updateSetting(settings, "KDUMP_DUMPFORMAT", "compressed");
+ } else {
+ this._updateSetting(settings, "KDUMP_DUMPFORMAT", "ELF");
+ }
+ }
+ return settings;
+ }
+
+ /* generate the config file from raw text and settings
+ */
+ _generateConfig(settings) {
+ settings = this._persistSettings(settings);
+
+ const lines = this._lines.slice(0);
+
+ // we take the lines from our last read operation and modify them with the new settings
+ Object.keys(settings._internal).forEach((key) => {
+ const entry = settings._internal[key];
+
+ let value = entry.value !== undefined ? entry.value : "";
+ // quote what was quoted before + empty values + multi-word values
+ if (entry.quoted || value === "" || value.includes(" "))
+ value = '"' + value + '"';
+ let line = key + "=" + value;
+ if (entry.suffix)
+ line = line + " " + entry.suffix;
+ // this might be a new entry
+ if (!(key in this._originalSettings)) {
+ lines.push(line);
+ return;
+ }
+ // otherwise edit the old line
+ const origEntry = this._originalSettings[key];
+ lines[origEntry.index] = line;
+ });
+
+ // make sure file ends with a newline
+ if (lines[lines.length - 1] !== "")
+ lines.push("");
+ return lines.join("\n");
+ }
+}
diff --git a/pkg/kdump/kdump-client.js b/pkg/kdump/kdump-client.js
index d001ebb0b5a..7af24dc1bcb 100644
--- a/pkg/kdump/kdump-client.js
+++ b/pkg/kdump/kdump-client.js
@@ -20,6 +20,7 @@
import cockpit from 'cockpit';
import { proxy as serviceProxy } from 'service';
import { ConfigFile } from './config-client.js';
+import { ConfigFileSUSE } from './config-client-suse.js';
import crashKernelScript from 'raw-loader!./crashkernel.sh';
import testWritableScript from 'raw-loader!./testwritable.sh';
@@ -61,6 +62,19 @@ export class KdumpClient {
// watch the config file
this.configClient = new ConfigFile("/etc/kdump.conf", true);
+ this._watchConfigChanges();
+
+ this.configClient.wait().then(() => {
+ // if no configuration found, try SUSE version
+ if (this.configClient.settings === null) {
+ this.configClient.close();
+ this.configClient = new ConfigFileSUSE("/etc/sysconfig/kdump", true);
+ this._watchConfigChanges();
+ }
+ });
+ }
+
+ _watchConfigChanges() {
// catch config changes
this.configClient.addEventListener('kdumpConfigChanged', () => {
this.state.config = this.configClient.settings;
diff --git a/pkg/kdump/kdump-view.jsx b/pkg/kdump/kdump-view.jsx
index 956811d7826..3de3761706b 100644
--- a/pkg/kdump/kdump-view.jsx
+++ b/pkg/kdump/kdump-view.jsx
@@ -364,6 +364,12 @@ export class KdumpPage extends React.Component {
/* mount targets outside of nfs are too complex for the
* current target dialog */
kdumpLocation = _("On a mounted device");
+ } else if (target.type == "ftp") {
+ kdumpLocation = _("Remote over FTP");
+ } else if (target.type == "sftp") {
+ kdumpLocation = _("Remote over SFTP");
+ } else if (target.type == "cifs") {
+ kdumpLocation = _("Remote over CIFS/SMB");
} else {
kdumpLocation = _("No configuration found");
}
@@ -372,7 +378,7 @@ export class KdumpPage extends React.Component {
// this.storeLocation(this.props.kdumpStatus.config);
const settingsLink = targetCanChange
? <Button variant="link" isInline id="kdump-change-target" onClick={this.handleSettingsClick}>{ kdumpLocation }</Button>
- : <span>{ kdumpLocation }</span>;
+ : <span id="kdump-target-info">{ kdumpLocation }</span>;
let reservedMemory;
if (this.props.reservedMemory === undefined) {
// still waiting for result
diff --git a/test/verify/check-kdump b/test/verify/check-kdump
index 03d9a199970..855636eb0da 100755
--- a/test/verify/check-kdump
+++ b/test/verify/check-kdump
@@ -248,6 +248,133 @@ class TestKdump(KdumpHelpers):
conf = m.execute("cat /etc/kdump.conf")
self.assertIn(current + " -c", conf)
+ @nondestructive
+ def testConfigurationSUSE(self):
+ b = self.browser
+ m = self.machine
+
+ testConfig = [
+ "# some comment",
+ "KDUMP_DUMPFORMAT=compressed # suffix",
+ "KDUMP_SSH_IDENTITY=\"\"",
+ "skip this line",
+ "BAD_QUOTES=unquoted value # suffix",
+ "BAD_SPACES = 42 # comment",
+ "MORE_BAD_SPACES = 4 2 # long comment",
+ "KDUMP_SAVEDIR=ssh//missing/colon",
+ ]
+
+ # clean default config to trigger SUSE config mode
+ self.write_file("/etc/kdump.conf", "")
+ # write initial SUSE config (append to keep original contents as well)
+ self.write_file("/etc/sysconfig/kdump", "\n".join(testConfig), append=True)
+
+ m.execute("systemctl disable --now kdump")
+
+ self.login_and_go("/kdump")
+ b.wait_visible("#app")
+
+ # Check malformed lines
+ b.wait_text("#kdump-target-info", "No configuration found")
+ b.wait(lambda: "warning: Malformed kdump config line: skip this line in /etc/sysconfig/kdump" in list(self.browser.get_js_log()))
+ b.wait(lambda: "warning: Malformed KDUMP_SAVEDIR entry: ssh//missing/colon in /etc/sysconfig/kdump" in list(self.browser.get_js_log()))
+
+ # Remove malformed KDUMP_SAVEDIR to check default if nothing specified
+ m.execute("sed -i '/KDUMP_SAVEDIR=.*/d' /etc/sysconfig/kdump")
+ b.wait_text("#kdump-change-target", "locally in /var/crash")
+
+ # Check fixing of (some) malformed lines and local target without file://
+ m.execute("echo KDUMP_SAVEDIR=/tmp >> /etc/sysconfig/kdump")
+ b.wait_text("#kdump-change-target", "locally in /tmp")
+ b.click("#kdump-change-target")
+ b.wait_visible("#kdump-settings-dialog")
+ b.click("button:contains('Save')")
+ b.wait_not_present("#kdump-settings-dialog")
+ conf = m.execute("cat /etc/sysconfig/kdump")
+ self.assertIn('KDUMP_SAVEDIR=file:///tmp', conf)
+ self.assertIn('BAD_QUOTES="unquoted value" # suffix', conf)
+ self.assertIn('BAD_SPACES=42 # comment', conf)
+ self.assertIn('MORE_BAD_SPACES="4 2" # long comment', conf)
+
+ # Check remote ssh location
+ b.click("#kdump-change-target")
+ b.wait_visible("#kdump-settings-dialog")
+ b.set_val("#kdump-settings-location", "ssh")
+ b.set_input_text("#kdump-settings-ssh-server", "admin@localhost")
+ b.set_input_text("#kdump-settings-ssh-key", "/home/admin/.ssh/id_rsa")
+ b.set_input_text("#kdump-settings-ssh-directory", "/var/tmp/crash")
+ b.click("button:contains('Save')")
+ b.wait_not_present("#kdump-settings-dialog")
+ b.wait_text("#kdump-change-target", "Remote over SSH")
+ conf = m.execute("cat /etc/sysconfig/kdump")
+ self.assertIn('KDUMP_SAVEDIR=ssh://admin@localhost/var/tmp/crash', conf)
+ self.assertIn('KDUMP_SSH_IDENTITY="/home/admin/.ssh/id_rsa"', conf)
+
+ # Check remote NFS location
+ b.click("#kdump-change-target")
+ b.wait_visible("#kdump-settings-dialog")
+ b.set_val("#kdump-settings-location", "nfs")
+ b.set_input_text("#kdump-settings-nfs-server", "someserver")
+ b.set_input_text("#kdump-settings-nfs-export", "/srv")
+ b.click("button:contains('Save')")
+ b.wait_not_present("#kdump-settings-dialog")
+ b.wait_text("#kdump-change-target", "Remote over NFS")
+ conf = m.execute("cat /etc/sysconfig/kdump")
+ self.assertIn('KDUMP_SAVEDIR=nfs://someserver/srv', conf)
+ self.assertNotIn("ssh://", conf)
+
+ # NFS with custom path
+ b.click("#kdump-change-target")
+ b.wait_visible("#kdump-settings-dialog")
+ b.set_input_text("#kdump-settings-nfs-directory", "dumps")
+ b.click("button:contains('Save')")
+ b.wait_not_present("#kdump-settings-dialog")
+ b.wait_text("#kdump-change-target", "Remote over NFS")
+ conf = m.execute("cat /etc/sysconfig/kdump")
+ self.assertIn('KDUMP_SAVEDIR=nfs://someserver/srv/dumps', conf)
+
+ # Check local location
+ b.click("#kdump-change-target")
+ b.wait_visible("#kdump-settings-dialog")
+ b.set_val("#kdump-settings-location", "local")
+ b.set_input_text("#kdump-settings-local-directory", "/var/tmp")
+ b.click("button:contains('Save')")
+ b.wait_not_present("#kdump-settings-dialog")
+ b.wait_text("#kdump-change-target", "locally in /var/tmp")
+ conf = m.execute("cat /etc/sysconfig/kdump")
+ self.assertIn('KDUMP_SAVEDIR=file:///var/tmp', conf)
+ self.assertNotIn("nfs://", conf)
+
+ # Check compression
+ conf = m.execute("cat /etc/sysconfig/kdump")
+ self.assertIn('KDUMP_DUMPFORMAT=compressed', conf)
+ b.click("#kdump-change-target")
+ b.wait_visible("#kdump-settings-dialog")
+ b.set_checked("#kdump-settings-compression", False)
+ b.click("button:contains('Save')")
+ b.wait_not_present("#kdump-settings-dialog")
+ conf = m.execute("cat /etc/sysconfig/kdump")
+ self.assertIn('KDUMP_DUMPFORMAT=ELF', conf)
+ b.click("#kdump-change-target")
+ b.wait_visible("#kdump-settings-dialog")
+ b.set_checked("#kdump-settings-compression", True)
+ b.click("button:contains('Save')")
+ b.wait_not_present("#kdump-settings-dialog")
+ conf = m.execute("cat /etc/sysconfig/kdump")
+ self.assertIn('KDUMP_DUMPFORMAT=compressed', conf)
+
+ # Check remote FTP location (no config dialog)
+ m.execute("sed -i 's/KDUMP_SAVEDIR=.*/KDUMP_SAVEDIR=ftp:\\/\\/user@ftpserver\\/dumps1/g' /etc/sysconfig/kdump")
+ b.wait_text("#kdump-target-info", "Remote over FTP")
+
+ # Check remote SFTP location (no config dialog)
+ m.execute("sed -i 's/KDUMP_SAVEDIR=.*/KDUMP_SAVEDIR=sftp:\\/\\/sftpserver\\/dumps2/g' /etc/sysconfig/kdump")
+ b.wait_text("#kdump-target-info", "Remote over SFTP")
+
+ # Check remote CIFS location (no config dialog)
+ m.execute("sed -i 's/KDUMP_SAVEDIR=.*/KDUMP_SAVEDIR=cifs:\\/\\/user:pass@smbserver\\/dumps3/g' /etc/sysconfig/kdump")
+ b.wait_text("#kdump-target-info", "Remote over CIFS/SMB")
+
@skipImage("kexec-tools not installed", "fedora-coreos", "debian-stable",
"debian-testing", "ubuntu-2204", "ubuntu-stable", "arch")

BIN
node_modules.obscpio (Stored with Git LFS)

Binary file not shown.

File diff suppressed because it is too large Load Diff

11740
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -30,9 +30,9 @@ Index: cockpit/pkg/lib/cockpit-components-password.jsx
}); });
} }
@@ -53,13 +56,12 @@ export const PasswordFormFields = ({ @@ -54,13 +57,12 @@ export const PasswordFormFields = ({
}) => { }) => {
const [password, setPassword] = useState(undefined); const [password, setPassword] = useState(initial_password);
const [passwordConfirm, setConfirmPassword] = useState(undefined); const [passwordConfirm, setConfirmPassword] = useState(undefined);
- const [passwordStrength, setPasswordStrength] = useState(""); - const [passwordStrength, setPasswordStrength] = useState("");
- const [passwordMessage, setPasswordMessage] = useState(""); - const [passwordMessage, setPasswordMessage] = useState("");
@ -44,8 +44,8 @@ Index: cockpit/pkg/lib/cockpit-components-password.jsx
+ /* + /*
if (value) { if (value) {
password_quality(value) password_quality(value)
.catch(ex => { .catch(() => {
@@ -73,7 +75,9 @@ export const PasswordFormFields = ({ @@ -74,7 +76,9 @@ export const PasswordFormFields = ({
setPasswordStrength(""); setPasswordStrength("");
setPasswordMessage(""); setPasswordMessage("");
} }
@ -55,7 +55,7 @@ Index: cockpit/pkg/lib/cockpit-components-password.jsx
let variant; let variant;
if (passwordStrength === "") if (passwordStrength === "")
@@ -84,6 +88,7 @@ export const PasswordFormFields = ({ @@ -85,6 +89,7 @@ export const PasswordFormFields = ({
variant = "warning"; variant = "warning";
else else
variant = "danger"; variant = "danger";
@ -63,7 +63,7 @@ Index: cockpit/pkg/lib/cockpit-components-password.jsx
return ( return (
<> <>
@@ -101,16 +106,6 @@ export const PasswordFormFields = ({ @@ -103,16 +108,6 @@ export const PasswordFormFields = ({
fieldId={idPrefix + "-pw1"}> fieldId={idPrefix + "-pw1"}>
<TextInput className="check-passwords" type="password" id={idPrefix + "-pw1"} <TextInput className="check-passwords" type="password" id={idPrefix + "-pw1"}
autocomplete="new-password" value={password} onChange={onPasswordChanged} /> autocomplete="new-password" value={password} onChange={onPasswordChanged} />