Skip to content

Add volume listing and pruning functionality#40457

Draft
kvega005 wants to merge 19 commits into
microsoft:masterfrom
kvega005:VolumeListAndPrune
Draft

Add volume listing and pruning functionality#40457
kvega005 wants to merge 19 commits into
microsoft:masterfrom
kvega005:VolumeListAndPrune

Conversation

@kvega005
Copy link
Copy Markdown
Contributor

@kvega005 kvega005 commented May 7, 2026

Summary of the Pull Request

  • Updated WSLCListVolumesOptions to include filtering options for volume listing, such as driver name, volume name, and labels.
  • Modified ListVolumes method to accept filtering options and return volumes based on specified criteria.
  • Implemented PruneVolumes method in WSLCVolumes to prune unused volumes based on user-defined filters.
  • Enhanced Docker HTTP client to support volume pruning requests.
  • Updated interfaces and implementations across various components to accommodate new volume management features.
  • Added tests to validate the new volume listing and pruning functionalities, ensuring correct behavior with various filters and conditions.

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 May 7, 2026 23:42
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 extends WSLC volume management by adding filterable volume listing and implementing volume pruning via Docker’s /volumes/prune API, with corresponding plumbing through the session/service layers and new test coverage.

Changes:

  • Added WSLCListVolumesOptions + flags and updated ListVolumes to support driver/name/label filters.
  • Implemented PruneVolumes end-to-end (session → volumes layer → Docker HTTP client), returning deleted volume names and reclaimed space.
  • Added/updated Windows tests validating list filters, pruning behavior, and related label-filter handling.

Reviewed changes

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

Show a summary per file
File Description
test/windows/WSLCTests.cpp Adds helpers plus new tests for volume list filtering and pruning; updates label-filter expectations.
src/windows/wslcsession/WSLCVolumes.h Updates ListVolumes signature and introduces PruneVolumesResult / PruneVolumes.
src/windows/wslcsession/WSLCVolumes.cpp Implements filtering logic for listing and a new prune flow that syncs with Docker prune results.
src/windows/wslcsession/WSLCVhdVolume.h Exposes volume labels through the IWSLCVolume interface.
src/windows/wslcsession/WSLCGuestVolume.h Exposes volume labels through the IWSLCVolume interface.
src/windows/wslcsession/IWSLCVolume.h Extends the volume interface with Labels() to support filtering.
src/windows/wslcsession/WSLCSession.h Updates session COM method signatures for volume list/prune.
src/windows/wslcsession/WSLCSession.cpp Wires options through ListVolumes and implements PruneVolumes COM method; tightens label validation.
src/windows/wslcsession/DockerHTTPClient.h Adds prune-volumes filters struct and new PruneVolumes API.
src/windows/wslcsession/DockerHTTPClient.cpp Extends prune filter JSON generation to support all; implements /volumes/prune request.
src/windows/wslc/services/VolumeService.cpp Updates service-side listing call to pass the new optional options pointer.
src/windows/service/inc/wslc.idl Adds list-volume options/flags and changes IWSLCSession method signatures for list/prune volumes.
src/windows/inc/docker_schema.h Adds Docker schema model for volume prune response.

Comment thread src/windows/service/inc/wslc.idl
Comment thread src/windows/wslcsession/WSLCSession.h
Comment thread src/windows/wslcsession/WSLCSession.cpp
Comment thread src/windows/wslcsession/WSLCSession.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 May 8, 2026 00:20
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 13 out of 13 changed files in this pull request and generated 4 comments.

Comment thread src/windows/service/inc/wslc.idl
Comment thread src/windows/service/inc/wslc.idl
Comment thread src/windows/wslcsession/WSLCVolumes.cpp
Comment thread src/windows/wslcsession/IWSLCVolume.h
@kvega005 kvega005 marked this pull request as ready for review May 8, 2026 17:15
@kvega005 kvega005 requested a review from a team as a code owner May 8, 2026 17:15
@kvega005 kvega005 marked this pull request as draft May 8, 2026 18:29
Copilot AI review requested due to automatic review settings May 12, 2026 22:50
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 16 out of 16 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (2)

