diff --git a/saltgui/static/scripts/Api.js b/saltgui/static/scripts/Api.js index 7ab67a93d..39ebd1f69 100644 --- a/saltgui/static/scripts/Api.js +++ b/saltgui/static/scripts/Api.js @@ -216,6 +216,14 @@ export class API { return this.apiRequest("POST", "/", params); } + getWheelMinionsConnected () { + const params = { + "client": "wheel", + "fun": "minions.connected" + }; + return this.apiRequest("POST", "/", params); + } + getStats () { const params = { }; diff --git a/saltgui/static/scripts/panels/Minions.js b/saltgui/static/scripts/panels/Minions.js index 4d55d2a91..14e6b1b2c 100644 --- a/saltgui/static/scripts/panels/Minions.js +++ b/saltgui/static/scripts/panels/Minions.js @@ -29,6 +29,7 @@ export class MinionsPanel extends Panel { onShow () { const wheelKeyListAllPromise = this.api.getWheelKeyListAll(); + const wheelMinionsConnectedPromise = this.api.getWheelMinionsConnected(); const localGrainsItemsPromise = this.api.getLocalGrainsItems(null); const runnerManageVersionsPromise = this.api.getRunnerManageVersions(); @@ -37,6 +38,14 @@ export class MinionsPanel extends Panel { wheelKeyListAllPromise.then((pWheelKeyListAllData) => { this._handleMinionsWheelKeyListAll(pWheelKeyListAllData); + wheelMinionsConnectedPromise.then((pWheelMinionsConnectedData) => { + this._handlewheelMinionsConnected(pWheelMinionsConnectedData); + return true; + }, (getWheelMinionsConnectedMsg) => { + console.log("getWheelMinionsConnectedMsg", getWheelMinionsConnectedMsg); + return false; + }); + localGrainsItemsPromise.then((pLocalGrainsItemsData) => { this.updateMinions(pLocalGrainsItemsData); return true; @@ -92,6 +101,30 @@ export class MinionsPanel extends Panel { this.setMsg(txt); } + _handlewheelMinionsConnected (pWheelMinionsConnectedData) { + if (this.showErrorRowInstead(pWheelMinionsConnectedData)) { + return; + } + + const minionIds = pWheelMinionsConnectedData.return[0].data.return; + + for (const tr of this.table.tBodies[0].childNodes) { + if (minionIds.indexOf(tr.dataset.minionId) >= 0) { + // skip the connected minions + continue; + } + const statusTd = tr.querySelector("td.status"); + if (!statusTd) { + continue; + } + // this is the initial warning only + // it will potentially be replaced by a less aggressive warning + // when the grains information is returned + statusTd.innerText = "offline"; + statusTd.classList.add("offline"); + } + } + updateOfflineMinion (pMinionId, pMinionsDict) { super.updateOfflineMinion(pMinionId, pMinionsDict); diff --git a/saltgui/static/scripts/panels/Panel.js b/saltgui/static/scripts/panels/Panel.js index 4f4816999..461829f25 100644 --- a/saltgui/static/scripts/panels/Panel.js +++ b/saltgui/static/scripts/panels/Panel.js @@ -303,6 +303,7 @@ export class Panel { minionTr = document.createElement("tr"); minionTr.id = Utils.getIdFromMinionId(pMinionId); + minionTr.dataset.minionId = pMinionId; minionTr.appendChild(Utils.createTd("minion-id", pMinionId)); @@ -577,12 +578,14 @@ export class Panel { if (pMinionId in pMinionsDict) { if (pMinionsDict[pMinionId] === "true") { Utils.addToolTip(offlineSpan, "Minion is offline\nIs the host running and is the salt-minion installed and started?\nUpdate file 'minions.txt' when needed", "bottom-left"); - offlineSpan.style.color = "red"; + offlineSpan.classList.add("offline"); } else { Utils.addToolTip(offlineSpan, "Minion is offline\nSince it is reported as inactive in file 'minions.txt', that should be OK", "bottom-left"); + offlineSpan.classList.remove("offline"); } + } else { + offlineSpan.classList.add("offline"); } - offlineSpan.classList.add("offline"); const offlineTd = Utils.createTd(); offlineTd.appendChild(offlineSpan); minionTr.appendChild(offlineTd); diff --git a/saltgui/static/stylesheets/page.css b/saltgui/static/stylesheets/page.css index c3386e9c4..dbfcc4441 100644 --- a/saltgui/static/stylesheets/page.css +++ b/saltgui/static/stylesheets/page.css @@ -189,6 +189,10 @@ table tr td:last-of-type { color: #00f; } +.offline { + color: red; +} + .osimage { max-width: 18px; max-height: 18px;