Shadow task fixes, asset link ids, backup verdict
This commit is contained in:
@@ -955,9 +955,12 @@ def _asset_facts(hostnames):
|
||||
'mapx': asset.mapx,
|
||||
'mapy': asset.mapy,
|
||||
'machinenumber': None, 'machineassetid': None,
|
||||
'machinepluginid': None,
|
||||
'toolassetnumber': None, 'toolassetid': None,
|
||||
'toolpluginid': None,
|
||||
'displayrole': None,
|
||||
'backupkind': None, 'backuplastseen': None,
|
||||
'backuplastseenat': None,
|
||||
}
|
||||
|
||||
_attach_controlled_assets(facts, assetidtohost)
|
||||
@@ -993,11 +996,24 @@ def _attach_controlled_assets(facts, assetidtohost):
|
||||
AssetRelationship.sourceassetid.in_(assetidtohost))
|
||||
.all())
|
||||
|
||||
toolassetids = set()
|
||||
# assetid -> the PLUGIN extension id the detail routes key on. /machines/:id
|
||||
# and /measuringtools/:id take machineid / measuringtoolid, NOT the core
|
||||
# assetid; linking with the assetid lands on whichever record happens to
|
||||
# share that number, which looks plausible and is wrong. Frontend
|
||||
# getAssetRoute resolves the same way.
|
||||
toolids = {}
|
||||
try:
|
||||
from plugins.measuringtools.models import MeasuringTool
|
||||
toolassetids = {row.assetid for row in
|
||||
MeasuringTool.query.with_entities(MeasuringTool.assetid)}
|
||||
toolids = {row.assetid: row.measuringtoolid for row in
|
||||
MeasuringTool.query.with_entities(
|
||||
MeasuringTool.assetid, MeasuringTool.measuringtoolid)}
|
||||
except ImportError:
|
||||
pass
|
||||
machineids = {}
|
||||
try:
|
||||
from plugins.machines.models import Machine
|
||||
machineids = {row.assetid: row.machineid for row in
|
||||
Machine.query.with_entities(Machine.assetid, Machine.machineid)}
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
@@ -1005,12 +1021,17 @@ def _attach_controlled_assets(facts, assetidtohost):
|
||||
entry = facts.get(assetidtohost.get(sourceassetid))
|
||||
if not entry:
|
||||
continue
|
||||
if asset.assetid in toolassetids:
|
||||
if asset.assetid in toolids:
|
||||
entry['toolassetnumber'] = asset.assetnumber
|
||||
entry['toolassetid'] = asset.assetid
|
||||
entry['toolpluginid'] = toolids.get(asset.assetid)
|
||||
else:
|
||||
entry['machinenumber'] = asset.assetnumber
|
||||
entry['machineassetid'] = asset.assetid
|
||||
# None when the machines plugin is not installed or the asset has no
|
||||
# extension row: the frontend then renders the number without a link
|
||||
# rather than a link that goes somewhere wrong.
|
||||
entry['machinepluginid'] = machineids.get(asset.assetid)
|
||||
|
||||
|
||||
def _attach_display_roles(facts, hostnames):
|
||||
@@ -1059,6 +1080,51 @@ def _attach_backup_state(facts, hostnames):
|
||||
entry['backuplastseen'] = (
|
||||
revision.lastseenat.isoformat() + 'Z'
|
||||
if revision.lastseenat else None)
|
||||
# Raw value kept beside the wire string so the verdict compares
|
||||
# datetimes rather than re-parsing its own output.
|
||||
entry['backuplastseenat'] = revision.lastseenat
|
||||
|
||||
|
||||
def _backup_ok(lastseenat, cutoff):
|
||||
"""Tri-state verdict for one PC's backup: True good, False stale, None unknown.
|
||||
|
||||
A BOOLEAN rather than a date, because the question is "is this backed up?"
|
||||
and every backup kind answers it the same way. Adding a new kind needs no
|
||||
change here - it reports a revision like the others and inherits the badge.
|
||||
|
||||
None means there is nothing to judge: no backup revision for this host at
|
||||
all, or the staleness check is disabled. The caller shows no badge rather
|
||||
than a green one, since "never seen" must not read as healthy.
|
||||
"""
|
||||
if cutoff is None or lastseenat is None:
|
||||
return None
|
||||
return lastseenat >= cutoff
|
||||
|
||||
|
||||
def _backup_stale_cutoff():
|
||||
"""(cutoff datetime, threshold days) for 'this PC's backup has gone quiet'.
|
||||
|
||||
A raw date makes the reader do the arithmetic, and the arithmetic is not
|
||||
obvious: the collector only ATTEMPTS every backups_intervalhours (24 by
|
||||
default), so a confirmation from yesterday is the healthy steady state, not
|
||||
a warning. What answers the question is the verdict.
|
||||
|
||||
The threshold is the backups plugin's own backups_staledays, read through
|
||||
its service so there is ONE definition of stale rather than a second one
|
||||
drifting here. Returns (None, 0) when the plugin is absent or the check is
|
||||
disabled, and callers then show the date alone.
|
||||
"""
|
||||
try:
|
||||
from plugins.backups.services import staleness
|
||||
except ImportError:
|
||||
return None, 0
|
||||
try:
|
||||
days = int(staleness.staledays())
|
||||
except (TypeError, ValueError):
|
||||
return None, 0
|
||||
if days <= 0:
|
||||
return None, 0
|
||||
return service._utcnow() - timedelta(days=days), days
|
||||
|
||||
|
||||
def _report_stale_cutoff():
|
||||
@@ -1108,6 +1174,7 @@ def list_reports():
|
||||
if report.hostname})
|
||||
|
||||
stalecutoff, stalafter = _report_stale_cutoff()
|
||||
backupcutoff, backupafterdays = _backup_stale_cutoff()
|
||||
latest_cache = {}
|
||||
data = []
|
||||
for report in reports:
|
||||
@@ -1142,13 +1209,23 @@ def list_reports():
|
||||
'mapy': known.get('mapy'),
|
||||
'machinenumber': known.get('machinenumber'),
|
||||
'machineassetid': known.get('machineassetid'),
|
||||
'machinepluginid': known.get('machinepluginid'),
|
||||
'toolassetnumber': known.get('toolassetnumber'),
|
||||
'toolassetid': known.get('toolassetid'),
|
||||
'toolpluginid': known.get('toolpluginid'),
|
||||
# Reported by the device wins; the DashboardDefault mapping is a
|
||||
# fallback for hosts on an older client that does not send it.
|
||||
'displayrole': report.subtype or known.get('displayrole'),
|
||||
'backupkind': known.get('backupkind'),
|
||||
'backuplastseen': known.get('backuplastseen'),
|
||||
# VERIFIED, not "last backup taken". Dedup means an unchanged config
|
||||
# writes no new revision, so lastseenat is the last time the
|
||||
# collector CHECKED and found the backup intact - which is the
|
||||
# question. backupok says whether that check is recent enough to
|
||||
# trust; the date alone reads as "nothing has happened since", which
|
||||
# is the healthy steady state and looks like neglect.
|
||||
'backupok': _backup_ok(known.get('backuplastseenat'), backupcutoff),
|
||||
'backupstaleafterdays': backupafterdays,
|
||||
'scopename': report.scopename,
|
||||
'phase': report.phase,
|
||||
'appliedversion': report.appliedversion,
|
||||
|
||||
Reference in New Issue
Block a user