Skip to content

Add WSLCVolumes class to track volumes with Docker event-driven synchronization#40300

Open
kvega005 wants to merge 17 commits intomicrosoft:feature/wsl-for-appsfrom
kvega005:WslcVolumesManager
Open

Add WSLCVolumes class to track volumes with Docker event-driven synchronization#40300
kvega005 wants to merge 17 commits intomicrosoft:feature/wsl-for-appsfrom
kvega005:WslcVolumesManager

Conversation

@kvega005
Copy link
Copy Markdown

Summary of the Pull Request

Refactors WSLC volume management into a dedicated WSLCVolumes class and replaces the old ContainerEventTracker with a broader DockerEventTracker that tracks both container and volume lifecycle events.

PR Checklist

  • Closes: Link to issue #xxx
  • Communication: I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
  • Tests: Added/updated if needed and all pass
  • Localization: All end user facing strings can be localized
  • Dev docs: Added/updated if needed
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

Validation Steps Performed

Copilot AI review requested due to automatic review settings April 24, 2026 00:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors WSLC volume management into a new WSLCVolumes component and broadens Docker event handling by replacing ContainerEventTracker with DockerEventTracker, enabling event-driven synchronization for both containers and volumes.

Changes:

  • Introduces WSLCVolumes to own volume recovery, tracking, and COM-facing volume operations.
  • Replaces ContainerEventTracker with DockerEventTracker, adding volume lifecycle event handling and “wait for create/destroy event” helpers.
  • Updates container volume behavior/tests to allow Docker to auto-create missing named volumes and to validate anonymous volume cleanup via the new tracking.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp Updates E2E expectation: named volume is auto-created and removable.
test/windows/WSLCTests.cpp Switches anonymous volume listing/cleanup logic to use ListVolumes() and event-driven waits.
src/windows/wslcsession/WSLCVolumes.h Adds new volume-tracking class interface.
src/windows/wslcsession/WSLCVolumes.cpp Implements volume recovery, event callbacks, and volume CRUD/inspect/list.
src/windows/wslcsession/WSLCVhdVolume.h Marks OnDeleted() as override to match new base hook.
src/windows/wslcsession/WSLCSession.h Replaces raw volume maps/locks with std::optional<WSLCVolumes> and swaps in DockerEventTracker.
src/windows/wslcsession/WSLCSession.cpp Wires up WSLCVolumes + DockerEventTracker; routes volume COM methods through WSLCVolumes.
src/windows/wslcsession/WSLCProcessControl.h / .cpp Updates process controls to use DockerEventTracker references.
src/windows/wslcsession/WSLCGuestVolume.cpp Removes WSLC metadata label dependency for guest volumes; opens from Docker fields directly.
src/windows/wslcsession/WSLCContainer.h / .cpp Removes session-side named-volume existence checks; adds waits for Docker create/destroy events.
src/windows/wslcsession/IWSLCVolume.h Adds OnDeleted() hook for “Docker already destroyed the volume” cleanup.
src/windows/wslcsession/DockerHTTPClient.h / .cpp Adds InspectVolume() endpoint wrapper.
src/windows/wslcsession/DockerEventTracker.h / .cpp New tracker for container+volume events and object create/destroy waiting.
src/windows/wslcsession/ContainerEventTracker.h / .cpp Removes the old container-only event tracker.
src/windows/wslcsession/CMakeLists.txt Updates build inputs for new/removed tracker and new WSLCVolumes.
src/windows/inc/docker_schema.h Extends InspectContainer schema to include Mounts.

Comment thread src/windows/wslcsession/DockerEventTracker.cpp Outdated
Comment thread src/windows/wslcsession/DockerEventTracker.h
Comment thread src/windows/wslcsession/WSLCSession.cpp
Comment thread src/windows/wslcsession/WSLCVolumes.h Outdated
Comment thread test/windows/WSLCTests.cpp
Comment thread src/windows/wslcsession/WSLCVolumes.cpp Outdated
Comment thread src/windows/wslcsession/WSLCVolumes.cpp Outdated
Copilot AI review requested due to automatic review settings April 24, 2026 03:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.

Comment thread src/windows/wslcsession/WSLCVolumes.cpp
Comment thread src/windows/wslcsession/DockerEventTracker.cpp
Comment thread src/windows/wslcsession/DockerEventTracker.cpp
Comment thread src/windows/wslcsession/DockerEventTracker.h Outdated
kvega005 and others added 3 commits April 24, 2026 00:48
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Copilot AI review requested due to automatic review settings April 24, 2026 21:16
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 8 comments.

Comment thread src/windows/wslcsession/DockerEventTracker.h
Comment thread src/windows/wslcsession/DockerEventTracker.cpp
Comment thread src/windows/wslcsession/DockerEventTracker.cpp
Comment thread src/windows/wslcsession/WSLCGuestVolume.cpp
Comment thread src/windows/wslcsession/WSLCVolumes.cpp Outdated
Comment thread src/windows/wslcsession/WSLCSession.cpp
Comment thread src/windows/wslcsession/WSLCVolumes.cpp Outdated
Comment thread src/windows/wslcsession/WSLCContainer.cpp
kvega005 and others added 2 commits April 24, 2026 14:44
Copilot AI review requested due to automatic review settings April 24, 2026 21:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 6 comments.

Comment thread src/windows/wslcsession/DockerEventTracker.cpp
Comment thread src/windows/wslcsession/WSLCSession.cpp
Comment thread src/windows/wslcsession/WSLCGuestVolume.cpp
Comment thread test/windows/WSLCTests.cpp
Comment thread test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp
Comment thread src/windows/wslcsession/DockerEventTracker.cpp Outdated
kvega005 and others added 3 commits April 24, 2026 22:47
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 25, 2026 06:23
@kvega005 kvega005 marked this pull request as ready for review April 25, 2026 06:24
@kvega005 kvega005 requested a review from a team as a code owner April 25, 2026 06:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.

