-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Implement more SDK APIs #14274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement more SDK APIs #14274
Changes from all commits
a224ac3
1db79e1
1f01682
7419773
b09447f
4ee8380
29116c2
633feba
cfa51fb
65ec129
e0d3dbe
eec1ada
2b84fd5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -86,7 +86,20 @@ WSLASignal ConvertSignal(WslcSignal signal) | |
| case WSLC_SIGNAL_SIGTERM: | ||
| return WSLASignal::WSLASignalSIGTERM; | ||
| default: | ||
| THROW_HR(E_INVALIDARG); | ||
| THROW_HR_MSG(E_INVALIDARG, "Invalid WslcSignal: %i", signal); | ||
| } | ||
| } | ||
|
|
||
| WSLA_CONTAINER_NETWORK_TYPE Convert(WslcContainerNetworkingMode mode) | ||
| { | ||
| switch (mode) | ||
| { | ||
| case WSLC_CONTAINER_NETWORKING_MODE_NONE: | ||
| return WSLA_CONTAINER_NETWORK_NONE; | ||
| case WSLC_CONTAINER_NETWORKING_MODE_BRIDGED: | ||
| return WSLA_CONTAINER_NETWORK_BRIDGE; | ||
| default: | ||
| THROW_HR_MSG(E_INVALIDARG, "Invalid WslcContainerNetworkingMode: %i", mode); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -102,6 +115,24 @@ void GetErrorInfoFromCOM(PWSTR* errorMessage) | |
| } | ||
| } | ||
| } | ||
|
|
||
| void EnsureAbsolutePath(const std::filesystem::path& path, bool containerPath) | ||
| { | ||
| THROW_HR_IF(E_INVALIDARG, path.empty()); | ||
|
|
||
| if (containerPath) | ||
| { | ||
| auto pathString = path.native(); | ||
| // Not allowed to mount to root | ||
| THROW_HR_IF(E_INVALIDARG, pathString.length() < 2); | ||
| // Must be absolute | ||
| THROW_HR_IF(E_INVALIDARG, pathString[0] != L'/'); | ||
| } | ||
| else | ||
| { | ||
| THROW_HR_IF(E_INVALIDARG, path.is_relative()); | ||
| } | ||
| } | ||
| } // namespace | ||
|
|
||
| // SESSION DEFINITIONS | ||
|
|
@@ -220,15 +251,6 @@ try | |
| } | ||
| CATCH_RETURN(); | ||
|
|
||
| STDAPI WslcContainerSettingsSetNetworkingMode(_In_ WslcContainerSettings* containerSettings, _In_ WslcContainerNetworkingMode networkingMode) | ||
| try | ||
| { | ||
| UNREFERENCED_PARAMETER(networkingMode); | ||
| UNREFERENCED_PARAMETER(containerSettings); | ||
| return E_NOTIMPL; | ||
| } | ||
| CATCH_RETURN(); | ||
|
|
||
| STDAPI WslcSessionSettingsSetTimeout(_In_ WslcSessionSettings* sessionSettings, _In_ uint32_t timeoutMS) | ||
| try | ||
| { | ||
|
|
@@ -360,6 +382,8 @@ try | |
| *internalType = {}; | ||
|
|
||
| internalType->image = imageName; | ||
| // Default network configuration to WSLC SDK `0`, which is NONE. | ||
| internalType->networking = WSLA_CONTAINER_NETWORK_NONE; | ||
|
|
||
| return S_OK; | ||
| } | ||
|
|
@@ -400,12 +424,45 @@ try | |
| // containerOptions.InitProcessOptions.User; | ||
| } | ||
|
|
||
| // TODO: Implement | ||
| // containerOptions.Volumes; | ||
| // containerOptions.VolumesCount; | ||
| // containerOptions.Ports; | ||
| // containerOptions.PortsCount; | ||
| // containerOptions.ContainerNetwork; | ||
| std::unique_ptr<WSLA_VOLUME[]> convertedVolumes; | ||
|
JohnMcPMS marked this conversation as resolved.
|
||
| if (internalContainerSettings->volumes && internalContainerSettings->volumesCount) | ||
| { | ||
| convertedVolumes = std::make_unique<WSLA_VOLUME[]>(internalContainerSettings->volumesCount); | ||
| for (uint32_t i = 0; i < internalContainerSettings->volumesCount; ++i) | ||
| { | ||
| const WslcContainerVolume& internalVolume = internalContainerSettings->volumes[i]; | ||
| WSLA_VOLUME& convertedVolume = convertedVolumes[i]; | ||
|
|
||
| convertedVolume.HostPath = internalVolume.windowsPath; | ||
| convertedVolume.ContainerPath = internalVolume.containerPath; | ||
| convertedVolume.ReadOnly = internalVolume.readOnly; | ||
| } | ||
| containerOptions.Volumes = convertedVolumes.get(); | ||
| containerOptions.VolumesCount = static_cast<ULONG>(internalContainerSettings->volumesCount); | ||
| } | ||
|
|
||
| std::unique_ptr<WSLA_PORT_MAPPING[]> convertedPorts; | ||
| if (internalContainerSettings->ports && internalContainerSettings->portsCount) | ||
| { | ||
| convertedPorts = std::make_unique<WSLA_PORT_MAPPING[]>(internalContainerSettings->portsCount); | ||
| for (uint32_t i = 0; i < internalContainerSettings->portsCount; ++i) | ||
| { | ||
| const WslcContainerPortMapping& internalPort = internalContainerSettings->ports[i]; | ||
| WSLA_PORT_MAPPING& convertedPort = convertedPorts[i]; | ||
|
|
||
| convertedPort.HostPort = internalPort.windowsPort; | ||
| convertedPort.ContainerPort = internalPort.containerPort; | ||
| // TODO: Only other supported value right now is AF_INET6; no user access. | ||
| convertedPort.Family = AF_INET; | ||
|
|
||
| // TODO: Unused protocol? | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's right, those aren't implemented in the service right now
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If they are both planned I can at least The port mapping in the runtime provides a choice between v4 and v6; should the SDK just create two mapping at all times (one for each IP version)? Or should we provide the user this control?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should let the user control that |
||
| // TODO: Unused windowsAddress? | ||
|
JohnMcPMS marked this conversation as resolved.
|
||
| } | ||
| containerOptions.Ports = convertedPorts.get(); | ||
| containerOptions.PortsCount = static_cast<ULONG>(internalContainerSettings->portsCount); | ||
| } | ||
|
|
||
| containerOptions.ContainerNetwork.ContainerNetworkType = internalContainerSettings->networking; | ||
|
|
||
| // TODO: No user access | ||
| // containerOptions.Entrypoint; | ||
|
|
@@ -473,24 +530,56 @@ try | |
| } | ||
| CATCH_RETURN(); | ||
|
|
||
| STDAPI WslcContainerSettingsSetNetworkingMode(_In_ WslcContainerSettings* containerSettings, _In_ WslcContainerNetworkingMode networkingMode) | ||
| try | ||
| { | ||
| auto internalType = CheckAndGetInternalType(containerSettings); | ||
|
|
||
| internalType->networking = Convert(networkingMode); | ||
|
|
||
| return S_OK; | ||
| } | ||
| CATCH_RETURN(); | ||
|
|
||
| STDAPI WslcContainerSettingsSetPortMapping( | ||
| _In_ WslcContainerSettings* containerSettings, _In_reads_(portMappingCount) const WslcContainerPortMapping* portMappings, _In_ uint32_t portMappingCount) | ||
| try | ||
| { | ||
| UNREFERENCED_PARAMETER(portMappings); | ||
| UNREFERENCED_PARAMETER(containerSettings); | ||
| UNREFERENCED_PARAMETER(portMappingCount); | ||
| return E_NOTIMPL; | ||
| auto internalType = CheckAndGetInternalType(containerSettings); | ||
| RETURN_HR_IF(E_INVALIDARG, (portMappings == nullptr && portMappingCount != 0) || (portMappings != nullptr && portMappingCount == 0)); | ||
|
|
||
| for (uint32_t i = 0; i < portMappingCount; ++i) | ||
| { | ||
| RETURN_HR_IF(E_NOTIMPL, portMappings[i].windowsAddress != nullptr); | ||
| RETURN_HR_IF(E_NOTIMPL, portMappings[i].protocol != 0); | ||
| } | ||
|
|
||
| internalType->ports = portMappings; | ||
| internalType->portsCount = portMappingCount; | ||
|
|
||
| return S_OK; | ||
| } | ||
|
JohnMcPMS marked this conversation as resolved.
|
||
| CATCH_RETURN(); | ||
|
|
||
| STDAPI WslcContainerSettingsAddVolume(_In_ WslcContainerSettings* containerSettings, _In_reads_(volumeCount) const WslcContainerVolume* volumes, _In_ uint32_t volumeCount) | ||
| STDAPI WslcContainerSettingsSetVolumes( | ||
| _In_ WslcContainerSettings* containerSettings, _In_reads_(volumeCount) const WslcContainerVolume* volumes, _In_ uint32_t volumeCount) | ||
| try | ||
| { | ||
| UNREFERENCED_PARAMETER(volumes); | ||
| UNREFERENCED_PARAMETER(volumeCount); | ||
| UNREFERENCED_PARAMETER(containerSettings); | ||
| return E_NOTIMPL; | ||
| auto internalType = CheckAndGetInternalType(containerSettings); | ||
| RETURN_HR_IF(E_INVALIDARG, (volumes == nullptr && volumeCount != 0) || (volumes != nullptr && volumeCount == 0)); | ||
|
|
||
| for (uint32_t i = 0; i < volumeCount; ++i) | ||
| { | ||
| RETURN_HR_IF_NULL(E_INVALIDARG, volumes[i].windowsPath); | ||
| EnsureAbsolutePath(volumes[i].windowsPath, false); | ||
| RETURN_HR_IF_NULL(E_INVALIDARG, volumes[i].containerPath); | ||
| EnsureAbsolutePath(volumes[i].containerPath, true); | ||
| } | ||
|
|
||
| internalType->volumes = volumes; | ||
|
JohnMcPMS marked this conversation as resolved.
|
||
| internalType->volumesCount = volumeCount; | ||
|
|
||
| return S_OK; | ||
| } | ||
|
JohnMcPMS marked this conversation as resolved.
|
||
| CATCH_RETURN(); | ||
|
|
||
|
|
@@ -608,10 +697,10 @@ try | |
| RETURN_HR_IF( | ||
| E_INVALIDARG, | ||
| (argv == nullptr && argc != 0) || (argv != nullptr && argc == 0) || | ||
| (argc > static_cast<size_t>(std::numeric_limits<UINT32>::max()))); | ||
| (argc > static_cast<size_t>(std::numeric_limits<uint32_t>::max()))); | ||
|
|
||
| internalType->commandLine = argv; | ||
| internalType->commandLineCount = static_cast<UINT32>(argc); | ||
| internalType->commandLineCount = static_cast<uint32_t>(argc); | ||
|
|
||
| return S_OK; | ||
| } | ||
|
|
@@ -620,10 +709,16 @@ CATCH_RETURN(); | |
| STDAPI WslcProcessSettingsSetEnvVariables(_In_ WslcProcessSettings* processSettings, _In_reads_(argc) PCSTR const* key_value, size_t argc) | ||
| try | ||
| { | ||
| UNREFERENCED_PARAMETER(key_value); | ||
| UNREFERENCED_PARAMETER(argc); | ||
| UNREFERENCED_PARAMETER(processSettings); | ||
| return E_NOTIMPL; | ||
| auto internalType = CheckAndGetInternalType(processSettings); | ||
| RETURN_HR_IF( | ||
| E_INVALIDARG, | ||
| (key_value == nullptr && argc != 0) || (key_value != nullptr && argc == 0) || | ||
| (argc > static_cast<size_t>(std::numeric_limits<uint32_t>::max()))); | ||
|
JohnMcPMS marked this conversation as resolved.
|
||
|
|
||
| internalType->environment = key_value; | ||
| internalType->environmentCount = static_cast<uint32_t>(argc); | ||
|
|
||
| return S_OK; | ||
| } | ||
| CATCH_RETURN(); | ||
|
|
||
|
|
@@ -748,9 +843,23 @@ CATCH_RETURN(); | |
| STDAPI WslcSessionImageLoad(_In_ WslcSession session, _In_ const WslcLoadImageOptions* options) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit For a future PR: We might want to also expose something like: So that the caller doesn't have to manually open the handle and get the file size |
||
| try | ||
| { | ||
| UNREFERENCED_PARAMETER(session); | ||
| UNREFERENCED_PARAMETER(options); | ||
| return E_NOTIMPL; | ||
| auto internalType = CheckAndGetInternalType(session); | ||
| RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType->session); | ||
| RETURN_HR_IF_NULL(E_POINTER, options); | ||
| RETURN_HR_IF(E_INVALIDARG, options->ImageHandle == nullptr || options->ImageHandle == INVALID_HANDLE_VALUE); | ||
| RETURN_HR_IF(E_INVALIDARG, options->ContentLength == 0); | ||
|
|
||
| auto progressCallback = ProgressCallback::CreateIf(options); | ||
|
|
||
| HRESULT hr = internalType->session->LoadImage(HandleToULong(options->ImageHandle), progressCallback.get(), options->ContentLength); | ||
|
|
||
| if (FAILED_LOG(hr)) | ||
| { | ||
| // TODO: Expected error message changes | ||
| // GetErrorInfoFromCOM(errorMessage); | ||
|
JohnMcPMS marked this conversation as resolved.
|
||
| } | ||
|
|
||
| return hr; | ||
| } | ||
| CATCH_RETURN(); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to default to NAT since this is often the default when creating containers on the command line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My only argument is that we should default to the 0 value of the SDK enum. NAT isn't a runtime value though, not sure if that is another name for HOST or BRIDGE, or a reference to the session networking mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry yeah by NAT I actually meant "bridged". We could make that the '0' value yeah