mirror of
https://github.com/microsoft/WSL.git
synced 2025-12-10 00:44:55 -06:00
Fix edge cases around .vhd support (#13061)
* Fix edge cases around .vhd support * PR feedback Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * pr feedback * remove unneeded scope exit in unit test --------- Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
c1b77b125d
commit
9e9ef6f145
@ -466,7 +466,7 @@ Arguments for managing Windows Subsystem for Linux:
|
|||||||
Move the distribution to a new location.
|
Move the distribution to a new location.
|
||||||
|
|
||||||
--set-sparse, -s <true|false>
|
--set-sparse, -s <true|false>
|
||||||
Set the vhdx of distro to be sparse, allowing disk space to be automatically reclaimed.
|
Set the VHD of distro to be sparse, allowing disk space to be automatically reclaimed.
|
||||||
|
|
||||||
--set-default-user <Username>
|
--set-default-user <Username>
|
||||||
Set the default user of the distribution.
|
Set the default user of the distribution.
|
||||||
@ -546,11 +546,11 @@ Arguments for managing distributions in Windows Subsystem for Linux:
|
|||||||
Specifies the version to use for the new distribution.
|
Specifies the version to use for the new distribution.
|
||||||
|
|
||||||
--vhd
|
--vhd
|
||||||
Specifies that the provided file is a .vhdx file, not a tar file.
|
Specifies that the provided file is a .vhd or .vhdx file, not a tar file.
|
||||||
This operation makes a copy of the .vhdx file at the specified install location.
|
This operation makes a copy of the VHD file at the specified install location.
|
||||||
|
|
||||||
--import-in-place <Distro> <FileName>
|
--import-in-place <Distro> <FileName>
|
||||||
Imports the specified .vhdx file as a new distribution.
|
Imports the specified VHD file as a new distribution.
|
||||||
This virtual hard disk must be formatted with the ext4 filesystem type.
|
This virtual hard disk must be formatted with the ext4 filesystem type.
|
||||||
|
|
||||||
--list, -l [Options]
|
--list, -l [Options]
|
||||||
@ -626,7 +626,7 @@ Build time: {}</value>
|
|||||||
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
|
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageCustomKernelModulesNotFound" xml:space="preserve">
|
<data name="MessageCustomKernelModulesNotFound" xml:space="preserve">
|
||||||
<value>The custom kernel modules vhd in {} was not found: '{}'.</value>
|
<value>The custom kernel modules VHD in {} was not found: '{}'.</value>
|
||||||
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
|
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageCustomSystemDistroError" xml:space="preserve">
|
<data name="MessageCustomSystemDistroError" xml:space="preserve">
|
||||||
@ -704,8 +704,13 @@ The system may need to be restarted so the changes can take effect.</value>
|
|||||||
<comment>{Locked="--install "}{Locked="--no-distribution
|
<comment>{Locked="--install "}{Locked="--no-distribution
|
||||||
"}Command line arguments, file names and string inserts should not be translated</comment>
|
"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageRequiresVhdxFileExtension" xml:space="preserve">
|
<data name="MessageRequiresFileExtension" xml:space="preserve">
|
||||||
<value>The specified file must have the .vhdx file extension.</value>
|
<value>The specified file must have the {} file extension.</value>
|
||||||
|
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||||
|
</data>
|
||||||
|
<data name="MessageRequiresFileExtensions" xml:space="preserve">
|
||||||
|
<value>The specified file must have the {} or {} file extension.</value>
|
||||||
|
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageVmSwitchNotFound" xml:space="preserve">
|
<data name="MessageVmSwitchNotFound" xml:space="preserve">
|
||||||
<value>The VmSwitch '{}' was not found. Available switches: {}</value>
|
<value>The VmSwitch '{}' was not found. Available switches: {}</value>
|
||||||
@ -998,7 +1003,7 @@ Falling back to NAT networking.</value>
|
|||||||
<value>See Docs</value>
|
<value>See Docs</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageVhdInUse" xml:space="preserve">
|
<data name="MessageVhdInUse" xml:space="preserve">
|
||||||
<value>The operation could not be completed because the vhdx is currently in use. To force WSL to stop use: wsl.exe --shutdown</value>
|
<value>The operation could not be completed because the VHD is currently in use. To force WSL to stop use: wsl.exe --shutdown</value>
|
||||||
<comment>{Locked="--shutdown"}Command line arguments, file names and string inserts should not be translated</comment>
|
<comment>{Locked="--shutdown"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageInvalidBoolean" xml:space="preserve">
|
<data name="MessageInvalidBoolean" xml:space="preserve">
|
||||||
@ -1006,7 +1011,7 @@ Falling back to NAT networking.</value>
|
|||||||
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
|
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageSparseVhdWsl2Only" xml:space="preserve">
|
<data name="MessageSparseVhdWsl2Only" xml:space="preserve">
|
||||||
<value>Sparse vhdx is supported on WSL2 only.</value>
|
<value>Sparse VHD is supported on WSL2 only.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageLocalSystemNotSupported" xml:space="preserve">
|
<data name="MessageLocalSystemNotSupported" xml:space="preserve">
|
||||||
<value>Running WSL as local system is not supported.</value>
|
<value>Running WSL as local system is not supported.</value>
|
||||||
@ -1055,7 +1060,7 @@ Falling back to NAT networking.</value>
|
|||||||
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
|
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessagePassVhdFlag" xml:space="preserve">
|
<data name="MessagePassVhdFlag" xml:space="preserve">
|
||||||
<value>This looks like a VHDX file. Use --vhd to import a VHDX instead of a tar.</value>
|
<value>This looks like a VHD file. Use --vhd to import a VHD instead of a tar.</value>
|
||||||
<comment>{Locked="--vhd "}Command line arguments, file names and string inserts should not be translated</comment>
|
<comment>{Locked="--vhd "}Command line arguments, file names and string inserts should not be translated</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="MessageDistroStoreInstallFailed" xml:space="preserve">
|
<data name="MessageDistroStoreInstallFailed" xml:space="preserve">
|
||||||
@ -1107,7 +1112,7 @@ Error code: {}</value>
|
|||||||
</data>
|
</data>
|
||||||
<data name="MessageSparseVhdDisabled" xml:space="preserve">
|
<data name="MessageSparseVhdDisabled" xml:space="preserve">
|
||||||
<value>Sparse VHD support is currently disabled due to potential data corruption.
|
<value>Sparse VHD support is currently disabled due to potential data corruption.
|
||||||
To force a distribution to use a sparse vhd, please run:
|
To force a distribution to use a sparse VHD, please run:
|
||||||
wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe</value>
|
wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe</value>
|
||||||
<comment>{Locked="--manage "}{Locked="--set-sparse "}{Locked="--allow-unsafe"}Command line arguments, file names and string inserts should not be translated</comment>
|
<comment>{Locked="--manage "}{Locked="--set-sparse "}{Locked="--allow-unsafe"}Command line arguments, file names and string inserts should not be translated</comment>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@ -275,14 +275,6 @@ int ExportDistribution(_In_ std::wstring_view commandLine)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If exporting to a vhd, ensure the filename ends with the vhdx file extension.
|
|
||||||
if (WI_IsFlagSet(flags, LXSS_EXPORT_DISTRO_FLAGS_VHD) &&
|
|
||||||
!wsl::windows::common::string::IsPathComponentEqual(filePath.extension().native(), wsl::windows::common::wslutil::c_vhdxFileExtension))
|
|
||||||
{
|
|
||||||
wsl::windows::common::wslutil::PrintMessage(wsl::shared::Localization::MessageRequiresVhdxFileExtension());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
file.reset(CreateFileW(
|
file.reset(CreateFileW(
|
||||||
filePath.c_str(), GENERIC_WRITE, (FILE_SHARE_READ | FILE_SHARE_DELETE), nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr));
|
filePath.c_str(), GENERIC_WRITE, (FILE_SHARE_READ | FILE_SHARE_DELETE), nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr));
|
||||||
|
|
||||||
@ -371,22 +363,10 @@ int ImportDistribution(_In_ std::wstring_view commandLine)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool isVhd = wsl::windows::common::string::IsPathComponentEqual(
|
if (WI_IsFlagClear(flags, LXSS_IMPORT_DISTRO_FLAGS_VHD))
|
||||||
filePath.extension().native(), wsl::windows::common::wslutil::c_vhdxFileExtension);
|
|
||||||
|
|
||||||
if (WI_IsFlagSet(flags, LXSS_IMPORT_DISTRO_FLAGS_VHD))
|
|
||||||
{
|
{
|
||||||
// If importing from a vhd, ensure the filename ends with the vhdx file extension.
|
// Fail if expecting a tar, but the file name has the .vhd or .vhdx extension.
|
||||||
if (!isVhd)
|
if (wsl::windows::common::wslutil::IsVhdFile(filePath))
|
||||||
{
|
|
||||||
wsl::windows::common::wslutil::PrintMessage(wsl::shared::Localization::MessageRequiresVhdxFileExtension());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Fail if we expect a tar, but the file name has the .vhdx extension.
|
|
||||||
if (isVhd)
|
|
||||||
{
|
{
|
||||||
wsl::windows::common::wslutil::PrintMessage(wsl::shared::Localization::MessagePassVhdFlag());
|
wsl::windows::common::wslutil::PrintMessage(wsl::shared::Localization::MessagePassVhdFlag());
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@ -1155,6 +1155,13 @@ bool wsl::windows::common::wslutil::IsRunningInMsix()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wsl::windows::common::wslutil::IsVhdFile(_In_ const std::filesystem::path& path)
|
||||||
|
{
|
||||||
|
return wsl::windows::common::string::IsPathComponentEqual(path.extension().native(), c_vhdFileExtension) ||
|
||||||
|
wsl::windows::common::string::IsPathComponentEqual(path.extension().native(), c_vhdxFileExtension);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<DWORD> wsl::windows::common::wslutil::ListRunningProcesses()
|
std::vector<DWORD> wsl::windows::common::wslutil::ListRunningProcesses()
|
||||||
{
|
{
|
||||||
std::vector<DWORD> pids(1024);
|
std::vector<DWORD> pids(1024);
|
||||||
|
|||||||
@ -122,6 +122,8 @@ void InitializeWil();
|
|||||||
|
|
||||||
bool IsRunningInMsix();
|
bool IsRunningInMsix();
|
||||||
|
|
||||||
|
bool IsVhdFile(_In_ const std::filesystem::path& path);
|
||||||
|
|
||||||
bool IsVirtualMachinePlatformInstalled();
|
bool IsVirtualMachinePlatformInstalled();
|
||||||
|
|
||||||
std::vector<DWORD> ListRunningProcesses();
|
std::vector<DWORD> ListRunningProcesses();
|
||||||
|
|||||||
@ -927,7 +927,7 @@ HRESULT LxssUserSessionImpl::MoveDistribution(_In_ LPCGUID DistroGuid, _In_ LPCW
|
|||||||
std::filesystem::path newVhdPath = Location;
|
std::filesystem::path newVhdPath = Location;
|
||||||
RETURN_HR_IF(E_INVALIDARG, newVhdPath.empty());
|
RETURN_HR_IF(E_INVALIDARG, newVhdPath.empty());
|
||||||
|
|
||||||
newVhdPath /= LXSS_VM_MODE_VHD_NAME;
|
newVhdPath /= distro.VhdFilePath.filename();
|
||||||
|
|
||||||
auto impersonate = wil::CoImpersonateClient();
|
auto impersonate = wil::CoImpersonateClient();
|
||||||
|
|
||||||
@ -952,7 +952,7 @@ HRESULT LxssUserSessionImpl::MoveDistribution(_In_ LPCGUID DistroGuid, _In_ LPCW
|
|||||||
|
|
||||||
// Update the registry location
|
// Update the registry location
|
||||||
registration.Write(Property::BasePath, Location);
|
registration.Write(Property::BasePath, Location);
|
||||||
registration.Write(Property::VhdFileName, LXSS_VM_MODE_VHD_NAME);
|
registration.Write(Property::VhdFileName, newVhdPath.filename().c_str());
|
||||||
|
|
||||||
revert.release();
|
revert.release();
|
||||||
|
|
||||||
@ -1079,6 +1079,22 @@ HRESULT LxssUserSessionImpl::ExportDistribution(_In_opt_ LPCGUID DistroGuid, _In
|
|||||||
{
|
{
|
||||||
const wil::unique_handle userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
|
const wil::unique_handle userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation);
|
||||||
auto runAsUser = wil::impersonate_token(userToken.get());
|
auto runAsUser = wil::impersonate_token(userToken.get());
|
||||||
|
|
||||||
|
// Ensure the target file has the correct file extension.
|
||||||
|
if (GetFileType(FileHandle) == FILE_TYPE_DISK)
|
||||||
|
{
|
||||||
|
std::wstring exportPath;
|
||||||
|
THROW_IF_FAILED(wil::GetFinalPathNameByHandleW(FileHandle, exportPath));
|
||||||
|
|
||||||
|
const auto sourceFileExtension = configuration.VhdFilePath.extension().native();
|
||||||
|
const auto targetFileExtension = std::filesystem::path(exportPath).extension().native();
|
||||||
|
if (!wsl::windows::common::string::IsPathComponentEqual(sourceFileExtension, targetFileExtension))
|
||||||
|
{
|
||||||
|
THROW_HR_WITH_USER_ERROR(
|
||||||
|
WSL_E_EXPORT_FAILED, wsl::shared::Localization::MessageRequiresFileExtension(sourceFileExtension.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const wil::unique_hfile vhdFile(CreateFileW(
|
const wil::unique_hfile vhdFile(CreateFileW(
|
||||||
configuration.VhdFilePath.c_str(), GENERIC_READ, (FILE_SHARE_READ | FILE_SHARE_DELETE), nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
|
configuration.VhdFilePath.c_str(), GENERIC_READ, (FILE_SHARE_READ | FILE_SHARE_DELETE), nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
|
||||||
|
|
||||||
@ -1258,13 +1274,9 @@ LxssUserSessionImpl::ImportDistributionInplace(_In_ LPCWSTR DistributionName, _I
|
|||||||
|
|
||||||
s_ValidateDistroName(DistributionName);
|
s_ValidateDistroName(DistributionName);
|
||||||
|
|
||||||
// Return an error if the path is not absolute or does not end in the .vhdx file extension.
|
// Return an error if the path is not absolute or does not have a valid VHD file extension.
|
||||||
const std::filesystem::path path{VhdPath};
|
const std::filesystem::path path{VhdPath};
|
||||||
RETURN_HR_IF(
|
RETURN_HR_IF(E_INVALIDARG, !path.is_absolute() || !wsl::windows::common::wslutil::IsVhdFile(path));
|
||||||
E_INVALIDARG,
|
|
||||||
!path.is_absolute() ||
|
|
||||||
(!wsl::windows::common::string::IsPathComponentEqual(path.extension().native(), wsl::windows::common::wslutil::c_vhdFileExtension) &&
|
|
||||||
!wsl::windows::common::string::IsPathComponentEqual(path.extension().c_str(), wsl::windows::common::wslutil::c_vhdxFileExtension)));
|
|
||||||
|
|
||||||
const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
|
const wil::unique_hkey lxssKey = s_OpenLxssUserKey();
|
||||||
std::lock_guard lock(m_instanceLock);
|
std::lock_guard lock(m_instanceLock);
|
||||||
@ -1448,6 +1460,24 @@ HRESULT LxssUserSessionImpl::RegisterDistribution(
|
|||||||
wil::CreateDirectoryDeep(distributionPath.c_str());
|
wil::CreateDirectoryDeep(distributionPath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If importing a vhd, determine if it is a .vhd or .vhdx.
|
||||||
|
std::wstring vhdName{LXSS_VM_MODE_VHD_NAME};
|
||||||
|
if ((WI_IsFlagSet(Flags, LXSS_IMPORT_DISTRO_FLAGS_VHD)) && (GetFileType(FileHandle) == FILE_TYPE_DISK))
|
||||||
|
{
|
||||||
|
std::wstring pathBuffer;
|
||||||
|
THROW_IF_FAILED(wil::GetFinalPathNameByHandleW(FileHandle, pathBuffer));
|
||||||
|
|
||||||
|
std::filesystem::path vhdPath{std::move(pathBuffer)};
|
||||||
|
if (!wsl::windows::common::wslutil::IsVhdFile(vhdPath))
|
||||||
|
{
|
||||||
|
using namespace wsl::windows::common::wslutil;
|
||||||
|
THROW_HR_WITH_USER_ERROR(
|
||||||
|
WSL_E_IMPORT_FAILED, wsl::shared::Localization::MessageRequiresFileExtensions(c_vhdFileExtension, c_vhdxFileExtension));
|
||||||
|
}
|
||||||
|
|
||||||
|
vhdName = vhdPath.filename();
|
||||||
|
}
|
||||||
|
|
||||||
registration = DistributionRegistration::Create(
|
registration = DistributionRegistration::Create(
|
||||||
lxssKey.get(),
|
lxssKey.get(),
|
||||||
DistributionId,
|
DistributionId,
|
||||||
@ -1457,7 +1487,7 @@ HRESULT LxssUserSessionImpl::RegisterDistribution(
|
|||||||
flags,
|
flags,
|
||||||
LX_UID_ROOT,
|
LX_UID_ROOT,
|
||||||
PackageFamilyName,
|
PackageFamilyName,
|
||||||
LXSS_VM_MODE_VHD_NAME,
|
vhdName.c_str(),
|
||||||
WI_IsFlagClear(Flags, LXSS_IMPORT_DISTRO_FLAGS_NO_OOBE));
|
WI_IsFlagClear(Flags, LXSS_IMPORT_DISTRO_FLAGS_NO_OOBE));
|
||||||
|
|
||||||
configuration = s_GetDistributionConfiguration(registration, DistributionName == nullptr);
|
configuration = s_GetDistributionConfiguration(registration, DistributionName == nullptr);
|
||||||
|
|||||||
@ -71,9 +71,7 @@ void wsl::core::filesystem::CreateVhd(_In_ LPCWSTR target, _In_ ULONGLONG maximu
|
|||||||
|
|
||||||
wil::unique_handle wsl::core::filesystem::OpenVhd(_In_ LPCWSTR Path, _In_ VIRTUAL_DISK_ACCESS_MASK Mask)
|
wil::unique_handle wsl::core::filesystem::OpenVhd(_In_ LPCWSTR Path, _In_ VIRTUAL_DISK_ACCESS_MASK Mask)
|
||||||
{
|
{
|
||||||
WI_ASSERT(
|
WI_ASSERT(wsl::windows::common::wslutil::IsVhdFile(std::filesystem::path{Path}));
|
||||||
wsl::shared::string::IsEqual(std::filesystem::path{Path}.extension().c_str(), windows::common::wslutil::c_vhdFileExtension, true) ||
|
|
||||||
wsl::shared::string::IsEqual(std::filesystem::path{Path}.extension().c_str(), windows::common::wslutil::c_vhdxFileExtension, true));
|
|
||||||
|
|
||||||
// N.B. Specifying unknown for device and vendor means the system will determine the type of VHD.
|
// N.B. Specifying unknown for device and vendor means the system will determine the type of VHD.
|
||||||
VIRTUAL_STORAGE_TYPE storageType{};
|
VIRTUAL_STORAGE_TYPE storageType{};
|
||||||
|
|||||||
@ -109,7 +109,7 @@ class SimpleTests
|
|||||||
std::format(L"{} {} {} {}", WSL_IMPORT_ARG, tempDistro, vhdDir.wstring(), tar.wstring()).c_str(),
|
std::format(L"{} {} {} {}", WSL_IMPORT_ARG, tempDistro, vhdDir.wstring(), tar.wstring()).c_str(),
|
||||||
L"The operation completed successfully. \r\n",
|
L"The operation completed successfully. \r\n",
|
||||||
L"wsl: Sparse VHD support is currently disabled due to potential data corruption.\r\n"
|
L"wsl: Sparse VHD support is currently disabled due to potential data corruption.\r\n"
|
||||||
L"To force a distribution to use a sparse vhd, please run:\r\n"
|
L"To force a distribution to use a sparse VHD, please run:\r\n"
|
||||||
L"wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe\r\n",
|
L"wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe\r\n",
|
||||||
0);
|
0);
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ class SimpleTests
|
|||||||
ValidateOutput(
|
ValidateOutput(
|
||||||
std::format(L"{} {} {} {}", WSL_MANAGE_ARG, tempDistro, WSL_MANAGE_ARG_SET_SPARSE_OPTION_LONG, L"true").c_str(),
|
std::format(L"{} {} {} {}", WSL_MANAGE_ARG, tempDistro, WSL_MANAGE_ARG_SET_SPARSE_OPTION_LONG, L"true").c_str(),
|
||||||
L"Sparse VHD support is currently disabled due to potential data corruption.\r\n"
|
L"Sparse VHD support is currently disabled due to potential data corruption.\r\n"
|
||||||
L"To force a distribution to use a sparse vhd, please run:\r\n"
|
L"To force a distribution to use a sparse VHD, please run:\r\n"
|
||||||
L"wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe\r\nError code: Wsl/Service/E_INVALIDARG\r\n",
|
L"wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe\r\nError code: Wsl/Service/E_INVALIDARG\r\n",
|
||||||
L"",
|
L"",
|
||||||
-1);
|
-1);
|
||||||
|
|||||||
@ -1016,7 +1016,7 @@ class UnitTests
|
|||||||
L"Error code: Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS\r\n");
|
L"Error code: Wsl/Service/RegisterDistro/ERROR_FILE_EXISTS\r\n");
|
||||||
|
|
||||||
commandLine = std::format(L"--import dummy {} {} --version {}", LXSST_IMPORT_DISTRO_TEST_DIR, vhdFileName, version);
|
commandLine = std::format(L"--import dummy {} {} --version {}", LXSST_IMPORT_DISTRO_TEST_DIR, vhdFileName, version);
|
||||||
validateOutput(commandLine.c_str(), L"This looks like a VHDX file. Use --vhd to import a VHDX instead of a tar.\r\n");
|
validateOutput(commandLine.c_str(), L"This looks like a VHD file. Use --vhd to import a VHD instead of a tar.\r\n");
|
||||||
|
|
||||||
if (!LxsstuVmMode())
|
if (!LxsstuVmMode())
|
||||||
{
|
{
|
||||||
@ -1557,7 +1557,7 @@ Arguments for managing Windows Subsystem for Linux:
|
|||||||
Move the distribution to a new location.
|
Move the distribution to a new location.
|
||||||
|
|
||||||
--set-sparse, -s <true|false>
|
--set-sparse, -s <true|false>
|
||||||
Set the vhdx of distro to be sparse, allowing disk space to be automatically reclaimed.
|
Set the VHD of distro to be sparse, allowing disk space to be automatically reclaimed.
|
||||||
|
|
||||||
--set-default-user <Username>
|
--set-default-user <Username>
|
||||||
Set the default user of the distribution.
|
Set the default user of the distribution.
|
||||||
@ -1637,11 +1637,11 @@ Arguments for managing distributions in Windows Subsystem for Linux:
|
|||||||
Specifies the version to use for the new distribution.
|
Specifies the version to use for the new distribution.
|
||||||
|
|
||||||
--vhd
|
--vhd
|
||||||
Specifies that the provided file is a .vhdx file, not a tar file.
|
Specifies that the provided file is a .vhd or .vhdx file, not a tar file.
|
||||||
This operation makes a copy of the .vhdx file at the specified install location.
|
This operation makes a copy of the VHD file at the specified install location.
|
||||||
|
|
||||||
--import-in-place <Distro> <FileName>
|
--import-in-place <Distro> <FileName>
|
||||||
Imports the specified .vhdx file as a new distribution.
|
Imports the specified VHD file as a new distribution.
|
||||||
This virtual hard disk must be formatted with the ext4 filesystem type.
|
This virtual hard disk must be formatted with the ext4 filesystem type.
|
||||||
|
|
||||||
--list, -l [Options]
|
--list, -l [Options]
|
||||||
@ -2896,8 +2896,7 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
|
|||||||
WslKeepAlive keepAlive;
|
WslKeepAlive keepAlive;
|
||||||
auto [out, _] = LxsstuLaunchWslAndCaptureOutput(L"--manage test_distro --resize 1500GB", -1);
|
auto [out, _] = LxsstuLaunchWslAndCaptureOutput(L"--manage test_distro --resize 1500GB", -1);
|
||||||
VERIFY_ARE_EQUAL(
|
VERIFY_ARE_EQUAL(
|
||||||
L"The operation could not be completed because the vhdx is currently in use. To force WSL to stop use: "
|
L"The operation could not be completed because the VHD is currently in use. To force WSL to stop use: wsl.exe "
|
||||||
L"wsl.exe "
|
|
||||||
L"--shutdown\r\nError code: Wsl/Service/WSL_E_DISTRO_NOT_STOPPED\r\n",
|
L"--shutdown\r\nError code: Wsl/Service/WSL_E_DISTRO_NOT_STOPPED\r\n",
|
||||||
out);
|
out);
|
||||||
}
|
}
|
||||||
@ -6276,5 +6275,71 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
|
|||||||
VERIFY_ARE_EQUAL(out, L"755\n");
|
VERIFY_ARE_EQUAL(out, L"755\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ExportImportVhd)
|
||||||
|
{
|
||||||
|
WSL2_TEST_ONLY();
|
||||||
|
|
||||||
|
WslShutdown();
|
||||||
|
|
||||||
|
constexpr auto vhdPath = L"exported-test-distro.vhd";
|
||||||
|
constexpr auto vhdxPath = L"exported-test-distro.vhdx";
|
||||||
|
constexpr auto exportedVhdPath = L"exported-vhd.vhd";
|
||||||
|
constexpr auto newDistroName = L"imported-test-distro";
|
||||||
|
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() {
|
||||||
|
LOG_IF_WIN32_BOOL_FALSE(DeleteFile(vhdPath));
|
||||||
|
LOG_IF_WIN32_BOOL_FALSE(DeleteFile(vhdxPath));
|
||||||
|
LOG_IF_WIN32_BOOL_FALSE(DeleteFile(exportedVhdPath));
|
||||||
|
LxsstuLaunchWsl(std::format(L"--unregister {}", newDistroName));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attempt to export the distribution to a .vhd (should fail).
|
||||||
|
auto [out, err] =
|
||||||
|
LxsstuLaunchWslAndCaptureOutput(std::format(L"--export {} {} --format vhd", LXSS_DISTRO_NAME_TEST_L, vhdPath), -1);
|
||||||
|
VERIFY_ARE_EQUAL(
|
||||||
|
out, L"The specified file must have the .vhdx file extension.\r\nError code: Wsl/Service/WSL_E_EXPORT_FAILED\r\n");
|
||||||
|
VERIFY_ARE_EQUAL(err, L"");
|
||||||
|
|
||||||
|
// Export the distribution to a .vhdx.
|
||||||
|
std::tie(out, err) =
|
||||||
|
LxsstuLaunchWslAndCaptureOutput(std::format(L"--export {} {} --format vhd", LXSS_DISTRO_NAME_TEST_L, vhdxPath));
|
||||||
|
VERIFY_ARE_EQUAL(out, L"The operation completed successfully. \r\n");
|
||||||
|
VERIFY_ARE_EQUAL(err, L"");
|
||||||
|
|
||||||
|
// Convert the .vhdx to .vhd.
|
||||||
|
LxsstuLaunchPowershellAndCaptureOutput(std::format(L"Convert-VHD -Path '{}' -DestinationPath '{}'", vhdxPath, vhdPath));
|
||||||
|
|
||||||
|
// Import a new distribution from the .vhd file.
|
||||||
|
std::tie(out, err) =
|
||||||
|
LxsstuLaunchWslAndCaptureOutput(std::format(L"--import {} {} {} --vhd", newDistroName, newDistroName, vhdPath));
|
||||||
|
VERIFY_ARE_EQUAL(out, L"The operation completed successfully. \r\n");
|
||||||
|
VERIFY_ARE_EQUAL(err, L"");
|
||||||
|
|
||||||
|
// Export the newly imported distribution to another .vhd file.
|
||||||
|
std::tie(out, err) = LxsstuLaunchWslAndCaptureOutput(std::format(L"--export {} {} --format vhd", newDistroName, exportedVhdPath));
|
||||||
|
VERIFY_ARE_EQUAL(out, L"The operation completed successfully. \r\n");
|
||||||
|
VERIFY_ARE_EQUAL(err, L"");
|
||||||
|
|
||||||
|
// Attempt to export to a .vhdx (should fail).
|
||||||
|
std::tie(out, err) = LxsstuLaunchWslAndCaptureOutput(std::format(L"--export {} {} --format vhd", newDistroName, vhdxPath), -1);
|
||||||
|
VERIFY_ARE_EQUAL(
|
||||||
|
out, L"The specified file must have the .vhd file extension.\r\nError code: Wsl/Service/WSL_E_EXPORT_FAILED\r\n");
|
||||||
|
VERIFY_ARE_EQUAL(err, L"");
|
||||||
|
|
||||||
|
// Attempt to import to a non VHD file.
|
||||||
|
auto tempFile = wsl::windows::common::filesystem::TempFile(
|
||||||
|
GENERIC_ALL, 0, CREATE_ALWAYS, wsl::windows::common::filesystem::TempFileFlags::None, L"txt");
|
||||||
|
|
||||||
|
tempFile.Handle.reset();
|
||||||
|
|
||||||
|
constexpr auto negativeVariationDistro = L"negative-variation-distro";
|
||||||
|
std::tie(out, err) = LxsstuLaunchWslAndCaptureOutput(
|
||||||
|
std::format(L"--import {} {} {} --vhd", negativeVariationDistro, negativeVariationDistro, tempFile.Path), -1);
|
||||||
|
VERIFY_ARE_EQUAL(
|
||||||
|
out,
|
||||||
|
L"The specified file must have the .vhd or .vhdx file extension.\r\nError code: "
|
||||||
|
L"Wsl/Service/RegisterDistro/WSL_E_IMPORT_FAILED\r\n");
|
||||||
|
VERIFY_ARE_EQUAL(err, L"");
|
||||||
|
}
|
||||||
|
|
||||||
}; // namespace UnitTests
|
}; // namespace UnitTests
|
||||||
} // namespace UnitTests
|
} // namespace UnitTests
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user