Comment on lines +1408 to +1421
// Validate that all named volumes mounted by the container were successfully recovered
// by the volumes manager. If any are missing (e.g. backing VHD removed while the service was
// down), refuse to open the container so it cannot enter a broken state.
for (const auto& mount : dockerContainer.Mounts)
{
if (mount.Type == "volume" && !mount.Name.empty())
{
THROW_HR_IF_MSG(
E_INVALIDARG,
!volumes.ContainsVolume(mount.Name),
"Cannot open container %hs: referenced volume '%hs' is not available",
dockerContainer.Id.c_str(),
mount.Name.c_str());
}
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

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

Container recovery now hard-fails if any mounted volume name isn’t present in WSLCVolumes. Given WSLCVolumes currently only tracks volumes it can successfully Open(), this can break recovery for containers that reference valid Docker volumes that WSLC chooses not to track (or failed to open due to stricter validation). Either ensure WSLCVolumes reliably tracks all volume mounts a container might reference (including non-WSLC local volumes), or scope this check to WSLC-managed volumes only (e.g., only enforce for volumes with the WSLC metadata label / VHD driver), and return a user-facing error (localized) when the check fails so callers don’t just get E_INVALIDARG.

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +64
if (vol.Labels.has_value() && vol.Labels->contains(WSLCVolumeMetadataLabel))
{
auto metadata = wsl::shared::FromJson<WSLCVolumeMetadata>(vol.Labels->at(WSLCVolumeMetadataLabel).c_str());

if (metadata.Driver == WSLCVhdVolumeDriver)
{
m_volumes.insert({vol.Name, WSLCVhdVolumeImpl::Open(vol, m_virtualMachine, m_dockerClient)});
return;
}
}

m_volumes.insert({vol.Name, WSLCGuestVolumeImpl::Open(vol, m_dockerClient)});
}
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

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

WSLCVolumes::OpenVolumeExclusiveLockHeld treats any volume with a WSLC metadata label but an unrecognized metadata.Driver as a guest volume (falls through to WSLCGuestVolumeImpl::Open). This can silently mis-handle future/unknown WSLC drivers and potentially leak host-side resources (e.g., if a new driver needs cleanup). Consider explicitly handling only the known drivers (vhd/guest) and skipping/logging unknown metadata.Driver values instead of defaulting to guest.

Copilot uses AI. Check for mistakes.
Comment on lines +1986 to +1992
// Clean up any leaked anonymous volumes when this block exits.
auto volumeCleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() {
auto volumes = listAnonymousVolumes();
for (const auto& name : volumes)
{
LOG_IF_FAILED(m_defaultSession->DeleteVolume(name.c_str()));
}
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

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

This cleanup scope deletes every volume returned by listAnonymousVolumes(), which currently includes all volumes with Driver == "guest". If the session contains other guest volumes (named volumes created by other tests), this cleanup will remove them and can cascade into unrelated failures. Tighten the selection criteria (e.g., track the specific volume names created during this test, or filter on Docker’s anonymous label).

Copilot uses AI. Check for mistakes.
Comment on lines 88 to 102
std::unique_ptr<WSLCGuestVolumeImpl> WSLCGuestVolumeImpl::Open(const wsl::windows::common::docker_schema::Volume& Volume, DockerHTTPClient& DockerClient)
{
THROW_HR_IF(E_INVALIDARG, !Volume.Labels.has_value());

auto metadataIt = Volume.Labels->find(WSLCVolumeMetadataLabel);
THROW_HR_IF(E_INVALIDARG, metadataIt == Volume.Labels->end());

auto metadata = wsl::shared::FromJson<WSLCVolumeMetadata>(metadataIt->second.c_str());
THROW_HR_IF(E_INVALIDARG, metadata.Driver != WSLCGuestVolumeDriver);

THROW_HR_IF(E_INVALIDARG, Volume.Driver != "local");

if (Volume.Options.has_value())
{
ValidateDriverOpts(Volume.Options.value());
}

// Extract user labels (all labels except our internal metadata label).
std::map<std::string, std::string> userLabels;
for (const auto& [key, value] : *Volume.Labels)
{
if (key != WSLCVolumeMetadataLabel)
{
userLabels[key] = value;
}
}

auto volume = std::make_unique<WSLCGuestVolumeImpl>(
std::string{Volume.Name}, std::string{Volume.CreatedAt}, std::move(metadata.DriverOpts), std::move(userLabels), DockerClient);
std::map<std::string, std::string> driverOpts = Volume.Options.value_or(std::map<std::string, std::string>{});
std::map<std::string, std::string> labels = Volume.Labels.value_or(std::map<std::string, std::string>{});

return volume;
return std::make_unique<WSLCGuestVolumeImpl>(
std::string{Volume.Name}, std::string{Volume.CreatedAt}, std::move(driverOpts), std::move(labels), DockerClient);
}
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

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

WSLCGuestVolumeImpl::Open now accepts any Docker "local" volume (no WSLC metadata required) and still enforces ValidateDriverOpts (only empty or type=tmpfs). This means non-WSLC local volumes created with common options (e.g. type=none,o=bind,device=...) will fail to open, causing WSLCVolumes recovery to skip them and later container recovery to fail when checking ContainsVolume(). Consider distinguishing WSLC-managed guest volumes from arbitrary Docker volumes (e.g. keep a WSLC metadata/label for guest volumes, or relax validation for volumes without WSLC labels, or track unknown volumes with a minimal implementation that doesn’t enforce WSLC-specific constraints).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants