-
Notifications
You must be signed in to change notification settings - Fork 0
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
Build mountinfo
on multiple platforms
#3
Conversation
It functions the same as before this commit on Linux OSs that use the `sysfs` pseudo filesystem, and will now work on macOS through the use of the OS tools `stat` and `diskutil`. Windows, Solaris, Plan9, etc... are currently not supported. `go build` should work on those operating systems, and this commit includes a shim for Windows: `device_windows.go`. I did notice that `GOOS=plan9 GOARCH=amd64 go build` failed because a transitive dependency does not support Plan9. move functions into new platform-specific files. The entrypoint for the platform-specific code is the `discoverDeviceName` function. move the `Test_DeviceName_Snapshots` function from `info_test.go` to `info_linux_test.go` so that the Linux test file will run a smoke test on `CWD` and also a test representing other mounted filesystems. Copy `Test_DeviceName_SmokeTest` from `info_linux_test.go` to `info_test.go` so that other operating systems will run the smoke test. upgrade all dependencies and add a new dependency: `github.com/moby/sys/mountinfo` to handle reading mount info in order to find the `sysfs` mount point. `discoverDeviceName` implementation for non-Unix/Linux/Windows operating systems. Currently returns a "not implemented" error. `discoverDeviceName` implementation for macOS. Uses `stat` and `diskutil`. `discoverDeviceName` implementation for Linux. Uses device identifier numbers and the `sysfs` pseudo filesystem to find block devices. Does not work for non-block devices (like Docker bind mounts). functions that work on both Unix and Linux (and derivative) operating systems, but not on others. This is where the `golang.org/x/sys/unix` package is used to stat files in order to find the device identifier numbers. `discoverDeviceName` implementation for Windows. Currently returns a "not implemented" error. Run `go test -v` on various platforms. `go test -v` will run a smoke test using the current working directory. The result should be a PASS, and if you provide the verbose option (`-v`), you'll see which device name was found from the current working directory. If you don't have Linux readily available, you can use Docker. From the project directory, run this command to launch a Go container and `go test` the project: ``` docker run --rm --volume $(pwd):/src --volume mountinfo_test:/test --volume ${GOPATH:-${HOME}/go}:/go --interactive --workdir /test golang bash <<EOF cp -R /src/* . go test -v EOF ``` The result should be a PASS, and if you provide the verbose option (`-v`), you'll see which device names were found in the tests. Afterward, you can clean up the `mountinfo_test` volume if you want ``` docker volume rm mountinfo_test ``` There is a stub for windows - `device_windows.go` - but it currently returns an error, which is by design, so `go test` on Windows will result in a FAIL with a "not implemented on windows" error message. We may be able to make this work on windows using the `DeviceIoControl` API, which is exposed in the `golang.org/x/sys/windows` package, alng with `STORAGE_PROPERTY_ID` and `STORAGE_DEVICE_ID_DESCRIPTOR` to get the SCSI device IDs. These device IDs may not be exactly what we need - `mountinfo` provides metrics for Prometheus, so the SCSI device IDs may be too long to be useful. There is a catch-all stub for unsupported operating systems, such as Plan9 and Solaris - `device.go`. It will return a "not implemented on [GOOS]" error message, so `go test` will FAIL. This is by design.
macOS impl looks good to me. Were there any changes to the Linux implementation, or was it just moving it to a separate file so it could be guarded by a build flag? I didn't review the Linux impl too closely. Higher-level question: do we a macOS implementation at all? I think it's safe to assume that binaries running on macOS will all be local instances. If that's the case, should we run Prometheus at all or just avoid the monitoring stack altogether? |
Co-authored-by: Beyang Liu <[email protected]>
The Linux implementation is basically unchanged. Code was moved around so it could conform to build constraints, and I changed some things to enable mocking for testing instead of requiring a struct to be passed in all of the time. I agree with your assumptions about macOS implementations, and we probably won't actually need the monitoring stack. I wrote it as more of a PoC to validate my multi-platform approach and figured I'd leave it in place because it'll be useful as a template, and in the off chance that it's useful at runtime. |
Build
mountinfo
on multiple platformsIt functions the same as before this commit on Linux OSs that use the
sysfs
pseudo filesystem, and will now work on macOS through the use of the OS toolsstat
anddiskutil
. Windows, Solaris, Plan9, etc... are currently not supported.go build
should work on those operating systems, and this commit includes a shim for Windows:device_windows.go
. I did notice thatGOOS=plan9 GOARCH=amd64 go build
failed because a transitive dependency does not support Plan9.Changed files
info.go
move functions into new platform-specific files. The entrypoint for the platform-specific code is the
discoverDeviceName
function.info_linux_test.go and info_test.go
move the
Test_DeviceName_Snapshots
function frominfo_test.go
toinfo_linux_test.go
so that the Linux test file will run a smoke test onCWD
and also a test representing other mounted filesystems. CopyTest_DeviceName_SmokeTest
frominfo_linux_test.go
toinfo_test.go
so that other operating systems will run the smoke test.go.mod and go.sum
upgrade all dependencies and add a new dependency:
github.com/moby/sys/mountinfo
to handle reading mount info in order to find thesysfs
mount point.New files
device.go
discoverDeviceName
implementation for non-Unix/Linux/Windows operating systems. Currently returns a "not implemented" error.device_darwin.go
discoverDeviceName
implementation for macOS. Usesstat
anddiskutil
.device_linux.go
discoverDeviceName
implementation for Linux. Uses device identifier numbers and thesysfs
pseudo filesystem to find block devices. Does not work for non-block devices (like Docker bind mounts).device_unix.go
functions that work on both Unix and Linux (and derivative) operating systems, but not on others. This is where the
golang.org/x/sys/unix
package is used to stat files in order to find the device identifier numbers.device_windows.go
discoverDeviceName
implementation for Windows. Currently returns a "not implemented" error.Test Plan
Run
go test -v
on various platforms.macOS
go test -v
will run a smoke test using the current working directory. The result should be a PASS, and if you provide the verbose option (-v
), you'll see which device name was found from the current working directory.Linux
If you don't have Linux readily available, you can use Docker. From the project directory, run this command to launch a Go container and
go test
the project:The result should be a PASS, and if you provide the verbose option (
-v
), you'll see which device names were found in the tests.Afterward, you can clean up the
mountinfo_test
volume if you wantWindows
There is a stub for windows -
device_windows.go
- but it currently returns an error, which is by design, sogo test
on Windows will result in a FAIL with a "not implemented on windows" error message.We may be able to make this work on windows using the
DeviceIoControl
API, which is exposed in thegolang.org/x/sys/windows
package, alng withSTORAGE_PROPERTY_ID
andSTORAGE_DEVICE_ID_DESCRIPTOR
to get the SCSI device IDs. These device IDs may not be exactly what we need -mountinfo
provides metrics for Prometheus, so the SCSI device IDs may be too long to be useful.Other Operating Systems
There is a catch-all stub for unsupported operating systems, such as Plan9 and Solaris -
device.go
. It will return a "not implemented on [GOOS]" error message, sogo test
will FAIL. This is by design.