-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Support for Windows paths in the source position of the volume mounts #17113
Support for Windows paths in the source position of the volume mounts #17113
Conversation
Added NO NEW TESTS NEEDED, because obviously there are no tests for QEMU machine on Windows as of now and all the code changes are isolated behind |
Tested with QEMU on Windows enabled build with the following commands for machine init.
After init machines were always launched and mounts being operational were verifies using ssh into machine. |
74c591a
to
3d73606
Compare
pkg/machine/qemu/machine.go
Outdated
if len(paths) > 1 && driveLetterMatcher.MatchString(paths[0]) { | ||
paths = strings.SplitN(volume, ":", 4) | ||
newpaths := []string{paths[0] + ":" + paths[1]} | ||
for _, v := range paths[2:] { |
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.
It's late and I can't quickly recall. If paths only has one value in it after the SplitN, i.e. the value in the volume variable had no colons, will this spit up?
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.
There is a check at line 309, that paths
will have at least 2 elements len(paths) > 1
.
Example of this check isolated https://go.dev/play/p/AhlcW74W5cH
@arixmkii looks like lint is picking on you:
|
3d73606
to
44a0667
Compare
Had another reading session about paths on Windows and it looks like this version of algorithm will fail for DOS device paths, which could used for referencing files: https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#dos-device-paths I'm not really sure if QEMU will accept them as valid, but I can update the algorithm to handle them (here Regexp will come really handy). |
Added DOS device path support in a separate commit. Will squash if it is accepted or remove it if this is not needed. Isolated example updated: https://go.dev/play/p/WGT06ek1RmB |
922b1b6
to
6881ca3
Compare
pkg/machine/qemu/machine.go
Outdated
@@ -302,8 +304,24 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { | |||
for i, volume := range opts.Volumes { | |||
tag := fmt.Sprintf("vol%d", i) | |||
paths := strings.SplitN(volume, ":", 3) | |||
if runtime.GOOS == "windows" { |
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.
I know this is a small amount of specific code here, but a general ask from the team is to try to break out any platform-specific code into a build-tag controlled unit (_windows etc), to try to keep code sizes from growing too rapidly.
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.
Sure. Will refactor and take into account for my future contributions.
pkg/machine/qemu/machine.go
Outdated
source := paths[0] | ||
target := source | ||
if runtime.GOOS == "windows" { |
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.
in addition to the above, this should check its even necessary to do so (if paths.len > 1 [ after its been altered above])
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.
Valid point. And simple fix. My idea was to mirror unconditional behavior of the above, but obviously that one was for variable initialization, which is not needed here.
pkg/machine/qemu/machine.go
Outdated
} | ||
target = strings.ReplaceAll(target, ":", "") | ||
prefixRemover := regexp.MustCompile(`^//[.?]/`) | ||
target = prefixRemover.ReplaceAllString(target, "/") |
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.
tiny nit: this could be a match target = target[3:] or ReplaceAllLiteralString
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.
Need to check this. I'm still not as good with Go lang as I would want to. Thank you for the hints.
6881ca3
to
4ab3beb
Compare
Applied some refactoring. Now getting paths and then processing of source, target, options are dedicated functions, which could be shared or platform specific. Applied some changes to source to target path conversion on Windows. Now algorithm looks more straight forward (at least to me).
|
4ab3beb
to
d9b9248
Compare
Updated example https://go.dev/play/p/Do-tBPHESLE |
Will fix linters in the morning and resubmit. |
fcc60c0
to
ec39837
Compare
@n1hility PTAL |
Sharing my opinion and giving some more insights. Code changes are isolated in Windows specific sources (refactored parts should not change current behavior), but Windows parts for now are also cut by the Compiler/Linker process, because QEMU is not yet referenced in the list of available machines for Windows. From my point of view, changes are safe looking and there is no need to delay it if possible, but there is no any business justification to include it in the current release, because it changes no behavior within the supported feature set. |
pkg/machine/qemu/machine_windows.go
Outdated
target := strings.ReplaceAll(paths[0], "\\", "/") | ||
target = strings.ReplaceAll(target, ":", "/") | ||
target = strings.ReplaceAll(target, "//./", "") | ||
target = strings.ReplaceAll(target, "//?/", "") |
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.
A minor nit, but not a blocker, is that these namespace prefixes can only occur at the start of the string, so you could just do something like:
if strings.HasPrefix(path, "//./") || strings.HasPrefix(path, "//?/") {
path = path[4:]
}
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.
Thanks. This is better indeed and more correct as we are eliminating only prefixes.
Applied as part of the same commit. Last line was changed to fix output of gofmt -d -s
.
@@ -42,10 +42,11 @@ func extractTargetPath(paths []string) string {
if len(paths) > 1 {
return paths[1]
}
target := strings.ReplaceAll(paths[0], "\\", "/")
target = strings.ReplaceAll(target, ":", "/")
- target = strings.ReplaceAll(target, "//./", "")
- target = strings.ReplaceAll(target, "//?/", "")
+ if strings.HasPrefix(target, "//./") || strings.HasPrefix(target, "//?/") {
+ target = target[4:]
+ }
dedup := regexp.MustCompile(`//+`)
- return dedup.ReplaceAllLiteralString("/" + target, "/")
+ return dedup.ReplaceAllLiteralString("/"+target, "/")
}
Other than the above nit LGTM. |
There are 2 things added. First there is added support for handling drive letters while doing value split. If drive letter is detected, then max number of elements will be increased by one, but then first two will be concatenated to reconstruct the path. Second part is basic, but working, conversion of Windows path to Unix path to be used, when target path is not explicitly specified. Signed-off-by: Arthur Sengileyev <[email protected]>
ec39837
to
952049f
Compare
@n1hility Thank you for the context and explaining some background processes to the community contributors. I noticed this already, when my gvproxy/installer PR was cherry-picked for the release branch. Thus, I tried to explain my opinion, that there is no need to backport this changes to the release branch, because they are more of a ground for some future work. |
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: arixmkii, rhatdan The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Fixes #17098
Was tested as part of #13006 (comment)
Implementation demo isolated https://go.dev/play/p/Do-tBPHESLE (
Original outdated version)There are 2 things added. First there is added support for handling drive letters while doing value split. If drive letter is detected, then max number of elements will be increased by one, but then first two will be concatenated to reconstruct the path. Second part is basic, but working conversion of Windows path to Unix to be used, when target path is not explicitly specified.
Used regex for drive letter detection, because init would be never used in the hotpath, so, performance wise it affordable.
Signed-off-by: Arthur Sengileyev [email protected]
[NO NEW TESTS NEEDED]
Does this PR introduce a user-facing change?