Full Changelog
Release: v6.5.2
Sprint: v6.5.2
Jira References
-
DEV-1609 - USP > Cpeadmin > update a cpe > ping not working
-
DEV-1745 - OneIoT ACS > USP > Monitoring > Bulk data > MQTT > Activate > Irrelevant object path in SPV task sent
-
DEV-1795 - OneIoT ACS > Group Update > Add USP compatibility for GU Diagnostics as Historical data
-
DEV-1828 - CPE Admin > USP > Group Update > Restore > Incorrect URL is sent to device
-
DEV-1857 - OneIoT ACS > USP > Monitoring > New / Edit > Save and activate > Subscriptions are duplicated
-
DEV-2061 - OneIoT ACS > Docs Portal > Installation & Deployment > "5.2. Docker Compose File" > Expand "compose.yml" example > Absent "TZ" environment variable
-
DEV-2117 - QoE GUI > Group update with Diagnostics > Diagnostic data present in QoE DB > Single device > No data available in table
-
DEV-2123 - Angular Project > Several devices > Management portal > Group update with Download / Upload diagnostics > "Add results to monitoring data" = "1" > Not all results are stored into CH DB
-
DEV-2131 - Angular Project > Several devices > Management portal > Group update with Download / Upload diagnostics > "Add results to monitoring data" = "1" > Data is not stored in the CH DB
-
DEV-2196 - OneIoT ACS > TR-069 > Any event from device > Prometheus metrics endpoint > Event distribution counter > No counter value
-
DEV-2209 - Angular Project > Support Portal > TR-098 > "Ports" cube > Edit > Add any port > "Request device to connect" = true > Device activity > Parameter name is empty for "Add object" task
-
DEV-2212 - Angular Project > TR-069 > Initiate Connection Request > Connection Request is not performed
-
DEV-2222 - OneIoT ACS > Multi-domain / Multi-ISP > Specific profile in super domain > Default profile in specific domain > Device related to specific domain > Specific profile related to super domain applied
-
DEV-2249 - OneIoT ACS > Big amount of devices > Update group > More than one diagnostic > "8 DIAGNOSTICS COMPLETE" event > Next diagnostic task stucked
-
DEV-2269 - CPE Admin > Device Update > Trace a Device > Start > Open device > Trace not active
-
DEV-2270 - OneIoT ACS > Oracle > Monitoring > "QoE: set periodic inform interval" task is not sent to the device
-
DEV-2286 - OneIoT ACS > Update group > More than one diagnostic > Add results to monitoring data="1" > "8 DIAGNOSTICS COMPLETE" event > Event absent from DB table
-
DEV-2307 - OneIoT ACS > Run > Error in server log file is present
-
DEV-2349 - OneIoT ACS > Monitoring > Device brings monitored value > Events from device stored in DB
-
DEV-539 - OneIoT ACS > USP > Group Update > Upload > Vendor Configuration File > Incorrect file format
-
DEV-688 - OneIoT ACS > MySQL > Management Portal > Monitoring > Active monitor > Add parameter > Save > Stop and start monitoring-related tasks are generated for all parameters
-
DEV-775 - OneIoT ACS > TR-069 / USP > Device Update > File Download > 7 TRANSFER COMPLETE > List of tasks disappears
-
DEV-893 - sensitive_params.xml placement
Features
-
Add dataStoreExclusionModels ACS setting to exclude old devices deletion with selected product classes and/or OUIs.
-
Added doNotDeletePreprovisionedDevices ACS setting to skip preprovisioned devices during old data deletion.
Bug Fixes
-
correct undefined variable in basic auth password check
Reference storedPassword instead of the nonexistent stored variable that broke compilation of tr069-http.
-
use storedPassword in BASIC auth comparison
_authenticateBasic referenced an undefined variable `stored` instead of the in-scope local `storedPassword`, failing compilation of tr069-http. Compare the decrypted stored password to the provided plaintext one.
-
set misfire instructions on UpdateGroup start triggers
In a clustered Quartz scheduler the UpdateGroup start triggers were created without an explicit misfire instruction, unlike the activate trigger which already sets MISFIRE_INSTRUCTION_DO_NOTHING. When a start trigger missed its scheduled fire-time (aggravated by a 60s batchTriggerAcquisitionFireAheadTimeWindow), the cluster MisfireHandler recovered it with smart policy (FIRE_ONCE_NOW) on another node, starting the whole UpdateGroup a second time within seconds of the on-time fire. Every CPE was re-activated, so a chained multi-diagnostic update group (IPPing -> Download -> Upload, "Add results to monitoring data") ran the full diagnostic chain twice and its tasks were duplicated. The "already running" guard does not help because the first activation finishes before the misfire re-fire. Mirror createActivateTrigger: the cron reactivation start trigger now uses MISFIRE_INSTRUCTION_DO_NOTHING (skip the missed occurrence) and the one-shot scheduled start trigger uses MISFIRE_INSTRUCTION_FIRE_NOW (fire exactly once, never duplicate, never drop the only activation).
-
move UG completion gate to authoritative cpe_pending_task DB query
In a chained multi-diagnostic update group (IPPing -> Download -> Upload, "Add results to monitoring data"), part of the CPEs stayed Pending in ug_cpe_completed even though cpe_pending_task had no rows left for them. onTaskResult decided "this CPE finished the UG transaction" via CpeTaskProcessor.isExistsSameTransactionTasksForCpe, which prefers a node-local in-memory cache kept consistent only for tasks completed on the same node. The diagnostic chain hops between ACS nodes across QoE sessions, so the node finishing the last diagnostic held a stale cache listing sibling tasks completed elsewhere -> false-positive "tasks still exist", addCpeToQueue skipped, CPE never moved to Completed. Gate the decision on pendingTaskDao.isExistsSameTransactionTasksForCpe giving the only correct cross-node view. The in-memory cache stays as an optimization for next-task selection but is no longer trusted for the cross-node completion gate.
-
log Inform events to cpe_log for QoE sessions
cpe_log rows for Inform events are written by FTACSInformAop.onInit, a @Before advice on synchronizeInformWithDB. A QoE session never reaches that method: TR069ManagementProcessor early-returns on qoeSession=true before tr069ResponseHandler.handle(Inform) runs, so the "8 DIAGNOSTICS COMPLETE" event (and any other event a QoE-session Inform carries) was never stored in cpe_log - visible e.g. for an "Add results to monitoring data" group update. Add CpeLogEventWriter and call it from the QoE-session branch before the early-return, so the Inform's events are logged exactly when the regular path (and its AOP advice) is skipped. Non-QoE Informs keep logging through the advice, so there is no double write. The VALUE CHANGE -> changed-parameter linkage is intentionally omitted: it belongs to the synchronizeInformWithDB flow, which a QoE session does not run.
-
send next chained diagnostic when 8 DC finalizes on GPV pass
A QoE-monitored CPE that reports "8 DIAGNOSTICS COMPLETE" runs a QoE session, so TR069ManagementProcessor skips the regular ACS task chain and the next chained DiagnosticUpdateGroup task is not sent until a Connection Request or the next ACS-session window (up to 24h) - the chain appeared stuck. For diagnostics whose values are not inline in the 8 DC Inform (IPPing, Upload report only DiagnosticsState; the values arrive via a follow-up GPV) the in-flight task finalizes only on the GPV-response pass, after handleInform already latched qoeSession=true. Clear qoeSession on that pass once the diagnostic is finalized so the next chained diagnostic is sent in the same session. That clearing check (and the inline path at handleInform) read isAcsSessionTime() right after nextSessionOnAcs() writes it, so switch that write from IMap.setAsync to a synchronous IMap.set: setAsync gave no happens-before guarantee and the immediate read-after-write saw the stale future timestamp under cluster/load.
-
send next chained diagnostic in the 8 DC session (DEV-2249)
After v3 fixed completion of the in-flight DiagnosticUpdateGroup task, the next chained diagnostic (IPPing -> Download -> Upload) still was not sent after "8 DIAGNOSTICS COMPLETE": for a QoE-monitored CPE that Inform is a QoE session (qoeSession=true) and TR069ManagementProcessor skips the regular ACS task chain, so the next type-66 task stays in cpe_pending_task until a manual Connection Request or the next ACS-session window (qoeMonitorCpeSyncDuration, default 1440 min = 24h). Confirmed on a single-device trace + cluster ACS checkDiagnosticComplete runs BEFORE setQoeSession on the Inform pass, and the 8 DC result is inline, so forcing the ACS session right after completing the diagnostic makes isAcsSessionTime() true -> qoeSession=false -> the next chained diagnostic is sent in the same session, with no manual CR and no 24h wait. Mirrors the existing WiFi-rescan path (nextSessionOnAcs).
-
resolve diagnostic task ids via ActionSetParamValueDao (DEV-2249)
The identity match that completes the in-flight DiagnosticUpdateGroup task (so
the next chained diagnostic can be sent) resolved the task-name ids via
cpeProvisionDao.getByIds (cpe_provision) using CPEProvision.getCPEParameterNameId.
Wrong table: a DiagnosticUpdateGroup (type 66) task name carries
ug_set_param_value ids, which UpdateGroupSetValueMessageCreator resolves via
ActionSetParamValueDao.getByIds -> ActionSetParamValue.getNameId. The
cpe_provision lookup matched nothing, so no task was completed, the in-flight
diagnostic stayed in cpe_pending_task, and CpeTaskProcessor.resolveRejected
skipped every subsequent diagnostic ("existing not finished diagnostic").
Deterministic, reproduced single-device with "Add to monitoring data=1"
(monitoring=0 is unaffected: it never routes completion through this path).
Switch resolveSetParamValueNameIds to the already-injected actionSetParamValueDao
-> ActionSetParamValue.getId()/getNameId(), mirroring the message creator. Update
the unit test to mock ActionSetParamValueDao (the previous mock hid the bug).
Identity-match algorithm, finalization gate and IPLayerCapacity exclusion
unchanged.
-
match in-flight diagnostic task by parameter identity (DEV-2249)
The "8 DIAGNOSTICS COMPLETE" cleanup identified the in-flight DiagnosticUpdateGroup task by confirmed=1, falling back to the oldest non-completed type-66 task. Under load / cross-node the confirmed and repeats flags are committed in a separate transaction on the SPV-response node, so the confirmed lookup lost the race (task stuck) while the oldest fallback completed the next, not-yet-sent diagnostic (silent drop, e.g. Download in IPPing -> Download -> Upload). Match the task to the diagnostic that actually finished, by that diagnostic's own <root>DiagnosticsState parameter name id (fixed at task creation, so it is immune to the async flags and visible cross-node). Gate completion on finalization (process*Diag queued no result GPV-fetch this pass) so the Inform + GPV-response double pass cannot complete a later round's task. Resolve all candidate tasks' provision name ids in a single batched getByIds.
-
DEV-2249
Harden the chained-UG diagnostic-complete cleanup so an unguarded IPLayerCapacity re-report can no longer complete a not-yet-sent DiagnosticUpdateGroup task (silent diagnostic skip / data loss). checkDiagnosticComplete now separates containsGuardedDiag (the five pending-cache-backed process*Diag: Download/Upload/UdpEcho/Trace/Ping, each of which proves an in-flight type-66 task exists) from the unguarded processIPLayerCapacityDiag, and passes it to resolveInFlightDiagnosticTasksToComplete(cpeId, allowOldestFallback). The confirmed=1 branch runs unconditionally (unchanged); the oldest-id fallback runs only for a guarded completion. IPLayerCapacity-only events keep the pre-DEV-2249 confirmed-only behaviour, so there is no regression and no stranding (IPLayerCapacity re-reports on every periodic Inform, so a genuine in-flight task still completes via the confirmed=1 branch). The repeats>0 filter was rejected (repeats is also written async, ~2s, which would reopen the race). Adds 2 boundary unit tests: oldest=not-yet-sent must not fall back, and a confirmed task is still completed on an unguarded trigger.
-
persist ACS parameters via AcsConfigurationCache
removeFromExclusionModels called the removed file-based method DMConfigurationInitializer.setConfigurationParameterValue, which broke the ftdm-core compilation after the migration to ft-configs-service. The ACS parameter write is moved into a shared AcsConfigurationCache — the single write point for the acs-configuration Hazelcast snapshot. The snapshot is updated via set(0, ...), mirroring IListCacheWriter.replaceSnapshot in ft-configs-service: an atomic in-place replace, so the list is never empty. The same event is consumed by FTIOTConfigurationSyncUtil (runtime parameters on each node) and by AcsConfigurationCacheListener in ft-configs-service (DB write-back). Reused in WSSystemService and FTCpeProductService. Snapshot writes are logged (key, mode, entry count); sensitive values (password/secret/token/credential keys) are masked.
-
DEV-2212
-
Fix an issue that caused the default autoDeleteCron value to be used instead of the configured one.
-
Do not ignore password’s case in Basic authentication.
-
Fix flow for device in the blocked list (blockedModelList ACS setting).
-
DEV-1828 OneIoT ACS > USP > Group Update > Restore > discover VendorConfigFile instance via USP GET
Replace the cache-only instance lookup with an async utility discoverObjectInstance(clientId, cpeId, prefix, onResult, onError) in AbstractUspTaskProcessor: tries the local parameter cache first; on a miss, issues a USP GET against the object prefix, back-fills the cache from the response, and extracts the lowest instance. Falls back to 0 (DEFAULT_INSTANCE_FALLBACK) only when both cache and GET yield nothing, matching the existing backupConfiguration/uploadLogFile defaults. Restore (UspRestoreCpeConfigurationTaskProcessor, AbstractUspDownloadTaskProcessor) and Backup/UploadLog (AbstractUploadTaskProcessor) all now route through the utility, so a freshly-registered device with no cached Device.DeviceInfo.VendorConfigFile.* parameters no longer falls through to a hard-coded instance 1 and triggers "Command not defined" (err 7026). Also lowers the legacy fallback in UspCommsService.getFileObjectInstanceNumber from 1 to 0 so any caller that bypasses the utility stays consistent with the rest of the file-transfer surface.
Documentation
-
update antora version to 6.5.2
-
document readonly registry credentials for docker login
Replace the <your-username>/<your-password> placeholders in the Docker registry authentication section with the actual read-only pull account (username: readonly), so users can authenticate against hub.friendly-tech.com and pull the published images. The account is pull-only and cannot push.
-
add TZ to mysql service in compose.yml example
The mysql service was the only one in the stack without timezone propagation (no env_file, no explicit TZ), leaving the container in UTC while the rest of the stack runs in Europe/Kiev. The mismatch causes drift between DB and application timestamps.
-
update antora version to 6.5.2 (dev)
Refactoring
-
use shared ProductClassGroupCacheDto for qoeProductClassGroupCache
Replace the internal ProductClassGroupExtended shadow class with the shared-dto ProductClassGroupCacheDto across all usages so the Hazelcast qoeProductClassGroupCache stores the common DTO and ft-configs-service can read it without a shadow class. Construction now goes through the DTO builder since it has no public no-arg or two-arg constructor. Add the shared-dto dependency (and its resolving repositories) to ftapp-core and qoe-streaming-core, which now reference the DTO directly. Drop the obsolete AcsProductModelsPublisher that duplicated the catalog into a separate IList; the IMap is read directly instead. Resolve model-level dataStoreExclusionModels tokens (OUI|model|protocol, protocol optional) to product_class.id(s) via the DAOs in FTCpeDeleteTaskJob, so exclusions work before any device has connected. This changes the IMap value type, so existing cache data is incompatible and the deployment must start with a fresh Hazelcast.
-
address DEV-1828 review feedback
HIGH-1 AbstractUspDownloadTaskProcessor.runRestore: stop mutating the shared TransferFile returned by findFile() inside the async lambda and build a fresh instance via the builder, mirroring what UspRestoreCpeConfigurationTaskProcessor already does. Eliminates a latent data race when concurrent restores share a cached DAO object. HIGH-3 AbstractUspDownloadTaskProcessor.runRestore: bring the VENDOR_CONFIG_FILE_3 path to parity with UspRestoreCpeConfigurationTaskProcessor by filling targetFileName from FileBackupProcessor.getCpeFileName when the caller did not supply one, and by appending the same filename to the URL when the caller's URL lacks a file extension. Mirrors the same logic in AbstractUploadTaskProcessor, ensuring symmetric handling between the group-update Download (file type 3) and the dedicated Restore task types. MEDIUM-1 UspCommsService.getFileObjectInstanceNumber: drop the legacy NumberUtils.isParsable(targetFileName) branch. With every caller now routed through AbstractUspTaskProcessor.discoverObjectInstance, the target filename is always a real .cfg name and never a numeric instance id, so the parsing branch was dead. Method is reduced to the early return + a single warning + a default of 0, consistent with backupConfiguration / uploadLogFile. Removes the now-unused NumberUtils import. MEDIUM-6 AbstractUspTaskProcessor.extractLowestInstance: pre-compile the two known instance-extraction patterns into a static Map keyed by prefix; only fall back to on-the-fly compile for unknown prefixes.