test/windows/WSLCTests.cpp:4336

  • The new helper ListVolumes() takes a std::multimap<..., optional> of WSLCFilter key/value pairs, but this test calls it with signatures like ListVolumes("vhd"), ListVolumes({}, "vhd"), and ListVolumes({}, {}, {{.Key=..., .Value=...}}). As written, these calls won’t resolve/compile. Either add overloads that build the appropriate WSLCFilter multimap (e.g., { {"driver","vhd"} }, { {"name","vhd"} }, { {"label","env"} }, { {"label","env=prod"} }) or update the call sites to pass the multimap directly.
        // No filter returns every volume.
        VERIFY_ARE_EQUAL(ListVolumes(), all);

        // Filter by driver name.
        VERIFY_ARE_EQUAL(ListVolumes("vhd"), (std::set<std::string>{vhdA, vhdB}));
        VERIFY_ARE_EQUAL(ListVolumes("guest"), (std::set<std::string>{guestA, guestB, otherName, emptyValVol}));
        VERIFY_ARE_EQUAL(ListVolumes("nonexistent"), empty);

        // Filter by volume name (substring match).
        VERIFY_ARE_EQUAL(ListVolumes({}, "vhd"), (std::set<std::string>{vhdA, vhdB}));

        // Anchored regex matches exactly one volume.
        VERIFY_ARE_EQUAL(ListVolumes({}, "^" + vhdA + "$"), std::set<std::string>{vhdA});

        // Regex name filter.
        VERIFY_ARE_EQUAL(ListVolumes({}, "vhd-."), (std::set<std::string>{vhdA, vhdB}));

        // Invalid regex is rejected.
        verifyListVolumesFails(E_INVALIDARG, {{.Key = "name", .Value = "["}});

        // Filter by label key (any value matches): Value = nullptr.
        {
            auto volumes = ListVolumes({}, {}, {{.Key = "env", .Value = nullptr}});
            VERIFY_ARE_EQUAL(volumes, (std::set<std::string>{vhdA, vhdB, guestA, otherName}));
        }

        // Filter by label key=value.
        {
            auto volumes = ListVolumes({}, {}, {{.Key = "env", .Value = "prod"}});
            VERIFY_ARE_EQUAL(volumes, (std::set<std::string>{vhdA, guestA}));
        }

        // Multiple labels are AND'ed together.
        {
            auto volumes = ListVolumes({}, {}, {{.Key = "env", .Value = "test"}, {.Key = "tier", .Value = "db"}});
            VERIFY_ARE_EQUAL(volumes, std::set<std::string>{vhdB});
        }

        // Unknown label key matches nothing.
        VERIFY_ARE_EQUAL(ListVolumes({}, {}, {{.Key = "nope", .Value = nullptr}}), empty);

        // Unknown name matches nothing.
        VERIFY_ARE_EQUAL(ListVolumes({}, "nope"), empty);

        // Combined driver + name + label filter.
        VERIFY_ARE_EQUAL(ListVolumes("vhd", "a", {{.Key = "env", .Value = "prod"}}), std::set<std::string>{vhdA});

        // Dangling filter is accepted but no-op today; update this test once dangling is wired up.
        VERIFY_ARE_EQUAL(ListVolumes({}, {}, {}, std::string("true")), all);

        // Value=nullptr (key-only) matches the volume with the marker label regardless of stored value.
        VERIFY_ARE_EQUAL(ListVolumes({}, {}, {{.Key = "marker", .Value = nullptr}}), std::set<std::string>{emptyValVol});

        // Value="" matches only volumes whose stored value is also the empty string.
        VERIFY_ARE_EQUAL(ListVolumes({}, {}, {{.Key = "marker", .Value = ""}}), std::set<std::string>{emptyValVol});

        // No volume stores `env` with an empty value, so env="" matches nothing.
        VERIFY_ARE_EQUAL(ListVolumes({}, {}, {{.Key = "env", .Value = ""}}), empty);

        // env=nullptr (key-only) matches every volume that has the key, regardless of its stored value.
        VERIFY_ARE_EQUAL(ListVolumes({}, {}, {{.Key = "env", .Value = nullptr}}), (std::set<std::string>{vhdA, vhdB, guestA, otherName}));

src/windows/service/inc/wslc.idl:748

  • PR description mentions updating a WSLCListVolumesOptions struct, but no such type exists in the updated IDL and the new API surface appears to be WSLCFilter-based instead. Please update the PR description to match the actual API changes (or add the described WSLCListVolumesOptions type if that was the intent).
    // Volume management.
    HRESULT CreateVolume([in] const WSLCVolumeOptions* Options, [out] WSLCVolumeInformation* VolumeInfo);
    HRESULT DeleteVolume([in] LPCSTR Name);
    HRESULT ListVolumes([in, unique, size_is(FiltersCount)] const WSLCFilter* Filters, [in] ULONG FiltersCount, [out, size_is(, *Count)] WSLCVolumeInformation** Volumes, [out] ULONG* Count);
    HRESULT InspectVolume([in] LPCSTR Name, [out] LPSTR* Output);

    HRESULT Authenticate([in] LPCSTR ServerAddress, [in] LPCSTR Username, [in] LPCSTR Password, [out] LPSTR* IdentityToken);
    HRESULT PushImage([in] LPCSTR Image, [in] LPCSTR RegistryAuthenticationInformation, [in, unique] IProgressCallback* ProgressCallback);
    HRESULT PruneVolumes([in, unique, size_is(FiltersCount)] const WSLCFilter* Filters, [in] ULONG FiltersCount, [out, size_is(, *VolumesCount)] WSLCVolumeName** Volumes, [out] ULONG* VolumesCount, [out] ULONGLONG* SpaceReclaimed);

Comment on lines 740 to 749
// Volume management.
HRESULT CreateVolume([in] const WSLCVolumeOptions* Options, [out] WSLCVolumeInformation* VolumeInfo);
HRESULT DeleteVolume([in] LPCSTR Name);
HRESULT ListVolumes([out, size_is(, *Count)] WSLCVolumeInformation** Volumes, [out] ULONG* Count);
HRESULT ListVolumes([in, unique, size_is(FiltersCount)] const WSLCFilter* Filters, [in] ULONG FiltersCount, [out, size_is(, *Count)] WSLCVolumeInformation** Volumes, [out] ULONG* Count);
HRESULT InspectVolume([in] LPCSTR Name, [out] LPSTR* Output);

HRESULT Authenticate([in] LPCSTR ServerAddress, [in] LPCSTR Username, [in] LPCSTR Password, [out] LPSTR* IdentityToken);
HRESULT PushImage([in] LPCSTR Image, [in] LPCSTR RegistryAuthenticationInformation, [in, unique] IProgressCallback* ProgressCallback);
HRESULT PruneVolumes([in, unique] const WSLCPruneVolumesOptions* Options, [out] WSLCPruneVolumesResults* Results);
HRESULT PruneVolumes([in, unique, size_is(FiltersCount)] const WSLCFilter* Filters, [in] ULONG FiltersCount, [out, size_is(, *VolumesCount)] WSLCVolumeName** Volumes, [out] ULONG* VolumesCount, [out] ULONGLONG* SpaceReclaimed);

wil::unique_cotaskmem_array_ptr<WSLCVolumeInformation> rawVolumes;
ULONG count = 0;
THROW_IF_FAILED(session.Get()->ListVolumes(&rawVolumes, &count));
THROW_IF_FAILED(session.Get()->ListVolumes(nullptr, &rawVolumes, &count));
Comment thread test/windows/WSLCTests.cpp Outdated
Comment on lines 4152 to 4155
// Verify empty list is returned when no volumes exist.
wil::unique_cotaskmem_array_ptr<WSLCVolumeInformation> volumes;
VERIFY_SUCCEEDED(m_defaultSession->ListVolumes(volumes.addressof(), volumes.size_address<ULONG>()));
VERIFY_SUCCEEDED(m_defaultSession->ListVolumes(nullptr, volumes.addressof(), volumes.size_address<ULONG>()));
VERIFY_ARE_EQUAL(0u, volumes.size());
Copilot AI review requested due to automatic review settings May 12, 2026 23:35
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 16 out of 16 changed files in this pull request and generated 4 comments.

HRESULT CreateVolume([in] const WSLCVolumeOptions* Options, [out] WSLCVolumeInformation* VolumeInfo);
HRESULT DeleteVolume([in] LPCSTR Name);
HRESULT ListVolumes([out, size_is(, *Count)] WSLCVolumeInformation** Volumes, [out] ULONG* Count);
HRESULT ListVolumes([in, unique, size_is(FiltersCount)] const WSLCFilter* Filters, [in] ULONG FiltersCount, [out, size_is(, *Count)] WSLCVolumeInformation** Volumes, [out] ULONG* Count);
Comment on lines 746 to 749
HRESULT Authenticate([in] LPCSTR ServerAddress, [in] LPCSTR Username, [in] LPCSTR Password, [out] LPSTR* IdentityToken);
HRESULT PushImage([in] LPCSTR Image, [in] LPCSTR RegistryAuthenticationInformation, [in, unique] IProgressCallback* ProgressCallback);
HRESULT PruneVolumes([in, unique] const WSLCPruneVolumesOptions* Options, [out] WSLCPruneVolumesResults* Results);
HRESULT PruneVolumes([in, unique, size_is(FiltersCount)] const WSLCFilter* Filters, [in] ULONG FiltersCount, [out, size_is(, *VolumesCount)] WSLCVolumeName** Volumes, [out] ULONG* VolumesCount, [out] ULONGLONG* SpaceReclaimed);

}
catch (const std::regex_error&)
{
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, Localization::MessageWslcInvalidName(value));
Comment on lines +261 to +265
WSLCVolumes::PruneVolumesResult WSLCVolumes::PruneVolumes(const std::map<std::string, std::vector<std::string>>& Filters)
{
auto lock = m_lock.lock_exclusive();

auto dockerResult = m_dockerClient.PruneVolumes(Filters);
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