Back to home page

EIC code displayed by LXR

 
 

    


Warning, /swf-monitor/docs/HARVESTER_REPORTER.md is written in an unsupported language. File is not indexed.

0001 # Harvester host reporter
0002 
0003 Pilot dispatch capabilities distinguish an image-bound OSG pilot from a
0004 batch pilot that launches each payload in its requested image. A native
0005 `per-job` template is reported as unrestricted only when its environment
0006 enables per-job dispatch and container launching, and its transferred
0007 launcher implements omission of the dispatch-image filter. The bootstrap
0008 image is retained separately in `bootstrap_images`.
0009 
0010 A reporter on each harvester host (pandaharvester01, pandaharvester02, osgsub01), and one for the Perlmutter harvester built from what it reports to the PanDA server (Perlmutter, below), delivers to swf-monitor
0011 what only that host knows about how its queues get work: when the harvester
0012 last asked PanDA for jobs for each queue, how many it asked for and got, and
0013 why it got none; how many workers it submitted and for which jobs; and every
0014 failed call to the PanDA server, by daemon and error class. It follows the
0015 pattern of the PanDA server reporter
0016 ([PANDA_SERVER_REPORTER.md](PANDA_SERVER_REPORTER.md)): a standalone script,
0017 standard library only, local state, a five-minute cron run, HTTPS delivery to
0018 the host-report ingest under a per-host token, read-only with respect to the
0019 harvester.
0020 
0021 It exists because of 2026-10-02. From 14:23 to 18:43 ET the harvester could
0022 not verify the PanDA server's renewed certificate. It fetched no jobs and
0023 sent no updates for any queue it serves, while the queues read only as
0024 "starved" from outside, and the one line that said why, `failed to POST with
0025 SSLError ... CERTIFICATE_VERIFY_FAILED`, sat in a log on a host the monitor
0026 cannot reach. A job that is activated and never fetched has no worker and so
0027 no worker logs; its explanation exists only in the harvester's own logs.
0028 
0029 ## Functions
0030 
0031 Each run posts one record covering the lines appended since the previous
0032 run (the logs are read from the byte position the previous run left; a
0033 rotated log restarts from its beginning and the record says so; the first
0034 run sets the positions and counts nothing).
0035 
0036 | Function | Source on the host | Fields delivered |
0037 |---|---|---|
0038 | Job fetching | `/var/log/harvester/panda-job_fetcher.log` | per queue: fetch attempts, jobs asked for and got, attempts that failed and their error classes in the interval; the last attempt with its time, label, numbers and outcome (`OK`, `No jobs in PanDA`, or the error) |
0039 | Worker submission | `panda-submitter.log` | per queue: workers submitted in the interval, the last worker counts the submitter read (`nQueue`, `nReady`, `nRunning`, `nNewWorkers`), the last job-chunk count; the most recent worker-to-PandaID pairs |
0040 | Worker adjustment | `panda-worker_adjuster.log` | per queue: the waiting-worker limit the adjuster last applied and the activated jobs it was set against, with the time it was logged. Harvester computes the limit from its running workers, so `pq_table`'s `nQueueLimitWorker` is only its cap. The adjuster logs it only in some cycles (half an hour apart on osgsub01, 2026-10-22), so the last value is kept in the reporter's state and delivered every run |
0041 | Calls to the PanDA server | `panda-communicator.log`, `panda-propagator.log` | failed calls in the interval by daemon, call and error class, with the last such line |
0042 | Daemon log freshness | `/var/log/harvester/panda-*.log` | seconds since each log's last write, and its size |
0043 | Harvester processes | the process table | the count of harvester processes |
0044 | Launch limits | the harvester database, `pq_table` | per queue: the queued-worker limit, the maximum workers, the new workers last decided, the last job fetch and submission times |
0045 | Workers now | `work_table` | per site, the live workers by status |
0046 | Workers ended | `work_table` | per site, the workers that ended in the interval by status and the median run of the finished ones |
0047 | Workers not finished | `work_table` and each worker's condor event log | per site, over the last 24 hours, every worker that did not finish or finished with a nonzero batch exit, grouped by the batch system's reason, with up to three examples (worker, batch ID, node, CE, log URL) |
0048 | Service metrics | `sm_table` | the harvester's latest metrics for its host |
0049 
0050 The reason for a worker that did not finish is the last terminal or hold
0051 event of its condor event log (aborted, held, terminated, shadow exception,
0052 disconnected), with its detail lines: "Job was aborted. removed by
0053 SYSTEM_PERIODIC_REMOVE due to job restarted undesirably." The harvester's
0054 own diagnostic carries the remove or hold reason too; the condor log adds
0055 the event, its time and the other terminations (exit codes, signals,
0056 shadow exceptions) the diagnostic does not. The reasons cover the last 24
0057 hours on every run; each worker's reason is read once and kept in the
0058 reporter's state. The log path is the worker's `batchLog` URL mapped to the local log directory
0059 through the queue configuration (`logBaseURL`, `logDir`); a worker without
0060 a readable log falls back to the harvester's diagnostic, and the record
0061 says which source each reason came from. A run reads at most 300 condor
0062 logs, newest first. The database is read through the `mysql` client with
0063 the harvester's own read settings from `panda_harvester.cfg`; nothing is
0064 written to it.
0065 
0066 Times in the harvester logs and database are UTC and are delivered as such. Every source
0067 that cannot be read is a field, never dropped; an unreachable monitor
0068 buffers records locally and posts the backlog on the next run.
0069 
0070 ## Where it shows
0071 
0072 The record is stored by the ingest in the cached-product store under the
0073 host's key. The PanDA queue page shows, for a queue the harvester serves,
0074 its last fetch and its outcome, the interval's fetch and submission counts,
0075 and the last failed call, with the record's age. The job page of a job that
0076 is activated and not yet fetched shows the same last fetch for its queue:
0077 when the harvester last asked, and what it got.
0078 
0079 ## Install
0080 
0081 1. The script at `~/.local/bin/harvester-reporter.py` and its environment
0082    file `~/.swf-harvester-reporter.env` (mode 600, `SWF_MONITOR_URL` and
0083    `SWF_REPORT_TOKEN`); state and buffer in `~/.swf-harvester-reporter/`
0084    for pandaharvester01 and `~/.swf-harvester-reporter-<key>/` for any
0085    other host key. The account's home directory is shared across the SCDF
0086    hosts, so one copy of the script serves every host.
0087 2. The token, of the Django user `pandaharvester01-reporter`, serves both
0088    hosts through the shared environment file.
0089 3. A cron entry for the account on each host, every five minutes. On
0090    osgsub01 the record is stored as `osgsub01-harvester`
0091    (`--report-as osgsub01-harvester`), since `osgsub01` is the OSG submit
0092    reporter's key.
0093 
0094 The reporter also runs on pandaharvester02, the third harvester
0095 instance, under its own host key; everything it reads there is readable
0096 by the account.
0097 
0098 Verified on 2026-10-02 for the account (`wenauseic`, group `eic`): the
0099 harvester logs are world-readable, cron is permitted, the host's `python3`
0100 is 3.6.8, and the monitor answers over HTTPS. No change to the harvester,
0101 its configuration or its submit descriptions is part of installing the
0102 reporter.
0103 
0104 ## Perlmutter
0105 
0106 The harvester `Perlmutter_test_1` serves the NERSC queues from a Perlmutter
0107 login node under PanDA operations' account (distcomp-services
0108 perlmutter-harvester/README.md). Its logs are in that account's scratch,
0109 `/pscratch/sd/x/xin/panda/log`, which the m3763 project cannot read, and its
0110 process table is not reachable. Its record, host key `perlmutter-harvester`,
0111 is built on pandaserver02 from what the harvester reports to the PanDA
0112 server and from its queue configuration, read through the NERSC IRI API
0113 under an m3763 member's token (`swf_epicprod/nersc_iri.py`):
0114 
0115 | Function | Source | Fields delivered |
0116 |---|---|---|
0117 | Heartbeat | `harvester_instances` | `instance`: start, last heartbeat and its age, version |
0118 | Launch limits | `panda_queueconfig.json` through IRI | per queue: the queued-worker limit, ratio, minimum and maximum, the maximum workers, the map type; the new workers last decided (`to_submit` in `harvester_worker_stats`) and the last submission |
0119 | Queue status | `panda_queueconfig.json` through IRI | `queue_status.status`: each queue's `queueStatus` |
0120 | Workers now, started, ended | `harvester_workers` | as the other records, from the workers the harvester reports; a worker not terminal after seven days is not counted live |
0121 | Workers submitted | `harvester_workers` | `submission`: per queue, the workers submitted in the interval |
0122 | Workers not finished | `harvester_workers` | per site over 24 hours, grouped by the harvester's diagnostic |
0123 | Errors | `harvester_dialogs` | `dialogs`: the harvester's ERROR and CRITICAL messages to the PanDA server over 24 hours, per module with the latest, and per kind of message (the message with its numbers set aside) with its count, first and latest (reporter 1.1) |
0124 | Service metrics | `harvester_metrics` | the latest per login node: memory, CPU, scratch use, proxy lifetime |
0125 
0126 Job fetching, the adjuster's applied limit, failed calls and log freshness
0127 come from the logs and are error fields naming why. The queue page shows a
0128 queue each kind of error that names it or names none of the harvester's
0129 queues; a kind that names only another of its queues is not shown there,
0130 so an error on a queue we do not use
0131 (NERSC_Perlmutter_epic, the non-ES queue) does not read as the Event
0132 Service queue's. The Perlmutter queues
0133 run in pull mode (`mapType` NoJob), so their pilots fetch their own jobs
0134 and the harvester fetches none. Every queue there sets no ratio, so the
0135 limit in force is its `nQueueLimitWorker`. The job-demand cache is in the
0136 harvester's own database and does not reach the PanDA server.
0137 
0138 `scripts/perlmutter-harvester-reporter.py` runs every five minutes from the
0139 deployed release under the deployment account's cron and stores the record
0140 through `host_reports.store`, the ingest's write path; `--print` prints it
0141 and stores nothing. The crontab line:
0142 
0143 ```
0144 1-56/5 * * * * bash -lc 'source ~/.env && timeout 240 /opt/swf-monitor/current/.venv/bin/python /opt/swf-monitor/current/scripts/perlmutter-harvester-reporter.py' >> /opt/swf-monitor/shared/logs/perlmutter-harvester-reporter.log 2>&1
0145 ```
0146 `host_reports.HARVESTER_HOSTS` is the one list of harvester records that
0147 every reader takes: the comp snapshot, the queue page, worker admission,
0148 the GREX pilot regulator and the queue registry's drift check.
0149 
0150 ## Related
0151 
0152 - [PANDA_SERVER_REPORTER.md](PANDA_SERVER_REPORTER.md),
0153   [OSG_SUBMIT_REPORTER.md](OSG_SUBMIT_REPORTER.md) — the other host reporters.
0154 - [PRODUCTION_DEPLOYMENT.md](PRODUCTION_DEPLOYMENT.md) § SSL/TLS — the
0155   2026-10-02 certificate outage.
0156 
0157 ## Regulation telemetry, 22 October 2026
0158 
0159 Version 1.3 adds actual worker starts, job-demand cache update times, and the ratio/minimum/maximum fields of the worker limit. OSG reporting runs every minute; other hosts keep their existing cadence.
0160 
0161 ## Admission telemetry
0162 
0163 Version 1.4 separates native OSG exit-73 pre-job refusals and recorded
0164 cancelled SIGTERM stops from unexpected worker errors. Admission telemetry
0165 covers one hour: remaining and required lifetime from launcher stderr,
0166 execution queue and host from startup, exact slot identity and measured
0167 slot-busy/execution seconds from the Condor event log. Repeated refusals are
0168 grouped by slot and admission floor. Up to 4,000 new startup records are read
0169 per run, with parsed evidence cached until it leaves the hour. Missing logs
0170 remain unclassified; evidence coverage is reported.
0171 
0172 The dashboard's slots/hour link opens `/panda/worker-starts/`, which combines
0173 this evidence with a cached worker-start cohort and current payload-job and
0174 worker counts. Recorded worker wall time includes startup and reporting
0175 delay; Condor slot-busy and execution time are stated separately. The page
0176 does not equate worker starts with useful payload capacity or diagnose a
0177 node from admission declines.
0178 
0179 Version 1.5 adds `queue_status`: each queue's `queueStatus` in the harvester queue configuration, the copy the queue registry's drift check compares (swf-epicprod QUEUE_REGISTRY.md).
0180 
0181 Version 1.6 adds `queue_status.pilot_dispatch`, read from each queue's
0182 actual `submitter.templateFile`: native pilots' exact bound image, known
0183 legacy ALRB launchers' dynamic image selection, or an explicit unknown
0184 with its reason. Each reading includes the template path and SHA-256.
0185 The registry's admission check reads this fresh host evidence; unavailable,
0186 unresolved or conflicting image bindings never imply compatibility.
0187 
0188 Version 1.7 follows an image allocator named by the native template's
0189 `EpicprodImagePolicyFile`. It advertises that policy's images only while
0190 the allocator's matching active state is fresh. Missing or expired state
0191 is unknown capability, so a stopped allocator cannot keep authorizing new
0192 work for an image it no longer supplies. The authenticated
0193 `/api/osg-image-demand/?memory_mb=4096&cores=1` read groups activated jobs
0194 by exact image in one query for the two-minute allocator. Disk selection
0195 remains the pilot dispatcher's actual-free-space check; a Condor disk
0196 reservation is not that free-space limit.
0197 
0198 Version 1.8 adds `health.volumes` for `/`, `/var`, `/data`, and `/tmp`:
0199 total and unprivileged available bytes, percent used, and filesystem device
0200 identity. The `host_disk_space` alarm reads these reports alongside the OSG
0201 submit and PanDA server reporters. It warns at 90% used, naming the host,
0202 filesystem and remaining space, before scheduler or log writes fail.
0203 Aliases of the same filesystem are counted once. Missing or stale disk
0204 readings raise a monitoring incident instead of implying recovery.