public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Max Carrara <m.carrara@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH v3 pve-manager 1/5] fix #5366: ui: ceph: services: parse and display build commit
Date: Wed, 24 Jul 2024 17:05:07 +0200	[thread overview]
Message-ID: <20240724150511.474844-2-m.carrara@proxmox.com> (raw)
In-Reply-To: <20240724150511.474844-1-m.carrara@proxmox.com>

The build commit is displayed and taken into account when comparing
monitor and manager versions in the client. Specifically, the
shortened build commit is now displayed in parentheses next to the
version for both monitors and managers like so:

  18.2.2 (build: abcd1234)

Should the build commit of the running service differ from the one
that's installed on the host, the newer build commit will also be
shown in parentheses:

  18.2.2 (build: abcd1234 -> 5678fedc)

The icon displayed for running a service with an outdated build is the
same as for running an outdated version. The conditional display of
icons related to cluster health remains the same otherwise.

The Ceph summary view also displays the hash and will show a warning
if a service is running with a build commit that doesn't match the one
that's advertised by the host.

This requires the introduction of two helper functions:

1. `PVE.Utils.parseCephBuildCommit`, which can be used to get the full
  hash "eccf199d..." in parentheses from a string like the following:

  ceph version 17.2.7 (eccf199d63457659c09677399928203b7903c888) quincy (stable)

2. `PVE.Utils.renderCephBuildCommit`, which is used to determine how
   to render a service's current build commit and which accompanying
   icon to choose.

Signed-off-by: Max Carrara <m.carrara@proxmox.com>
Fixes: https://bugzilla.proxmox.com/show_bug.cgi?id=5366
---
Changes v2 --> v3:
  * add new `renderCephBuildCommit` helper function (thanks Thomas!)
  * add docstrings for helpers
  * use less ambiguous variable names (thanks Thomas!)
  * put 'build: ' in front of build commit when rendering (thanks Thomas!)
  * handle no rendered build commit being available in MGR / MON lists,
    returning the icon + version without the commit instead
  * make the modified logic in Services.js more readable
  * reword message about differing builds in the overview
  * reword commit title & message
  * add 'Fixes' trailer
  * remove outdated R-b and T-b trailers

Changes v1 --> v2:
  * use camelCase instead of snake_case (thanks Lukas!)
  * use more descriptive variable names (thanks Lukas!)
  * use `let` instead of `const` for variables where applicable (thanks Lukas!)

 www/manager6/Utils.js            | 107 +++++++++++++++++++++++++++++++
 www/manager6/ceph/ServiceList.js |  33 +++++++---
 www/manager6/ceph/Services.js    |  19 +++++-
 3 files changed, 148 insertions(+), 11 deletions(-)

diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index db86fa9a..1d42be34 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -128,6 +128,113 @@ Ext.define('PVE.Utils', {
 	return undefined;
     },
 
+    /**
+     * Parses a Ceph build commit from its version string.
+     *
+     * @param {object} service
+     * @param {string} service.ceph_version - The long form of a Ceph version string
+     * @returns {(undefined|string)} The matched build commit or `undefined`
+     */
+    parseCephBuildCommit: function(service) {
+	if (service.ceph_version) {
+	    // See PVE/Ceph/Tools.pm - get_local_version
+	    const match = service.ceph_version.match(
+		/^ceph.*\sv?(?:\d+(?:\.\d+)+)\s+(?:\(([a-zA-Z0-9]+)\))/,
+	    );
+	    if (match) {
+		return match[1];
+	    }
+	}
+
+	return undefined;
+    },
+
+    /**
+     * Determines how Ceph build commits should be rendered and which icon
+     * should be chosen depending on the Ceph versions and build commits given.
+     *
+     * Should the two build commits be identical, the commit is shortened.
+     * Should they differ, they're rendered as e.g.:
+     *
+     *	    0558a7146 -> b72f4fd04
+     *
+     *	Note that the arrow `->` is rendered as a Font Awesome icon.
+     *
+     * @param {Object} versionInfo
+     * @param {string} versionInfo.runningVersion - The version of the currently
+     *	    running Ceph service
+     * @param {string} versionInfo.installedVersion - The version of the Ceph
+     *	    service (or its executable) as reported by the node
+     * @param {string} versionInfo.runningBuildCommit - The build commit of the
+     *	    currently running Ceph service
+     * @param {string} versionInfo.installedBuildCommit - The build commit of the
+     *	    Ceph service (or its executable) as reported by the node
+     * @param {string} versionInfo.maxVersion - The highest version of the
+     *	    Ceph service in the cluster
+     * @param {boolean} versionInfo.hasMixedVersions - Whether different
+     *	    versions of the service are currently running in the cluster
+     * @param {number} [buildCommitLength] - (Optional) The length to which to
+     *	    shorten the rendered build commit(s), `9` by default
+     * @returns {Object} - An object containing the selected `icon`, whether the
+     *	    current build commit has `changed` and the build commit (or build
+     *	    commit changes) as `renderedBuildCommit`
+     */
+    renderCephBuildCommit: function(versionInfo, buildCommitLength) {
+	buildCommitLength ??= 9;
+
+	versionInfo = versionInfo ?? {};
+
+	let runningVersion = versionInfo.runningVersion ?? '';
+	let installedVersion = versionInfo.installedVersion ?? '';
+
+	let runningBuildCommit = versionInfo.runningBuildCommit ?? '';
+	let installedBuildCommit = versionInfo.installedBuildCommit ?? '';
+
+	let maxVersion = versionInfo.maxVersion ?? '';
+	let hasMixedVersions = versionInfo.hasMixedVersions ?? false;
+
+	let hasBuildCommits = runningBuildCommit !== '' && installedBuildCommit !== '';
+	let hasRunningBuildCommitChanged = hasBuildCommits &&
+	    runningBuildCommit !== installedBuildCommit;
+
+	let icon = '';
+
+	if (PVE.Utils.compare_ceph_versions(maxVersion, installedVersion) > 0) {
+	    icon = PVE.Utils.get_ceph_icon_html('HEALTH_UPGRADE');
+	} else if (PVE.Utils.compare_ceph_versions(installedVersion, runningVersion) > 0) {
+	    icon = PVE.Utils.get_ceph_icon_html('HEALTH_OLD');
+	} else if (hasMixedVersions && !hasRunningBuildCommitChanged) {
+	    icon = PVE.Utils.get_ceph_icon_html('HEALTH_OK');
+	}
+
+	if (!hasBuildCommits) {
+	    return {
+		icon: icon,
+		changed: hasRunningBuildCommitChanged,
+		renderedBuildCommit: (runningBuildCommit || installedBuildCommit)
+		    .substring(0, buildCommitLength),
+	    };
+	}
+
+	let renderedBuildCommit = runningBuildCommit.substring(0, buildCommitLength);
+
+	if (hasRunningBuildCommitChanged) {
+	    const arrow = '<i class="fa fa-fw fa-long-arrow-right"></i>';
+	    icon ||= PVE.Utils.get_ceph_icon_html('HEALTH_OLD');
+
+	    let buildCommitFrom = runningBuildCommit.substring(0, buildCommitLength);
+	    let buildCommitTo = installedBuildCommit.substring(0, buildCommitLength);
+
+	    renderedBuildCommit = `${buildCommitFrom}${arrow}${buildCommitTo}`;
+	}
+
+	return {
+	    icon: icon,
+	    changed: hasRunningBuildCommitChanged,
+	    renderedBuildCommit: renderedBuildCommit,
+	};
+    },
+
     compare_ceph_versions: function(a, b) {
 	let avers = [];
 	let bvers = [];
diff --git a/www/manager6/ceph/ServiceList.js b/www/manager6/ceph/ServiceList.js
index 2dd80c14..20dfb5d0 100644
--- a/www/manager6/ceph/ServiceList.js
+++ b/www/manager6/ceph/ServiceList.js
@@ -103,21 +103,34 @@ Ext.define('PVE.node.CephServiceController', {
 	if (value === undefined) {
 	    return '';
 	}
+
 	let view = this.getView();
-	let host = rec.data.host, nodev = [0];
+	let host = rec.data.host;
+
+	let nodeVersion = [0];
+	let nodeBuildCommit = '';
+
 	if (view.nodeversions[host] !== undefined) {
-	    nodev = view.nodeversions[host].version.parts;
+	    nodeVersion = view.nodeversions[host].version.parts;
+	    nodeBuildCommit = view.nodeversions[host].buildcommit;
 	}
 
-	let icon = '';
-	if (PVE.Utils.compare_ceph_versions(view.maxversion, nodev) > 0) {
-	    icon = PVE.Utils.get_ceph_icon_html('HEALTH_UPGRADE');
-	} else if (PVE.Utils.compare_ceph_versions(nodev, value) > 0) {
-	    icon = PVE.Utils.get_ceph_icon_html('HEALTH_OLD');
-	} else if (view.mixedversions) {
-	    icon = PVE.Utils.get_ceph_icon_html('HEALTH_OK');
+	let versionInfo = {
+	    runningVersion: value,
+	    installedVersion: nodeVersion,
+	    runningBuildCommit: PVE.Utils.parseCephBuildCommit(rec.data) ?? '',
+	    installedBuildCommit: nodeBuildCommit,
+	    maxVersion: view.maxversion,
+	    hasMixedVersions: view.mixedversions,
+	};
+
+	let { icon, renderedBuildCommit } = PVE.Utils.renderCephBuildCommit(versionInfo, 9);
+
+	if (renderedBuildCommit) {
+	    return `${icon}${value} (build: ${renderedBuildCommit})`;
 	}
-	return icon + value;
+
+	return `${icon}${value}`;
     },
 
     getMaxVersions: function(store, records, success) {
diff --git a/www/manager6/ceph/Services.js b/www/manager6/ceph/Services.js
index dfafee43..ff6f80e9 100644
--- a/www/manager6/ceph/Services.js
+++ b/www/manager6/ceph/Services.js
@@ -155,6 +155,7 @@ Ext.define('PVE.ceph.Services', {
 		    title: metadata[type][id].name || name,
 		    host: host,
 		    version: PVE.Utils.parse_ceph_version(metadata[type][id]),
+		    buildcommit: PVE.Utils.parseCephBuildCommit(metadata[type][id]),
 		    service: metadata[type][id].service,
 		    addr: metadata[type][id].addr || metadata[type][id].addrs || Proxmox.Utils.unknownText,
 		};
@@ -181,7 +182,15 @@ Ext.define('PVE.ceph.Services', {
 		}
 
 		if (result.version) {
-		    result.statuses.push(gettext('Version') + ": " + result.version);
+		    let installedBuildCommit = metadata.node[host]?.buildcommit ?? '';
+		    let runningBuildCommit = result.buildcommit ?? '';
+
+		    let statusLine = gettext('Version') + `: ${result.version}`;
+		    if (runningBuildCommit) {
+			statusLine += ` (build: ${runningBuildCommit.substring(0, 9)})`;
+		    }
+
+		    result.statuses.push(statusLine);
 
 		    if (PVE.Utils.compare_ceph_versions(result.version, maxversion) !== 0) {
 			let host_version = metadata.node[host]?.version?.parts || metadata.version?.[host] || "";
@@ -202,6 +211,14 @@ Ext.define('PVE.ceph.Services', {
 				gettext('Other cluster members use a newer version of this service, please upgrade and restart'),
 			    );
 			}
+		    } else if (installedBuildCommit !== "" && runningBuildCommit !== installedBuildCommit) {
+			if (result.health > healthstates.HEALTH_OLD) {
+			    result.health = healthstates.HEALTH_OLD;
+			}
+			result.messages.push(
+			    PVE.Utils.get_ceph_icon_html('HEALTH_OLD', true) +
+			    gettext('A newer build of this release was installed but old build still running, please restart'),
+			);
 		    }
 		}
 
-- 
2.39.2



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  reply	other threads:[~2024-07-24 15:04 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-24 15:05 [pve-devel] [PATCH v3 pve-manager 0/5] Fix #5366: Ceph Build Commit in UI Max Carrara
2024-07-24 15:05 ` Max Carrara [this message]
2024-07-24 15:05 ` [pve-devel] [PATCH v3 pve-manager 2/5] fix #5366: api: ceph: add host build commit to Ceph OSD index data Max Carrara
2024-07-24 15:05 ` [pve-devel] [PATCH v3 pve-manager 3/5] fix #5366: ui: ceph: osd: rework version field rendering Max Carrara
2024-07-24 15:05 ` [pve-devel] [PATCH v3 pve-manager 4/5] ui: ceph: osd: increase width of version column Max Carrara
2024-07-24 15:05 ` [pve-devel] [PATCH v3 pve-manager 5/5] fix #5366: api: ceph: change version format in OSD metadata endpoint Max Carrara

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240724150511.474844-2-m.carrara@proxmox.com \
    --to=m.carrara@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal