Skip to content

Feature imagemanager - #684

Merged
al1img merged 54 commits into
developfrom
feature_imagemanager
Nov 6, 2026
Merged

al1img merged 54 commits into
developfrom
feature_imagemanager

Conversation

@al1img

@al1img al1img commented Nov 6, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

Mykola Solianko and others added 30 commits November 6, 2026 15:34
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Add eIntegrity error to the error enum to report integrity issues.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Implement SubscribeListener, UnsubscribeListener and GetItemsStatuses.
GetItemsStatuses appends the stored state of each item version to the
output array. Subscribe and unsubscribe must not be called from a
listener notification callback.

Add unit tests for listener subscription and items statuses.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Implement installing of a single deployable item version in the common
image manager.

The item version is locked for the install, so InstallItem and RemoveItem
of the same version are mutually exclusive. A new item is added to the
storage in the eInstalling state, a stored item is set to eInstalling
and, if it was removed, restored from the outdated items of the space
allocator. The root blob is the image index or the image manifest. The
item blobs are processed starting from it: the manifests, the item and
image configs and the layers.

Each blob is locked while it is processed and is added to the item blob
references before it is validated. A missing or invalid blob is removed,
downloaded with DownloadBlob using the download blob info and validated
again. Its space is allocated before the download, accepted on success
and released on failure. A layer is checked with ValidateLayer first: if
it is valid, the layer blob is not checked. eNotSupported means the layer
is kept as packed blob only. Otherwise the unpacked layer is removed with
RemoveLayer, the layer blob is processed and unpacked with UnpackLayer.

The image path is synced whatever the install result. On success the
item is set to eInstalled, on failure to eFailed with the error. The
eInstalling, eDownloading and the final states are notified to the
listeners, and GetItemsStatuses reports the last notified state of the
item being installed.

Add OCI image index and manifest media types to imagespec.hpp.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Implement removing of a single deployable item version in the common
image manager.

The item version is locked for the removal, so RemoveItem and InstallItem
of the same version are mutually exclusive. RemoveItem fails with
eNotFound if the item version is not stored and does nothing if the item
is already in the eRemoved state. Items in any other state are removed
the same way.

The eRemoving state is notified and reported by GetItemsStatuses while
the item is being removed. Then the item is set to eRemoved with the
current timestamp in the storage, keeping its blobs and blob references,
and eRemoved is notified. If the storage update fails, the previous item
state is notified again with the error. Finally, the item is added as
outdated to the space allocator without the image manager mutex locked.

SetInProgressItemState takes the item ID, version and type instead of
InstallItemInfo, so it is used by both install and remove.

Add unit tests for RemoveItem.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Register outdated items on start and implement the item remover used by
the space allocator to remove them.

On start, the items whose install was interrupted, i.e. left in the
eInstalling state, are set to the eRemoved state, keeping their blobs.
Then all the items in the eRemoved state are added as outdated to the
space allocator. A failure to add an outdated item is only logged. No
item status is notified on start.

The item remover skips the items being installed or removed and the
items which are not in the eRemoved state anymore. It is called with the
space allocator lock held, so it never waits for an item or a blob: it
tries to lock them and skips them if they can't be locked. One extra slot
is reserved in the lists of the items and blobs in progress for it, so
it can lock them while all the other slots are taken. A full list is
logged as an error. The item and its blob references are removed from
the storage first. Then each item blob which is not locked and not used
by other items is removed, together with its unpacked layer data for the
layers. The freed size is returned to the space allocator and
OnItemRemovedFromCache is notified. A blob which fails to be removed is
logged and left as orphan.

Add unit tests for start and the item remover.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Replace LocalBlobInfoProviderItf with ItemInfoProviderItf in a separate
header. Besides GetBlobPath, it provides GetLayerPath to get the path of
an unpacked layer by its diff ID. The common image manager doesn't keep
the unpacked layers, so its GetLayerPath returns eNotSupported. The SM
image manager overrides it.

Rename DownloadBlobInfoProviderItf to BlobInfoProviderItf, as it is the
only blob info provider of the common image manager now.

Update the mocks accordingly and add a unit test for GetLayerPath.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Before a new item version is added to the storage, InstallItem checks
whether the storage is full, i.e. it keeps cMaxNumStoredItems items or
more. While it is full, the oldest outdated item is removed with
RemoveOutdatedItem of the space allocator. If the item remover skips the
item, the next oldest outdated item is removed. If there is no outdated
item to remove, InstallItem fails with eNoMemory before any blob is
downloaded. Any other error of RemoveOutdatedItem is returned as is.

The storage count check, the removal of the outdated items and adding
the item are done under a separate storage mutex, so concurrent installs
don't exceed the storage limit. The item remover never takes this mutex,
so it can be held while the space allocator is called.

Add unit tests for installing items when the storage is full.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Remove the items whose cache TTL is expired, i.e. the items in the
eRemoved state for longer than mItemCacheTTL. The removal is done by a
separate thread on start, after the outdated items are registered, and
then every mRemoveOutdatedPeriod triggered by a timer.

Each expired item is locked without waiting: the items being installed
or removed are skipped and checked again in the next period. The item is
restored from the outdated items of the space allocator, then read again
from the storage, as it could be removed from the cache, installed again
or removed again with a new timestamp after the items are read. Only the
item which is still expired is removed with its unused blobs, the freed
size is released with FreeSpace and OnItemRemovedFromCache is notified.
The item which stays in the eRemoved state is added as outdated again.

The removal of the item and its blobs is shared with the item remover.
The lists of the items and blobs in progress get one more extra slot for
the expired items removal, so it doesn't take the slot of the item
remover. Stop stops the timer and the thread.

Add unit tests for the expired items removal.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Remove the orphan blobs, i.e. the blobs not used by any item, in the
cleanup done by the separate thread on start and every
mRemoveOutdatedPeriod, after the expired items are removed.

The blobs folder is iterated and the digest of each blob is built from
its path. The files which don't match a valid digest are removed. Each
valid blob is locked without waiting: a locked blob is being processed by
an item being installed, so it is skipped. The blob is removed if it is
not used by any item. A blob which fails to be removed is logged and
removed in the next period.

After the orphan blobs, the private virtual RemoveOrphanLayers is called,
so the derived image managers which keep the unpacked layers remove the
orphan ones. Both return the removed size, which is freed in the space
allocator at once, even if an error is returned. The default
RemoveOrphanLayers returns eNotSupported, which is treated as nothing to
do.

Add unit tests for the orphan blobs removal.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Add CancelContext, which is passed to long operations, so that they can
be canceled, similar to the Go context. The operation checks the context
periodically with IsCanceled or Err, or waits on it with Wait instead of
sleeping, e.g. between retries.

Cancel sets the canceled state and wakes up the waiters, calling it on
the canceled context does nothing. Wait returns eCanceled when the
context is canceled, and Wait with timeout returns eTimeout if the
timeout expires before. Reset clears the canceled state, so the context
can be used again when no operation uses it.

As the operation checks the context itself, a cancel which comes before
the operation starts is not lost, unlike canceling the operation by its
ID after it is registered.

Add unit tests for the cancel context.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Cancel cancels all items being installed with a cancel context, which is
passed to DownloadBlob. The download checks the context before it is
started and while it runs, so a cancel which comes before the download is
registered is not lost. CancelDownload is removed, as canceling the
download by its digest can't avoid this race.

InstallItem checks the context before each blob, so a canceled item
doesn't validate, unpack or allocate the space for its next blobs and
doesn't finish successfully if they are already in the cache. The retry
of GetBlobInfo waits on the context, so it is interrupted by Cancel. A
canceled item fails with eCanceled the same way as any other failure.

Cancel doesn't cancel RemoveItem. It waits until all InstallItem and
RemoveItem calls in progress return, the items started while it waits
are canceled as well. Then the context is reset with the image manager
mutex locked, so InstallItem called after Cancel returns is not
affected. Stop calls Cancel before the cleanup is stopped.

Add unit tests for Cancel.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Move ParseDigest from the anonymous namespace to a protected static
member of the common image manager, so the derived image managers can
use it instead of their own digest parsing, for example to build the
unpacked layer paths from a diff ID.

Add a unit test for valid and malformed digests.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Assigning an existing error in the init-statement keeps a call and its
check in one statement. It is a readability preference, not a defect, and
the project uses this form in new code.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Describe the common image manager the same way as the other modules: the
interfaces it implements and requires, item states, configuration, install,
remove and cleanup flows, locking rules and what the derived CM and SM image
managers have to implement.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Mykola Solianko and others added 24 commits November 6, 2026 15:34
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
DatabaseItf lists all storage interfaces the CM database implements.
common::database::Database of aos_core_cpp implements the image manager
storage, which creates a diamond in cm::Database. Inherit StorageItf
virtually to keep a single instance of it: StorageItf is a pure interface
without data. This deviates from MISRA C++:2023 advisory rule 13.1.1.

Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Signed-off-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
ThreadPool::Run returns on the first thread that fails to start, leaving
the already started threads running. A following Run overwrites their
handles, so they can never be joined.

Shut the pool down before returning the error. This requires unlocking
the pool mutex first, so use UniqueLock instead of LockGuard in Run.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
The install thread pool is started in Start and stopped in Stop, so its
threads exist for the whole handler lifetime even when no update is in
progress.

Run and shut down the pool in InstallUpdateItems to allocate the threads
only while update items are being installed.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
InstallUpdateItems installs all items of the desired status, even if they
are already installed or failed.

Get items statuses first and install only items that are missing or not
in installed or failed state. A failed item can be retried only by
removing it first and installing it again.

