Let a share-backed backup say what is in it

This commit is contained in:
2026-08-25 13:52:06 -04:00
parent c7fd00c225
commit f1e265190e
6 changed files with 712 additions and 12 deletions

View File

@@ -279,11 +279,60 @@ class PartMarkerKind(BackupKind):
key = 'partmarker'
displayname = 'Part Marker Configuration'
storagebackend = 'share'
# NO asset panel. The marker's DNC settings are a tab on the single DNC Info
# card, and a separate card that is empty on 145 of 147 machines earns
# nobody anything. The kind is still fully live - it stores, dedupes and
# serves revisions, which are listed on the backup history page.
assettypes = []
# Marker assets are core type 'machine', like the other 144 machines - but
# only a marker ever has a partmarker revision, and the list renderer hides
# a panel with no rows and no empty text. So declaring 'machine' shows the
# panel on markers and nowhere else, with no special-casing.
#
# This was deliberately EMPTY while backups were filed against the operation
# number, when a partmarker card would have appeared on every machine and
# said nothing. Since a marker PC's backup is filed against its own marker
# asset (see markerforsource), the panel has a home of its own.
assettypes = ['machine']
def sharedir(self, machinetype, identifier, shareroot=None):
"""<root>\\partmarker\\<marker asset>\\ - the SITE's layout, which
inverts the base class's <root>\\<machinetype>\\<identifier>\\<kind>.
Overridden rather than left to the default so what ShopDB displays and
validates matches what the collector actually writes. Still advisory:
the authoritative path is the sharepath on each revision, which is what
keeps older snapshots resolvable after a PC swap renames the asset.
Snapshots live in timestamped subdirectories BELOW this - one per
capture, so a pattern deleted from the controller stays recoverable
from the snapshot that still holds it.
"""
root = shareroot or DEFAULTSHAREROOT
if not root:
return ''
return '{}\\{}\\{}'.format(root, self.key, identifier or 'unknown')
def infopanel(self):
"""Contents of the latest snapshot, on the marker's own asset page.
A 'share' kind stores no bytes in ShopDB, so this is built from the
manifest the collector sends alongside the hash. Without it the app
server would have to mount SFLD to say what a snapshot contains, which
the read routes refuse to do on purpose.
"""
return {
'id': 'backups-partmarker-contents',
'title': 'Marker Contents',
'assettypes': ['machine'],
'endpoint': '/api/backups/asset/{assetid}/info?kind=partmarker',
'render': 'keyvalue',
# Above the history panel: "what is on this marker" is the question
# a tech arrives with; the history is for the rarer restore.
'position': 39,
}
def buildinfo(self, projection, assetid, **options):
from . import partmarkerinfo
return partmarkerinfo.build(
projection, assetid,
revisionid=options.get('revisionid'),
sourcehostname=options.get('sourcehostname'))
def resolveassetid(self, payload):
from shopdb.api import db, Asset