mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-23 03:33:53 +00:00
fix: resolve PBS alert toggle and offline alert issues (addresses #426)
- Fixed PBS alert toggle not responding in thresholds settings - PBS servers now use connectivity toggle like nodes instead of disabled toggle - Added support for disableConnectivity flag on PBS instances in backend - Fixed PBS ID format mismatch between frontend and backend - PBS offline alerts now properly respect the disableConnectivity setting - Prevents spam alerts by checking disableConnectivity flag for PBS offline alerts
This commit is contained in:
@@ -250,16 +250,17 @@ export function ResourceTable(props: ResourceTableProps) {
|
||||
{resource.disabled ? 'Disabled' : 'Enabled'}
|
||||
</button>
|
||||
</Show>
|
||||
<Show when={resource.type === 'pbs' && props.onToggleDisabled}>
|
||||
<Show when={resource.type === 'pbs' && props.onToggleNodeConnectivity}>
|
||||
<button type="button"
|
||||
onClick={() => props.onToggleDisabled?.(resource.id)}
|
||||
onClick={() => props.onToggleNodeConnectivity?.(resource.id)}
|
||||
class={`px-2 py-0.5 text-xs font-medium rounded transition-colors ${
|
||||
resource.disabled
|
||||
resource.disableConnectivity
|
||||
? 'bg-red-100 dark:bg-red-900/50 text-red-700 dark:text-red-300 hover:bg-red-200 dark:hover:bg-red-800/50'
|
||||
: 'bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-300 hover:bg-green-200 dark:hover:bg-green-800/50'
|
||||
}`}
|
||||
title="Toggle connectivity alerts for this PBS server"
|
||||
>
|
||||
{resource.disabled ? 'Disabled' : 'Enabled'}
|
||||
{resource.disableConnectivity ? 'No Offline' : 'Alert Offline'}
|
||||
</button>
|
||||
</Show>
|
||||
</td>
|
||||
@@ -471,16 +472,17 @@ export function ResourceTable(props: ResourceTableProps) {
|
||||
{resource.disabled ? 'Disabled' : 'Enabled'}
|
||||
</button>
|
||||
</Show>
|
||||
<Show when={resource.type === 'pbs' && props.onToggleDisabled}>
|
||||
<Show when={resource.type === 'pbs' && props.onToggleNodeConnectivity}>
|
||||
<button type="button"
|
||||
onClick={() => props.onToggleDisabled?.(resource.id)}
|
||||
onClick={() => props.onToggleNodeConnectivity?.(resource.id)}
|
||||
class={`px-2 py-0.5 text-xs font-medium rounded transition-colors ${
|
||||
resource.disabled
|
||||
resource.disableConnectivity
|
||||
? 'bg-red-100 dark:bg-red-900/50 text-red-700 dark:text-red-300 hover:bg-red-200 dark:hover:bg-red-800/50'
|
||||
: 'bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-300 hover:bg-green-200 dark:hover:bg-green-800/50'
|
||||
}`}
|
||||
title="Toggle connectivity alerts for this PBS server"
|
||||
>
|
||||
{resource.disabled ? 'Disabled' : 'Enabled'}
|
||||
{resource.disableConnectivity ? 'No Offline' : 'Alert Offline'}
|
||||
</button>
|
||||
</Show>
|
||||
</td>
|
||||
|
||||
@@ -238,7 +238,8 @@ export function ThresholdsTable(props: ThresholdsTableProps) {
|
||||
const pbsInstances = props.pbsInstances || [];
|
||||
|
||||
const pbsServers = pbsInstances.filter((pbs) => (pbs.cpu || 0) > 0 || (pbs.memory?.usage || 0) > 0).map((pbs) => {
|
||||
const pbsId = `pbs-${pbs.id}`;
|
||||
// PBS IDs already have "pbs-" prefix from backend, don't double it
|
||||
const pbsId = pbs.id;
|
||||
const override = overridesMap.get(pbsId);
|
||||
|
||||
// Check if any threshold values actually differ from defaults
|
||||
@@ -264,6 +265,7 @@ export function ThresholdsTable(props: ThresholdsTableProps) {
|
||||
uptime: pbs.uptime,
|
||||
hasOverride: hasCustomThresholds || false,
|
||||
disabled: false,
|
||||
disableConnectivity: override?.disableConnectivity || false,
|
||||
thresholds: override?.thresholds || {},
|
||||
defaults: {
|
||||
cpu: props.nodeDefaults.cpu,
|
||||
@@ -502,15 +504,18 @@ export function ThresholdsTable(props: ThresholdsTableProps) {
|
||||
};
|
||||
|
||||
|
||||
const toggleNodeConnectivity = (nodeId: string, forceState?: boolean) => {
|
||||
const node = nodesWithOverrides().find(r => r.id === nodeId);
|
||||
if (!node || node.type !== 'node') return;
|
||||
const toggleNodeConnectivity = (resourceId: string, forceState?: boolean) => {
|
||||
// Find the resource - could be a node or PBS server
|
||||
const nodes = nodesWithOverrides();
|
||||
const pbsServers = pbsServersWithOverrides();
|
||||
const resource = [...nodes, ...pbsServers].find(r => r.id === resourceId);
|
||||
if (!resource || (resource.type !== 'node' && resource.type !== 'pbs')) return;
|
||||
|
||||
// Get existing override if it exists
|
||||
const existingOverride = props.overrides().find(o => o.id === nodeId);
|
||||
const existingOverride = props.overrides().find(o => o.id === resourceId);
|
||||
|
||||
// Determine the current state - use the node's computed state, not just the override
|
||||
const currentDisableConnectivity = node.disableConnectivity;
|
||||
// Determine the current state - use the resource's computed state, not just the override
|
||||
const currentDisableConnectivity = resource.disableConnectivity;
|
||||
const newDisableConnectivity = forceState !== undefined ? forceState : !currentDisableConnectivity;
|
||||
|
||||
// Clean the thresholds to exclude any unwanted fields
|
||||
@@ -521,25 +526,25 @@ export function ThresholdsTable(props: ThresholdsTableProps) {
|
||||
// If enabling connectivity alerts (disableConnectivity = false) and no custom thresholds exist, remove the override entirely
|
||||
if (!newDisableConnectivity && Object.keys(cleanThresholds).length === 0) {
|
||||
// Remove the override completely
|
||||
props.setOverrides(props.overrides().filter(o => o.id !== nodeId));
|
||||
props.setOverrides(props.overrides().filter(o => o.id !== resourceId));
|
||||
|
||||
// Remove from raw config
|
||||
const newRawConfig = { ...props.rawOverridesConfig() };
|
||||
delete newRawConfig[nodeId];
|
||||
delete newRawConfig[resourceId];
|
||||
props.setRawOverridesConfig(newRawConfig);
|
||||
} else {
|
||||
// Update or create the override
|
||||
const override: Override = {
|
||||
id: nodeId,
|
||||
name: node.name,
|
||||
type: node.type,
|
||||
resourceType: node.resourceType,
|
||||
id: resourceId,
|
||||
name: resource.name,
|
||||
type: resource.type as 'node' | 'guest' | 'storage',
|
||||
resourceType: resource.resourceType,
|
||||
disableConnectivity: newDisableConnectivity,
|
||||
thresholds: cleanThresholds
|
||||
};
|
||||
|
||||
// Update overrides list
|
||||
const existingIndex = props.overrides().findIndex(o => o.id === nodeId);
|
||||
const existingIndex = props.overrides().findIndex(o => o.id === resourceId);
|
||||
if (existingIndex >= 0) {
|
||||
const newOverrides = [...props.overrides()];
|
||||
newOverrides[existingIndex] = override;
|
||||
@@ -566,7 +571,7 @@ export function ThresholdsTable(props: ThresholdsTableProps) {
|
||||
hysteresisThresholds.disableConnectivity = true;
|
||||
}
|
||||
|
||||
newRawConfig[nodeId] = hysteresisThresholds;
|
||||
newRawConfig[resourceId] = hysteresisThresholds;
|
||||
props.setRawOverridesConfig(newRawConfig);
|
||||
}
|
||||
|
||||
@@ -915,7 +920,7 @@ export function ThresholdsTable(props: ThresholdsTableProps) {
|
||||
onSaveEdit={saveEdit}
|
||||
onCancelEdit={cancelEdit}
|
||||
onRemoveOverride={removeOverride}
|
||||
onToggleDisabled={toggleDisabled}
|
||||
onToggleNodeConnectivity={toggleNodeConnectivity}
|
||||
editingId={editingId}
|
||||
editingThresholds={editingThresholds}
|
||||
setEditingThresholds={setEditingThresholds}
|
||||
|
||||
@@ -1408,14 +1408,14 @@ func (m *Manager) checkPBSOffline(pbs models.PBSInstance) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
// Check if PBS offline alerts are disabled
|
||||
if override, exists := m.config.Overrides[pbs.ID]; exists && override.Disabled {
|
||||
// PBS alerts are disabled, clear any existing alert and return
|
||||
// Check if PBS offline alerts are disabled via disableConnectivity flag
|
||||
if override, exists := m.config.Overrides[pbs.ID]; exists && (override.Disabled || override.DisableConnectivity) {
|
||||
// PBS connectivity alerts are disabled, clear any existing alert and return
|
||||
if _, alertExists := m.activeAlerts[alertID]; alertExists {
|
||||
delete(m.activeAlerts, alertID)
|
||||
log.Debug().
|
||||
Str("pbs", pbs.Name).
|
||||
Msg("PBS offline alert cleared (alerts disabled)")
|
||||
Msg("PBS offline alert cleared (connectivity alerts disabled)")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
+16
-2
@@ -40,8 +40,11 @@ pkill -f vite 2>/dev/null
|
||||
pkill -f "npm run dev" 2>/dev/null
|
||||
pkill -f "npm exec" 2>/dev/null
|
||||
|
||||
# Kill Pulse binary (exact match only)
|
||||
# Kill Pulse binary - first try gracefully, then force
|
||||
pkill -x "pulse" 2>/dev/null
|
||||
sleep 1
|
||||
# Force kill if still running
|
||||
pkill -9 -x "pulse" 2>/dev/null
|
||||
|
||||
# Force-kill ANYTHING on our ports
|
||||
kill_port 7655
|
||||
@@ -158,11 +161,22 @@ EOF
|
||||
cleanup() {
|
||||
echo ""
|
||||
echo "Stopping services..."
|
||||
kill $BACKEND_PID 2>/dev/null
|
||||
# Try graceful shutdown first
|
||||
if [ -n "$BACKEND_PID" ] && kill -0 $BACKEND_PID 2>/dev/null; then
|
||||
kill $BACKEND_PID 2>/dev/null
|
||||
sleep 1
|
||||
# Force kill if still running
|
||||
if kill -0 $BACKEND_PID 2>/dev/null; then
|
||||
echo "Backend not responding to SIGTERM, force killing..."
|
||||
kill -9 $BACKEND_PID 2>/dev/null
|
||||
fi
|
||||
fi
|
||||
rm -f vite.config.dev.ts
|
||||
# Clean up any leftover Vite processes
|
||||
pkill -f vite 2>/dev/null
|
||||
pkill -f "npm run dev" 2>/dev/null
|
||||
# Final cleanup of any stuck pulse processes
|
||||
pkill -9 -x "pulse" 2>/dev/null
|
||||
echo "Hot-dev stopped. To restart normal service, run: sudo systemctl start pulse-backend"
|
||||
exit
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user