Update IsUpdateItemsRequired accordingly: a failed item in the desired
status doesn't require an update, and a failed item not in the desired
status does, so it gets removed by the update finalization.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Items left in eInstalling state on start are set to eRemoved, so they can be
removed by the cleanup, while a canceled install sets the item to eFailed
with the eCanceled error.

Handle an interrupted install the same way as a canceled one: set items left
in eInstalling or eDownloading state to eFailed with the eCanceled error on
start and keep their blobs, so the caller can distinguish them from a real
failure and install them again.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
The image manager reports a canceled or interrupted install as eFailed with
the eCanceled error. Such items are skipped by InstallUpdateItems, so an item
interrupted by a new desired status or by a restart is never installed.

Treat eFailed with the eCanceled error as installable in InstallUpdateItems
and IsUpdateItemsRequired. Other failed items are still retried only after
removing them.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
FinalizeUpdate removes items one by one. Remove them in the thread pool used
for the install, which is renamed from mInstallThreadPool to mThreadPool, so
up to cMaxNumConcurrentItems items are removed at the same time.

There can be up to cMaxNumUpdateItems * 2 items to remove, so increase the
pool queue size accordingly. Otherwise the items that don't fit in the queue
are not removed.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
An external module may detect that a stored item is not usable, for example
when the item instances fail, but there is no way to report it to the image
manager.

Add SetItemFail to ItemStatusProviderItf. It sets the item to eFailed with the
provided error and waits while the item version is being processed. It fails
with eNotFound if the version is not stored and with eWrongState if the item
is in eRemoved state.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Instances can fail because of corrupted item blobs, but the update is finished
without trying to repair them.

After waiting for the instances to become active, set an item to eFailed if
at least one of its instances has the eIntegrity error, or if all of them are
failed. If there are items with the eIntegrity error, go to the new eRecovering
state, which installs these items again, and launch all the instances again.
The recovery is performed once per update: if the instances fail again, the
update is finalized and their states are reported.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Integrity recovery needs to distinguish broken file content from other
read failures, but ReadFile returns raw errno values.

Return eIntegrity for EIO and EBADMSG, and eNotFound for ENOENT, any other
errno is returned as is. ReadFileToString gets the same errors. Check for
eNotFound in unit config and node config to detect a missing file. The
previous check compared only the error type, so any errno was treated as a
missing file. Now such errors are reported as failed config.

Also fix two issues in ReadFile:
- the read loop never ended if the file was truncated during the read: stop
  on end of file and return the content that is left;
- the file was closed twice, which could close a descriptor reused by another
  thread: close it only by the deferred release. An error of closing the
  read-only file is not returned anymore.

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Reviewed-by: Mykola Solianko <mykola_solianko@epam.com>
Reviewed-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
The SM uses the blob info and item info providers of the common
image manager instead.

Signed-off-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Signed-off-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Implement the SM image manager on top of the common image manager.
It downloads blobs from the CM and keeps the unpacked layers.

Signed-off-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Use the common item info, item status and blob info providers in the
launcher and smclient, and cancel installed items on launcher stop.
Make ValidateBlob of the common image manager protected for the SM
image manager.

Signed-off-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Signed-off-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
CalculateSize and DirIterator used stat, so symlinks to directories
were traversed, the targets of file symlinks were counted and dangling
symlinks stopped the directory walk. Use lstat to count the links
themselves and return errno on failure.

Signed-off-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
DatabaseItf lists all storage interfaces the SM database implements.
common::database::Database of aos_core_cpp implements the common
image manager storage, which creates a diamond in sm::Database.
Inherit StorageItf virtually to keep a single instance of it:
StorageItf is a pure interface without data. This deviates from
MISRA C++:2023 advisory rule 13.1.1.

Signed-off-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
UpdateInstancesImpl returned on a failed allocation of the remove or
install items after the launch thread pool was started, so the pool
was left running and the next request started it again. Allocate
all buffers before starting the pool.

Signed-off-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
CM image manager registers download files as outdated items using
the blob digest as ID. A sha256 digest is 71 chars, longer than
cIDLen, so assigning it to OutdatedItem::mID triggered the String
assignment assert and aborted CM on start when a leftover download
file was present.

Size the outdated item ID to hold either an item ID or a digest and
return an error instead of asserting when the ID or version doesn't
fit.

Signed-off-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
A component manifest may reference a regular image config without
rootfs instead of the empty config. Installing such an item failed
with "diff ID's size mismatch" as the check required a diff ID for
every layer.

Treat a config without diff IDs as the empty config: its layers are
kept as packed blobs without diff IDs.

Signed-off-by: Mykhailo Lohvynenko <mykhailo_lohvynenko@epam.com>
Reviewed-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
Copilot AI balanced review requested due to automatic review settings November 6, 2026 17:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@al1img
al1img merged commit ccfd25b into develop Nov 6, 2026
10 of 11 checks passed
@al1img
al1img deleted the feature_imagemanager branch November 6, 2026 18:00
@sonarqubecloud

sonarqubecloud Bot commented Nov 6, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
74.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants