mirror of
https://github.com/NVIDIA/nvidia-container-toolkit
synced 2025-06-26 18:18:24 +00:00
Compare commits
93 Commits
v1.11.0-rc
...
v1.12.0-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6a68c4add | ||
|
|
e588bfac7d | ||
|
|
224020533e | ||
|
|
3736bb3aca | ||
|
|
1e72f92b74 | ||
|
|
896f5b2e9f | ||
|
|
c068d4048f | ||
|
|
8796cd76b0 | ||
|
|
1597ede2af | ||
|
|
3dd8020695 | ||
|
|
dfa041991f | ||
|
|
568896742b | ||
|
|
f52973217f | ||
|
|
efd29f1cec | ||
|
|
4b02670049 | ||
|
|
8550874686 | ||
|
|
38513d5a53 | ||
|
|
a35236a8f6 | ||
|
|
0c2e72b7c1 | ||
|
|
f0bdfbebe4 | ||
|
|
a4fa61d05d | ||
|
|
6e23a635c6 | ||
|
|
4dedac6a24 | ||
|
|
8c1b9b33c1 | ||
|
|
d37c17857e | ||
|
|
a0065456d0 | ||
|
|
a34a571d2e | ||
|
|
bb4cfece61 | ||
|
|
b16d263ee7 | ||
|
|
027395bb8a | ||
|
|
3ecd790206 | ||
|
|
52bb9e186b | ||
|
|
68b6d1cab1 | ||
|
|
bdb67b4fba | ||
|
|
d0c39a11d5 | ||
|
|
9de6361938 | ||
|
|
fb016dca86 | ||
|
|
a9fb7a4a88 | ||
|
|
b5dbcaeaf9 | ||
|
|
80a46d4a5c | ||
|
|
febce822d5 | ||
|
|
e8099a713c | ||
|
|
d9de4a09b8 | ||
|
|
2dbcda2619 | ||
|
|
691b93ffb0 | ||
|
|
cb0c94cd40 | ||
|
|
3168718563 | ||
|
|
dc8972a26a | ||
|
|
0a2d8f4d22 | ||
|
|
8d623967ed | ||
|
|
503ed96275 | ||
|
|
d8ba84d427 | ||
|
|
8e8c41a3bc | ||
|
|
e34fe17b45 | ||
|
|
c5b0278c58 | ||
|
|
8daa257b35 | ||
|
|
6329174cfc | ||
|
|
1ec41c1bf1 | ||
|
|
581a76de38 | ||
|
|
5d52ca8909 | ||
|
|
ad7151d394 | ||
|
|
3269a7b0e7 | ||
|
|
6a155cc606 | ||
|
|
a5bbf613e8 | ||
|
|
22427c1359 | ||
|
|
f17121fd6c | ||
|
|
256e37eb3f | ||
|
|
bdfd123b9d | ||
|
|
3f7dce202a | ||
|
|
a6d21abe14 | ||
|
|
d0f1fe2273 | ||
|
|
8de9593209 | ||
|
|
64b2b50470 | ||
|
|
4dc1451c49 | ||
|
|
211081ff25 | ||
|
|
c1c1d5cf8e | ||
|
|
e91ffef258 | ||
|
|
47c8aa3790 | ||
|
|
33b4e7fb0a | ||
|
|
936da0295b | ||
|
|
c2205c14fb | ||
|
|
56935f5743 | ||
|
|
1b3bae790c | ||
|
|
47559a8c87 | ||
|
|
86412ea821 | ||
|
|
b8aa844171 | ||
|
|
f9464c5cf9 | ||
|
|
9df75e1fa3 | ||
|
|
0218e2ebf7 | ||
|
|
a9dc6550d5 | ||
|
|
ffd6ec3c54 | ||
|
|
de3e0df96c | ||
|
|
e5dadf34d9 |
@@ -34,12 +34,23 @@ stages:
|
||||
- scan
|
||||
- release
|
||||
|
||||
.main-or-manual:
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
- if: $CI_COMMIT_TAG && $CI_COMMIT_TAG != ""
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
when: manual
|
||||
|
||||
# Define the distribution targets
|
||||
.dist-amazonlinux2:
|
||||
rules:
|
||||
- !reference [.main-or-manual, rules]
|
||||
variables:
|
||||
DIST: amazonlinux2
|
||||
|
||||
.dist-centos7:
|
||||
rules:
|
||||
- !reference [.main-or-manual, rules]
|
||||
variables:
|
||||
DIST: centos7
|
||||
CVE_UPDATES: "cyrus-sasl-lib"
|
||||
@@ -50,23 +61,39 @@ stages:
|
||||
CVE_UPDATES: "cyrus-sasl-lib"
|
||||
|
||||
.dist-debian10:
|
||||
rules:
|
||||
- !reference [.main-or-manual, rules]
|
||||
variables:
|
||||
DIST: debian10
|
||||
|
||||
.dist-debian9:
|
||||
rules:
|
||||
- !reference [.main-or-manual, rules]
|
||||
variables:
|
||||
DIST: debian9
|
||||
|
||||
.dist-fedora35:
|
||||
rules:
|
||||
- !reference [.main-or-manual, rules]
|
||||
variables:
|
||||
DIST: fedora35
|
||||
|
||||
.dist-opensuse-leap15.1:
|
||||
rules:
|
||||
- !reference [.main-or-manual, rules]
|
||||
variables:
|
||||
DIST: opensuse-leap15.1
|
||||
|
||||
.dist-ubi8:
|
||||
rules:
|
||||
- !reference [.main-or-manual, rules]
|
||||
variables:
|
||||
DIST: ubi8
|
||||
CVE_UPDATES: "cyrus-sasl-lib"
|
||||
|
||||
.dist-ubuntu16.04:
|
||||
rules:
|
||||
- !reference [.main-or-manual, rules]
|
||||
variables:
|
||||
DIST: ubuntu16.04
|
||||
|
||||
@@ -76,6 +103,8 @@ stages:
|
||||
CVE_UPDATES: "libsasl2-2 libsasl2-modules-db"
|
||||
|
||||
.dist-ubuntu20.04:
|
||||
rules:
|
||||
- !reference [.main-or-manual, rules]
|
||||
variables:
|
||||
DIST: ubuntu20.04
|
||||
CVE_UPDATES: "libsasl2-2 libsasl2-modules-db"
|
||||
@@ -98,6 +127,8 @@ stages:
|
||||
ARCH: arm64
|
||||
|
||||
.arch-ppc64le:
|
||||
rules:
|
||||
- !reference [.main-or-manual, rules]
|
||||
variables:
|
||||
ARCH: ppc64le
|
||||
|
||||
@@ -232,10 +263,7 @@ release:staging-ubuntu20.04:
|
||||
- .release:staging
|
||||
- .dist-ubuntu20.04
|
||||
needs:
|
||||
- test-toolkit-ubuntu20.04
|
||||
- test-containerd-ubuntu20.04
|
||||
- test-crio-ubuntu20.04
|
||||
- test-docker-ubuntu20.04
|
||||
- image-ubuntu20.04
|
||||
|
||||
release:staging-packaging:
|
||||
extends:
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,6 +4,8 @@ dist
|
||||
/coverage.out*
|
||||
/test/output/
|
||||
/nvidia-container-runtime
|
||||
/nvidia-container-runtime-hook
|
||||
/nvidia-container-toolkit
|
||||
/nvidia-ctk
|
||||
/shared-*
|
||||
/release-*
|
||||
@@ -94,7 +94,7 @@ unit-tests:
|
||||
- .multi-arch-build
|
||||
- .package-artifacts
|
||||
stage: package-build
|
||||
timeout: 2h 30m
|
||||
timeout: 3h
|
||||
script:
|
||||
- ./scripts/build-packages.sh ${DIST}-${ARCH}
|
||||
|
||||
@@ -158,6 +158,18 @@ package-debian9-amd64:
|
||||
- .dist-debian9
|
||||
- .arch-amd64
|
||||
|
||||
package-fedora35-aarch64:
|
||||
extends:
|
||||
- .package-build
|
||||
- .dist-fedora35
|
||||
- .arch-aarch64
|
||||
|
||||
package-fedora35-x86_64:
|
||||
extends:
|
||||
- .package-build
|
||||
- .dist-fedora35
|
||||
- .arch-x86_64
|
||||
|
||||
package-opensuse-leap15.1-x86_64:
|
||||
extends:
|
||||
- .package-build
|
||||
@@ -250,7 +262,8 @@ image-ubuntu18.04:
|
||||
needs:
|
||||
- package-ubuntu18.04-amd64
|
||||
- package-ubuntu18.04-arm64
|
||||
- package-ubuntu18.04-ppc64le
|
||||
- job: package-ubuntu18.04-ppc64le
|
||||
optional: true
|
||||
|
||||
image-ubuntu20.04:
|
||||
extends:
|
||||
@@ -269,21 +282,36 @@ image-packaging:
|
||||
- .package-artifacts
|
||||
- .dist-packaging
|
||||
needs:
|
||||
- package-amazonlinux2-aarch64
|
||||
- package-amazonlinux2-x86_64
|
||||
- package-centos7-ppc64le
|
||||
- package-centos7-x86_64
|
||||
- package-centos8-aarch64
|
||||
- package-centos8-ppc64le
|
||||
- package-centos8-x86_64
|
||||
- package-debian10-amd64
|
||||
- package-debian9-amd64
|
||||
- package-opensuse-leap15.1-x86_64
|
||||
- package-ubuntu16.04-amd64
|
||||
- package-ubuntu16.04-ppc64le
|
||||
- package-ubuntu18.04-amd64
|
||||
- package-ubuntu18.04-arm64
|
||||
- package-ubuntu18.04-ppc64le
|
||||
- job: package-centos8-aarch64
|
||||
- job: package-centos8-x86_64
|
||||
- job: package-ubuntu18.04-amd64
|
||||
- job: package-ubuntu18.04-arm64
|
||||
- job: package-amazonlinux2-aarch64
|
||||
optional: true
|
||||
- job: package-amazonlinux2-x86_64
|
||||
optional: true
|
||||
- job: package-centos7-ppc64le
|
||||
optional: true
|
||||
- job: package-centos7-x86_64
|
||||
optional: true
|
||||
- job: package-centos8-ppc64le
|
||||
optional: true
|
||||
- job: package-debian10-amd64
|
||||
optional: true
|
||||
- job: package-debian9-amd64
|
||||
optional: true
|
||||
- job: package-fedora35-aarch64
|
||||
optional: true
|
||||
- job: package-fedora35-x86_64
|
||||
optional: true
|
||||
- job: package-opensuse-leap15.1-x86_64
|
||||
optional: true
|
||||
- job: package-ubuntu16.04-amd64
|
||||
optional: true
|
||||
- job: package-ubuntu16.04-ppc64le
|
||||
optional: true
|
||||
- job: package-ubuntu18.04-ppc64le
|
||||
optional: true
|
||||
|
||||
# Define publish test helpers
|
||||
.test:toolkit:
|
||||
@@ -343,31 +371,3 @@ test-docker-ubuntu18.04:
|
||||
needs:
|
||||
- image-ubuntu18.04
|
||||
|
||||
test-toolkit-ubuntu20.04:
|
||||
extends:
|
||||
- .test:toolkit
|
||||
- .dist-ubuntu20.04
|
||||
needs:
|
||||
- image-ubuntu20.04
|
||||
|
||||
test-containerd-ubuntu20.04:
|
||||
extends:
|
||||
- .test:containerd
|
||||
- .dist-ubuntu20.04
|
||||
needs:
|
||||
- image-ubuntu20.04
|
||||
|
||||
test-crio-ubuntu20.04:
|
||||
extends:
|
||||
- .test:crio
|
||||
- .dist-ubuntu20.04
|
||||
needs:
|
||||
- image-ubuntu20.04
|
||||
|
||||
test-docker-ubuntu20.04:
|
||||
extends:
|
||||
- .test:docker
|
||||
- .dist-ubuntu20.04
|
||||
needs:
|
||||
- image-ubuntu20.04
|
||||
|
||||
|
||||
@@ -48,8 +48,9 @@ variables:
|
||||
OUT_IMAGE_NAME: "${CI_REGISTRY_IMAGE}/container-toolkit"
|
||||
PUSH_MULTIPLE_TAGS: "false"
|
||||
# We delay the job start to allow the public pipeline to generate the required images.
|
||||
when: delayed
|
||||
start_in: 30 minutes
|
||||
rules:
|
||||
- when: delayed
|
||||
start_in: 30 minutes
|
||||
timeout: 30 minutes
|
||||
retry:
|
||||
max: 2
|
||||
@@ -67,29 +68,29 @@ variables:
|
||||
|
||||
image-centos7:
|
||||
extends:
|
||||
- .image-pull
|
||||
- .dist-centos7
|
||||
- .image-pull
|
||||
|
||||
image-ubi8:
|
||||
extends:
|
||||
- .image-pull
|
||||
- .dist-ubi8
|
||||
- .image-pull
|
||||
|
||||
image-ubuntu18.04:
|
||||
extends:
|
||||
- .image-pull
|
||||
- .dist-ubuntu18.04
|
||||
- .image-pull
|
||||
|
||||
image-ubuntu20.04:
|
||||
extends:
|
||||
- .image-pull
|
||||
- .dist-ubuntu20.04
|
||||
- .image-pull
|
||||
|
||||
# The DIST=packaging target creates an image containing all built packages
|
||||
image-packaging:
|
||||
extends:
|
||||
- .image-pull
|
||||
- .dist-packaging
|
||||
- .image-pull
|
||||
|
||||
# We skip the integration tests for the internal CI:
|
||||
.integration:
|
||||
@@ -107,9 +108,9 @@ image-packaging:
|
||||
variables:
|
||||
IMAGE: "${CI_REGISTRY_IMAGE}/container-toolkit:${CI_COMMIT_SHORT_SHA}-${DIST}"
|
||||
IMAGE_ARCHIVE: "container-toolkit.tar"
|
||||
except:
|
||||
variables:
|
||||
- $SKIP_SCANS && $SKIP_SCANS == "yes"
|
||||
rules:
|
||||
- if: $SKIP_SCANS != "yes"
|
||||
- when: manual
|
||||
before_script:
|
||||
- docker login -u "${CI_REGISTRY_USER}" -p "${CI_REGISTRY_PASSWORD}" "${CI_REGISTRY}"
|
||||
# TODO: We should specify the architecture here and scan all architectures
|
||||
@@ -134,59 +135,59 @@ image-packaging:
|
||||
# Define the scan targets
|
||||
scan-centos7-amd64:
|
||||
extends:
|
||||
- .scan
|
||||
- .dist-centos7
|
||||
- .platform-amd64
|
||||
- .scan
|
||||
needs:
|
||||
- image-centos7
|
||||
|
||||
scan-centos7-arm64:
|
||||
extends:
|
||||
- .scan
|
||||
- .dist-centos7
|
||||
- .platform-arm64
|
||||
- .scan
|
||||
needs:
|
||||
- image-centos7
|
||||
- scan-centos7-amd64
|
||||
|
||||
scan-ubuntu18.04-amd64:
|
||||
extends:
|
||||
- .scan
|
||||
- .dist-ubuntu18.04
|
||||
- .platform-amd64
|
||||
- .scan
|
||||
needs:
|
||||
- image-ubuntu18.04
|
||||
|
||||
scan-ubuntu20.04-amd64:
|
||||
extends:
|
||||
- .scan
|
||||
- .dist-ubuntu20.04
|
||||
- .platform-amd64
|
||||
- .scan
|
||||
needs:
|
||||
- image-ubuntu20.04
|
||||
|
||||
scan-ubuntu20.04-arm64:
|
||||
extends:
|
||||
- .scan
|
||||
- .dist-ubuntu20.04
|
||||
- .platform-arm64
|
||||
- .scan
|
||||
needs:
|
||||
- image-ubuntu20.04
|
||||
- scan-ubuntu20.04-amd64
|
||||
|
||||
scan-ubi8-amd64:
|
||||
extends:
|
||||
- .scan
|
||||
- .dist-ubi8
|
||||
- .platform-amd64
|
||||
- .scan
|
||||
needs:
|
||||
- image-ubi8
|
||||
|
||||
scan-ubi8-arm64:
|
||||
extends:
|
||||
- .scan
|
||||
- .dist-ubi8
|
||||
- .platform-arm64
|
||||
- .scan
|
||||
needs:
|
||||
- image-ubi8
|
||||
- scan-ubi8-amd64
|
||||
@@ -208,31 +209,24 @@ release:staging-ubuntu18.04:
|
||||
needs:
|
||||
- image-ubuntu18.04
|
||||
|
||||
release:staging-ubuntu20.04:
|
||||
extends:
|
||||
- .release:staging
|
||||
- .dist-ubuntu20.04
|
||||
needs:
|
||||
- image-ubuntu20.04
|
||||
|
||||
# Define the external release targets
|
||||
# Release to NGC
|
||||
release:ngc-centos7:
|
||||
extends:
|
||||
- .release:ngc
|
||||
- .dist-centos7
|
||||
- .release:ngc
|
||||
|
||||
release:ngc-ubuntu18.04:
|
||||
extends:
|
||||
- .release:ngc
|
||||
- .dist-ubuntu18.04
|
||||
- .release:ngc
|
||||
|
||||
release:ngc-ubuntu20.04:
|
||||
extends:
|
||||
- .release:ngc
|
||||
- .dist-ubuntu20.04
|
||||
- .release:ngc
|
||||
|
||||
release:ngc-ubi8:
|
||||
extends:
|
||||
- .release:ngc
|
||||
- .dist-ubi8
|
||||
- .release:ngc
|
||||
|
||||
23
CHANGELOG.md
23
CHANGELOG.md
@@ -1,11 +1,30 @@
|
||||
# NVIDIA Container Toolkit Changelog
|
||||
|
||||
## v1.11.1-rc.2
|
||||
## v1.12.0-rc.1
|
||||
|
||||
* Add support for multiple Docker Swarm resources
|
||||
* Improve injection of Vulkan configurations and libraries
|
||||
* Add `nvidia-ctk info generate-cdi` command to generated CDI specification for available devices
|
||||
* [libnvidia-container] Include NVVM compiler library in compute libs
|
||||
## v1.11.0
|
||||
|
||||
* Promote v1.11.0-rc.3 to v1.11.0
|
||||
|
||||
## v1.11.0-rc.3
|
||||
|
||||
* Build fedora35 packages
|
||||
* Introduce an `nvidia-container-toolkit-base` package for better dependency management
|
||||
* Fix removal of `nvidia-container-runtime-hook` on RPM-based systems
|
||||
* Inject platform files into container on Tegra-based systems
|
||||
* [toolkit container] Update CUDA base images to 11.7.1
|
||||
* [libnvidia-container] Preload libgcc_s.so.1 on arm64 systems
|
||||
|
||||
## v1.11.0-rc.2
|
||||
|
||||
* Allow `accept-nvidia-visible-devices-*` config options to be set by toolkit container
|
||||
* [libnvidia-container] Fix bug where LDCache was not updated when the `--no-pivot-root` option was specified
|
||||
|
||||
## v1.11.1-rc.1
|
||||
## v1.11.0-rc.1
|
||||
|
||||
* Add discovery of GPUDirect Storage (`nvidia-fs*`) devices if the `NVIDIA_GDS` environment variable of the container is set to `enabled`
|
||||
* Add discovery of MOFED Infiniband devices if the `NVIDIA_MOFED` environment variable of the container is set to `enabled`
|
||||
|
||||
3
Makefile
3
Makefile
@@ -51,6 +51,7 @@ CLI_VERSION = $(LIB_VERSION)$(if $(LIB_TAG),-$(LIB_TAG))
|
||||
else
|
||||
CLI_VERSION = $(VERSION)
|
||||
endif
|
||||
CLI_VERSION_PACKAGE = github.com/NVIDIA/nvidia-container-toolkit/internal/info
|
||||
|
||||
GOOS ?= linux
|
||||
|
||||
@@ -60,7 +61,7 @@ cmd-%: COMMAND_BUILD_OPTIONS = -o $(PREFIX)/$(*)
|
||||
endif
|
||||
cmds: $(CMD_TARGETS)
|
||||
$(CMD_TARGETS): cmd-%:
|
||||
GOOS=$(GOOS) go build -ldflags "-s -w -X github.com/NVIDIA/nvidia-container-toolkit/internal/info.gitCommit=$(GIT_COMMIT) -X github.com/NVIDIA/nvidia-container-toolkit/internal/info.version=$(CLI_VERSION)" $(COMMAND_BUILD_OPTIONS) $(MODULE)/cmd/$(*)
|
||||
GOOS=$(GOOS) go build -ldflags "-s -w -X $(CLI_VERSION_PACKAGE).gitCommit=$(GIT_COMMIT) -X $(CLI_VERSION_PACKAGE).version=$(CLI_VERSION)" $(COMMAND_BUILD_OPTIONS) $(MODULE)/cmd/$(*)
|
||||
|
||||
build:
|
||||
GOOS=$(GOOS) go build ./...
|
||||
|
||||
@@ -69,7 +69,7 @@ RUN PACKAGE_ARCH=${PACKAGE_ARCH/amd64/x86_64} && PACKAGE_ARCH=${PACKAGE_ARCH/arm
|
||||
yum localinstall -y \
|
||||
${PACKAGE_DIST}/${PACKAGE_ARCH}/libnvidia-container1-1.*.rpm \
|
||||
${PACKAGE_DIST}/${PACKAGE_ARCH}/libnvidia-container-tools-1.*.rpm \
|
||||
${PACKAGE_DIST}/${PACKAGE_ARCH}/nvidia-container-toolkit-${PACKAGE_VERSION}*.rpm
|
||||
${PACKAGE_DIST}/${PACKAGE_ARCH}/nvidia-container-toolkit*-${PACKAGE_VERSION}*.rpm
|
||||
|
||||
WORKDIR /work
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ RUN if [ "${PACKAGE_ARCH}" = "arm64" ]; then \
|
||||
RUN dpkg -i \
|
||||
${PACKAGE_DIST}/${PACKAGE_ARCH}/libnvidia-container1_1.*.deb \
|
||||
${PACKAGE_DIST}/${PACKAGE_ARCH}/libnvidia-container-tools_1.*.deb \
|
||||
${PACKAGE_DIST}/${PACKAGE_ARCH}/nvidia-container-toolkit_${PACKAGE_VERSION}*.deb
|
||||
${PACKAGE_DIST}/${PACKAGE_ARCH}/nvidia-container-toolkit*_${PACKAGE_VERSION}*.deb
|
||||
|
||||
WORKDIR /work
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ import (
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
var envSwarmGPU *string
|
||||
|
||||
const (
|
||||
envCUDAVersion = "CUDA_VERSION"
|
||||
envNVRequirePrefix = "NVIDIA_REQUIRE_"
|
||||
@@ -165,13 +163,9 @@ func isPrivileged(s *Spec) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func getDevicesFromEnvvar(image image.CUDA) *string {
|
||||
// Build a list of envvars to consider.
|
||||
envVars := []string{envNVVisibleDevices}
|
||||
if envSwarmGPU != nil {
|
||||
// The Swarm envvar has higher precedence.
|
||||
envVars = append([]string{*envSwarmGPU}, envVars...)
|
||||
}
|
||||
func getDevicesFromEnvvar(image image.CUDA, swarmResourceEnvvars []string) *string {
|
||||
// Build a list of envvars to consider. Note that the Swarm Resource envvars have a higher precedence.
|
||||
envVars := append(swarmResourceEnvvars, envNVVisibleDevices)
|
||||
|
||||
devices := image.DevicesFromEnvvars(envVars...)
|
||||
if len(devices) == 0 {
|
||||
@@ -230,7 +224,7 @@ func getDevices(hookConfig *HookConfig, image image.CUDA, mounts []Mount, privil
|
||||
}
|
||||
|
||||
// Fallback to reading from the environment variable if privileges are correct
|
||||
devices := getDevicesFromEnvvar(image)
|
||||
devices := getDevicesFromEnvvar(image, hookConfig.getSwarmResourceEnvvars())
|
||||
if devices == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -348,7 +342,6 @@ func getContainerConfig(hook HookConfig) (config containerConfig) {
|
||||
}
|
||||
|
||||
privileged := isPrivileged(s)
|
||||
envSwarmGPU = hook.SwarmResource
|
||||
return containerConfig{
|
||||
Pid: h.Pid,
|
||||
Rootfs: s.Root.Path,
|
||||
|
||||
@@ -69,7 +69,7 @@ func TestGetNvidiaConfig(t *testing.T) {
|
||||
description: "Legacy image, devices 'void', no capabilities, no requirements",
|
||||
env: map[string]string{
|
||||
envCUDAVersion: "9.0",
|
||||
envNVVisibleDevices: "",
|
||||
envNVVisibleDevices: "void",
|
||||
},
|
||||
privileged: false,
|
||||
expectedConfig: nil,
|
||||
@@ -226,7 +226,7 @@ func TestGetNvidiaConfig(t *testing.T) {
|
||||
description: "Modern image, devices 'void', no capabilities, no requirements",
|
||||
env: map[string]string{
|
||||
envNVRequireCUDA: "cuda>=9.0",
|
||||
envNVVisibleDevices: "",
|
||||
envNVVisibleDevices: "void",
|
||||
},
|
||||
privileged: false,
|
||||
expectedConfig: nil,
|
||||
@@ -449,6 +449,44 @@ func TestGetNvidiaConfig(t *testing.T) {
|
||||
DriverCapabilities: defaultDriverCapabilities.String(),
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Hook config set, swarmResource overrides device selection",
|
||||
env: map[string]string{
|
||||
envNVVisibleDevices: "all",
|
||||
"DOCKER_SWARM_RESOURCE": "GPU1,GPU2",
|
||||
},
|
||||
privileged: true,
|
||||
hookConfig: &HookConfig{
|
||||
SwarmResource: func() *string {
|
||||
s := "DOCKER_SWARM_RESOURCE"
|
||||
return &s
|
||||
}(),
|
||||
SupportedDriverCapabilities: "video,display,utility,compute",
|
||||
},
|
||||
expectedConfig: &nvidiaConfig{
|
||||
Devices: "GPU1,GPU2",
|
||||
DriverCapabilities: defaultDriverCapabilities.String(),
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Hook config set, comma separated swarmResource is split and overrides device selection",
|
||||
env: map[string]string{
|
||||
envNVVisibleDevices: "all",
|
||||
"DOCKER_SWARM_RESOURCE": "GPU1,GPU2",
|
||||
},
|
||||
privileged: true,
|
||||
hookConfig: &HookConfig{
|
||||
SwarmResource: func() *string {
|
||||
s := "NOT_DOCKER_SWARM_RESOURCE,DOCKER_SWARM_RESOURCE"
|
||||
return &s
|
||||
}(),
|
||||
SupportedDriverCapabilities: "video,display,utility,compute",
|
||||
},
|
||||
expectedConfig: &nvidiaConfig{
|
||||
Devices: "GPU1,GPU2",
|
||||
DriverCapabilities: defaultDriverCapabilities.String(),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
@@ -689,12 +727,13 @@ func TestGetDevicesFromEnvvar(t *testing.T) {
|
||||
envDockerResourceGPUs := "DOCKER_RESOURCE_GPUS"
|
||||
gpuID := "GPU-12345"
|
||||
anotherGPUID := "GPU-67890"
|
||||
thirdGPUID := "MIG-12345"
|
||||
|
||||
var tests = []struct {
|
||||
description string
|
||||
envSwarmGPU *string
|
||||
env map[string]string
|
||||
expectedDevices *string
|
||||
description string
|
||||
swarmResourceEnvvars []string
|
||||
env map[string]string
|
||||
expectedDevices *string
|
||||
}{
|
||||
{
|
||||
description: "empty env returns nil for non-legacy image",
|
||||
@@ -798,42 +837,42 @@ func TestGetDevicesFromEnvvar(t *testing.T) {
|
||||
// Add the `DOCKER_RESOURCE_GPUS` envvar and ensure that this is selected when
|
||||
// enabled
|
||||
{
|
||||
description: "empty env returns nil for non-legacy image",
|
||||
envSwarmGPU: &envDockerResourceGPUs,
|
||||
description: "empty env returns nil for non-legacy image",
|
||||
swarmResourceEnvvars: []string{envDockerResourceGPUs},
|
||||
},
|
||||
{
|
||||
description: "blank DOCKER_RESOURCE_GPUS returns nil for non-legacy image",
|
||||
envSwarmGPU: &envDockerResourceGPUs,
|
||||
description: "blank DOCKER_RESOURCE_GPUS returns nil for non-legacy image",
|
||||
swarmResourceEnvvars: []string{envDockerResourceGPUs},
|
||||
env: map[string]string{
|
||||
envDockerResourceGPUs: "",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "'void' DOCKER_RESOURCE_GPUS returns nil for non-legacy image",
|
||||
envSwarmGPU: &envDockerResourceGPUs,
|
||||
description: "'void' DOCKER_RESOURCE_GPUS returns nil for non-legacy image",
|
||||
swarmResourceEnvvars: []string{envDockerResourceGPUs},
|
||||
env: map[string]string{
|
||||
envDockerResourceGPUs: "void",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "'none' DOCKER_RESOURCE_GPUS returns empty for non-legacy image",
|
||||
envSwarmGPU: &envDockerResourceGPUs,
|
||||
description: "'none' DOCKER_RESOURCE_GPUS returns empty for non-legacy image",
|
||||
swarmResourceEnvvars: []string{envDockerResourceGPUs},
|
||||
env: map[string]string{
|
||||
envDockerResourceGPUs: "none",
|
||||
},
|
||||
expectedDevices: &empty,
|
||||
},
|
||||
{
|
||||
description: "DOCKER_RESOURCE_GPUS set returns value for non-legacy image",
|
||||
envSwarmGPU: &envDockerResourceGPUs,
|
||||
description: "DOCKER_RESOURCE_GPUS set returns value for non-legacy image",
|
||||
swarmResourceEnvvars: []string{envDockerResourceGPUs},
|
||||
env: map[string]string{
|
||||
envDockerResourceGPUs: gpuID,
|
||||
},
|
||||
expectedDevices: &gpuID,
|
||||
},
|
||||
{
|
||||
description: "DOCKER_RESOURCE_GPUS set returns value for legacy image",
|
||||
envSwarmGPU: &envDockerResourceGPUs,
|
||||
description: "DOCKER_RESOURCE_GPUS set returns value for legacy image",
|
||||
swarmResourceEnvvars: []string{envDockerResourceGPUs},
|
||||
env: map[string]string{
|
||||
envDockerResourceGPUs: gpuID,
|
||||
envCUDAVersion: "legacy",
|
||||
@@ -841,28 +880,55 @@ func TestGetDevicesFromEnvvar(t *testing.T) {
|
||||
expectedDevices: &gpuID,
|
||||
},
|
||||
{
|
||||
description: "DOCKER_RESOURCE_GPUS is selected if present",
|
||||
envSwarmGPU: &envDockerResourceGPUs,
|
||||
description: "DOCKER_RESOURCE_GPUS is selected if present",
|
||||
swarmResourceEnvvars: []string{envDockerResourceGPUs},
|
||||
env: map[string]string{
|
||||
envDockerResourceGPUs: anotherGPUID,
|
||||
},
|
||||
expectedDevices: &anotherGPUID,
|
||||
},
|
||||
{
|
||||
description: "DOCKER_RESOURCE_GPUS overrides NVIDIA_VISIBLE_DEVICES if present",
|
||||
envSwarmGPU: &envDockerResourceGPUs,
|
||||
description: "DOCKER_RESOURCE_GPUS overrides NVIDIA_VISIBLE_DEVICES if present",
|
||||
swarmResourceEnvvars: []string{envDockerResourceGPUs},
|
||||
env: map[string]string{
|
||||
envNVVisibleDevices: gpuID,
|
||||
envDockerResourceGPUs: anotherGPUID,
|
||||
},
|
||||
expectedDevices: &anotherGPUID,
|
||||
},
|
||||
{
|
||||
description: "DOCKER_RESOURCE_GPUS_ADDITIONAL overrides NVIDIA_VISIBLE_DEVICES if present",
|
||||
swarmResourceEnvvars: []string{"DOCKER_RESOURCE_GPUS_ADDITIONAL"},
|
||||
env: map[string]string{
|
||||
envNVVisibleDevices: gpuID,
|
||||
"DOCKER_RESOURCE_GPUS_ADDITIONAL": anotherGPUID,
|
||||
},
|
||||
expectedDevices: &anotherGPUID,
|
||||
},
|
||||
{
|
||||
description: "First available swarm resource envvar is selected and overrides NVIDIA_VISIBLE_DEVICES if present",
|
||||
swarmResourceEnvvars: []string{"DOCKER_RESOURCE_GPUS", "DOCKER_RESOURCE_GPUS_ADDITIONAL"},
|
||||
env: map[string]string{
|
||||
envNVVisibleDevices: gpuID,
|
||||
"DOCKER_RESOURCE_GPUS": thirdGPUID,
|
||||
"DOCKER_RESOURCE_GPUS_ADDITIONAL": anotherGPUID,
|
||||
},
|
||||
expectedDevices: &thirdGPUID,
|
||||
},
|
||||
{
|
||||
description: "DOCKER_RESOURCE_GPUS_ADDITIONAL or DOCKER_RESOURCE_GPUS overrides NVIDIA_VISIBLE_DEVICES if present",
|
||||
swarmResourceEnvvars: []string{"DOCKER_RESOURCE_GPUS", "DOCKER_RESOURCE_GPUS_ADDITIONAL"},
|
||||
env: map[string]string{
|
||||
envNVVisibleDevices: gpuID,
|
||||
"DOCKER_RESOURCE_GPUS_ADDITIONAL": anotherGPUID,
|
||||
},
|
||||
expectedDevices: &anotherGPUID,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range tests {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
envSwarmGPU = tc.envSwarmGPU
|
||||
devices := getDevicesFromEnvvar(image.CUDA(tc.env))
|
||||
devices := getDevicesFromEnvvar(image.CUDA(tc.env), tc.swarmResourceEnvvars)
|
||||
if tc.expectedDevices == nil {
|
||||
require.Nil(t, devices, "%d: %v", i, tc)
|
||||
return
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
|
||||
@@ -116,3 +117,22 @@ func (c HookConfig) getConfigOption(fieldName string) string {
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// getSwarmResourceEnvvars returns the swarm resource envvars for the config.
|
||||
func (c *HookConfig) getSwarmResourceEnvvars() []string {
|
||||
if c.SwarmResource == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
candidates := strings.Split(*c.SwarmResource, ",")
|
||||
|
||||
var envvars []string
|
||||
for _, c := range candidates {
|
||||
trimmed := strings.TrimSpace(c)
|
||||
if len(trimmed) > 0 {
|
||||
envvars = append(envvars, trimmed)
|
||||
}
|
||||
}
|
||||
|
||||
return envvars
|
||||
}
|
||||
|
||||
@@ -103,3 +103,59 @@ func TestGetHookConfig(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSwarmResourceEnvvars(t *testing.T) {
|
||||
testCases := []struct {
|
||||
value string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
value: "nil",
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
value: "",
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
value: " ",
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
value: "single",
|
||||
expected: []string{"single"},
|
||||
},
|
||||
{
|
||||
value: "single ",
|
||||
expected: []string{"single"},
|
||||
},
|
||||
{
|
||||
value: "one,two",
|
||||
expected: []string{"one", "two"},
|
||||
},
|
||||
{
|
||||
value: "one ,two",
|
||||
expected: []string{"one", "two"},
|
||||
},
|
||||
{
|
||||
value: "one, two",
|
||||
expected: []string{"one", "two"},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
c := &HookConfig{
|
||||
SwarmResource: func() *string {
|
||||
if tc.value == "nil" {
|
||||
return nil
|
||||
}
|
||||
return &tc.value
|
||||
}(),
|
||||
}
|
||||
|
||||
envvars := c.getSwarmResourceEnvvars()
|
||||
require.EqualValues(t, tc.expected, envvars)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,11 @@ func newSpecModifier(logger *logrus.Logger, cfg *config.Config, ociSpec oci.Spec
|
||||
return nil, err
|
||||
}
|
||||
|
||||
graphicsModifier, err := modifier.NewGraphicsModifier(logger, cfg, ociSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gdsModifier, err := modifier.NewGDSModifier(logger, cfg, ociSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -77,10 +82,17 @@ func newSpecModifier(logger *logrus.Logger, cfg *config.Config, ociSpec oci.Spec
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tegraModifier, err := modifier.NewTegraPlatformFiles(logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
modifiers := modifier.Merge(
|
||||
modeModifier,
|
||||
graphicsModifier,
|
||||
gdsModifier,
|
||||
mofedModifier,
|
||||
tegraModifier,
|
||||
)
|
||||
return modifiers, nil
|
||||
}
|
||||
|
||||
386
cmd/nvidia-ctk/info/generate-cdi/generate-cdi.go
Normal file
386
cmd/nvidia-ctk/info/generate-cdi/generate-cdi.go
Normal file
@@ -0,0 +1,386 @@
|
||||
/**
|
||||
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
**/
|
||||
|
||||
package cdi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/discover"
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/ldcache"
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup"
|
||||
specs "github.com/container-orchestrated-devices/container-device-interface/specs-go"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvlib/device"
|
||||
"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvml"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
const (
|
||||
nvidiaCTKExecutable = "nvidia-ctk"
|
||||
nvidiaCTKDefaultFilePath = "/usr/bin/" + nvidiaCTKExecutable
|
||||
)
|
||||
|
||||
type command struct {
|
||||
logger *logrus.Logger
|
||||
}
|
||||
|
||||
type config struct {
|
||||
output string
|
||||
jsonMode bool
|
||||
}
|
||||
|
||||
// NewCommand constructs a generate-cdi command with the specified logger
|
||||
func NewCommand(logger *logrus.Logger) *cli.Command {
|
||||
c := command{
|
||||
logger: logger,
|
||||
}
|
||||
return c.build()
|
||||
}
|
||||
|
||||
// build creates the CLI command
|
||||
func (m command) build() *cli.Command {
|
||||
cfg := config{}
|
||||
|
||||
// Create the 'generate-cdi' command
|
||||
c := cli.Command{
|
||||
Name: "generate-cdi",
|
||||
Usage: "Generate CDI specifications for use with CDI-enabled runtimes",
|
||||
Action: func(c *cli.Context) error {
|
||||
return m.run(c, &cfg)
|
||||
},
|
||||
}
|
||||
|
||||
c.Flags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "output",
|
||||
Usage: "Specify the file to output the generated CDI specification to. If this is '-' or '' the specification is output to STDOUT",
|
||||
Destination: &cfg.output,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "json",
|
||||
Usage: "Output the generated CDI spec in JSON mode instead of YAML",
|
||||
Destination: &cfg.jsonMode,
|
||||
},
|
||||
}
|
||||
|
||||
return &c
|
||||
}
|
||||
|
||||
func (m command) run(c *cli.Context, cfg *config) error {
|
||||
spec, err := m.generateSpec()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate CDI spec: %v", err)
|
||||
}
|
||||
|
||||
var outputTo io.Writer
|
||||
if cfg.output == "" || cfg.output == "-" {
|
||||
outputTo = os.Stdout
|
||||
} else {
|
||||
outputFile, err := os.Create(cfg.output)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create output file: %v", err)
|
||||
}
|
||||
defer outputFile.Close()
|
||||
outputTo = outputFile
|
||||
}
|
||||
|
||||
if filepath.Ext(cfg.output) == ".json" {
|
||||
cfg.jsonMode = true
|
||||
} else if filepath.Ext(cfg.output) == ".yaml" || filepath.Ext(cfg.output) == ".yml" {
|
||||
cfg.jsonMode = false
|
||||
}
|
||||
|
||||
data, err := yaml.Marshal(spec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal CDI spec: %v", err)
|
||||
}
|
||||
|
||||
if cfg.jsonMode {
|
||||
data, err = yaml.YAMLToJSONStrict(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert CDI spec from YAML to JSON: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = outputTo.Write(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write output: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m command) generateSpec() (*specs.Spec, error) {
|
||||
nvmllib := nvml.New()
|
||||
if r := nvmllib.Init(); r != nvml.SUCCESS {
|
||||
return nil, r
|
||||
}
|
||||
defer nvmllib.Shutdown()
|
||||
|
||||
devicelib := device.New(device.WithNvml(nvmllib))
|
||||
|
||||
spec := specs.Spec{
|
||||
Version: "0.4.0",
|
||||
Kind: "nvidia.com/gpu",
|
||||
ContainerEdits: specs.ContainerEdits{},
|
||||
}
|
||||
err := devicelib.VisitDevices(func(i int, d device.Device) error {
|
||||
isMig, err := d.IsMigEnabled()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check whether device is MIG device: %v", err)
|
||||
}
|
||||
if isMig {
|
||||
return nil
|
||||
}
|
||||
device, err := generateEditsForDevice(newGPUDevice(i, d))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate CDI spec for device %v: %v", i, err)
|
||||
}
|
||||
|
||||
spec.Devices = append(spec.Devices, device)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate CDI spec for GPU devices: %v", err)
|
||||
}
|
||||
|
||||
err = devicelib.VisitMigDevices(func(i int, d device.Device, j int, m device.MigDevice) error {
|
||||
device, err := generateEditsForDevice(newMigDevice(i, j, m))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate CDI spec for device %v: %v", i, err)
|
||||
}
|
||||
|
||||
spec.Devices = append(spec.Devices, device)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("falied to generate CDI spec for MIG devices: %v", err)
|
||||
}
|
||||
|
||||
// We create an "all" device with all the discovered device nodes
|
||||
var allDeviceNodes []*specs.DeviceNode
|
||||
for _, d := range spec.Devices {
|
||||
for _, dn := range d.ContainerEdits.DeviceNodes {
|
||||
allDeviceNodes = append(allDeviceNodes, dn)
|
||||
}
|
||||
}
|
||||
all := specs.Device{
|
||||
Name: "all",
|
||||
ContainerEdits: specs.ContainerEdits{
|
||||
DeviceNodes: allDeviceNodes,
|
||||
},
|
||||
}
|
||||
|
||||
spec.Devices = append(spec.Devices, all)
|
||||
spec.ContainerEdits.DeviceNodes = m.getExistingMetaDeviceNodes()
|
||||
|
||||
libraries, err := m.findLibs(nvmllib)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to locate driver libraries: %v", err)
|
||||
}
|
||||
|
||||
binaries, err := m.findBinaries()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to locate driver binaries: %v", err)
|
||||
}
|
||||
|
||||
ipcs, err := m.findIPC()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to locate driver IPC sockets: %v", err)
|
||||
}
|
||||
|
||||
spec.ContainerEdits.Mounts = generateMountsForPaths(libraries, binaries, ipcs)
|
||||
|
||||
ldcacheUpdateHook := m.generateUpdateLdCacheHook(libraries)
|
||||
|
||||
spec.ContainerEdits.Hooks = []*specs.Hook{ldcacheUpdateHook}
|
||||
|
||||
return &spec, nil
|
||||
}
|
||||
|
||||
func generateEditsForDevice(name string, d deviceInfo) (specs.Device, error) {
|
||||
deviceNodePaths, err := d.GetDeviceNodes()
|
||||
if err != nil {
|
||||
return specs.Device{}, fmt.Errorf("failed to get paths for device: %v", err)
|
||||
}
|
||||
|
||||
deviceNodes := getDeviceNodesFromPaths(deviceNodePaths)
|
||||
|
||||
device := specs.Device{
|
||||
Name: name,
|
||||
ContainerEdits: specs.ContainerEdits{
|
||||
DeviceNodes: deviceNodes,
|
||||
},
|
||||
}
|
||||
|
||||
return device, nil
|
||||
}
|
||||
|
||||
func (m command) getExistingMetaDeviceNodes() []*specs.DeviceNode {
|
||||
metaDeviceNodePaths := []string{
|
||||
"/dev/nvidia-modeset",
|
||||
"/dev/nvidia-uvm-tools",
|
||||
"/dev/nvidia-uvm",
|
||||
"/dev/nvidiactl",
|
||||
}
|
||||
|
||||
var existingDeviceNodePaths []string
|
||||
for _, p := range metaDeviceNodePaths {
|
||||
if _, err := os.Stat(p); err != nil {
|
||||
m.logger.Infof("Ignoring missing meta device %v", p)
|
||||
continue
|
||||
}
|
||||
existingDeviceNodePaths = append(existingDeviceNodePaths, p)
|
||||
}
|
||||
|
||||
return getDeviceNodesFromPaths(existingDeviceNodePaths)
|
||||
}
|
||||
|
||||
func getDeviceNodesFromPaths(deviceNodePaths []string) []*specs.DeviceNode {
|
||||
var deviceNodes []*specs.DeviceNode
|
||||
for _, p := range deviceNodePaths {
|
||||
deviceNode := specs.DeviceNode{
|
||||
Path: p,
|
||||
}
|
||||
deviceNodes = append(deviceNodes, &deviceNode)
|
||||
}
|
||||
|
||||
return deviceNodes
|
||||
}
|
||||
|
||||
func (m command) findLibs(nvmllib nvml.Interface) ([]string, error) {
|
||||
version, r := nvmllib.SystemGetDriverVersion()
|
||||
if r != nvml.SUCCESS {
|
||||
return nil, fmt.Errorf("failed to determine driver version: %v", r)
|
||||
}
|
||||
m.logger.Infof("Using driver version %v", version)
|
||||
|
||||
cache, err := ldcache.New(m.logger, "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load ldcache: %v", err)
|
||||
}
|
||||
|
||||
libs32, libs64 := cache.List()
|
||||
|
||||
var libs []string
|
||||
for _, l := range libs64 {
|
||||
if strings.HasSuffix(l, version) {
|
||||
m.logger.Infof("found 64-bit driver lib: %v", l)
|
||||
libs = append(libs, l)
|
||||
}
|
||||
}
|
||||
|
||||
for _, l := range libs32 {
|
||||
if strings.HasSuffix(l, version) {
|
||||
m.logger.Infof("found 32-bit driver lib: %v", l)
|
||||
libs = append(libs, l)
|
||||
}
|
||||
}
|
||||
|
||||
return libs, nil
|
||||
}
|
||||
|
||||
func (m command) findBinaries() ([]string, error) {
|
||||
candidates := []string{
|
||||
"nvidia-smi", /* System management interface */
|
||||
"nvidia-debugdump", /* GPU coredump utility */
|
||||
"nvidia-persistenced", /* Persistence mode utility */
|
||||
"nvidia-cuda-mps-control", /* Multi process service CLI */
|
||||
"nvidia-cuda-mps-server", /* Multi process service server */
|
||||
}
|
||||
|
||||
locator := lookup.NewExecutableLocator(m.logger, "")
|
||||
|
||||
var binaries []string
|
||||
for _, c := range candidates {
|
||||
targets, err := locator.Locate(c)
|
||||
if err != nil {
|
||||
m.logger.Warningf("skipping %v: %v", c, err)
|
||||
continue
|
||||
}
|
||||
|
||||
binaries = append(binaries, targets[0])
|
||||
}
|
||||
return binaries, nil
|
||||
}
|
||||
|
||||
func (m command) findIPC() ([]string, error) {
|
||||
candidates := []string{
|
||||
"/var/run/nvidia-persistenced/socket",
|
||||
"/var/run/nvidia-fabricmanager/socket",
|
||||
// TODO: This can be controlled by the NV_MPS_PIPE_DIR envvar
|
||||
"/tmp/nvidia-mps",
|
||||
}
|
||||
|
||||
locator := lookup.NewFileLocator(m.logger, "")
|
||||
|
||||
var ipcs []string
|
||||
for _, c := range candidates {
|
||||
targets, err := locator.Locate(c)
|
||||
if err != nil {
|
||||
m.logger.Warningf("skipping %v: %v", c, err)
|
||||
continue
|
||||
}
|
||||
|
||||
ipcs = append(ipcs, targets[0])
|
||||
}
|
||||
return ipcs, nil
|
||||
}
|
||||
|
||||
func generateMountsForPaths(pathSets ...[]string) []*specs.Mount {
|
||||
var mounts []*specs.Mount
|
||||
for _, paths := range pathSets {
|
||||
for _, p := range paths {
|
||||
mount := specs.Mount{
|
||||
HostPath: p,
|
||||
// We may want to adjust the container path
|
||||
ContainerPath: p,
|
||||
Type: "bind",
|
||||
Options: []string{
|
||||
"ro",
|
||||
"nosuid",
|
||||
"nodev",
|
||||
"bind",
|
||||
},
|
||||
}
|
||||
mounts = append(mounts, &mount)
|
||||
}
|
||||
}
|
||||
return mounts
|
||||
}
|
||||
|
||||
func (m command) generateUpdateLdCacheHook(libraries []string) *specs.Hook {
|
||||
locator := lookup.NewExecutableLocator(m.logger, "")
|
||||
|
||||
hook := discover.CreateLDCacheUpdateHook(
|
||||
m.logger,
|
||||
locator,
|
||||
nvidiaCTKExecutable,
|
||||
nvidiaCTKDefaultFilePath,
|
||||
libraries,
|
||||
)
|
||||
return &specs.Hook{
|
||||
HookName: hook.Lifecycle,
|
||||
Path: hook.Path,
|
||||
Args: hook.Args,
|
||||
}
|
||||
}
|
||||
123
cmd/nvidia-ctk/info/generate-cdi/nvml_devices.go
Normal file
123
cmd/nvidia-ctk/info/generate-cdi/nvml_devices.go
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY Type, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cdi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/nvcaps"
|
||||
"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvlib/device"
|
||||
"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvml"
|
||||
)
|
||||
|
||||
// nvmlDevice wraps an nvml.Device with more functions.
|
||||
type nvmlDevice struct {
|
||||
nvml.Device
|
||||
}
|
||||
|
||||
// nvmlMigDevice allows for specific functions of nvmlDevice to be overridden.
|
||||
type nvmlMigDevice nvmlDevice
|
||||
|
||||
// deviceInfo defines the information the required to construct a Device
|
||||
type deviceInfo interface {
|
||||
GetUUID() (string, error)
|
||||
GetDeviceNodes() ([]string, error)
|
||||
}
|
||||
|
||||
var _ deviceInfo = (*nvmlDevice)(nil)
|
||||
var _ deviceInfo = (*nvmlMigDevice)(nil)
|
||||
|
||||
func newGPUDevice(i int, gpu device.Device) (string, nvmlDevice) {
|
||||
return fmt.Sprintf("gpu%v", i), nvmlDevice{gpu}
|
||||
}
|
||||
|
||||
func newMigDevice(i int, j int, mig device.MigDevice) (string, nvmlMigDevice) {
|
||||
return fmt.Sprintf("mig%v:%v", i, j), nvmlMigDevice{mig}
|
||||
}
|
||||
|
||||
// GetUUID returns the UUID of the device
|
||||
func (d nvmlDevice) GetUUID() (string, error) {
|
||||
uuid, ret := d.Device.GetUUID()
|
||||
if ret != nvml.SUCCESS {
|
||||
return "", ret
|
||||
}
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
// GetUUID returns the UUID of the device
|
||||
func (d nvmlMigDevice) GetUUID() (string, error) {
|
||||
return nvmlDevice(d).GetUUID()
|
||||
}
|
||||
|
||||
// GetDeviceNodes returns the device node paths for a GPU device
|
||||
func (d nvmlDevice) GetDeviceNodes() ([]string, error) {
|
||||
minor, ret := d.GetMinorNumber()
|
||||
if ret != nvml.SUCCESS {
|
||||
return nil, fmt.Errorf("error getting GPU device minor number: %v", ret)
|
||||
}
|
||||
path := fmt.Sprintf("/dev/nvidia%d", minor)
|
||||
|
||||
return []string{path}, nil
|
||||
}
|
||||
|
||||
// GetDeviceNodes returns the device node paths for a MIG device
|
||||
func (d nvmlMigDevice) GetDeviceNodes() ([]string, error) {
|
||||
parent, ret := d.GetDeviceHandleFromMigDeviceHandle()
|
||||
if ret != nvml.SUCCESS {
|
||||
return nil, fmt.Errorf("error getting parent device: %v", ret)
|
||||
}
|
||||
minor, ret := parent.GetMinorNumber()
|
||||
if ret != nvml.SUCCESS {
|
||||
return nil, fmt.Errorf("error getting GPU device minor number: %v", ret)
|
||||
}
|
||||
parentPath := fmt.Sprintf("/dev/nvidia%d", minor)
|
||||
|
||||
migCaps, err := nvcaps.NewMigCaps()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting MIG capability device paths: %v", err)
|
||||
}
|
||||
|
||||
gi, ret := d.GetGpuInstanceId()
|
||||
if ret != nvml.SUCCESS {
|
||||
return nil, fmt.Errorf("error getting GPU Instance ID: %v", ret)
|
||||
}
|
||||
|
||||
ci, ret := d.GetComputeInstanceId()
|
||||
if ret != nvml.SUCCESS {
|
||||
return nil, fmt.Errorf("error getting Compute Instance ID: %v", ret)
|
||||
}
|
||||
|
||||
giCap := nvcaps.NewGPUInstanceCap(minor, gi)
|
||||
giCapDevicePath, err := migCaps.GetCapDevicePath(giCap)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get GI cap device path: %v", err)
|
||||
}
|
||||
|
||||
ciCap := nvcaps.NewComputeInstanceCap(minor, gi, ci)
|
||||
ciCapDevicePath, err := migCaps.GetCapDevicePath(ciCap)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get CI cap device path: %v", err)
|
||||
}
|
||||
|
||||
devicePaths := []string{
|
||||
parentPath,
|
||||
giCapDevicePath,
|
||||
ciCapDevicePath,
|
||||
}
|
||||
|
||||
return devicePaths, nil
|
||||
}
|
||||
50
cmd/nvidia-ctk/info/info.go
Normal file
50
cmd/nvidia-ctk/info/info.go
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
**/
|
||||
|
||||
package info
|
||||
|
||||
import (
|
||||
cdi "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk/info/generate-cdi"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type command struct {
|
||||
logger *logrus.Logger
|
||||
}
|
||||
|
||||
// NewCommand constructs an info command with the specified logger
|
||||
func NewCommand(logger *logrus.Logger) *cli.Command {
|
||||
c := command{
|
||||
logger: logger,
|
||||
}
|
||||
return c.build()
|
||||
}
|
||||
|
||||
// build
|
||||
func (m command) build() *cli.Command {
|
||||
// Create the 'hook' command
|
||||
hook := cli.Command{
|
||||
Name: "info",
|
||||
Usage: "Provide information about the system",
|
||||
}
|
||||
|
||||
hook.Subcommands = []*cli.Command{
|
||||
cdi.NewCommand(m.logger),
|
||||
}
|
||||
|
||||
return &hook
|
||||
}
|
||||
@@ -20,8 +20,10 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk/hook"
|
||||
infoCLI "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk/info"
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk/runtime"
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/info"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
cli "github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -72,6 +74,7 @@ func main() {
|
||||
c.Commands = []*cli.Command{
|
||||
hook.NewCommand(logger),
|
||||
runtime.NewCommand(logger),
|
||||
infoCLI.NewCommand(logger),
|
||||
}
|
||||
|
||||
// Run the CLI
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
disable-require = false
|
||||
#swarm-resource = "DOCKER_RESOURCE_GPU"
|
||||
#accept-nvidia-visible-devices-envvar-when-unprivileged = true
|
||||
#accept-nvidia-visible-devices-as-volume-mounts = false
|
||||
|
||||
[nvidia-container-cli]
|
||||
#root = "/run/nvidia/driver"
|
||||
#path = "/usr/bin/nvidia-container-cli"
|
||||
environment = []
|
||||
#debug = "/var/log/nvidia-container-toolkit.log"
|
||||
#ldcache = "/etc/ld.so.cache"
|
||||
load-kmods = true
|
||||
#no-cgroups = false
|
||||
#user = "root:video"
|
||||
ldconfig = "@/sbin/ldconfig"
|
||||
|
||||
[nvidia-container-runtime]
|
||||
#debug = "/var/log/nvidia-container-runtime.log"
|
||||
log-level = "info"
|
||||
|
||||
# Specify the runtimes to consider. This list is processed in order and the PATH
|
||||
# searched for matching executables unless the entry is an absolute path.
|
||||
runtimes = [
|
||||
"docker-runc",
|
||||
"runc",
|
||||
]
|
||||
|
||||
mode = "auto"
|
||||
|
||||
[nvidia-container-runtime.modes.csv]
|
||||
|
||||
mount-spec-path = "/etc/nvidia-container-runtime/host-files-for-container.d"
|
||||
@@ -1,76 +0,0 @@
|
||||
ARG BASEIMAGE
|
||||
FROM ${BASEIMAGE}
|
||||
|
||||
RUN yum install -y \
|
||||
ca-certificates \
|
||||
gcc \
|
||||
wget \
|
||||
git \
|
||||
rpm-build \
|
||||
make && \
|
||||
rm -rf /var/cache/yum/*
|
||||
|
||||
ARG GOLANG_VERSION=0.0.0
|
||||
RUN set -eux; \
|
||||
\
|
||||
arch="$(uname -m)"; \
|
||||
case "${arch##*-}" in \
|
||||
x86_64 | amd64) ARCH='amd64' ;; \
|
||||
ppc64el | ppc64le) ARCH='ppc64le' ;; \
|
||||
aarch64) ARCH='arm64' ;; \
|
||||
*) echo "unsupported architecture"; exit 1 ;; \
|
||||
esac; \
|
||||
wget -nv -O - https://storage.googleapis.com/golang/go${GOLANG_VERSION}.linux-${ARCH}.tar.gz \
|
||||
| tar -C /usr/local -xz
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
||||
|
||||
# packaging
|
||||
ARG PKG_NAME
|
||||
ARG PKG_VERS
|
||||
ARG PKG_REV
|
||||
|
||||
ENV VERSION $PKG_VERS
|
||||
ENV RELEASE $PKG_REV
|
||||
|
||||
# output directory
|
||||
ENV DIST_DIR=/tmp/nvidia-container-toolkit-$PKG_VERS/SOURCES
|
||||
RUN mkdir -p $DIST_DIR /dist
|
||||
|
||||
# nvidia-container-toolkit
|
||||
WORKDIR $GOPATH/src/nvidia-container-toolkit
|
||||
COPY . .
|
||||
|
||||
ARG GIT_COMMIT
|
||||
ENV GIT_COMMIT ${GIT_COMMIT}
|
||||
RUN make PREFIX=${DIST_DIR} cmds
|
||||
|
||||
ARG CONFIG_TOML_SUFFIX
|
||||
ENV CONFIG_TOML_SUFFIX ${CONFIG_TOML_SUFFIX}
|
||||
COPY config/config.toml.${CONFIG_TOML_SUFFIX} $DIST_DIR/config.toml
|
||||
|
||||
# Hook for Project Atomic's fork of Docker: https://github.com/projectatomic/docker/tree/docker-1.13.1-rhel#add-dockerhooks-exec-custom-hooks-for-prestartpoststop-containerspatch
|
||||
# This might not be useful on Amazon Linux, but it's simpler to keep the RHEL
|
||||
# and Amazon Linux packages identical.
|
||||
COPY oci-nvidia-hook $DIST_DIR/oci-nvidia-hook
|
||||
|
||||
# Hook for libpod/CRI-O: https://github.com/containers/libpod/blob/v0.8.5/pkg/hooks/docs/oci-hooks.5.md
|
||||
COPY oci-nvidia-hook.json $DIST_DIR/oci-nvidia-hook.json
|
||||
|
||||
WORKDIR $DIST_DIR/..
|
||||
COPY packaging/rpm .
|
||||
|
||||
ARG LIBNVIDIA_CONTAINER_TOOLS_VERSION
|
||||
ENV LIBNVIDIA_CONTAINER_TOOLS_VERSION ${LIBNVIDIA_CONTAINER_TOOLS_VERSION}
|
||||
|
||||
CMD arch=$(uname -m) && \
|
||||
rpmbuild --clean --target=$arch -bb \
|
||||
-D "_topdir $PWD" \
|
||||
-D "release_date $(date +'%a %b %d %Y')" \
|
||||
-D "git_commit ${GIT_COMMIT}" \
|
||||
-D "version $VERSION" \
|
||||
-D "libnvidia_container_tools_version ${LIBNVIDIA_CONTAINER_TOOLS_VERSION}" \
|
||||
-D "release $RELEASE" \
|
||||
SPECS/nvidia-container-toolkit.spec && \
|
||||
mv RPMS/$arch/*.rpm /dist
|
||||
@@ -76,6 +76,6 @@ RUN dch --create --package="${PKG_NAME}" \
|
||||
if [ "$REVISION" != "$(dpkg-parsechangelog --show-field=Version)" ]; then exit 1; fi
|
||||
|
||||
CMD export DISTRIB="$(lsb_release -cs)" && \
|
||||
debuild -eDISTRIB -eSECTION -eLIBNVIDIA_CONTAINER_TOOLS_VERSION \
|
||||
debuild -eDISTRIB -eSECTION -eLIBNVIDIA_CONTAINER_TOOLS_VERSION -eVERSION="${REVISION}" \
|
||||
--dpkg-buildpackage-hook='sh debian/prepare' -i -us -uc -b && \
|
||||
mv /tmp/nvidia-container-toolkit_*.deb /dist
|
||||
mv /tmp/*.deb /dist
|
||||
|
||||
@@ -28,9 +28,9 @@ ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
||||
ARG PKG_NAME
|
||||
ARG PKG_VERS
|
||||
ARG PKG_REV
|
||||
|
||||
ENV VERSION $PKG_VERS
|
||||
ENV RELEASE $PKG_REV
|
||||
ENV PKG_NAME ${PKG_NAME}
|
||||
ENV PKG_VERS ${PKG_VERS}
|
||||
ENV PKG_REV ${PKG_REV}
|
||||
|
||||
# output directory
|
||||
ENV DIST_DIR=/tmp/nvidia-container-toolkit-$PKG_VERS/SOURCES
|
||||
@@ -65,8 +65,8 @@ CMD arch=$(uname -m) && \
|
||||
-D "_topdir $PWD" \
|
||||
-D "release_date $(date +'%a %b %d %Y')" \
|
||||
-D "git_commit ${GIT_COMMIT}" \
|
||||
-D "version $VERSION" \
|
||||
-D "version ${PKG_VERS}" \
|
||||
-D "libnvidia_container_tools_version ${LIBNVIDIA_CONTAINER_TOOLS_VERSION}" \
|
||||
-D "release $RELEASE" \
|
||||
-D "release ${PKG_REV}" \
|
||||
SPECS/nvidia-container-toolkit.spec && \
|
||||
mv RPMS/$arch/*.rpm /dist
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# This is the dockerfile for building packages on yum-based RPM systems.
|
||||
|
||||
ARG BASEIMAGE
|
||||
FROM ${BASEIMAGE}
|
||||
|
||||
@@ -30,9 +46,9 @@ ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
||||
ARG PKG_NAME
|
||||
ARG PKG_VERS
|
||||
ARG PKG_REV
|
||||
|
||||
ENV VERSION $PKG_VERS
|
||||
ENV RELEASE $PKG_REV
|
||||
ENV PKG_NAME ${PKG_NAME}
|
||||
ENV PKG_VERS ${PKG_VERS}
|
||||
ENV PKG_REV ${PKG_REV}
|
||||
|
||||
# output directory
|
||||
ENV DIST_DIR=/tmp/nvidia-container-toolkit-$PKG_VERS/SOURCES
|
||||
@@ -67,8 +83,8 @@ CMD arch=$(uname -m) && \
|
||||
-D "_topdir $PWD" \
|
||||
-D "release_date $(date +'%a %b %d %Y')" \
|
||||
-D "git_commit ${GIT_COMMIT}" \
|
||||
-D "version $VERSION" \
|
||||
-D "version ${PKG_VERS}" \
|
||||
-D "libnvidia_container_tools_version ${LIBNVIDIA_CONTAINER_TOOLS_VERSION}" \
|
||||
-D "release $RELEASE" \
|
||||
-D "release ${PKG_REV}" \
|
||||
SPECS/nvidia-container-toolkit.spec && \
|
||||
mv RPMS/$arch/*.rpm /dist
|
||||
@@ -69,6 +69,6 @@ RUN dch --create --package="${PKG_NAME}" \
|
||||
if [ "$REVISION" != "$(dpkg-parsechangelog --show-field=Version)" ]; then exit 1; fi
|
||||
|
||||
CMD export DISTRIB="$(lsb_release -cs)" && \
|
||||
debuild -eDISTRIB -eSECTION -eLIBNVIDIA_CONTAINER_TOOLS_VERSION \
|
||||
debuild -eDISTRIB -eSECTION -eLIBNVIDIA_CONTAINER_TOOLS_VERSION -eVERSION="${REVISION}" \
|
||||
--dpkg-buildpackage-hook='sh debian/prepare' -i -us -uc -b && \
|
||||
mv /tmp/*.deb /dist
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
# Supported OSs by architecture
|
||||
AMD64_TARGETS := ubuntu20.04 ubuntu18.04 ubuntu16.04 debian10 debian9
|
||||
X86_64_TARGETS := centos7 centos8 rhel7 rhel8 amazonlinux2 opensuse-leap15.1
|
||||
X86_64_TARGETS := fedora35 centos7 centos8 rhel7 rhel8 amazonlinux2 opensuse-leap15.1
|
||||
PPC64LE_TARGETS := ubuntu18.04 ubuntu16.04 centos7 centos8 rhel7 rhel8
|
||||
ARM64_TARGETS := ubuntu20.04 ubuntu18.04
|
||||
AARCH64_TARGETS := centos8 rhel8 amazonlinux2
|
||||
AARCH64_TARGETS := fedora35 centos8 rhel8 amazonlinux2
|
||||
|
||||
# Define top-level build targets
|
||||
docker%: SHELL:=/bin/bash
|
||||
@@ -104,12 +104,26 @@ LIBNVIDIA_CONTAINER_TAG ?= $(LIB_TAG)
|
||||
--centos%: OS := centos
|
||||
--centos%: PKG_REV := $(if $(LIB_TAG),0.1.$(LIB_TAG),1)
|
||||
--centos%: LIBNVIDIA_CONTAINER_TOOLS_VERSION := $(LIBNVIDIA_CONTAINER_VERSION)-$(if $(LIBNVIDIA_CONTAINER_TAG),0.1.$(LIBNVIDIA_CONTAINER_TAG),1)
|
||||
--centos%: DOCKERFILE = $(CURDIR)/docker/Dockerfile.rpm-yum
|
||||
--centos%: CONFIG_TOML_SUFFIX := rpm-yum
|
||||
--centos8%: BASEIMAGE = quay.io/centos/centos:stream8
|
||||
|
||||
# private fedora target
|
||||
--fedora%: OS := fedora
|
||||
--fedora%: PKG_REV := $(if $(LIB_TAG),0.1.$(LIB_TAG),1)
|
||||
--fedora%: LIBNVIDIA_CONTAINER_TOOLS_VERSION := $(LIBNVIDIA_CONTAINER_VERSION)-$(if $(LIBNVIDIA_CONTAINER_TAG),0.1.$(LIBNVIDIA_CONTAINER_TAG),1)
|
||||
--fedora%: DOCKERFILE = $(CURDIR)/docker/Dockerfile.rpm-yum
|
||||
--fedora%: CONFIG_TOML_SUFFIX := rpm-yum
|
||||
# The fedora(35) base image has very slow performance when building aarch64 packages.
|
||||
# Since our primary concern here is glibc versions, we use the older glibc version available in centos8.
|
||||
--fedora35%: BASEIMAGE = quay.io/centos/centos:stream8
|
||||
|
||||
# private amazonlinux target
|
||||
--amazonlinux%: OS := amazonlinux
|
||||
--amazonlinux%: LIBNVIDIA_CONTAINER_TOOLS_VERSION := $(LIBNVIDIA_CONTAINER_VERSION)-$(if $(LIBNVIDIA_CONTAINER_TAG),0.1.$(LIBNVIDIA_CONTAINER_TAG),1)
|
||||
--amazonlinux%: PKG_REV := $(if $(LIB_TAG),0.1.$(LIB_TAG),1)
|
||||
--amazonlinux%: DOCKERFILE = $(CURDIR)/docker/Dockerfile.rpm-yum
|
||||
--amazonlinux%: CONFIG_TOML_SUFFIX := rpm-yum
|
||||
|
||||
# private opensuse-leap target
|
||||
--opensuse-leap%: OS = opensuse-leap
|
||||
@@ -123,8 +137,11 @@ LIBNVIDIA_CONTAINER_TAG ?= $(LIB_TAG)
|
||||
--rhel%: PKG_REV := $(if $(LIB_TAG),0.1.$(LIB_TAG),1)
|
||||
--rhel%: VERSION = $(patsubst rhel%-$(ARCH),%,$(TARGET_PLATFORM))
|
||||
--rhel%: ARTIFACTS_DIR = $(DIST_DIR)/rhel$(VERSION)/$(ARCH)
|
||||
--rhel%: DOCKERFILE = $(CURDIR)/docker/Dockerfile.rpm-yum
|
||||
--rhel%: CONFIG_TOML_SUFFIX := rpm-yum
|
||||
--rhel8%: BASEIMAGE = quay.io/centos/centos:stream8
|
||||
|
||||
|
||||
# We allow the CONFIG_TOML_SUFFIX to be overridden.
|
||||
CONFIG_TOML_SUFFIX ?= $(OS)
|
||||
|
||||
@@ -140,9 +157,9 @@ docker-build-%:
|
||||
--build-arg PKG_NAME="$(LIB_NAME)" \
|
||||
--build-arg PKG_VERS="$(LIB_VERSION)" \
|
||||
--build-arg PKG_REV="$(PKG_REV)" \
|
||||
--build-arg LIBNVIDIA_CONTAINER_TOOLS_VERSION="$(LIBNVIDIA_CONTAINER_TOOLS_VERSION)" \
|
||||
--build-arg LIBNVIDIA_CONTAINER_TOOLS_VERSION="$(LIBNVIDIA_CONTAINER_TOOLS_VERSION)" \
|
||||
--build-arg CONFIG_TOML_SUFFIX="$(CONFIG_TOML_SUFFIX)" \
|
||||
--build-arg GIT_COMMIT="$(GIT_COMMIT)" \
|
||||
--build-arg GIT_COMMIT="$(GIT_COMMIT)" \
|
||||
--tag $(BUILDIMAGE) \
|
||||
--file $(DOCKERFILE) .
|
||||
$(DOCKER) run \
|
||||
|
||||
37
go.mod
37
go.mod
@@ -1,18 +1,41 @@
|
||||
module github.com/NVIDIA/nvidia-container-toolkit
|
||||
|
||||
go 1.14
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.0.0
|
||||
github.com/NVIDIA/go-nvml v0.11.6-0
|
||||
github.com/container-orchestrated-devices/container-device-interface v0.4.1-0.20220614144320-dc973e22f674
|
||||
github.com/containers/podman/v4 v4.0.3
|
||||
github.com/opencontainers/runc v1.1.3
|
||||
github.com/NVIDIA/go-nvml v0.11.6-0.0.20220823120812-7e2082095e82
|
||||
github.com/container-orchestrated-devices/container-device-interface v0.5.2
|
||||
github.com/opencontainers/runc v1.1.4
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20211214071223-8958f93039ab
|
||||
github.com/pelletier/go-toml v1.9.4
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
gitlab.com/nvidia/cloud-native/go-nvlib v0.0.0-20220922133427-1049a7fa76a9
|
||||
golang.org/x/mod v0.5.0
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
|
||||
golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20220110225228-7e2d60f1e41f // indirect
|
||||
github.com/opencontainers/selinux v1.10.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
)
|
||||
|
||||
63
internal/discover/graphics.go
Normal file
63
internal/discover/graphics.go
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
**/
|
||||
|
||||
package discover
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// NewGraphicsDiscoverer returns the discoverer for graphics tools such as Vulkan.
|
||||
func NewGraphicsDiscoverer(logger *logrus.Logger, root string) (Discover, error) {
|
||||
locator, err := lookup.NewLibraryLocator(logger, root)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to construct library locator: %v", err)
|
||||
}
|
||||
libraries := NewMounts(
|
||||
logger,
|
||||
locator,
|
||||
root,
|
||||
[]string{
|
||||
"libnvidia-egl-gbm.so",
|
||||
},
|
||||
)
|
||||
|
||||
jsonMounts := NewMounts(
|
||||
logger,
|
||||
lookup.NewFileLocator(logger, root),
|
||||
root,
|
||||
[]string{
|
||||
// TODO: We should handle this more cleanly
|
||||
"/etc/glvnd/egl_vendor.d/10_nvidia.json",
|
||||
"/etc/vulkan/icd.d/nvidia_icd.json",
|
||||
"/etc/vulkan/implicit_layer.d/nvidia_layers.json",
|
||||
"/usr/share/glvnd/egl_vendor.d/10_nvidia.json",
|
||||
"/usr/share/vulkan/icd.d/nvidia_icd.json",
|
||||
"/usr/share/vulkan/implicit_layer.d/nvidia_layers.json",
|
||||
"/usr/share/egl/egl_external_platform.d/15_nvidia_gbm.json",
|
||||
},
|
||||
)
|
||||
|
||||
discover := Merge(
|
||||
libraries,
|
||||
jsonMounts,
|
||||
)
|
||||
|
||||
return discover, nil
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package discover
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup"
|
||||
@@ -57,58 +56,50 @@ func (d ldconfig) Hooks() ([]Hook, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to discover mounts for ldcache update: %v", err)
|
||||
}
|
||||
h := CreateLDCacheUpdateHook(
|
||||
d.logger,
|
||||
d.lookup,
|
||||
d.nvidiaCTKExecutablePath,
|
||||
nvidiaCTKDefaultFilePath,
|
||||
getLibraryPaths(mounts),
|
||||
)
|
||||
return []Hook{h}, nil
|
||||
}
|
||||
|
||||
libDirs := getLibDirs(mounts)
|
||||
|
||||
hookPath := nvidiaCTKDefaultFilePath
|
||||
targets, err := d.lookup.Locate(d.nvidiaCTKExecutablePath)
|
||||
// CreateLDCacheUpdateHook locates the NVIDIA Container Toolkit CLI and creates a hook for updating the LD Cache
|
||||
func CreateLDCacheUpdateHook(logger *logrus.Logger, lookup lookup.Locator, execuable string, defaultPath string, libraries []string) Hook {
|
||||
hookPath := defaultPath
|
||||
targets, err := lookup.Locate(execuable)
|
||||
if err != nil {
|
||||
d.logger.Warnf("Failed to locate %v: %v", d.nvidiaCTKExecutablePath, err)
|
||||
logger.Warnf("Failed to locate %v: %v", execuable, err)
|
||||
} else if len(targets) == 0 {
|
||||
d.logger.Warnf("%v not found", d.nvidiaCTKExecutablePath)
|
||||
logger.Warnf("%v not found", execuable)
|
||||
} else {
|
||||
d.logger.Debugf("Found %v candidates: %v", d.nvidiaCTKExecutablePath, targets)
|
||||
logger.Debugf("Found %v candidates: %v", execuable, targets)
|
||||
hookPath = targets[0]
|
||||
}
|
||||
d.logger.Debugf("Using NVIDIA Container Toolkit CLI path %v", hookPath)
|
||||
logger.Debugf("Using NVIDIA Container Toolkit CLI path %v", hookPath)
|
||||
|
||||
args := []string{hookPath, "hook", "update-ldcache"}
|
||||
for _, f := range libDirs {
|
||||
args := []string{filepath.Base(hookPath), "hook", "update-ldcache"}
|
||||
for _, f := range uniqueFolders(libraries) {
|
||||
args = append(args, "--folder", f)
|
||||
}
|
||||
h := Hook{
|
||||
return Hook{
|
||||
Lifecycle: cdi.CreateContainerHook,
|
||||
Path: hookPath,
|
||||
Args: args,
|
||||
}
|
||||
|
||||
return []Hook{h}, nil
|
||||
}
|
||||
|
||||
// getLibDirs extracts the library dirs from the specified mounts
|
||||
func getLibDirs(mounts []Mount) []string {
|
||||
// getLibraryPaths extracts the library dirs from the specified mounts
|
||||
func getLibraryPaths(mounts []Mount) []string {
|
||||
var paths []string
|
||||
checked := make(map[string]bool)
|
||||
|
||||
for _, m := range mounts {
|
||||
dir := filepath.Dir(m.Path)
|
||||
if dir == "" {
|
||||
if !isLibName(m.Path) {
|
||||
continue
|
||||
}
|
||||
|
||||
_, exists := checked[dir]
|
||||
if exists {
|
||||
continue
|
||||
}
|
||||
checked[dir] = isLibName(m.Path)
|
||||
|
||||
if checked[dir] {
|
||||
paths = append(paths, dir)
|
||||
}
|
||||
paths = append(paths, m.Path)
|
||||
}
|
||||
|
||||
sort.Strings(paths)
|
||||
|
||||
return paths
|
||||
}
|
||||
|
||||
@@ -129,3 +120,22 @@ func isLibName(filename string) bool {
|
||||
|
||||
return parts[len(parts)-1] == "" || strings.HasPrefix(parts[len(parts)-1], ".")
|
||||
}
|
||||
|
||||
// uniqueFolders returns the unique set of folders for the specified files
|
||||
func uniqueFolders(libraries []string) []string {
|
||||
var paths []string
|
||||
checked := make(map[string]bool)
|
||||
|
||||
for _, l := range libraries {
|
||||
dir := filepath.Dir(l)
|
||||
if dir == "" {
|
||||
continue
|
||||
}
|
||||
if checked[dir] {
|
||||
continue
|
||||
}
|
||||
checked[dir] = true
|
||||
paths = append(paths, dir)
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
@@ -17,11 +17,110 @@
|
||||
package discover
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
testlog "github.com/sirupsen/logrus/hooks/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestLDCacheUpdateHook(t *testing.T) {
|
||||
logger, _ := testlog.NewNullLogger()
|
||||
|
||||
cfg := Config{
|
||||
Root: "/",
|
||||
NVIDIAContainerToolkitCLIExecutablePath: "/foo/bar/nvidia-ctk",
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
description string
|
||||
mounts []Mount
|
||||
mountError error
|
||||
expectedError error
|
||||
expectedArgs []string
|
||||
}{
|
||||
{
|
||||
description: "empty mounts",
|
||||
expectedArgs: []string{"nvidia-ctk", "hook", "update-ldcache"},
|
||||
},
|
||||
{
|
||||
description: "mount error",
|
||||
mountError: fmt.Errorf("mountError"),
|
||||
expectedError: fmt.Errorf("mountError"),
|
||||
},
|
||||
{
|
||||
description: "library folders are added to args",
|
||||
mounts: []Mount{
|
||||
{
|
||||
Path: "/usr/local/lib/libfoo.so",
|
||||
},
|
||||
{
|
||||
Path: "/usr/bin/notlib",
|
||||
},
|
||||
{
|
||||
Path: "/usr/local/libother/libfoo.so",
|
||||
},
|
||||
{
|
||||
Path: "/usr/local/lib/libbar.so",
|
||||
},
|
||||
},
|
||||
expectedArgs: []string{"nvidia-ctk", "hook", "update-ldcache", "--folder", "/usr/local/lib", "--folder", "/usr/local/libother"},
|
||||
},
|
||||
{
|
||||
description: "host paths are ignored",
|
||||
mounts: []Mount{
|
||||
{
|
||||
HostPath: "/usr/local/other/libfoo.so",
|
||||
Path: "/usr/local/lib/libfoo.so",
|
||||
},
|
||||
},
|
||||
expectedArgs: []string{"nvidia-ctk", "hook", "update-ldcache", "--folder", "/usr/local/lib"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
mountMock := &DiscoverMock{
|
||||
MountsFunc: func() ([]Mount, error) {
|
||||
return tc.mounts, tc.mountError
|
||||
},
|
||||
}
|
||||
expectedHook := Hook{
|
||||
Path: "/usr/bin/nvidia-ctk",
|
||||
Args: tc.expectedArgs,
|
||||
Lifecycle: "createContainer",
|
||||
}
|
||||
|
||||
d, err := NewLDCacheUpdateHook(logger, mountMock, &cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
hooks, err := d.Hooks()
|
||||
require.Len(t, mountMock.MountsCalls(), 1)
|
||||
require.Len(t, mountMock.DevicesCalls(), 0)
|
||||
require.Len(t, mountMock.HooksCalls(), 0)
|
||||
if tc.expectedError != nil {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, hooks, 1)
|
||||
|
||||
require.EqualValues(t, hooks[0], expectedHook)
|
||||
|
||||
devices, err := d.Devices()
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, devices)
|
||||
|
||||
mounts, err := d.Mounts()
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, mounts)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIsLibName(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package info
|
||||
|
||||
import "gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvlib/info"
|
||||
|
||||
// Logger is a basic interface for logging to allow these functions to be called
|
||||
// from code where logrus is not used.
|
||||
type Logger interface {
|
||||
@@ -32,10 +34,12 @@ func ResolveAutoMode(logger Logger, mode string) (rmode string) {
|
||||
logger.Infof("Auto-detected mode as '%v'", rmode)
|
||||
}()
|
||||
|
||||
isTegra, reason := IsTegraSystem()
|
||||
nvinfo := info.New()
|
||||
|
||||
isTegra, reason := nvinfo.IsTegraSystem()
|
||||
logger.Debugf("Is Tegra-based system? %v: %v", isTegra, reason)
|
||||
|
||||
hasNVML, reason := HasNVML()
|
||||
hasNVML, reason := nvinfo.HasNvml()
|
||||
logger.Debugf("Has NVML? %v: %v", hasNVML, reason)
|
||||
|
||||
if isTegra && !hasNVML {
|
||||
|
||||
292
internal/ldcache/ldcache.go
Normal file
292
internal/ldcache/ldcache.go
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
// Adapted from https://github.com/rai-project/ldcache
|
||||
|
||||
package ldcache
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const ldcachePath = "/etc/ld.so.cache"
|
||||
|
||||
const (
|
||||
magicString1 = "ld.so-1.7.0"
|
||||
magicString2 = "glibc-ld.so.cache"
|
||||
magicVersion = "1.1"
|
||||
)
|
||||
|
||||
const (
|
||||
flagTypeMask = 0x00ff
|
||||
flagTypeELF = 0x0001
|
||||
|
||||
flagArchMask = 0xff00
|
||||
flagArchI386 = 0x0000
|
||||
flagArchX8664 = 0x0300
|
||||
flagArchX32 = 0x0800
|
||||
flagArchPpc64le = 0x0500
|
||||
)
|
||||
|
||||
var errInvalidCache = errors.New("invalid ld.so.cache file")
|
||||
|
||||
type header1 struct {
|
||||
Magic [len(magicString1) + 1]byte // include null delimiter
|
||||
NLibs uint32
|
||||
}
|
||||
|
||||
type entry1 struct {
|
||||
Flags int32
|
||||
Key, Value uint32
|
||||
}
|
||||
|
||||
type header2 struct {
|
||||
Magic [len(magicString2)]byte
|
||||
Version [len(magicVersion)]byte
|
||||
NLibs uint32
|
||||
TableSize uint32
|
||||
_ [3]uint32 // unused
|
||||
_ uint64 // force 8 byte alignment
|
||||
}
|
||||
|
||||
type entry2 struct {
|
||||
Flags int32
|
||||
Key, Value uint32
|
||||
OSVersion uint32
|
||||
HWCap uint64
|
||||
}
|
||||
|
||||
// LDCache represents the interface for performing lookups into the LDCache
|
||||
type LDCache interface {
|
||||
List() ([]string, []string)
|
||||
Lookup(...string) ([]string, []string)
|
||||
}
|
||||
|
||||
type ldcache struct {
|
||||
*bytes.Reader
|
||||
|
||||
data, libs []byte
|
||||
header header2
|
||||
entries []entry2
|
||||
|
||||
root string
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
// New creates a new LDCache with the specified logger and root.
|
||||
func New(logger *log.Logger, root string) (LDCache, error) {
|
||||
path := filepath.Join(root, ldcachePath)
|
||||
|
||||
logger.Debugf("Opening ld.conf at %v", path)
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d, err := syscall.Mmap(int(f.Fd()), 0, int(fi.Size()),
|
||||
syscall.PROT_READ, syscall.MAP_PRIVATE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cache := &ldcache{
|
||||
data: d,
|
||||
Reader: bytes.NewReader(d),
|
||||
root: root,
|
||||
logger: logger,
|
||||
}
|
||||
return cache, cache.parse()
|
||||
}
|
||||
|
||||
func (c *ldcache) Close() error {
|
||||
return syscall.Munmap(c.data)
|
||||
}
|
||||
|
||||
func (c *ldcache) Magic() string {
|
||||
return string(c.header.Magic[:])
|
||||
}
|
||||
|
||||
func (c *ldcache) Version() string {
|
||||
return string(c.header.Version[:])
|
||||
}
|
||||
|
||||
func strn(b []byte, n int) string {
|
||||
return string(b[:n])
|
||||
}
|
||||
|
||||
func (c *ldcache) parse() error {
|
||||
var header header1
|
||||
|
||||
// Check for the old format (< glibc-2.2)
|
||||
if c.Len() <= int(unsafe.Sizeof(header)) {
|
||||
return errInvalidCache
|
||||
}
|
||||
if strn(c.data, len(magicString1)) == magicString1 {
|
||||
if err := binary.Read(c, binary.LittleEndian, &header); err != nil {
|
||||
return err
|
||||
}
|
||||
n := int64(header.NLibs) * int64(unsafe.Sizeof(entry1{}))
|
||||
offset, err := c.Seek(n, 1) // skip old entries
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n = (-offset) & int64(unsafe.Alignof(c.header)-1)
|
||||
_, err = c.Seek(n, 1) // skip padding
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
c.libs = c.data[c.Size()-int64(c.Len()):] // kv offsets start here
|
||||
if err := binary.Read(c, binary.LittleEndian, &c.header); err != nil {
|
||||
return err
|
||||
}
|
||||
if c.Magic() != magicString2 || c.Version() != magicVersion {
|
||||
return errInvalidCache
|
||||
}
|
||||
c.entries = make([]entry2, c.header.NLibs)
|
||||
if err := binary.Read(c, binary.LittleEndian, &c.entries); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// List creates a list of libraires in the ldcache.
|
||||
// The 32-bit and 64-bit libraries are returned separately.
|
||||
func (c *ldcache) List() ([]string, []string) {
|
||||
paths := make(map[int][]string)
|
||||
|
||||
processed := make(map[string]bool)
|
||||
|
||||
for _, e := range c.entries {
|
||||
bits := 0
|
||||
if ((e.Flags & flagTypeMask) & flagTypeELF) == 0 {
|
||||
continue
|
||||
}
|
||||
switch e.Flags & flagArchMask {
|
||||
case flagArchX8664:
|
||||
fallthrough
|
||||
case flagArchPpc64le:
|
||||
bits = 64
|
||||
case flagArchX32:
|
||||
fallthrough
|
||||
case flagArchI386:
|
||||
bits = 32
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if e.Key > uint32(len(c.libs)) || e.Value > uint32(len(c.libs)) {
|
||||
continue
|
||||
}
|
||||
value := c.libs[e.Value:]
|
||||
|
||||
n := bytes.IndexByte(value, 0)
|
||||
if n < 0 {
|
||||
break
|
||||
}
|
||||
|
||||
name := filepath.Join(c.root, strn(value, n))
|
||||
c.logger.Debugf("checking %v", string(name))
|
||||
|
||||
path, err := filepath.EvalSymlinks(name)
|
||||
if err != nil {
|
||||
c.logger.Debugf("could not resolve symlink for %v", name)
|
||||
break
|
||||
}
|
||||
if processed[path] {
|
||||
continue
|
||||
}
|
||||
paths[bits] = append(paths[bits], path)
|
||||
processed[path] = true
|
||||
}
|
||||
|
||||
return paths[32], paths[64]
|
||||
}
|
||||
|
||||
// Lookup searches the ldcache for the specified prefixes.
|
||||
// The 32-bit and 64-bit libraries matching the prefixes are returned.
|
||||
func (c *ldcache) Lookup(libs ...string) (paths32, paths64 []string) {
|
||||
c.logger.Debugf("Looking up %v in cache", libs)
|
||||
type void struct{}
|
||||
var paths *[]string
|
||||
|
||||
set := make(map[string]void)
|
||||
prefix := make([][]byte, len(libs))
|
||||
|
||||
for i := range libs {
|
||||
prefix[i] = []byte(libs[i])
|
||||
}
|
||||
for _, e := range c.entries {
|
||||
if ((e.Flags & flagTypeMask) & flagTypeELF) == 0 {
|
||||
continue
|
||||
}
|
||||
switch e.Flags & flagArchMask {
|
||||
case flagArchX8664:
|
||||
fallthrough
|
||||
case flagArchPpc64le:
|
||||
paths = &paths64
|
||||
case flagArchX32:
|
||||
fallthrough
|
||||
case flagArchI386:
|
||||
paths = &paths32
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if e.Key > uint32(len(c.libs)) || e.Value > uint32(len(c.libs)) {
|
||||
continue
|
||||
}
|
||||
lib := c.libs[e.Key:]
|
||||
value := c.libs[e.Value:]
|
||||
|
||||
for _, p := range prefix {
|
||||
if bytes.HasPrefix(lib, p) {
|
||||
n := bytes.IndexByte(value, 0)
|
||||
if n < 0 {
|
||||
break
|
||||
}
|
||||
|
||||
name := filepath.Join(c.root, strn(value, n))
|
||||
c.logger.Debugf("checking %v", string(name))
|
||||
|
||||
path, err := filepath.EvalSymlinks(name)
|
||||
if err != nil {
|
||||
c.logger.Debugf("could not resolve symlink for %v", name)
|
||||
break
|
||||
}
|
||||
if _, ok := set[path]; ok {
|
||||
break
|
||||
}
|
||||
set[path] = void{}
|
||||
*paths = append(*paths, path)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
68
internal/lookup/library.go
Normal file
68
internal/lookup/library.go
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
package lookup
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/ldcache"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type library struct {
|
||||
logger *log.Logger
|
||||
symlink Locator
|
||||
cache ldcache.LDCache
|
||||
}
|
||||
|
||||
var _ Locator = (*library)(nil)
|
||||
|
||||
// NewLibraryLocator creates a library locator using the specified logger.
|
||||
func NewLibraryLocator(logger *log.Logger, root string) (Locator, error) {
|
||||
cache, err := ldcache.New(logger, root)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error loading ldcache: %v", err)
|
||||
}
|
||||
|
||||
l := library{
|
||||
symlink: NewSymlinkLocator(logger, root),
|
||||
cache: cache,
|
||||
}
|
||||
|
||||
return &l, nil
|
||||
}
|
||||
|
||||
// Locate finds the specified libraryname.
|
||||
// If the input is a library name, the ldcache is searched otherwise the
|
||||
// provided path is resolved as a symlink.
|
||||
func (l library) Locate(libname string) ([]string, error) {
|
||||
if strings.Contains(libname, "/") {
|
||||
return l.symlink.Locate(libname)
|
||||
}
|
||||
|
||||
paths32, paths64 := l.cache.Lookup(libname)
|
||||
if len(paths32) > 0 {
|
||||
l.logger.Warnf("Ignoring 32-bit libraries for %v: %v", libname, paths32)
|
||||
}
|
||||
|
||||
if len(paths64) == 0 {
|
||||
return nil, fmt.Errorf("64-bit library %v not found", libname)
|
||||
}
|
||||
|
||||
return paths64, nil
|
||||
}
|
||||
67
internal/modifier/graphics.go
Normal file
67
internal/modifier/graphics.go
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
**/
|
||||
|
||||
package modifier
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/config/image"
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/discover"
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// NewGraphicsModifier constructs a modifier that injects graphics-related modifications into an OCI runtime specification.
|
||||
// The value of the NVIDIA_DRIVER_CAPABILITIES environment variable is checked to determine if this modification should be made.
|
||||
func NewGraphicsModifier(logger *logrus.Logger, cfg *config.Config, ociSpec oci.Spec) (oci.SpecModifier, error) {
|
||||
rawSpec, err := ociSpec.Load()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load OCI spec: %v", err)
|
||||
}
|
||||
|
||||
image, err := image.NewCUDAImageFromSpec(rawSpec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if devices := image.DevicesFromEnvvars(visibleDevicesEnvvar); len(devices) == 0 {
|
||||
logger.Infof("No modification required; no devices requested")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var hasGraphics bool
|
||||
for _, c := range strings.Split(image["NVIDIA_DRIVER_CAPABILITIES"], ",") {
|
||||
if c == "graphics" || c == "all" {
|
||||
hasGraphics = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasGraphics {
|
||||
logger.Debugf("Capability %q not selected", "graphics")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
d, err := discover.NewGraphicsDiscoverer(logger, cfg.NVIDIAContainerCLIConfig.Root)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to construct discoverer: %v", err)
|
||||
}
|
||||
|
||||
return NewModifierFromDiscoverer(logger, d)
|
||||
}
|
||||
45
internal/modifier/tegra.go
Normal file
45
internal/modifier/tegra.go
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
**/
|
||||
|
||||
package modifier
|
||||
|
||||
import (
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/discover"
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup"
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gitlab.com/nvidia/cloud-native/go-nvlib/pkg/nvlib/info"
|
||||
)
|
||||
|
||||
// NewTegraPlatformFiles creates a modifier to inject the Tegra platform files into a container.
|
||||
func NewTegraPlatformFiles(logger *logrus.Logger) (oci.SpecModifier, error) {
|
||||
isTegra, _ := info.New().IsTegraSystem()
|
||||
if !isTegra {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
tegraSystemMounts := discover.NewMounts(
|
||||
logger,
|
||||
lookup.NewFileLocator(logger, ""),
|
||||
"",
|
||||
[]string{
|
||||
"/etc/nv_tegra_release",
|
||||
"/sys/devices/soc0/family",
|
||||
},
|
||||
)
|
||||
|
||||
return NewModifierFromDiscoverer(logger, tegraSystemMounts)
|
||||
}
|
||||
166
internal/nvcaps/nvcaps.go
Normal file
166
internal/nvcaps/nvcaps.go
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
package nvcaps
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
nvidiaProcDriverPath = "/proc/driver/nvidia"
|
||||
nvidiaCapabilitiesPath = nvidiaProcDriverPath + "/capabilities"
|
||||
|
||||
nvcapsProcDriverPath = "/proc/driver/nvidia-caps"
|
||||
nvcapsMigMinorsPath = nvcapsProcDriverPath + "/mig-minors"
|
||||
nvcapsDevicePath = "/dev/nvidia-caps"
|
||||
)
|
||||
|
||||
// MigMinor represents the minor number of a MIG device
|
||||
type MigMinor int
|
||||
|
||||
// MigCap represents the path to a MIG cap file
|
||||
type MigCap string
|
||||
|
||||
// MigCaps stores a map of MIG cap file paths to MIG minors
|
||||
type MigCaps map[MigCap]MigMinor
|
||||
|
||||
// NewGPUInstanceCap creates a MigCap for the specified MIG GPU instance.
|
||||
// A GPU instance is uniquely defined by the GPU minor number and GI instance ID.
|
||||
func NewGPUInstanceCap(gpu, gi int) MigCap {
|
||||
return MigCap(fmt.Sprintf(nvidiaCapabilitiesPath+"/gpu%d/mig/gi%d/access", gpu, gi))
|
||||
}
|
||||
|
||||
// NewComputeInstanceCap creates a MigCap for the specified MIG Compute instance.
|
||||
// A GPU instance is uniquely defined by the GPU minor number, GI instance ID, and CI instance ID.
|
||||
func NewComputeInstanceCap(gpu, gi, ci int) MigCap {
|
||||
return MigCap(fmt.Sprintf(nvidiaCapabilitiesPath+"/gpu%d/mig/gi%d/ci%d/access", gpu, gi, ci))
|
||||
}
|
||||
|
||||
// GetCapDevicePath returns the path to the cap device for the specified cap.
|
||||
// An error is returned if the cap is invalid.
|
||||
func (m MigCaps) GetCapDevicePath(cap MigCap) (string, error) {
|
||||
minor, exists := m[cap]
|
||||
if !exists {
|
||||
return "", fmt.Errorf("invalid MIG capability path %v", cap)
|
||||
}
|
||||
return minor.DevicePath(), nil
|
||||
}
|
||||
|
||||
// NewMigCaps creates a MigCaps structure based on the contents of the MIG minors file.
|
||||
func NewMigCaps() (MigCaps, error) {
|
||||
// Open nvcapsMigMinorsPath for walking.
|
||||
// If the nvcapsMigMinorsPath does not exist, then we are not on a MIG
|
||||
// capable machine, so there is nothing to do.
|
||||
// The format of this file is discussed in:
|
||||
// https://docs.nvidia.com/datacenter/tesla/mig-user-guide/index.html#unique_1576522674
|
||||
minorsFile, err := os.Open(nvcapsMigMinorsPath)
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening MIG minors file: %v", err)
|
||||
}
|
||||
defer minorsFile.Close()
|
||||
|
||||
return processMinorsFile(minorsFile), nil
|
||||
}
|
||||
|
||||
func processMinorsFile(minorsFile io.Reader) MigCaps {
|
||||
// Walk each line of nvcapsMigMinorsPath and construct a mapping of nvidia
|
||||
// capabilities path to device minor for that capability
|
||||
migCaps := make(MigCaps)
|
||||
scanner := bufio.NewScanner(minorsFile)
|
||||
for scanner.Scan() {
|
||||
cap, minor, err := processMigMinorsLine(scanner.Text())
|
||||
if err != nil {
|
||||
log.Printf("Skipping line in MIG minors file: %v", err)
|
||||
continue
|
||||
}
|
||||
migCaps[cap] = minor
|
||||
}
|
||||
return migCaps
|
||||
}
|
||||
|
||||
func processMigMinorsLine(line string) (MigCap, MigMinor, error) {
|
||||
parts := strings.Split(line, " ")
|
||||
if len(parts) != 2 {
|
||||
return "", 0, fmt.Errorf("error processing line: %v", line)
|
||||
}
|
||||
|
||||
migCap := MigCap(parts[0])
|
||||
if !migCap.isValid() {
|
||||
return "", 0, fmt.Errorf("invalid MIG minors line: '%v'", line)
|
||||
}
|
||||
|
||||
minor, err := strconv.Atoi(parts[1])
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("error reading MIG minor from '%v': %v", line, err)
|
||||
}
|
||||
|
||||
return migCap, MigMinor(minor), nil
|
||||
}
|
||||
|
||||
func (m MigCap) isValid() bool {
|
||||
cap := string(m)
|
||||
switch cap {
|
||||
case "config", "monitor":
|
||||
return true
|
||||
default:
|
||||
var gpu int
|
||||
var gi int
|
||||
var ci int
|
||||
// Look for a CI access file
|
||||
n, _ := fmt.Sscanf(cap, "gpu%d/gi%d/ci%d/access", &gpu, &gi, &ci)
|
||||
if n == 3 {
|
||||
return true
|
||||
}
|
||||
// Look for a GI access file
|
||||
n, _ = fmt.Sscanf(cap, "gpu%d/gi%d/access %d", &gpu, &gi)
|
||||
if n == 2 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ProcPath returns the proc path associated with the MIG capability
|
||||
func (m MigCap) ProcPath() string {
|
||||
id := string(m)
|
||||
|
||||
var path string
|
||||
switch id {
|
||||
case "config", "monitor":
|
||||
path = "mig/" + id
|
||||
default:
|
||||
parts := strings.SplitN(id, "/", 2)
|
||||
path = strings.Join([]string{parts[0], "mig", parts[1]}, "/")
|
||||
}
|
||||
return filepath.Join(nvidiaCapabilitiesPath, path)
|
||||
}
|
||||
|
||||
// DevicePath returns the path for the nvidia-caps device with the specified
|
||||
// minor number
|
||||
func (m MigMinor) DevicePath() string {
|
||||
return fmt.Sprintf(nvcapsDevicePath+"/nvidia-cap%d", m)
|
||||
}
|
||||
100
internal/nvcaps/nvcaps_test.go
Normal file
100
internal/nvcaps/nvcaps_test.go
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
*/
|
||||
|
||||
package nvcaps
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestProcessMinorsFile(t *testing.T) {
|
||||
testCases := []struct {
|
||||
lines []string
|
||||
expected MigCaps
|
||||
}{
|
||||
{[]string{}, MigCaps{}},
|
||||
{[]string{"invalidLine"}, MigCaps{}},
|
||||
{[]string{"config 1"}, MigCaps{"config": 1}},
|
||||
{[]string{"gpu0/gi0/ci0/access 4"}, MigCaps{"gpu0/gi0/ci0/access": 4}},
|
||||
{[]string{"config 1", "invalidLine"}, MigCaps{"config": 1}},
|
||||
{[]string{"config 1", "gpu0/gi0/ci0/access 4"}, MigCaps{"config": 1, "gpu0/gi0/ci0/access": 4}},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("testcase %d", i), func(t *testing.T) {
|
||||
contents := strings.NewReader(strings.Join(tc.lines, "\n"))
|
||||
d := processMinorsFile(contents)
|
||||
require.Equal(t, tc.expected, d)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessMigMinorsLine(t *testing.T) {
|
||||
testCases := []struct {
|
||||
line string
|
||||
cap MigCap
|
||||
minor MigMinor
|
||||
err bool
|
||||
}{
|
||||
{"config 1", "config", 1, false},
|
||||
{"monitor 2", "monitor", 2, false},
|
||||
{"gpu0/gi0/access 3", "gpu0/gi0/access", 3, false},
|
||||
{"gpu0/gi0/ci0/access 4", "gpu0/gi0/ci0/access", 4, false},
|
||||
{"notconfig 99", "", 0, true},
|
||||
{"config notanint", "", 0, true},
|
||||
{"", "", 0, true},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("testcase %d", i), func(t *testing.T) {
|
||||
cap, minor, err := processMigMinorsLine(tc.line)
|
||||
|
||||
require.Equal(t, tc.cap, cap)
|
||||
require.Equal(t, tc.minor, minor)
|
||||
if tc.err {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMigCapProcPaths(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{"config", "/proc/driver/nvidia/capabilities/mig/config"},
|
||||
{"monitor", "/proc/driver/nvidia/capabilities/mig/monitor"},
|
||||
{"gpu0/gi0/access", "/proc/driver/nvidia/capabilities/gpu0/mig/gi0/access"},
|
||||
{"gpu0/gi0/ci0/access", "/proc/driver/nvidia/capabilities/gpu0/mig/gi0/ci0/access"},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("testcase %d", i), func(t *testing.T) {
|
||||
m := MigCap(tc.input)
|
||||
require.Equal(t, tc.expected, m.ProcPath())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMigMinorDevicePath(t *testing.T) {
|
||||
m := MigMinor(0)
|
||||
require.Equal(t, "/dev/nvidia-caps/nvidia-cap0", m.DevicePath())
|
||||
}
|
||||
@@ -10,8 +10,16 @@ Build-Depends: debhelper (>= 9)
|
||||
|
||||
Package: nvidia-container-toolkit
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, libnvidia-container-tools (>= @LIBNVIDIA_CONTAINER_TOOLS_VERSION@), libnvidia-container-tools (<< 2.0.0), libseccomp2
|
||||
Depends: ${misc:Depends}, nvidia-container-toolkit-base (= @VERSION@), libnvidia-container-tools (>= @LIBNVIDIA_CONTAINER_TOOLS_VERSION@), libnvidia-container-tools (<< 2.0.0), libseccomp2
|
||||
Breaks: nvidia-container-runtime (<= 3.5.0-1), nvidia-container-runtime-hook
|
||||
Replaces: nvidia-container-runtime (<= 3.5.0-1), nvidia-container-runtime-hook
|
||||
Description: NVIDIA Container toolkit
|
||||
Provides tools and utilities to enable GPU support in containers.
|
||||
|
||||
Package: nvidia-container-toolkit-base
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}
|
||||
Breaks: nvidia-container-runtime (<= 3.5.0-1), nvidia-container-runtime-hook, nvidia-container-toolkit (<= 1.10.0-1)
|
||||
Replaces: nvidia-container-runtime (<= 3.5.0-1), nvidia-container-runtime-hook
|
||||
Description: NVIDIA Container Toolkit Base
|
||||
Provides tools such as the NVIDIA Container Runtime and NVIDIA Container Toolkit CLI to enable GPU support in containers.
|
||||
|
||||
3
packaging/debian/nvidia-container-toolkit-base.install
Normal file
3
packaging/debian/nvidia-container-toolkit-base.install
Normal file
@@ -0,0 +1,3 @@
|
||||
config.toml /etc/nvidia-container-runtime
|
||||
nvidia-container-runtime /usr/bin
|
||||
nvidia-ctk /usr/bin
|
||||
@@ -1,4 +1 @@
|
||||
config.toml /etc/nvidia-container-runtime
|
||||
nvidia-container-runtime-hook /usr/bin
|
||||
nvidia-container-runtime /usr/bin
|
||||
nvidia-ctk /usr/bin
|
||||
|
||||
@@ -4,6 +4,7 @@ set -e
|
||||
|
||||
sed -i "s;@SECTION@;${SECTION:+$SECTION/};g" debian/control
|
||||
sed -i "s;@LIBNVIDIA_CONTAINER_TOOLS_VERSION@;${LIBNVIDIA_CONTAINER_TOOLS_VERSION:+$LIBNVIDIA_CONTAINER_TOOLS_VERSION};g" debian/control
|
||||
sed -i "s;@VERSION@;${VERSION:+$VERSION};g" debian/control
|
||||
|
||||
if [ -n "$DISTRIB" ]; then
|
||||
sed -i "s;UNRELEASED;$DISTRIB;" debian/changelog
|
||||
|
||||
@@ -18,10 +18,11 @@ Source4: oci-nvidia-hook
|
||||
Source5: oci-nvidia-hook.json
|
||||
Source6: LICENSE
|
||||
|
||||
Obsoletes: nvidia-container-runtime <= 3.5.0-1, nvidia-container-runtime-hook
|
||||
Obsoletes: nvidia-container-runtime <= 3.5.0-1, nvidia-container-runtime-hook <= 1.4.0-2
|
||||
Provides: nvidia-container-runtime
|
||||
Provides: nvidia-container-runtime-hook
|
||||
Requires: libnvidia-container-tools >= %{libnvidia_container_tools_version}, libnvidia-container-tools < 2.0.0
|
||||
Requires: nvidia-container-toolkit-base == %{version}-%{release}
|
||||
|
||||
%if 0%{?suse_version}
|
||||
Requires: libseccomp2
|
||||
@@ -55,14 +56,11 @@ install -m 644 -t %{buildroot}/usr/share/containers/oci/hooks.d oci-nvidia-hook.
|
||||
ln -sf %{_bindir}/nvidia-container-runtime-hook %{_bindir}/nvidia-container-toolkit
|
||||
|
||||
%postun
|
||||
rm -f %{_bindir}/nvidia-container-runtime-toolkit
|
||||
rm -f %{_bindir}/nvidia-container-toolkit
|
||||
|
||||
%files
|
||||
%license LICENSE
|
||||
%{_bindir}/nvidia-container-runtime-hook
|
||||
%{_bindir}/nvidia-container-runtime
|
||||
%{_bindir}/nvidia-ctk
|
||||
%config /etc/nvidia-container-runtime/config.toml
|
||||
/usr/libexec/oci/hooks.d/oci-nvidia-hook
|
||||
/usr/share/containers/oci/hooks.d/oci-nvidia-hook.json
|
||||
|
||||
@@ -71,3 +69,22 @@ rm -f %{_bindir}/nvidia-container-runtime-toolkit
|
||||
* %{release_date} NVIDIA CORPORATION <cudatools@nvidia.com> %{version}-%{release}
|
||||
- See https://gitlab.com/nvidia/container-toolkit/container-toolkit/-/blob/%{git_commit}/CHANGELOG.md
|
||||
- Bump libnvidia-container dependency to libnvidia-container-tools >= %{libnvidia_container_tools_version}
|
||||
|
||||
# The BASE package consists of the NVIDIA Container Runtime and the NVIDIA Container Toolkit CLI.
|
||||
# This allows the package to be installed on systems where no NVIDIA Container CLI is available.
|
||||
%package base
|
||||
Summary: NVIDIA Container Toolkit Base
|
||||
Obsoletes: nvidia-container-runtime <= 3.5.0-1, nvidia-container-runtime-hook <= 1.4.0-2
|
||||
Provides: nvidia-container-runtime
|
||||
# Since this package allows certain components of the NVIDIA Container Toolkit to be installed separately
|
||||
# it conflicts with older versions of the nvidia-container-toolkit package that also provide these files.
|
||||
Conflicts: nvidia-container-toolkit <= 1.10.0-1
|
||||
|
||||
%description base
|
||||
Provides tools such as the NVIDIA Container Runtime and NVIDIA Container Toolkit CLI to enable GPU support in containers.
|
||||
|
||||
%files base
|
||||
%license LICENSE
|
||||
%config /etc/nvidia-container-runtime/config.toml
|
||||
%{_bindir}/nvidia-container-runtime
|
||||
%{_bindir}/nvidia-ctk
|
||||
|
||||
@@ -37,6 +37,8 @@ all=(
|
||||
centos8-x86_64
|
||||
debian10-amd64
|
||||
debian9-amd64
|
||||
fedora35-aarch64
|
||||
fedora35-x86_64
|
||||
opensuse-leap15.1-x86_64
|
||||
ubuntu16.04-amd64
|
||||
ubuntu16.04-ppc64le
|
||||
|
||||
@@ -61,6 +61,8 @@ function sign() {
|
||||
;;
|
||||
debian*) pkg_type=deb
|
||||
;;
|
||||
fedora*) pkg_type=rpm
|
||||
;;
|
||||
opensuse-leap*) pkg_type=rpm
|
||||
;;
|
||||
ubuntu*) pkg_type=deb
|
||||
|
||||
@@ -94,6 +94,8 @@ function sync() {
|
||||
;;
|
||||
debian*) pkg_type=deb
|
||||
;;
|
||||
fedora*) pkg_type=rpm
|
||||
;;
|
||||
opensuse-leap*) pkg_type=rpm
|
||||
;;
|
||||
ubuntu*) pkg_type=deb
|
||||
@@ -130,8 +132,17 @@ function sync() {
|
||||
|
||||
done
|
||||
if [[ ${REPO} == "stable" ]]; then
|
||||
cp ${src}/nvidia-container-runtime*.${pkg_type} ${dst}
|
||||
cp ${src}/nvidia-docker*.${pkg_type} ${dst}
|
||||
for f in $(ls ${src}/nvidia-container-runtime*.${pkg_type} ${src}/nvidia-docker*.${pkg_type}); do
|
||||
df=${dst}/$(basename ${f})
|
||||
df_stable=${df//"/experimental/"/"/stable/"}
|
||||
if [[ -f "${df}" ]]; then
|
||||
echo "${df} already exists; skipping"
|
||||
elif [[ ${REPO} == "experimental" && -f ${df_stable} ]]; then
|
||||
echo "${df_stable} already exists; skipping"
|
||||
else
|
||||
cp ${f} ${df}
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -148,6 +159,8 @@ all=(
|
||||
centos8-x86_64
|
||||
debian10-amd64
|
||||
debian9-amd64
|
||||
fedora35-aarch64
|
||||
fedora35-x86_64
|
||||
opensuse-leap15.1-x86_64
|
||||
ubuntu16.04-amd64
|
||||
ubuntu16.04-ppc64le
|
||||
|
||||
@@ -43,8 +43,8 @@ testing::containerd::toolkit::run() {
|
||||
|
||||
# Ensure that we can run some non GPU containers from within dind
|
||||
with_retry 3 5s testing::containerd::dind::exec " \
|
||||
ctr --address=${containerd_dind_containerd_dir}/containerd.sock image pull nvcr.io/nvidia/cuda:11.1-base; \
|
||||
ctr --address=${containerd_dind_containerd_dir}/containerd.sock run --rm --runtime=io.containerd.runtime.v1.linux nvcr.io/nvidia/cuda:11.1-base cuda echo foo"
|
||||
ctr --address=${containerd_dind_containerd_dir}/containerd.sock image pull nvcr.io/nvidia/cuda:11.1.1-base-ubuntu20.04; \
|
||||
ctr --address=${containerd_dind_containerd_dir}/containerd.sock run --rm --runtime=io.containerd.runtime.v1.linux nvcr.io/nvidia/cuda:11.1.1-base-ubuntu20.04 cuda echo foo"
|
||||
|
||||
# Share the volumes so that we can edit the config file and point to the new runtime
|
||||
# Share the pid so that we can ask docker to reload its config
|
||||
@@ -63,8 +63,8 @@ testing::containerd::toolkit::run() {
|
||||
|
||||
# Ensure that we haven't broken non GPU containers
|
||||
with_retry 3 5s testing::containerd::dind::exec " \
|
||||
ctr --address=${containerd_dind_containerd_dir}/containerd.sock image pull nvcr.io/nvidia/cuda:11.1-base; \
|
||||
ctr --address=${containerd_dind_containerd_dir}/containerd.sock run --rm --runtime=io.containerd.runtime.v1.linux nvcr.io/nvidia/cuda:11.1-base cuda echo foo"
|
||||
ctr --address=${containerd_dind_containerd_dir}/containerd.sock image pull nvcr.io/nvidia/cuda:11.1.1-base-ubuntu20.04; \
|
||||
ctr --address=${containerd_dind_containerd_dir}/containerd.sock run --rm --runtime=io.containerd.runtime.v1.linux nvcr.io/nvidia/cuda:11.1.1-base-ubuntu20.04 cuda echo foo"
|
||||
}
|
||||
|
||||
# This test runs containerd setup and containerd cleanup in succession to ensure that the
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
WORKFLOW ?= nvidia-docker
|
||||
|
||||
DISTRIBUTIONS := ubuntu18.04 centos8
|
||||
DISTRIBUTIONS := ubuntu18.04 centos8 fedora35
|
||||
|
||||
IMAGE_TARGETS := $(patsubst %,image-%, $(DISTRIBUTIONS))
|
||||
RUN_TARGETS := $(patsubst %,run-%, $(DISTRIBUTIONS))
|
||||
@@ -28,7 +28,6 @@ image-%: DOCKERFILE = docker/$(*)/Dockerfile
|
||||
images: $(IMAGE_TARGETS)
|
||||
$(IMAGE_TARGETS): image-%: $(DOCKERFILE)
|
||||
docker build ${PLATFORM_ARGS} \
|
||||
--build-arg WORKFLOW="$(WORKFLOW)" \
|
||||
-t nvidia-container-toolkit-repo-test:$(*) \
|
||||
-f $(DOCKERFILE) \
|
||||
$(shell dirname $(DOCKERFILE))
|
||||
@@ -36,6 +35,7 @@ $(IMAGE_TARGETS): image-%: $(DOCKERFILE)
|
||||
|
||||
%-ubuntu18.04: ARCH ?= amd64
|
||||
%-centos8: ARCH ?= x86_64
|
||||
%-fedora35: ARCH ?= x86_64
|
||||
|
||||
PLATFORM_ARGS = --platform=linux/${ARCH}
|
||||
|
||||
|
||||
@@ -1,16 +1,6 @@
|
||||
ARG BASEIMAGE=centos:8
|
||||
ARG BASEIMAGE=quay.io/centos/centos:stream8
|
||||
FROM ${BASEIMAGE}
|
||||
|
||||
ARG BASEIMAGE
|
||||
# See https://www.centos.org/centos-linux-eol/
|
||||
# and https://stackoverflow.com/a/70930049 for move to vault.centos.org
|
||||
# and https://serverfault.com/questions/1093922/failing-to-run-yum-update-in-centos-8 for move to vault.epel.cloud
|
||||
RUN [[ "${BASEIMAGE}" != "centos:8" ]] || \
|
||||
( \
|
||||
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-Linux-* && \
|
||||
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.epel.cloud|g' /etc/yum.repos.d/CentOS-Linux-* \
|
||||
)
|
||||
|
||||
RUN yum install -y \
|
||||
yum-utils \
|
||||
ruby-devel \
|
||||
@@ -35,9 +25,8 @@ RUN fpm -s empty \
|
||||
rm -f /tmp/docker.rpm
|
||||
|
||||
|
||||
ARG WORKFLOW=nvidia-docker
|
||||
RUN curl -s -L https://nvidia.github.io/${WORKFLOW}/centos8/nvidia-docker.repo \
|
||||
| tee /etc/yum.repos.d/nvidia-docker.repo
|
||||
RUN curl -s -L https://nvidia.github.io/libnvidia-container/centos8/libnvidia-container.repo \
|
||||
| tee /etc/yum.repos.d/nvidia-container-toolkit.repo
|
||||
|
||||
COPY entrypoint.sh /
|
||||
COPY install_repo.sh /
|
||||
|
||||
@@ -21,5 +21,5 @@
|
||||
|
||||
test_repo=$1
|
||||
echo "Setting up TEST repo: ${test_repo}"
|
||||
sed -i -e "s#nvidia\.github\.io/libnvidia-container#${test_repo}/libnvidia-container#g" /etc/yum.repos.d/nvidia-docker.repo
|
||||
sed -i -e "s#nvidia\.github\.io/libnvidia-container#${test_repo}/libnvidia-container#g" /etc/yum.repos.d/nvidia-container-toolkit.repo
|
||||
yum-config-manager --enable libnvidia-container-experimental
|
||||
|
||||
34
test/release/docker/fedora35/Dockerfile
Normal file
34
test/release/docker/fedora35/Dockerfile
Normal file
@@ -0,0 +1,34 @@
|
||||
ARG BASEIMAGE=fedora:35
|
||||
FROM ${BASEIMAGE}
|
||||
|
||||
RUN yum install -y \
|
||||
yum-utils \
|
||||
ruby-devel \
|
||||
gcc \
|
||||
make \
|
||||
rpm-build \
|
||||
rubygems \
|
||||
createrepo
|
||||
|
||||
RUN gem install --no-document fpm
|
||||
|
||||
# We create and install a dummy docker package since these dependencies are out of
|
||||
# scope for the tests performed here.
|
||||
RUN fpm -s empty \
|
||||
-t rpm \
|
||||
--description "A dummy package for docker-ce_18.06.3.ce-3.el7" \
|
||||
-n docker-ce --version 18.06.3.ce-3.el7 \
|
||||
-p /tmp/docker.rpm \
|
||||
&& \
|
||||
yum localinstall -y /tmp/docker.rpm \
|
||||
&& \
|
||||
rm -f /tmp/docker.rpm
|
||||
|
||||
|
||||
RUN curl -s -L https://nvidia.github.io/libnvidia-container/fedora35/libnvidia-container.repo \
|
||||
| tee /etc/yum.repos.d/nvidia-container-toolkit.repo
|
||||
|
||||
COPY entrypoint.sh /
|
||||
COPY install_repo.sh /
|
||||
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||
42
test/release/docker/fedora35/entrypoint.sh
Executable file
42
test/release/docker/fedora35/entrypoint.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# This script is used to build the packages for the components of the NVIDIA
|
||||
# Container Stack. These include the nvidia-container-toolkit in this repository
|
||||
# as well as the components included in the third_party folder.
|
||||
# All required packages are generated in the specified dist folder.
|
||||
|
||||
: ${LOCAL_REPO_DIRECTORY:=/local-repository}
|
||||
if [[ -d ${LOCAL_REPO_DIRECTORY} ]]; then
|
||||
echo "Setting up local-repository"
|
||||
createrepo /local-repository
|
||||
|
||||
cat >/etc/yum.repos.d/local.repo <<EOL
|
||||
[local-repository]
|
||||
name=NVIDIA Container Toolkit Local Packages
|
||||
baseurl=file:///local-repository
|
||||
enabled=0
|
||||
gpgcheck=0
|
||||
protect=1
|
||||
EOL
|
||||
yum-config-manager --enable local-repository
|
||||
elif [[ -n ${TEST_REPO} ]]; then
|
||||
./install_repo.sh ${TEST_REPO}
|
||||
else
|
||||
echo "Skipping repo setup"
|
||||
fi
|
||||
|
||||
exec bash $@
|
||||
25
test/release/docker/fedora35/install_repo.sh
Executable file
25
test/release/docker/fedora35/install_repo.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# This script is used to build the packages for the components of the NVIDIA
|
||||
# Container Stack. These include the nvidia-container-toolkit in this repository
|
||||
# as well as the components included in the third_party folder.
|
||||
# All required packages are generated in the specified dist folder.
|
||||
|
||||
test_repo=$1
|
||||
echo "Setting up TEST repo: ${test_repo}"
|
||||
sed -i -e "s#nvidia\.github\.io/libnvidia-container#${test_repo}/libnvidia-container#g" /etc/yum.repos.d/nvidia-container-toolkit.repo
|
||||
yum-config-manager --enable libnvidia-container-experimental
|
||||
@@ -39,9 +39,8 @@ RUN fpm -s empty \
|
||||
rm -f /tmp/docker.deb
|
||||
|
||||
|
||||
ARG WORKFLOW=nvidia-docker
|
||||
RUN curl -s -L https://nvidia.github.io/${WORKFLOW}/gpgkey | apt-key add - \
|
||||
&& curl -s -L https://nvidia.github.io/${WORKFLOW}/ubuntu18.04/nvidia-docker.list | tee /etc/apt/sources.list.d/nvidia-docker.list \
|
||||
RUN curl -s -L https://nvidia.github.io/libnvidia-container/gpgkey | apt-key add - \
|
||||
&& curl -s -L https://nvidia.github.io/libnvidia-container/ubuntu18.04/libnvidia-container.list | tee /etc/apt/sources.list.d/nvidia-container-toolkit.list \
|
||||
&& apt-get update
|
||||
|
||||
COPY entrypoint.sh /
|
||||
|
||||
@@ -21,5 +21,5 @@
|
||||
|
||||
test_repo=$1
|
||||
echo "Setting up TEST repo: ${test_repo}"
|
||||
sed -i -e "s#nvidia\.github\.io/libnvidia-container#${test_repo}/libnvidia-container#g" /etc/apt/sources.list.d/nvidia-docker.list
|
||||
sed -i -e '/experimental/ s/^#//g' /etc/apt/sources.list.d/nvidia-docker.list
|
||||
sed -i -e "s#nvidia\.github\.io/libnvidia-container#${test_repo}/libnvidia-container#g" /etc/apt/sources.list.d/nvidia-container-toolkit.list
|
||||
sed -i -e '/experimental/ s/^#//g' /etc/apt/sources.list.d/nvidia-container-toolkit.list
|
||||
|
||||
2
third_party/libnvidia-container
vendored
2
third_party/libnvidia-container
vendored
Submodule third_party/libnvidia-container updated: ab4ac25ea4...90bc7a540a
2
third_party/nvidia-container-runtime
vendored
2
third_party/nvidia-container-runtime
vendored
Submodule third_party/nvidia-container-runtime updated: d2bb9d0afe...68b81a207b
2
third_party/nvidia-docker
vendored
2
third_party/nvidia-docker
vendored
Submodule third_party/nvidia-docker updated: 0c082f6e75...80902fe3af
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -12,7 +12,8 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
*/
|
||||
**/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -22,8 +23,6 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
|
||||
hooks "github.com/containers/podman/v4/pkg/hooks/1.0.0"
|
||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
cli "github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -164,20 +163,20 @@ func getHookPath(hooksDir string, hookFilename string) string {
|
||||
return filepath.Join(hooksDir, hookFilename)
|
||||
}
|
||||
|
||||
func generateOciHook(toolkitDir string) hooks.Hook {
|
||||
func generateOciHook(toolkitDir string) podmanHook {
|
||||
hookPath := filepath.Join(toolkitDir, config.NVIDIAContainerRuntimeHookExecutable)
|
||||
envPath := "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:" + toolkitDir
|
||||
always := true
|
||||
|
||||
hook := hooks.Hook{
|
||||
hook := podmanHook{
|
||||
Version: "1.0.0",
|
||||
Stages: []string{"prestart"},
|
||||
Hook: rspec.Hook{
|
||||
Hook: specHook{
|
||||
Path: hookPath,
|
||||
Args: []string{filepath.Base(config.NVIDIAContainerRuntimeHookExecutable), "prestart"},
|
||||
Env: []string{envPath},
|
||||
},
|
||||
When: hooks.When{
|
||||
When: When{
|
||||
Always: &always,
|
||||
Commands: []string{".*"},
|
||||
},
|
||||
|
||||
50
tools/container/crio/hooks.go
Normal file
50
tools/container/crio/hooks.go
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
**/
|
||||
|
||||
package main
|
||||
|
||||
// podmanHook is the hook configuration structure.
|
||||
// This is taken from `Hook` at https://github.com/containers/podman/blob/3c53200e9d61fdf95fe1da825bb2a89372551350/pkg/hooks/1.0.0/hook.go#L18
|
||||
type podmanHook struct {
|
||||
Version string `json:"version"`
|
||||
Hook specHook `json:"hook"`
|
||||
When When `json:"when"`
|
||||
Stages []string `json:"stages"`
|
||||
}
|
||||
|
||||
// specHook specifies a command that is run at a particular event in the lifecycle of a container
|
||||
// This is taken from `Hook` at https://github.com/opencontainers/runtime-spec/blob/9ee22abf867e374c5464c7bbe0d0db01482254ab/specs-go/config.go#L128
|
||||
type specHook struct {
|
||||
Path string `json:"path"`
|
||||
Args []string `json:"args,omitempty"`
|
||||
Env []string `json:"env,omitempty"`
|
||||
Timeout *int `json:"timeout,omitempty"`
|
||||
}
|
||||
|
||||
// When holds hook-injection conditions.
|
||||
// This is taken from `When` at https://github.com/containers/podman/blob/3c53200e9d61fdf95fe1da825bb2a89372551350/pkg/hooks/1.0.0/when.go#L11
|
||||
type When struct {
|
||||
Always *bool `json:"always,omitempty"`
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
Commands []string `json:"commands,omitempty"`
|
||||
HasBindMounts *bool `json:"hasBindMounts,omitempty"`
|
||||
|
||||
// Or enables any-of matching.
|
||||
//
|
||||
// Deprecated: this property is for is backwards-compatibility with
|
||||
// 0.1.0 hooks. It will be removed when we drop support for them.
|
||||
Or bool `json:"-"`
|
||||
}
|
||||
@@ -30,23 +30,35 @@ var availableRuntimes = map[string]struct{}{"docker": {}, "crio": {}, "container
|
||||
var waitingForSignal = make(chan bool, 1)
|
||||
var signalReceived = make(chan bool, 1)
|
||||
|
||||
var destinationArg string
|
||||
var noDaemonFlag bool
|
||||
var runtimeFlag string
|
||||
var runtimeArgsFlag string
|
||||
// options stores the command line arguments
|
||||
type options struct {
|
||||
noDaemon bool
|
||||
runtime string
|
||||
runtimeArgs string
|
||||
root string
|
||||
}
|
||||
|
||||
// Version defines the CLI version. This is set at build time using LD FLAGS
|
||||
var Version = "development"
|
||||
|
||||
func main() {
|
||||
remainingArgs, root, err := ParseArgs(os.Args)
|
||||
if err != nil {
|
||||
log.Errorf("Error: unable to parse arguments: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
options := options{}
|
||||
// Create the top-level CLI
|
||||
c := cli.NewApp()
|
||||
c.Name = "nvidia-toolkit"
|
||||
c.Usage = "Install the nvidia-container-toolkit for use by a given runtime"
|
||||
c.UsageText = "DESTINATION [-n | --no-daemon] [-r | --runtime] [-u | --runtime-args]"
|
||||
c.UsageText = "[DESTINATION] [-n | --no-daemon] [-r | --runtime] [-u | --runtime-args]"
|
||||
c.Description = "DESTINATION points to the host path underneath which the nvidia-container-toolkit should be installed.\nIt will be installed at ${DESTINATION}/toolkit"
|
||||
c.Version = Version
|
||||
c.Action = Run
|
||||
c.Action = func(ctx *cli.Context) error {
|
||||
return Run(ctx, &options)
|
||||
}
|
||||
|
||||
// Setup flags for the CLI
|
||||
c.Flags = []cli.Flag{
|
||||
@@ -54,7 +66,7 @@ func main() {
|
||||
Name: "no-daemon",
|
||||
Aliases: []string{"n"},
|
||||
Usage: "terminate immediatly after setting up the runtime. Note that no cleanup will be performed",
|
||||
Destination: &noDaemonFlag,
|
||||
Destination: &options.noDaemon,
|
||||
EnvVars: []string{"NO_DAEMON"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
@@ -62,7 +74,7 @@ func main() {
|
||||
Aliases: []string{"r"},
|
||||
Usage: "the runtime to setup on this node. One of {'docker', 'crio', 'containerd'}",
|
||||
Value: defaultRuntime,
|
||||
Destination: &runtimeFlag,
|
||||
Destination: &options.runtime,
|
||||
EnvVars: []string{"RUNTIME"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
@@ -70,20 +82,20 @@ func main() {
|
||||
Aliases: []string{"u"},
|
||||
Usage: "arguments to pass to 'docker', 'crio', or 'containerd' setup command",
|
||||
Value: defaultRuntimeArgs,
|
||||
Destination: &runtimeArgsFlag,
|
||||
Destination: &options.runtimeArgs,
|
||||
EnvVars: []string{"RUNTIME_ARGS"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "root",
|
||||
Value: root,
|
||||
Usage: "the folder where the NVIDIA Container Toolkit is to be installed. It will be installed to `ROOT`/toolkit",
|
||||
Destination: &options.root,
|
||||
EnvVars: []string{"ROOT"},
|
||||
},
|
||||
}
|
||||
|
||||
// Run the CLI
|
||||
log.Infof("Starting %v", c.Name)
|
||||
|
||||
remainingArgs, err := ParseArgs(os.Args)
|
||||
if err != nil {
|
||||
log.Errorf("Error: unable to parse arguments: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := c.Run(remainingArgs); err != nil {
|
||||
log.Errorf("error running nvidia-toolkit: %v", err)
|
||||
os.Exit(1)
|
||||
@@ -93,8 +105,8 @@ func main() {
|
||||
}
|
||||
|
||||
// Run runs the core logic of the CLI
|
||||
func Run(c *cli.Context) error {
|
||||
err := verifyFlags()
|
||||
func Run(c *cli.Context, o *options) error {
|
||||
err := verifyFlags(o)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to verify flags: %v", err)
|
||||
}
|
||||
@@ -105,23 +117,23 @@ func Run(c *cli.Context) error {
|
||||
}
|
||||
defer shutdown()
|
||||
|
||||
err = installToolkit()
|
||||
err = installToolkit(o)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to install toolkit: %v", err)
|
||||
}
|
||||
|
||||
err = setupRuntime()
|
||||
err = setupRuntime(o)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to setup runtime: %v", err)
|
||||
}
|
||||
|
||||
if !noDaemonFlag {
|
||||
if !o.noDaemon {
|
||||
err = waitForSignal()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to wait for signal: %v", err)
|
||||
}
|
||||
|
||||
err = cleanupRuntime()
|
||||
err = cleanupRuntime(o)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to cleanup runtime: %v", err)
|
||||
}
|
||||
@@ -130,46 +142,42 @@ func Run(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseArgs parses the command line arguments and returns the remaining arguments
|
||||
func ParseArgs(args []string) ([]string, error) {
|
||||
// ParseArgs checks if a single positional argument was defined and extracts this the root.
|
||||
// If no positional arguments are defined, the it is assumed that the root is specified as a flag.
|
||||
func ParseArgs(args []string) ([]string, string, error) {
|
||||
log.Infof("Parsing arguments")
|
||||
|
||||
numPositionalArgs := 2 // Includes command itself
|
||||
|
||||
if len(args) < numPositionalArgs {
|
||||
return nil, fmt.Errorf("missing arguments")
|
||||
if len(args) < 2 {
|
||||
return args, "", nil
|
||||
}
|
||||
|
||||
for _, arg := range args {
|
||||
if arg == "--help" || arg == "-h" {
|
||||
return []string{args[0], arg}, nil
|
||||
}
|
||||
if arg == "--version" || arg == "-v" {
|
||||
return []string{args[0], arg}, nil
|
||||
}
|
||||
}
|
||||
|
||||
for _, arg := range args[:numPositionalArgs] {
|
||||
var lastPositionalArg int
|
||||
for i, arg := range args {
|
||||
if strings.HasPrefix(arg, "-") {
|
||||
return nil, fmt.Errorf("unexpected flag where argument should be")
|
||||
break
|
||||
}
|
||||
lastPositionalArg = i
|
||||
}
|
||||
|
||||
for _, arg := range args[numPositionalArgs:] {
|
||||
if !strings.HasPrefix(arg, "-") {
|
||||
return nil, fmt.Errorf("unexpected argument where flag should be")
|
||||
}
|
||||
if lastPositionalArg == 0 {
|
||||
return args, "", nil
|
||||
}
|
||||
|
||||
destinationArg = args[1]
|
||||
if lastPositionalArg == 1 {
|
||||
return append([]string{args[0]}, args[2:]...), args[1], nil
|
||||
}
|
||||
|
||||
return append([]string{args[0]}, args[numPositionalArgs:]...), nil
|
||||
return nil, "", fmt.Errorf("unexpected positional argument(s) %v", args[2:lastPositionalArg+1])
|
||||
}
|
||||
|
||||
func verifyFlags() error {
|
||||
func verifyFlags(o *options) error {
|
||||
log.Infof("Verifying Flags")
|
||||
if _, exists := availableRuntimes[runtimeFlag]; !exists {
|
||||
return fmt.Errorf("unknown runtime: %v", runtimeFlag)
|
||||
if o.root == "" {
|
||||
return fmt.Errorf("the install root must be specified")
|
||||
}
|
||||
|
||||
if _, exists := availableRuntimes[o.runtime]; !exists {
|
||||
return fmt.Errorf("unknown runtime: %v", o.runtime)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -211,14 +219,14 @@ func initialize() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func installToolkit() error {
|
||||
func installToolkit(o *options) error {
|
||||
log.Infof("Installing toolkit")
|
||||
|
||||
cmdline := []string{
|
||||
toolkitCommand,
|
||||
"install",
|
||||
"--toolkit-root",
|
||||
filepath.Join(destinationArg, toolkitSubDir),
|
||||
filepath.Join(o.root, toolkitSubDir),
|
||||
}
|
||||
|
||||
cmd := exec.Command("sh", "-c", strings.Join(cmdline, " "))
|
||||
@@ -232,19 +240,19 @@ func installToolkit() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupRuntime() error {
|
||||
toolkitDir := filepath.Join(destinationArg, toolkitSubDir)
|
||||
func setupRuntime(o *options) error {
|
||||
toolkitDir := filepath.Join(o.root, toolkitSubDir)
|
||||
|
||||
log.Infof("Setting up runtime")
|
||||
|
||||
cmdline := fmt.Sprintf("%v setup %v %v\n", runtimeFlag, runtimeArgsFlag, toolkitDir)
|
||||
cmdline := fmt.Sprintf("%v setup %v %v\n", o.runtime, o.runtimeArgs, toolkitDir)
|
||||
|
||||
cmd := exec.Command("sh", "-c", cmdline)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error running %v command: %v", runtimeFlag, err)
|
||||
return fmt.Errorf("error running %v command: %v", o.runtime, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -257,19 +265,19 @@ func waitForSignal() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func cleanupRuntime() error {
|
||||
toolkitDir := filepath.Join(destinationArg, toolkitSubDir)
|
||||
func cleanupRuntime(o *options) error {
|
||||
toolkitDir := filepath.Join(o.root, toolkitSubDir)
|
||||
|
||||
log.Infof("Cleaning up Runtime")
|
||||
|
||||
cmdline := fmt.Sprintf("%v cleanup %v %v\n", runtimeFlag, runtimeArgsFlag, toolkitDir)
|
||||
cmdline := fmt.Sprintf("%v cleanup %v %v\n", o.runtime, o.runtimeArgs, toolkitDir)
|
||||
|
||||
cmd := exec.Command("sh", "-c", cmdline)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error running %v command: %v", runtimeFlag, err)
|
||||
return fmt.Errorf("error running %v command: %v", o.runtime, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
84
tools/container/nvidia-toolkit/run_test.go
Normal file
84
tools/container/nvidia-toolkit/run_test.go
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
**/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParseArgs(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
expectedRemaining []string
|
||||
expectedRoot string
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
args: []string{},
|
||||
expectedRemaining: []string{},
|
||||
expectedRoot: "",
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
args: []string{"app"},
|
||||
expectedRemaining: []string{"app"},
|
||||
},
|
||||
{
|
||||
args: []string{"app", "root"},
|
||||
expectedRemaining: []string{"app"},
|
||||
expectedRoot: "root",
|
||||
},
|
||||
{
|
||||
args: []string{"app", "--flag"},
|
||||
expectedRemaining: []string{"app", "--flag"},
|
||||
},
|
||||
{
|
||||
args: []string{"app", "root", "--flag"},
|
||||
expectedRemaining: []string{"app", "--flag"},
|
||||
expectedRoot: "root",
|
||||
},
|
||||
{
|
||||
args: []string{"app", "root", "not-root", "--flag"},
|
||||
expectedError: fmt.Errorf("unexpected positional argument(s) [not-root]"),
|
||||
},
|
||||
{
|
||||
args: []string{"app", "root", "not-root"},
|
||||
expectedError: fmt.Errorf("unexpected positional argument(s) [not-root]"),
|
||||
},
|
||||
{
|
||||
args: []string{"app", "root", "not-root", "also"},
|
||||
expectedError: fmt.Errorf("unexpected positional argument(s) [not-root also]"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
remaining, root, err := ParseArgs(tc.args)
|
||||
if tc.expectedError != nil {
|
||||
require.EqualError(t, err, tc.expectedError.Error())
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
require.ElementsMatch(t, tc.expectedRemaining, remaining)
|
||||
require.Equal(t, tc.expectedRoot, root)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -117,13 +117,14 @@ func main() {
|
||||
&cli.BoolFlag{
|
||||
Name: "accept-nvidia-visible-devices-envvar-when-unprivileged",
|
||||
Usage: "Set the accept-nvidia-visible-devices-envvar-when-unprivileged config option",
|
||||
Value: true,
|
||||
Destination: &opts.acceptNVIDIAVisibleDevicesWhenUnprivileged,
|
||||
EnvVars: []string{"ACCEPT_NVIDIA_VISIBLE_DEVICES_ENVVAR_WHEN_UNPRIVILEGED"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "accept-nvidia-visible-devices-as-volume-mounts",
|
||||
Usage: "Set the accept-nvidia-visible-devices-as-volume-mounts config option",
|
||||
Destination: &opts.acceptNVIDIAVisibleDevicesWhenUnprivileged,
|
||||
Destination: &opts.acceptNVIDIAVisibleDevicesAsVolumeMounts,
|
||||
EnvVars: []string{"ACCEPT_NVIDIA_VISIBLE_DEVICES_AS_VOLUME_MOUNTS"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
@@ -314,6 +315,10 @@ func installToolkitConfig(toolkitConfigPath string, nvidiaContainerCliExecutable
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing config: %v", err)
|
||||
}
|
||||
|
||||
os.Stdout.WriteString("Using config:\n")
|
||||
config.WriteTo(os.Stdout)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
3
vendor/github.com/BurntSushi/toml/go.mod
generated
vendored
3
vendor/github.com/BurntSushi/toml/go.mod
generated
vendored
@@ -1,3 +0,0 @@
|
||||
module github.com/BurntSushi/toml
|
||||
|
||||
go 1.16
|
||||
64
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/cgo_helpers.go
generated
vendored
Normal file
64
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/cgo_helpers.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nvml
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
import "C"
|
||||
|
||||
var cgoAllocsUnknown = new(struct{})
|
||||
|
||||
type stringHeader struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
}
|
||||
|
||||
func clen(n []byte) int {
|
||||
for i := 0; i < len(n); i++ {
|
||||
if n[i] == 0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return len(n)
|
||||
}
|
||||
|
||||
func uint32SliceToIntSlice(s []uint32) []int {
|
||||
ret := make([]int, len(s))
|
||||
for i := range s {
|
||||
ret[i] = int(s[i])
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// packPCharString creates a Go string backed by *C.char and avoids copying.
|
||||
func packPCharString(p *C.char) (raw string) {
|
||||
if p != nil && *p != 0 {
|
||||
h := (*stringHeader)(unsafe.Pointer(&raw))
|
||||
h.Data = unsafe.Pointer(p)
|
||||
for *p != 0 {
|
||||
p = (*C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + 1)) // p++
|
||||
}
|
||||
h.Len = int(uintptr(unsafe.Pointer(p)) - uintptr(h.Data))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// unpackPCharString represents the data from Go string as *C.char and avoids copying.
|
||||
func unpackPCharString(str string) (*C.char, *struct{}) {
|
||||
h := (*stringHeader)(unsafe.Pointer(&str))
|
||||
return (*C.char)(h.Data), cgoAllocsUnknown
|
||||
}
|
||||
23
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/cgo_helpers.h
generated
vendored
Normal file
23
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/cgo_helpers.h
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// WARNING: THIS FILE WAS AUTOMATICALLY GENERATED.
|
||||
// Code generated by https://git.io/c-for-go. DO NOT EDIT.
|
||||
|
||||
#include "nvml.h"
|
||||
#include <stdlib.h>
|
||||
#pragma once
|
||||
|
||||
#define __CGOGEN 1
|
||||
|
||||
1139
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/const.go
generated
vendored
Normal file
1139
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/const.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
27
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/const_gen.go
generated
vendored
Normal file
27
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/const_gen.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nvml
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
const (
|
||||
SYSTEM_PROCESS_NAME_BUFFER_SIZE = 256
|
||||
)
|
||||
|
||||
func STRUCT_VERSION(data interface{}, version uint32) uint32 {
|
||||
return uint32(uint32(reflect.Indirect(reflect.ValueOf(data)).Type().Size()) | (version << uint32(24)))
|
||||
}
|
||||
2288
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/device.go
generated
vendored
Normal file
2288
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/device.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
21
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/doc.go
generated
vendored
Normal file
21
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/doc.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// WARNING: THIS FILE WAS AUTOMATICALLY GENERATED.
|
||||
// Code generated by https://git.io/c-for-go. DO NOT EDIT.
|
||||
|
||||
/*
|
||||
Package NVML bindings
|
||||
*/
|
||||
package nvml
|
||||
42
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/event_set.go
generated
vendored
Normal file
42
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/event_set.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nvml
|
||||
|
||||
// nvml.EventSetCreate()
|
||||
func EventSetCreate() (EventSet, Return) {
|
||||
var Set EventSet
|
||||
ret := nvmlEventSetCreate(&Set)
|
||||
return Set, ret
|
||||
}
|
||||
|
||||
// nvml.EventSetWait()
|
||||
func EventSetWait(Set EventSet, Timeoutms uint32) (EventData, Return) {
|
||||
var Data EventData
|
||||
ret := nvmlEventSetWait(Set, &Data, Timeoutms)
|
||||
return Data, ret
|
||||
}
|
||||
|
||||
func (Set EventSet) Wait(Timeoutms uint32) (EventData, Return) {
|
||||
return EventSetWait(Set, Timeoutms)
|
||||
}
|
||||
|
||||
// nvml.EventSetFree()
|
||||
func EventSetFree(Set EventSet) Return {
|
||||
return nvmlEventSetFree(Set)
|
||||
}
|
||||
|
||||
func (Set EventSet) Free() Return {
|
||||
return EventSetFree(Set)
|
||||
}
|
||||
218
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/init.go
generated
vendored
Normal file
218
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/init.go
generated
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
// Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nvml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/NVIDIA/go-nvml/pkg/dl"
|
||||
)
|
||||
|
||||
import "C"
|
||||
|
||||
const (
|
||||
nvmlLibraryName = "libnvidia-ml.so.1"
|
||||
nvmlLibraryLoadFlags = dl.RTLD_LAZY | dl.RTLD_GLOBAL
|
||||
)
|
||||
|
||||
var nvml *dl.DynamicLibrary
|
||||
|
||||
// nvml.Init()
|
||||
func Init() Return {
|
||||
lib := dl.New(nvmlLibraryName, nvmlLibraryLoadFlags)
|
||||
err := lib.Open()
|
||||
if err != nil {
|
||||
return ERROR_LIBRARY_NOT_FOUND
|
||||
}
|
||||
|
||||
nvml = lib
|
||||
updateVersionedSymbols()
|
||||
|
||||
return nvmlInit()
|
||||
}
|
||||
|
||||
// nvml.InitWithFlags()
|
||||
func InitWithFlags(Flags uint32) Return {
|
||||
lib := dl.New(nvmlLibraryName, nvmlLibraryLoadFlags)
|
||||
err := lib.Open()
|
||||
if err != nil {
|
||||
return ERROR_LIBRARY_NOT_FOUND
|
||||
}
|
||||
|
||||
nvml = lib
|
||||
|
||||
return nvmlInitWithFlags(Flags)
|
||||
}
|
||||
|
||||
// nvml.Shutdown()
|
||||
func Shutdown() Return {
|
||||
ret := nvmlShutdown()
|
||||
if ret != SUCCESS {
|
||||
return ret
|
||||
}
|
||||
|
||||
err := nvml.Close()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error closing %s: %v", nvmlLibraryName, err))
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Default all versioned APIs to v1 (to infer the types)
|
||||
var nvmlInit = nvmlInit_v1
|
||||
var nvmlDeviceGetPciInfo = nvmlDeviceGetPciInfo_v1
|
||||
var nvmlDeviceGetCount = nvmlDeviceGetCount_v1
|
||||
var nvmlDeviceGetHandleByIndex = nvmlDeviceGetHandleByIndex_v1
|
||||
var nvmlDeviceGetHandleByPciBusId = nvmlDeviceGetHandleByPciBusId_v1
|
||||
var nvmlDeviceGetNvLinkRemotePciInfo = nvmlDeviceGetNvLinkRemotePciInfo_v1
|
||||
var nvmlDeviceRemoveGpu = nvmlDeviceRemoveGpu_v1
|
||||
var nvmlDeviceGetGridLicensableFeatures = nvmlDeviceGetGridLicensableFeatures_v1
|
||||
var nvmlEventSetWait = nvmlEventSetWait_v1
|
||||
var nvmlDeviceGetAttributes = nvmlDeviceGetAttributes_v1
|
||||
var nvmlComputeInstanceGetInfo = nvmlComputeInstanceGetInfo_v1
|
||||
var DeviceGetComputeRunningProcesses = deviceGetComputeRunningProcesses_v1
|
||||
var DeviceGetGraphicsRunningProcesses = deviceGetGraphicsRunningProcesses_v1
|
||||
var DeviceGetMPSComputeRunningProcesses = deviceGetMPSComputeRunningProcesses_v1
|
||||
var GetBlacklistDeviceCount = GetExcludedDeviceCount
|
||||
var GetBlacklistDeviceInfoByIndex = GetExcludedDeviceInfoByIndex
|
||||
var nvmlDeviceGetGpuInstancePossiblePlacements = nvmlDeviceGetGpuInstancePossiblePlacements_v1
|
||||
var nvmlVgpuInstanceGetLicenseInfo = nvmlVgpuInstanceGetLicenseInfo_v1
|
||||
|
||||
type BlacklistDeviceInfo = ExcludedDeviceInfo
|
||||
type ProcessInfo_v1Slice []ProcessInfo_v1
|
||||
type ProcessInfo_v2Slice []ProcessInfo_v2
|
||||
|
||||
func (pis ProcessInfo_v1Slice) ToProcessInfoSlice() []ProcessInfo {
|
||||
var newInfos []ProcessInfo
|
||||
for _, pi := range pis {
|
||||
info := ProcessInfo{
|
||||
Pid: pi.Pid,
|
||||
UsedGpuMemory: pi.UsedGpuMemory,
|
||||
GpuInstanceId: 0xFFFFFFFF, // GPU instance ID is invalid in v1
|
||||
ComputeInstanceId: 0xFFFFFFFF, // Compute instance ID is invalid in v1
|
||||
}
|
||||
newInfos = append(newInfos, info)
|
||||
}
|
||||
return newInfos
|
||||
}
|
||||
|
||||
func (pis ProcessInfo_v2Slice) ToProcessInfoSlice() []ProcessInfo {
|
||||
var newInfos []ProcessInfo
|
||||
for _, pi := range pis {
|
||||
info := ProcessInfo{
|
||||
Pid: pi.Pid,
|
||||
UsedGpuMemory: pi.UsedGpuMemory,
|
||||
GpuInstanceId: pi.GpuInstanceId,
|
||||
ComputeInstanceId: pi.ComputeInstanceId,
|
||||
}
|
||||
newInfos = append(newInfos, info)
|
||||
}
|
||||
return newInfos
|
||||
}
|
||||
|
||||
// updateVersionedSymbols()
|
||||
func updateVersionedSymbols() {
|
||||
err := nvml.Lookup("nvmlInit_v2")
|
||||
if err == nil {
|
||||
nvmlInit = nvmlInit_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetPciInfo_v2")
|
||||
if err == nil {
|
||||
nvmlDeviceGetPciInfo = nvmlDeviceGetPciInfo_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetPciInfo_v3")
|
||||
if err == nil {
|
||||
nvmlDeviceGetPciInfo = nvmlDeviceGetPciInfo_v3
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetCount_v2")
|
||||
if err == nil {
|
||||
nvmlDeviceGetCount = nvmlDeviceGetCount_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetHandleByIndex_v2")
|
||||
if err == nil {
|
||||
nvmlDeviceGetHandleByIndex = nvmlDeviceGetHandleByIndex_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetHandleByPciBusId_v2")
|
||||
if err == nil {
|
||||
nvmlDeviceGetHandleByPciBusId = nvmlDeviceGetHandleByPciBusId_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetNvLinkRemotePciInfo_v2")
|
||||
if err == nil {
|
||||
nvmlDeviceGetNvLinkRemotePciInfo = nvmlDeviceGetNvLinkRemotePciInfo_v2
|
||||
}
|
||||
// Unable to overwrite nvmlDeviceRemoveGpu() because the v2 function takes
|
||||
// a different set of parameters than the v1 function.
|
||||
//err = nvml.Lookup("nvmlDeviceRemoveGpu_v2")
|
||||
//if err == nil {
|
||||
// nvmlDeviceRemoveGpu = nvmlDeviceRemoveGpu_v2
|
||||
//}
|
||||
err = nvml.Lookup("nvmlDeviceGetGridLicensableFeatures_v2")
|
||||
if err == nil {
|
||||
nvmlDeviceGetGridLicensableFeatures = nvmlDeviceGetGridLicensableFeatures_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetGridLicensableFeatures_v3")
|
||||
if err == nil {
|
||||
nvmlDeviceGetGridLicensableFeatures = nvmlDeviceGetGridLicensableFeatures_v3
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetGridLicensableFeatures_v4")
|
||||
if err == nil {
|
||||
nvmlDeviceGetGridLicensableFeatures = nvmlDeviceGetGridLicensableFeatures_v4
|
||||
}
|
||||
err = nvml.Lookup("nvmlEventSetWait_v2")
|
||||
if err == nil {
|
||||
nvmlEventSetWait = nvmlEventSetWait_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetAttributes_v2")
|
||||
if err == nil {
|
||||
nvmlDeviceGetAttributes = nvmlDeviceGetAttributes_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlComputeInstanceGetInfo_v2")
|
||||
if err == nil {
|
||||
nvmlComputeInstanceGetInfo = nvmlComputeInstanceGetInfo_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetComputeRunningProcesses_v2")
|
||||
if err == nil {
|
||||
DeviceGetComputeRunningProcesses = deviceGetComputeRunningProcesses_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetComputeRunningProcesses_v3")
|
||||
if err == nil {
|
||||
DeviceGetComputeRunningProcesses = deviceGetComputeRunningProcesses_v3
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetGraphicsRunningProcesses_v2")
|
||||
if err == nil {
|
||||
DeviceGetGraphicsRunningProcesses = deviceGetGraphicsRunningProcesses_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetGraphicsRunningProcesses_v3")
|
||||
if err == nil {
|
||||
DeviceGetGraphicsRunningProcesses = deviceGetGraphicsRunningProcesses_v3
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetMPSComputeRunningProcesses_v2")
|
||||
if err == nil {
|
||||
DeviceGetMPSComputeRunningProcesses = deviceGetMPSComputeRunningProcesses_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetMPSComputeRunningProcesses_v3")
|
||||
if err == nil {
|
||||
DeviceGetMPSComputeRunningProcesses = deviceGetMPSComputeRunningProcesses_v3
|
||||
}
|
||||
err = nvml.Lookup("nvmlDeviceGetGpuInstancePossiblePlacements_v2")
|
||||
if err == nil {
|
||||
nvmlDeviceGetGpuInstancePossiblePlacements = nvmlDeviceGetGpuInstancePossiblePlacements_v2
|
||||
}
|
||||
err = nvml.Lookup("nvmlVgpuInstanceGetLicenseInfo_v2")
|
||||
if err == nil {
|
||||
nvmlVgpuInstanceGetLicenseInfo = nvmlVgpuInstanceGetLicenseInfo_v2
|
||||
}
|
||||
}
|
||||
2583
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/nvml.go
generated
vendored
Normal file
2583
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/nvml.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8459
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/nvml.h
generated
vendored
Normal file
8459
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/nvml.h
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
20
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/return.go
generated
vendored
Normal file
20
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/return.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nvml
|
||||
|
||||
// nvml.ErrorString()
|
||||
func ErrorString(Result Return) string {
|
||||
return nvmlErrorString(Result)
|
||||
}
|
||||
81
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/system.go
generated
vendored
Normal file
81
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/system.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nvml
|
||||
|
||||
// nvml.SystemGetDriverVersion()
|
||||
func SystemGetDriverVersion() (string, Return) {
|
||||
Version := make([]byte, SYSTEM_DRIVER_VERSION_BUFFER_SIZE)
|
||||
ret := nvmlSystemGetDriverVersion(&Version[0], SYSTEM_DRIVER_VERSION_BUFFER_SIZE)
|
||||
return string(Version[:clen(Version)]), ret
|
||||
}
|
||||
|
||||
// nvml.SystemGetNVMLVersion()
|
||||
func SystemGetNVMLVersion() (string, Return) {
|
||||
Version := make([]byte, SYSTEM_NVML_VERSION_BUFFER_SIZE)
|
||||
ret := nvmlSystemGetNVMLVersion(&Version[0], SYSTEM_NVML_VERSION_BUFFER_SIZE)
|
||||
return string(Version[:clen(Version)]), ret
|
||||
}
|
||||
|
||||
// nvml.SystemGetCudaDriverVersion()
|
||||
func SystemGetCudaDriverVersion() (int, Return) {
|
||||
var CudaDriverVersion int32
|
||||
ret := nvmlSystemGetCudaDriverVersion(&CudaDriverVersion)
|
||||
return int(CudaDriverVersion), ret
|
||||
}
|
||||
|
||||
// nvml.SystemGetCudaDriverVersion_v2()
|
||||
func SystemGetCudaDriverVersion_v2() (int, Return) {
|
||||
var CudaDriverVersion int32
|
||||
ret := nvmlSystemGetCudaDriverVersion_v2(&CudaDriverVersion)
|
||||
return int(CudaDriverVersion), ret
|
||||
}
|
||||
|
||||
// nvml.SystemGetProcessName()
|
||||
func SystemGetProcessName(Pid int) (string, Return) {
|
||||
Name := make([]byte, SYSTEM_PROCESS_NAME_BUFFER_SIZE)
|
||||
ret := nvmlSystemGetProcessName(uint32(Pid), &Name[0], SYSTEM_PROCESS_NAME_BUFFER_SIZE)
|
||||
return string(Name[:clen(Name)]), ret
|
||||
}
|
||||
|
||||
// nvml.SystemGetHicVersion()
|
||||
func SystemGetHicVersion() ([]HwbcEntry, Return) {
|
||||
var HwbcCount uint32 = 1 // Will be reduced upon returning
|
||||
for {
|
||||
HwbcEntries := make([]HwbcEntry, HwbcCount)
|
||||
ret := nvmlSystemGetHicVersion(&HwbcCount, &HwbcEntries[0])
|
||||
if ret == SUCCESS {
|
||||
return HwbcEntries[:HwbcCount], ret
|
||||
}
|
||||
if ret != ERROR_INSUFFICIENT_SIZE {
|
||||
return nil, ret
|
||||
}
|
||||
HwbcCount *= 2
|
||||
}
|
||||
}
|
||||
|
||||
// nvml.SystemGetTopologyGpuSet()
|
||||
func SystemGetTopologyGpuSet(CpuNumber int) ([]Device, Return) {
|
||||
var Count uint32
|
||||
ret := nvmlSystemGetTopologyGpuSet(uint32(CpuNumber), &Count, nil)
|
||||
if ret != SUCCESS {
|
||||
return nil, ret
|
||||
}
|
||||
if Count == 0 {
|
||||
return []Device{}, ret
|
||||
}
|
||||
DeviceArray := make([]Device, Count)
|
||||
ret = nvmlSystemGetTopologyGpuSet(uint32(CpuNumber), &Count, &DeviceArray[0])
|
||||
return DeviceArray, ret
|
||||
}
|
||||
445
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/types_gen.go
generated
vendored
Normal file
445
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/types_gen.go
generated
vendored
Normal file
@@ -0,0 +1,445 @@
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs types.go
|
||||
|
||||
package nvml
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type Device struct {
|
||||
Handle *_Ctype_struct_nvmlDevice_st
|
||||
}
|
||||
|
||||
type PciInfo struct {
|
||||
BusIdLegacy [16]int8
|
||||
Domain uint32
|
||||
Bus uint32
|
||||
Device uint32
|
||||
PciDeviceId uint32
|
||||
PciSubSystemId uint32
|
||||
BusId [32]int8
|
||||
}
|
||||
|
||||
type EccErrorCounts struct {
|
||||
L1Cache uint64
|
||||
L2Cache uint64
|
||||
DeviceMemory uint64
|
||||
RegisterFile uint64
|
||||
}
|
||||
|
||||
type Utilization struct {
|
||||
Gpu uint32
|
||||
Memory uint32
|
||||
}
|
||||
|
||||
type Memory struct {
|
||||
Total uint64
|
||||
Free uint64
|
||||
Used uint64
|
||||
}
|
||||
|
||||
type Memory_v2 struct {
|
||||
Version uint32
|
||||
Total uint64
|
||||
Reserved uint64
|
||||
Free uint64
|
||||
Used uint64
|
||||
}
|
||||
|
||||
type BAR1Memory struct {
|
||||
Bar1Total uint64
|
||||
Bar1Free uint64
|
||||
Bar1Used uint64
|
||||
}
|
||||
|
||||
type ProcessInfo_v1 struct {
|
||||
Pid uint32
|
||||
UsedGpuMemory uint64
|
||||
}
|
||||
|
||||
type ProcessInfo_v2 struct {
|
||||
Pid uint32
|
||||
UsedGpuMemory uint64
|
||||
GpuInstanceId uint32
|
||||
ComputeInstanceId uint32
|
||||
}
|
||||
|
||||
type ProcessInfo struct {
|
||||
Pid uint32
|
||||
UsedGpuMemory uint64
|
||||
GpuInstanceId uint32
|
||||
ComputeInstanceId uint32
|
||||
}
|
||||
|
||||
type DeviceAttributes struct {
|
||||
MultiprocessorCount uint32
|
||||
SharedCopyEngineCount uint32
|
||||
SharedDecoderCount uint32
|
||||
SharedEncoderCount uint32
|
||||
SharedJpegCount uint32
|
||||
SharedOfaCount uint32
|
||||
GpuInstanceSliceCount uint32
|
||||
ComputeInstanceSliceCount uint32
|
||||
MemorySizeMB uint64
|
||||
}
|
||||
|
||||
type RowRemapperHistogramValues struct {
|
||||
Max uint32
|
||||
High uint32
|
||||
Partial uint32
|
||||
Low uint32
|
||||
None uint32
|
||||
}
|
||||
|
||||
type NvLinkUtilizationControl struct {
|
||||
Units uint32
|
||||
Pktfilter uint32
|
||||
}
|
||||
|
||||
type BridgeChipInfo struct {
|
||||
Type uint32
|
||||
FwVersion uint32
|
||||
}
|
||||
|
||||
type BridgeChipHierarchy struct {
|
||||
BridgeCount uint8
|
||||
BridgeChipInfo [128]BridgeChipInfo
|
||||
}
|
||||
|
||||
const sizeofValue = unsafe.Sizeof([8]byte{})
|
||||
|
||||
type Value [sizeofValue]byte
|
||||
|
||||
type Sample struct {
|
||||
TimeStamp uint64
|
||||
SampleValue [8]byte
|
||||
}
|
||||
|
||||
type ViolationTime struct {
|
||||
ReferenceTime uint64
|
||||
ViolationTime uint64
|
||||
}
|
||||
|
||||
type ClkMonFaultInfo struct {
|
||||
ClkApiDomain uint32
|
||||
ClkDomainFaultMask uint32
|
||||
}
|
||||
|
||||
type ClkMonStatus struct {
|
||||
BGlobalStatus uint32
|
||||
ClkMonListSize uint32
|
||||
ClkMonList [32]ClkMonFaultInfo
|
||||
}
|
||||
|
||||
type VgpuTypeId uint32
|
||||
|
||||
type VgpuInstance uint32
|
||||
|
||||
type VgpuInstanceUtilizationSample struct {
|
||||
VgpuInstance uint32
|
||||
TimeStamp uint64
|
||||
SmUtil [8]byte
|
||||
MemUtil [8]byte
|
||||
EncUtil [8]byte
|
||||
DecUtil [8]byte
|
||||
}
|
||||
|
||||
type VgpuProcessUtilizationSample struct {
|
||||
VgpuInstance uint32
|
||||
Pid uint32
|
||||
ProcessName [64]int8
|
||||
TimeStamp uint64
|
||||
SmUtil uint32
|
||||
MemUtil uint32
|
||||
EncUtil uint32
|
||||
DecUtil uint32
|
||||
}
|
||||
|
||||
type VgpuLicenseExpiry struct {
|
||||
Year uint32
|
||||
Month uint16
|
||||
Day uint16
|
||||
Hour uint16
|
||||
Min uint16
|
||||
Sec uint16
|
||||
Status uint8
|
||||
Pad_cgo_0 [1]byte
|
||||
}
|
||||
|
||||
type VgpuLicenseInfo struct {
|
||||
IsLicensed uint8
|
||||
LicenseExpiry VgpuLicenseExpiry
|
||||
CurrentState uint32
|
||||
}
|
||||
|
||||
type ProcessUtilizationSample struct {
|
||||
Pid uint32
|
||||
TimeStamp uint64
|
||||
SmUtil uint32
|
||||
MemUtil uint32
|
||||
EncUtil uint32
|
||||
DecUtil uint32
|
||||
}
|
||||
|
||||
type GridLicenseExpiry struct {
|
||||
Year uint32
|
||||
Month uint16
|
||||
Day uint16
|
||||
Hour uint16
|
||||
Min uint16
|
||||
Sec uint16
|
||||
Status uint8
|
||||
Pad_cgo_0 [1]byte
|
||||
}
|
||||
|
||||
type GridLicensableFeature struct {
|
||||
FeatureCode uint32
|
||||
FeatureState uint32
|
||||
LicenseInfo [128]int8
|
||||
ProductName [128]int8
|
||||
FeatureEnabled uint32
|
||||
LicenseExpiry GridLicenseExpiry
|
||||
}
|
||||
|
||||
type GridLicensableFeatures struct {
|
||||
IsGridLicenseSupported int32
|
||||
LicensableFeaturesCount uint32
|
||||
GridLicensableFeatures [3]GridLicensableFeature
|
||||
}
|
||||
|
||||
type DeviceArchitecture uint32
|
||||
|
||||
type BusType uint32
|
||||
|
||||
type PowerSource uint32
|
||||
|
||||
type FieldValue struct {
|
||||
FieldId uint32
|
||||
ScopeId uint32
|
||||
Timestamp int64
|
||||
LatencyUsec int64
|
||||
ValueType uint32
|
||||
NvmlReturn uint32
|
||||
Value [8]byte
|
||||
}
|
||||
|
||||
type Unit struct {
|
||||
Handle *_Ctype_struct_nvmlUnit_st
|
||||
}
|
||||
|
||||
type HwbcEntry struct {
|
||||
HwbcId uint32
|
||||
FirmwareVersion [32]int8
|
||||
}
|
||||
|
||||
type LedState struct {
|
||||
Cause [256]int8
|
||||
Color uint32
|
||||
}
|
||||
|
||||
type UnitInfo struct {
|
||||
Name [96]int8
|
||||
Id [96]int8
|
||||
Serial [96]int8
|
||||
FirmwareVersion [96]int8
|
||||
}
|
||||
|
||||
type PSUInfo struct {
|
||||
State [256]int8
|
||||
Current uint32
|
||||
Voltage uint32
|
||||
Power uint32
|
||||
}
|
||||
|
||||
type UnitFanInfo struct {
|
||||
Speed uint32
|
||||
State uint32
|
||||
}
|
||||
|
||||
type UnitFanSpeeds struct {
|
||||
Fans [24]UnitFanInfo
|
||||
Count uint32
|
||||
}
|
||||
|
||||
type EventSet struct {
|
||||
Handle *_Ctype_struct_nvmlEventSet_st
|
||||
}
|
||||
|
||||
type EventData struct {
|
||||
Device Device
|
||||
EventType uint64
|
||||
EventData uint64
|
||||
GpuInstanceId uint32
|
||||
ComputeInstanceId uint32
|
||||
}
|
||||
|
||||
type AccountingStats struct {
|
||||
GpuUtilization uint32
|
||||
MemoryUtilization uint32
|
||||
MaxMemoryUsage uint64
|
||||
Time uint64
|
||||
StartTime uint64
|
||||
IsRunning uint32
|
||||
Reserved [5]uint32
|
||||
}
|
||||
|
||||
type EncoderSessionInfo struct {
|
||||
SessionId uint32
|
||||
Pid uint32
|
||||
VgpuInstance uint32
|
||||
CodecType uint32
|
||||
HResolution uint32
|
||||
VResolution uint32
|
||||
AverageFps uint32
|
||||
AverageLatency uint32
|
||||
}
|
||||
|
||||
type FBCStats struct {
|
||||
SessionsCount uint32
|
||||
AverageFPS uint32
|
||||
AverageLatency uint32
|
||||
}
|
||||
|
||||
type FBCSessionInfo struct {
|
||||
SessionId uint32
|
||||
Pid uint32
|
||||
VgpuInstance uint32
|
||||
DisplayOrdinal uint32
|
||||
SessionType uint32
|
||||
SessionFlags uint32
|
||||
HMaxResolution uint32
|
||||
VMaxResolution uint32
|
||||
HResolution uint32
|
||||
VResolution uint32
|
||||
AverageFPS uint32
|
||||
AverageLatency uint32
|
||||
}
|
||||
|
||||
type AffinityScope uint32
|
||||
|
||||
type VgpuVersion struct {
|
||||
MinVersion uint32
|
||||
MaxVersion uint32
|
||||
}
|
||||
|
||||
type nvmlVgpuMetadata struct {
|
||||
Version uint32
|
||||
Revision uint32
|
||||
GuestInfoState uint32
|
||||
GuestDriverVersion [80]int8
|
||||
HostDriverVersion [80]int8
|
||||
Reserved [6]uint32
|
||||
VgpuVirtualizationCaps uint32
|
||||
GuestVgpuVersion uint32
|
||||
OpaqueDataSize uint32
|
||||
OpaqueData [4]int8
|
||||
}
|
||||
|
||||
type nvmlVgpuPgpuMetadata struct {
|
||||
Version uint32
|
||||
Revision uint32
|
||||
HostDriverVersion [80]int8
|
||||
PgpuVirtualizationCaps uint32
|
||||
Reserved [5]uint32
|
||||
HostSupportedVgpuRange VgpuVersion
|
||||
OpaqueDataSize uint32
|
||||
OpaqueData [4]int8
|
||||
}
|
||||
|
||||
type VgpuPgpuCompatibility struct {
|
||||
VgpuVmCompatibility uint32
|
||||
CompatibilityLimitCode uint32
|
||||
}
|
||||
|
||||
type ExcludedDeviceInfo struct {
|
||||
PciInfo PciInfo
|
||||
Uuid [80]int8
|
||||
}
|
||||
|
||||
type GpuInstancePlacement struct {
|
||||
Start uint32
|
||||
Size uint32
|
||||
}
|
||||
|
||||
type GpuInstanceProfileInfo struct {
|
||||
Id uint32
|
||||
IsP2pSupported uint32
|
||||
SliceCount uint32
|
||||
InstanceCount uint32
|
||||
MultiprocessorCount uint32
|
||||
CopyEngineCount uint32
|
||||
DecoderCount uint32
|
||||
EncoderCount uint32
|
||||
JpegCount uint32
|
||||
OfaCount uint32
|
||||
MemorySizeMB uint64
|
||||
}
|
||||
|
||||
type GpuInstanceProfileInfo_v2 struct {
|
||||
Version uint32
|
||||
Id uint32
|
||||
IsP2pSupported uint32
|
||||
SliceCount uint32
|
||||
InstanceCount uint32
|
||||
MultiprocessorCount uint32
|
||||
CopyEngineCount uint32
|
||||
DecoderCount uint32
|
||||
EncoderCount uint32
|
||||
JpegCount uint32
|
||||
OfaCount uint32
|
||||
MemorySizeMB uint64
|
||||
Name [96]int8
|
||||
}
|
||||
|
||||
type GpuInstanceInfo struct {
|
||||
Device Device
|
||||
Id uint32
|
||||
ProfileId uint32
|
||||
Placement GpuInstancePlacement
|
||||
}
|
||||
|
||||
type GpuInstance struct {
|
||||
Handle *_Ctype_struct_nvmlGpuInstance_st
|
||||
}
|
||||
|
||||
type ComputeInstancePlacement struct {
|
||||
Start uint32
|
||||
Size uint32
|
||||
}
|
||||
|
||||
type ComputeInstanceProfileInfo struct {
|
||||
Id uint32
|
||||
SliceCount uint32
|
||||
InstanceCount uint32
|
||||
MultiprocessorCount uint32
|
||||
SharedCopyEngineCount uint32
|
||||
SharedDecoderCount uint32
|
||||
SharedEncoderCount uint32
|
||||
SharedJpegCount uint32
|
||||
SharedOfaCount uint32
|
||||
}
|
||||
|
||||
type ComputeInstanceProfileInfo_v2 struct {
|
||||
Version uint32
|
||||
Id uint32
|
||||
SliceCount uint32
|
||||
InstanceCount uint32
|
||||
MultiprocessorCount uint32
|
||||
SharedCopyEngineCount uint32
|
||||
SharedDecoderCount uint32
|
||||
SharedEncoderCount uint32
|
||||
SharedJpegCount uint32
|
||||
SharedOfaCount uint32
|
||||
Name [96]int8
|
||||
}
|
||||
|
||||
type ComputeInstanceInfo struct {
|
||||
Device Device
|
||||
GpuInstance GpuInstance
|
||||
Id uint32
|
||||
ProfileId uint32
|
||||
Placement ComputeInstancePlacement
|
||||
}
|
||||
|
||||
type ComputeInstance struct {
|
||||
Handle *_Ctype_struct_nvmlComputeInstance_st
|
||||
}
|
||||
113
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/unit.go
generated
vendored
Normal file
113
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/unit.go
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nvml
|
||||
|
||||
// nvml.UnitGetCount()
|
||||
func UnitGetCount() (int, Return) {
|
||||
var UnitCount uint32
|
||||
ret := nvmlUnitGetCount(&UnitCount)
|
||||
return int(UnitCount), ret
|
||||
}
|
||||
|
||||
// nvml.UnitGetHandleByIndex()
|
||||
func UnitGetHandleByIndex(Index int) (Unit, Return) {
|
||||
var Unit Unit
|
||||
ret := nvmlUnitGetHandleByIndex(uint32(Index), &Unit)
|
||||
return Unit, ret
|
||||
}
|
||||
|
||||
// nvml.UnitGetUnitInfo()
|
||||
func UnitGetUnitInfo(Unit Unit) (UnitInfo, Return) {
|
||||
var Info UnitInfo
|
||||
ret := nvmlUnitGetUnitInfo(Unit, &Info)
|
||||
return Info, ret
|
||||
}
|
||||
|
||||
func (Unit Unit) GetUnitInfo() (UnitInfo, Return) {
|
||||
return UnitGetUnitInfo(Unit)
|
||||
}
|
||||
|
||||
// nvml.UnitGetLedState()
|
||||
func UnitGetLedState(Unit Unit) (LedState, Return) {
|
||||
var State LedState
|
||||
ret := nvmlUnitGetLedState(Unit, &State)
|
||||
return State, ret
|
||||
}
|
||||
|
||||
func (Unit Unit) GetLedState() (LedState, Return) {
|
||||
return UnitGetLedState(Unit)
|
||||
}
|
||||
|
||||
// nvml.UnitGetPsuInfo()
|
||||
func UnitGetPsuInfo(Unit Unit) (PSUInfo, Return) {
|
||||
var Psu PSUInfo
|
||||
ret := nvmlUnitGetPsuInfo(Unit, &Psu)
|
||||
return Psu, ret
|
||||
}
|
||||
|
||||
func (Unit Unit) GetPsuInfo() (PSUInfo, Return) {
|
||||
return UnitGetPsuInfo(Unit)
|
||||
}
|
||||
|
||||
// nvml.UnitGetTemperature()
|
||||
func UnitGetTemperature(Unit Unit, Type int) (uint32, Return) {
|
||||
var Temp uint32
|
||||
ret := nvmlUnitGetTemperature(Unit, uint32(Type), &Temp)
|
||||
return Temp, ret
|
||||
}
|
||||
|
||||
func (Unit Unit) GetTemperature(Type int) (uint32, Return) {
|
||||
return UnitGetTemperature(Unit, Type)
|
||||
}
|
||||
|
||||
// nvml.UnitGetFanSpeedInfo()
|
||||
func UnitGetFanSpeedInfo(Unit Unit) (UnitFanSpeeds, Return) {
|
||||
var FanSpeeds UnitFanSpeeds
|
||||
ret := nvmlUnitGetFanSpeedInfo(Unit, &FanSpeeds)
|
||||
return FanSpeeds, ret
|
||||
}
|
||||
|
||||
func (Unit Unit) GetFanSpeedInfo() (UnitFanSpeeds, Return) {
|
||||
return UnitGetFanSpeedInfo(Unit)
|
||||
}
|
||||
|
||||
// nvml.UnitGetDevices()
|
||||
func UnitGetDevices(Unit Unit) ([]Device, Return) {
|
||||
var DeviceCount uint32 = 1 // Will be reduced upon returning
|
||||
for {
|
||||
Devices := make([]Device, DeviceCount)
|
||||
ret := nvmlUnitGetDevices(Unit, &DeviceCount, &Devices[0])
|
||||
if ret == SUCCESS {
|
||||
return Devices[:DeviceCount], ret
|
||||
}
|
||||
if ret != ERROR_INSUFFICIENT_SIZE {
|
||||
return nil, ret
|
||||
}
|
||||
DeviceCount *= 2
|
||||
}
|
||||
}
|
||||
|
||||
func (Unit Unit) GetDevices() ([]Device, Return) {
|
||||
return UnitGetDevices(Unit)
|
||||
}
|
||||
|
||||
// nvml.UnitSetLedState()
|
||||
func UnitSetLedState(Unit Unit, Color LedColor) Return {
|
||||
return nvmlUnitSetLedState(Unit, Color)
|
||||
}
|
||||
|
||||
func (Unit Unit) SetLedState(Color LedColor) Return {
|
||||
return UnitSetLedState(Unit, Color)
|
||||
}
|
||||
462
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/vgpu.go
generated
vendored
Normal file
462
vendor/github.com/NVIDIA/go-nvml/pkg/nvml/vgpu.go
generated
vendored
Normal file
@@ -0,0 +1,462 @@
|
||||
// Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nvml
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// nvml.VgpuMetadata
|
||||
type VgpuMetadata struct {
|
||||
nvmlVgpuMetadata
|
||||
OpaqueData []byte
|
||||
}
|
||||
|
||||
// nvml.VgpuPgpuMetadata
|
||||
type VgpuPgpuMetadata struct {
|
||||
nvmlVgpuPgpuMetadata
|
||||
OpaqueData []byte
|
||||
}
|
||||
|
||||
// nvml.VgpuTypeGetClass()
|
||||
func VgpuTypeGetClass(VgpuTypeId VgpuTypeId) (string, Return) {
|
||||
var Size uint32 = DEVICE_NAME_BUFFER_SIZE
|
||||
VgpuTypeClass := make([]byte, DEVICE_NAME_BUFFER_SIZE)
|
||||
ret := nvmlVgpuTypeGetClass(VgpuTypeId, &VgpuTypeClass[0], &Size)
|
||||
return string(VgpuTypeClass[:clen(VgpuTypeClass)]), ret
|
||||
}
|
||||
|
||||
func (VgpuTypeId VgpuTypeId) GetClass() (string, Return) {
|
||||
return VgpuTypeGetClass(VgpuTypeId)
|
||||
}
|
||||
|
||||
// nvml.VgpuTypeGetName()
|
||||
func VgpuTypeGetName(VgpuTypeId VgpuTypeId) (string, Return) {
|
||||
var Size uint32 = DEVICE_NAME_BUFFER_SIZE
|
||||
VgpuTypeName := make([]byte, DEVICE_NAME_BUFFER_SIZE)
|
||||
ret := nvmlVgpuTypeGetName(VgpuTypeId, &VgpuTypeName[0], &Size)
|
||||
return string(VgpuTypeName[:clen(VgpuTypeName)]), ret
|
||||
}
|
||||
|
||||
func (VgpuTypeId VgpuTypeId) GetName() (string, Return) {
|
||||
return VgpuTypeGetName(VgpuTypeId)
|
||||
}
|
||||
|
||||
// nvml.VgpuTypeGetGpuInstanceProfileId()
|
||||
func VgpuTypeGetGpuInstanceProfileId(VgpuTypeId VgpuTypeId) (uint32, Return) {
|
||||
var Size uint32
|
||||
ret := nvmlVgpuTypeGetGpuInstanceProfileId(VgpuTypeId, &Size)
|
||||
return Size, ret
|
||||
}
|
||||
|
||||
func (VgpuTypeId VgpuTypeId) GetGpuInstanceProfileId() (uint32, Return) {
|
||||
return VgpuTypeGetGpuInstanceProfileId(VgpuTypeId)
|
||||
}
|
||||
|
||||
// nvml.VgpuTypeGetDeviceID()
|
||||
func VgpuTypeGetDeviceID(VgpuTypeId VgpuTypeId) (uint64, uint64, Return) {
|
||||
var DeviceID, SubsystemID uint64
|
||||
ret := nvmlVgpuTypeGetDeviceID(VgpuTypeId, &DeviceID, &SubsystemID)
|
||||
return DeviceID, SubsystemID, ret
|
||||
}
|
||||
|
||||
func (VgpuTypeId VgpuTypeId) GetDeviceID() (uint64, uint64, Return) {
|
||||
return VgpuTypeGetDeviceID(VgpuTypeId)
|
||||
}
|
||||
|
||||
// nvml.VgpuTypeGetFramebufferSize()
|
||||
func VgpuTypeGetFramebufferSize(VgpuTypeId VgpuTypeId) (uint64, Return) {
|
||||
var FbSize uint64
|
||||
ret := nvmlVgpuTypeGetFramebufferSize(VgpuTypeId, &FbSize)
|
||||
return FbSize, ret
|
||||
}
|
||||
|
||||
func (VgpuTypeId VgpuTypeId) GetFramebufferSize() (uint64, Return) {
|
||||
return VgpuTypeGetFramebufferSize(VgpuTypeId)
|
||||
}
|
||||
|
||||
// nvml.VgpuTypeGetNumDisplayHeads()
|
||||
func VgpuTypeGetNumDisplayHeads(VgpuTypeId VgpuTypeId) (int, Return) {
|
||||
var NumDisplayHeads uint32
|
||||
ret := nvmlVgpuTypeGetNumDisplayHeads(VgpuTypeId, &NumDisplayHeads)
|
||||
return int(NumDisplayHeads), ret
|
||||
}
|
||||
|
||||
func (VgpuTypeId VgpuTypeId) GetNumDisplayHeads() (int, Return) {
|
||||
return VgpuTypeGetNumDisplayHeads(VgpuTypeId)
|
||||
}
|
||||
|
||||
// nvml.VgpuTypeGetResolution()
|
||||
func VgpuTypeGetResolution(VgpuTypeId VgpuTypeId, DisplayIndex int) (uint32, uint32, Return) {
|
||||
var Xdim, Ydim uint32
|
||||
ret := nvmlVgpuTypeGetResolution(VgpuTypeId, uint32(DisplayIndex), &Xdim, &Ydim)
|
||||
return Xdim, Ydim, ret
|
||||
}
|
||||
|
||||
func (VgpuTypeId VgpuTypeId) GetResolution(DisplayIndex int) (uint32, uint32, Return) {
|
||||
return VgpuTypeGetResolution(VgpuTypeId, DisplayIndex)
|
||||
}
|
||||
|
||||
// nvml.VgpuTypeGetLicense()
|
||||
func VgpuTypeGetLicense(VgpuTypeId VgpuTypeId) (string, Return) {
|
||||
VgpuTypeLicenseString := make([]byte, GRID_LICENSE_BUFFER_SIZE)
|
||||
ret := nvmlVgpuTypeGetLicense(VgpuTypeId, &VgpuTypeLicenseString[0], GRID_LICENSE_BUFFER_SIZE)
|
||||
return string(VgpuTypeLicenseString[:clen(VgpuTypeLicenseString)]), ret
|
||||
}
|
||||
|
||||
func (VgpuTypeId VgpuTypeId) GetLicense() (string, Return) {
|
||||
return VgpuTypeGetLicense(VgpuTypeId)
|
||||
}
|
||||
|
||||
// nvml.VgpuTypeGetFrameRateLimit()
|
||||
func VgpuTypeGetFrameRateLimit(VgpuTypeId VgpuTypeId) (uint32, Return) {
|
||||
var FrameRateLimit uint32
|
||||
ret := nvmlVgpuTypeGetFrameRateLimit(VgpuTypeId, &FrameRateLimit)
|
||||
return FrameRateLimit, ret
|
||||
}
|
||||
|
||||
func (VgpuTypeId VgpuTypeId) GetFrameRateLimit() (uint32, Return) {
|
||||
return VgpuTypeGetFrameRateLimit(VgpuTypeId)
|
||||
}
|
||||
|
||||
// nvml.VgpuTypeGetMaxInstances()
|
||||
func VgpuTypeGetMaxInstances(Device Device, VgpuTypeId VgpuTypeId) (int, Return) {
|
||||
var VgpuInstanceCount uint32
|
||||
ret := nvmlVgpuTypeGetMaxInstances(Device, VgpuTypeId, &VgpuInstanceCount)
|
||||
return int(VgpuInstanceCount), ret
|
||||
}
|
||||
|
||||
func (Device Device) VgpuTypeGetMaxInstances(VgpuTypeId VgpuTypeId) (int, Return) {
|
||||
return VgpuTypeGetMaxInstances(Device, VgpuTypeId)
|
||||
}
|
||||
|
||||
func (VgpuTypeId VgpuTypeId) GetMaxInstances(Device Device) (int, Return) {
|
||||
return VgpuTypeGetMaxInstances(Device, VgpuTypeId)
|
||||
}
|
||||
|
||||
// nvml.VgpuTypeGetMaxInstancesPerVm()
|
||||
func VgpuTypeGetMaxInstancesPerVm(VgpuTypeId VgpuTypeId) (int, Return) {
|
||||
var VgpuInstanceCountPerVm uint32
|
||||
ret := nvmlVgpuTypeGetMaxInstancesPerVm(VgpuTypeId, &VgpuInstanceCountPerVm)
|
||||
return int(VgpuInstanceCountPerVm), ret
|
||||
}
|
||||
|
||||
func (VgpuTypeId VgpuTypeId) GetMaxInstancesPerVm() (int, Return) {
|
||||
return VgpuTypeGetMaxInstancesPerVm(VgpuTypeId)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetVmID()
|
||||
func VgpuInstanceGetVmID(VgpuInstance VgpuInstance) (string, VgpuVmIdType, Return) {
|
||||
var VmIdType VgpuVmIdType
|
||||
VmId := make([]byte, DEVICE_UUID_BUFFER_SIZE)
|
||||
ret := nvmlVgpuInstanceGetVmID(VgpuInstance, &VmId[0], DEVICE_UUID_BUFFER_SIZE, &VmIdType)
|
||||
return string(VmId[:clen(VmId)]), VmIdType, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetVmID() (string, VgpuVmIdType, Return) {
|
||||
return VgpuInstanceGetVmID(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetUUID()
|
||||
func VgpuInstanceGetUUID(VgpuInstance VgpuInstance) (string, Return) {
|
||||
Uuid := make([]byte, DEVICE_UUID_BUFFER_SIZE)
|
||||
ret := nvmlVgpuInstanceGetUUID(VgpuInstance, &Uuid[0], DEVICE_UUID_BUFFER_SIZE)
|
||||
return string(Uuid[:clen(Uuid)]), ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetUUID() (string, Return) {
|
||||
return VgpuInstanceGetUUID(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetVmDriverVersion()
|
||||
func VgpuInstanceGetVmDriverVersion(VgpuInstance VgpuInstance) (string, Return) {
|
||||
Version := make([]byte, SYSTEM_DRIVER_VERSION_BUFFER_SIZE)
|
||||
ret := nvmlVgpuInstanceGetVmDriverVersion(VgpuInstance, &Version[0], SYSTEM_DRIVER_VERSION_BUFFER_SIZE)
|
||||
return string(Version[:clen(Version)]), ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetVmDriverVersion() (string, Return) {
|
||||
return VgpuInstanceGetVmDriverVersion(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetFbUsage()
|
||||
func VgpuInstanceGetFbUsage(VgpuInstance VgpuInstance) (uint64, Return) {
|
||||
var FbUsage uint64
|
||||
ret := nvmlVgpuInstanceGetFbUsage(VgpuInstance, &FbUsage)
|
||||
return FbUsage, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetFbUsage() (uint64, Return) {
|
||||
return VgpuInstanceGetFbUsage(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetLicenseInfo()
|
||||
func VgpuInstanceGetLicenseInfo(VgpuInstance VgpuInstance) (VgpuLicenseInfo, Return) {
|
||||
var LicenseInfo VgpuLicenseInfo
|
||||
ret := nvmlVgpuInstanceGetLicenseInfo(VgpuInstance, &LicenseInfo)
|
||||
return LicenseInfo, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetLicenseInfo() (VgpuLicenseInfo, Return) {
|
||||
return VgpuInstanceGetLicenseInfo(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetLicenseStatus()
|
||||
func VgpuInstanceGetLicenseStatus(VgpuInstance VgpuInstance) (int, Return) {
|
||||
var Licensed uint32
|
||||
ret := nvmlVgpuInstanceGetLicenseStatus(VgpuInstance, &Licensed)
|
||||
return int(Licensed), ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetLicenseStatus() (int, Return) {
|
||||
return VgpuInstanceGetLicenseStatus(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetType()
|
||||
func VgpuInstanceGetType(VgpuInstance VgpuInstance) (VgpuTypeId, Return) {
|
||||
var VgpuTypeId VgpuTypeId
|
||||
ret := nvmlVgpuInstanceGetType(VgpuInstance, &VgpuTypeId)
|
||||
return VgpuTypeId, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetType() (VgpuTypeId, Return) {
|
||||
return VgpuInstanceGetType(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetFrameRateLimit()
|
||||
func VgpuInstanceGetFrameRateLimit(VgpuInstance VgpuInstance) (uint32, Return) {
|
||||
var FrameRateLimit uint32
|
||||
ret := nvmlVgpuInstanceGetFrameRateLimit(VgpuInstance, &FrameRateLimit)
|
||||
return FrameRateLimit, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetFrameRateLimit() (uint32, Return) {
|
||||
return VgpuInstanceGetFrameRateLimit(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetEccMode()
|
||||
func VgpuInstanceGetEccMode(VgpuInstance VgpuInstance) (EnableState, Return) {
|
||||
var EccMode EnableState
|
||||
ret := nvmlVgpuInstanceGetEccMode(VgpuInstance, &EccMode)
|
||||
return EccMode, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetEccMode() (EnableState, Return) {
|
||||
return VgpuInstanceGetEccMode(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetEncoderCapacity()
|
||||
func VgpuInstanceGetEncoderCapacity(VgpuInstance VgpuInstance) (int, Return) {
|
||||
var EncoderCapacity uint32
|
||||
ret := nvmlVgpuInstanceGetEncoderCapacity(VgpuInstance, &EncoderCapacity)
|
||||
return int(EncoderCapacity), ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetEncoderCapacity() (int, Return) {
|
||||
return VgpuInstanceGetEncoderCapacity(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceSetEncoderCapacity()
|
||||
func VgpuInstanceSetEncoderCapacity(VgpuInstance VgpuInstance, EncoderCapacity int) Return {
|
||||
return nvmlVgpuInstanceSetEncoderCapacity(VgpuInstance, uint32(EncoderCapacity))
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) SetEncoderCapacity(EncoderCapacity int) Return {
|
||||
return VgpuInstanceSetEncoderCapacity(VgpuInstance, EncoderCapacity)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetEncoderStats()
|
||||
func VgpuInstanceGetEncoderStats(VgpuInstance VgpuInstance) (int, uint32, uint32, Return) {
|
||||
var SessionCount, AverageFps, AverageLatency uint32
|
||||
ret := nvmlVgpuInstanceGetEncoderStats(VgpuInstance, &SessionCount, &AverageFps, &AverageLatency)
|
||||
return int(SessionCount), AverageFps, AverageLatency, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetEncoderStats() (int, uint32, uint32, Return) {
|
||||
return VgpuInstanceGetEncoderStats(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetEncoderSessions()
|
||||
func VgpuInstanceGetEncoderSessions(VgpuInstance VgpuInstance) (int, EncoderSessionInfo, Return) {
|
||||
var SessionCount uint32
|
||||
var SessionInfo EncoderSessionInfo
|
||||
ret := nvmlVgpuInstanceGetEncoderSessions(VgpuInstance, &SessionCount, &SessionInfo)
|
||||
return int(SessionCount), SessionInfo, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetEncoderSessions() (int, EncoderSessionInfo, Return) {
|
||||
return VgpuInstanceGetEncoderSessions(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetFBCStats()
|
||||
func VgpuInstanceGetFBCStats(VgpuInstance VgpuInstance) (FBCStats, Return) {
|
||||
var FbcStats FBCStats
|
||||
ret := nvmlVgpuInstanceGetFBCStats(VgpuInstance, &FbcStats)
|
||||
return FbcStats, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetFBCStats() (FBCStats, Return) {
|
||||
return VgpuInstanceGetFBCStats(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetFBCSessions()
|
||||
func VgpuInstanceGetFBCSessions(VgpuInstance VgpuInstance) (int, FBCSessionInfo, Return) {
|
||||
var SessionCount uint32
|
||||
var SessionInfo FBCSessionInfo
|
||||
ret := nvmlVgpuInstanceGetFBCSessions(VgpuInstance, &SessionCount, &SessionInfo)
|
||||
return int(SessionCount), SessionInfo, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetFBCSessions() (int, FBCSessionInfo, Return) {
|
||||
return VgpuInstanceGetFBCSessions(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetGpuInstanceId()
|
||||
func VgpuInstanceGetGpuInstanceId(VgpuInstance VgpuInstance) (int, Return) {
|
||||
var gpuInstanceId uint32
|
||||
ret := nvmlVgpuInstanceGetGpuInstanceId(VgpuInstance, &gpuInstanceId)
|
||||
return int(gpuInstanceId), ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetGpuInstanceId() (int, Return) {
|
||||
return VgpuInstanceGetGpuInstanceId(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetGpuPciId()
|
||||
func VgpuInstanceGetGpuPciId(VgpuInstance VgpuInstance) (string, Return) {
|
||||
var Length uint32 = 1 // Will be reduced upon returning
|
||||
for {
|
||||
VgpuPciId := make([]byte, Length)
|
||||
ret := nvmlVgpuInstanceGetGpuPciId(VgpuInstance, &VgpuPciId[0], &Length)
|
||||
if ret == SUCCESS {
|
||||
return string(VgpuPciId[:clen(VgpuPciId)]), ret
|
||||
}
|
||||
if ret != ERROR_INSUFFICIENT_SIZE {
|
||||
return "", ret
|
||||
}
|
||||
Length *= 2
|
||||
}
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetGpuPciId() (string, Return) {
|
||||
return VgpuInstanceGetGpuPciId(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetMetadata()
|
||||
func VgpuInstanceGetMetadata(VgpuInstance VgpuInstance) (VgpuMetadata, Return) {
|
||||
var VgpuMetadata VgpuMetadata
|
||||
OpaqueDataSize := unsafe.Sizeof(VgpuMetadata.nvmlVgpuMetadata.OpaqueData)
|
||||
VgpuMetadataSize := unsafe.Sizeof(VgpuMetadata.nvmlVgpuMetadata) - OpaqueDataSize
|
||||
for {
|
||||
BufferSize := uint32(VgpuMetadataSize + OpaqueDataSize)
|
||||
Buffer := make([]byte, BufferSize)
|
||||
nvmlVgpuMetadataPtr := (*nvmlVgpuMetadata)(unsafe.Pointer(&Buffer[0]))
|
||||
ret := nvmlVgpuInstanceGetMetadata(VgpuInstance, nvmlVgpuMetadataPtr, &BufferSize)
|
||||
if ret == SUCCESS {
|
||||
VgpuMetadata.nvmlVgpuMetadata = *nvmlVgpuMetadataPtr
|
||||
VgpuMetadata.OpaqueData = Buffer[VgpuMetadataSize:BufferSize]
|
||||
return VgpuMetadata, ret
|
||||
}
|
||||
if ret != ERROR_INSUFFICIENT_SIZE {
|
||||
return VgpuMetadata, ret
|
||||
}
|
||||
OpaqueDataSize = 2 * OpaqueDataSize
|
||||
}
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetMetadata() (VgpuMetadata, Return) {
|
||||
return VgpuInstanceGetMetadata(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetAccountingMode()
|
||||
func VgpuInstanceGetAccountingMode(VgpuInstance VgpuInstance) (EnableState, Return) {
|
||||
var Mode EnableState
|
||||
ret := nvmlVgpuInstanceGetAccountingMode(VgpuInstance, &Mode)
|
||||
return Mode, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetAccountingMode() (EnableState, Return) {
|
||||
return VgpuInstanceGetAccountingMode(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetAccountingPids()
|
||||
func VgpuInstanceGetAccountingPids(VgpuInstance VgpuInstance) ([]int, Return) {
|
||||
var Count uint32 = 1 // Will be reduced upon returning
|
||||
for {
|
||||
Pids := make([]uint32, Count)
|
||||
ret := nvmlVgpuInstanceGetAccountingPids(VgpuInstance, &Count, &Pids[0])
|
||||
if ret == SUCCESS {
|
||||
return uint32SliceToIntSlice(Pids[:Count]), ret
|
||||
}
|
||||
if ret != ERROR_INSUFFICIENT_SIZE {
|
||||
return nil, ret
|
||||
}
|
||||
Count *= 2
|
||||
}
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetAccountingPids() ([]int, Return) {
|
||||
return VgpuInstanceGetAccountingPids(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetAccountingStats()
|
||||
func VgpuInstanceGetAccountingStats(VgpuInstance VgpuInstance, Pid int) (AccountingStats, Return) {
|
||||
var Stats AccountingStats
|
||||
ret := nvmlVgpuInstanceGetAccountingStats(VgpuInstance, uint32(Pid), &Stats)
|
||||
return Stats, ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetAccountingStats(Pid int) (AccountingStats, Return) {
|
||||
return VgpuInstanceGetAccountingStats(VgpuInstance, Pid)
|
||||
}
|
||||
|
||||
// nvml.GetVgpuCompatibility()
|
||||
func GetVgpuCompatibility(nvmlVgpuMetadata *nvmlVgpuMetadata, PgpuMetadata *nvmlVgpuPgpuMetadata) (VgpuPgpuCompatibility, Return) {
|
||||
var CompatibilityInfo VgpuPgpuCompatibility
|
||||
ret := nvmlGetVgpuCompatibility(nvmlVgpuMetadata, PgpuMetadata, &CompatibilityInfo)
|
||||
return CompatibilityInfo, ret
|
||||
}
|
||||
|
||||
// nvml.GetVgpuVersion()
|
||||
func GetVgpuVersion() (VgpuVersion, VgpuVersion, Return) {
|
||||
var Supported, Current VgpuVersion
|
||||
ret := nvmlGetVgpuVersion(&Supported, &Current)
|
||||
return Supported, Current, ret
|
||||
}
|
||||
|
||||
// nvml.SetVgpuVersion()
|
||||
func SetVgpuVersion(VgpuVersion *VgpuVersion) Return {
|
||||
return SetVgpuVersion(VgpuVersion)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceClearAccountingPids()
|
||||
func VgpuInstanceClearAccountingPids(VgpuInstance VgpuInstance) Return {
|
||||
return nvmlVgpuInstanceClearAccountingPids(VgpuInstance)
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) ClearAccountingPids() Return {
|
||||
return VgpuInstanceClearAccountingPids(VgpuInstance)
|
||||
}
|
||||
|
||||
// nvml.VgpuInstanceGetMdevUUID()
|
||||
func VgpuInstanceGetMdevUUID(VgpuInstance VgpuInstance) (string, Return) {
|
||||
MdevUuid := make([]byte, DEVICE_UUID_BUFFER_SIZE)
|
||||
ret := nvmlVgpuInstanceGetMdevUUID(VgpuInstance, &MdevUuid[0], DEVICE_UUID_BUFFER_SIZE)
|
||||
return string(MdevUuid[:clen(MdevUuid)]), ret
|
||||
}
|
||||
|
||||
func (VgpuInstance VgpuInstance) GetMdevUUID() (string, Return) {
|
||||
return VgpuInstanceGetMdevUUID(VgpuInstance)
|
||||
}
|
||||
@@ -446,7 +446,7 @@ func (w *watch) setup(dirs []string, dirErrors map[string]error) {
|
||||
|
||||
// Start watching Spec directories for relevant changes.
|
||||
func (w *watch) start(m *sync.Mutex, refresh func() error, dirErrors map[string]error) {
|
||||
go w.watch(m, refresh, dirErrors)
|
||||
go w.watch(w.watcher, m, refresh, dirErrors)
|
||||
}
|
||||
|
||||
// Stop watching directories.
|
||||
@@ -460,8 +460,8 @@ func (w *watch) stop() {
|
||||
}
|
||||
|
||||
// Watch Spec directory changes, triggering a refresh if necessary.
|
||||
func (w *watch) watch(m *sync.Mutex, refresh func() error, dirErrors map[string]error) {
|
||||
watch := w.watcher
|
||||
func (w *watch) watch(fsw *fsnotify.Watcher, m *sync.Mutex, refresh func() error, dirErrors map[string]error) {
|
||||
watch := fsw
|
||||
if watch == nil {
|
||||
return
|
||||
}
|
||||
|
||||
26
vendor/github.com/container-orchestrated-devices/container-device-interface/pkg/cdi/cache_test_unix.go
generated
vendored
Normal file
26
vendor/github.com/container-orchestrated-devices/container-device-interface/pkg/cdi/cache_test_unix.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright © 2021 The CDI Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cdi
|
||||
|
||||
import "syscall"
|
||||
|
||||
func osSync() {
|
||||
syscall.Sync()
|
||||
}
|
||||
22
vendor/github.com/container-orchestrated-devices/container-device-interface/pkg/cdi/cache_test_windows.go
generated
vendored
Normal file
22
vendor/github.com/container-orchestrated-devices/container-device-interface/pkg/cdi/cache_test_windows.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright © 2021 The CDI Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cdi
|
||||
|
||||
func osSync() {}
|
||||
@@ -27,8 +27,6 @@ import (
|
||||
"github.com/container-orchestrated-devices/container-device-interface/specs-go"
|
||||
oci "github.com/opencontainers/runtime-spec/specs-go"
|
||||
ocigen "github.com/opencontainers/runtime-tools/generate"
|
||||
|
||||
runc "github.com/opencontainers/runc/libcontainer/devices"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -85,11 +83,13 @@ func (e *ContainerEdits) Apply(spec *oci.Spec) error {
|
||||
}
|
||||
|
||||
for _, d := range e.DeviceNodes {
|
||||
dev := d.ToOCI()
|
||||
if err := fillMissingInfo(&dev); err != nil {
|
||||
dn := DeviceNode{d}
|
||||
|
||||
err := dn.fillMissingInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dev := d.ToOCI()
|
||||
if dev.UID == nil && spec.Process != nil {
|
||||
if uid := spec.Process.User.UID; uid > 0 {
|
||||
dev.UID = &uid
|
||||
@@ -287,32 +287,6 @@ func ensureOCIHooks(spec *oci.Spec) {
|
||||
}
|
||||
}
|
||||
|
||||
// fillMissingInfo fills in missing mandatory attributes from the host device.
|
||||
func fillMissingInfo(dev *oci.LinuxDevice) error {
|
||||
if dev.Type != "" && (dev.Major != 0 || dev.Type == "p") {
|
||||
return nil
|
||||
}
|
||||
hostDev, err := runc.DeviceFromPath(dev.Path, "rwm")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to stat CDI host device %q", dev.Path)
|
||||
}
|
||||
|
||||
if dev.Type == "" {
|
||||
dev.Type = string(hostDev.Type)
|
||||
} else {
|
||||
if dev.Type != string(hostDev.Type) {
|
||||
return errors.Errorf("CDI device %q, host type mismatch (%s, %s)",
|
||||
dev.Path, dev.Type, string(hostDev.Type))
|
||||
}
|
||||
}
|
||||
if dev.Major == 0 && dev.Type != "p" {
|
||||
dev.Major = hostDev.Major
|
||||
dev.Minor = hostDev.Minor
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// sortMounts sorts the mounts in the given OCI Spec.
|
||||
func sortMounts(specgen *ocigen.Generator) {
|
||||
mounts := specgen.Mounts()
|
||||
|
||||
56
vendor/github.com/container-orchestrated-devices/container-device-interface/pkg/cdi/container-edits_unix.go
generated
vendored
Normal file
56
vendor/github.com/container-orchestrated-devices/container-device-interface/pkg/cdi/container-edits_unix.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright © 2021 The CDI Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cdi
|
||||
|
||||
import (
|
||||
runc "github.com/opencontainers/runc/libcontainer/devices"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// fillMissingInfo fills in missing mandatory attributes from the host device.
|
||||
func (d *DeviceNode) fillMissingInfo() error {
|
||||
if d.HostPath == "" {
|
||||
d.HostPath = d.Path
|
||||
}
|
||||
|
||||
if d.Type != "" && (d.Major != 0 || d.Type == "p") {
|
||||
return nil
|
||||
}
|
||||
|
||||
hostDev, err := runc.DeviceFromPath(d.HostPath, "rwm")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to stat CDI host device %q", d.HostPath)
|
||||
}
|
||||
|
||||
if d.Type == "" {
|
||||
d.Type = string(hostDev.Type)
|
||||
} else {
|
||||
if d.Type != string(hostDev.Type) {
|
||||
return errors.Errorf("CDI device (%q, %q), host type mismatch (%s, %s)",
|
||||
d.Path, d.HostPath, d.Type, string(hostDev.Type))
|
||||
}
|
||||
}
|
||||
if d.Major == 0 && d.Type != "p" {
|
||||
d.Major = hostDev.Major
|
||||
d.Minor = hostDev.Minor
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
27
vendor/github.com/container-orchestrated-devices/container-device-interface/pkg/cdi/container-edits_windows.go
generated
vendored
Normal file
27
vendor/github.com/container-orchestrated-devices/container-device-interface/pkg/cdi/container-edits_windows.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright © 2021 The CDI Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cdi
|
||||
|
||||
import "fmt"
|
||||
|
||||
// fillMissingInfo fills in missing mandatory attributes from the host device.
|
||||
func (d *DeviceNode) fillMissingInfo() error {
|
||||
return fmt.Errorf("unimplemented")
|
||||
}
|
||||
@@ -130,7 +130,7 @@ func ValidateVendorName(vendor string) error {
|
||||
}
|
||||
}
|
||||
if !isAlphaNumeric(rune(vendor[len(vendor)-1])) {
|
||||
return errors.Errorf("invalid vendor %q, should end with letter", vendor)
|
||||
return errors.Errorf("invalid vendor %q, should end with a letter or digit", vendor)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -158,7 +158,7 @@ func ValidateClassName(class string) error {
|
||||
}
|
||||
}
|
||||
if !isAlphaNumeric(rune(class[len(class)-1])) {
|
||||
return errors.Errorf("invalid class %q, should end with letter", class)
|
||||
return errors.Errorf("invalid class %q, should end with a letter or digit", class)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -172,8 +172,11 @@ func ValidateDeviceName(name string) error {
|
||||
if name == "" {
|
||||
return errors.Errorf("invalid (empty) device name")
|
||||
}
|
||||
if !isLetter(rune(name[0])) {
|
||||
return errors.Errorf("invalid name %q, should start with letter", name)
|
||||
if !isAlphaNumeric(rune(name[0])) {
|
||||
return errors.Errorf("invalid class %q, should start with a letter or digit", name)
|
||||
}
|
||||
if len(name) == 1 {
|
||||
return nil
|
||||
}
|
||||
for _, c := range string(name[1 : len(name)-1]) {
|
||||
switch {
|
||||
@@ -185,7 +188,7 @@ func ValidateDeviceName(name string) error {
|
||||
}
|
||||
}
|
||||
if !isAlphaNumeric(rune(name[len(name)-1])) {
|
||||
return errors.Errorf("invalid name %q, should start with letter", name)
|
||||
return errors.Errorf("invalid name %q, should end with a letter or digit", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
package cdi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -79,6 +79,9 @@ func scanSpecDirs(dirs []string, scanFn scanSpecFunc) error {
|
||||
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
// for initial stat failure Walk calls us with nil info
|
||||
if info == nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
// first call from Walk is for dir itself, others we skip
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
oci "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
@@ -36,10 +37,12 @@ var (
|
||||
"0.2.0": {},
|
||||
"0.3.0": {},
|
||||
"0.4.0": {},
|
||||
"0.5.0": {},
|
||||
}
|
||||
|
||||
// Externally set CDI Spec validation function.
|
||||
specValidator func(*cdi.Spec) error
|
||||
validatorLock sync.RWMutex
|
||||
)
|
||||
|
||||
// Spec represents a single CDI Spec. It is usually loaded from a
|
||||
@@ -248,11 +251,16 @@ func ParseSpec(data []byte) (*cdi.Spec, error) {
|
||||
// is used for extra CDI Spec content validation whenever a Spec file
|
||||
// loaded (using ReadSpec() or NewSpec()) or written (Spec.Write()).
|
||||
func SetSpecValidator(fn func(*cdi.Spec) error) {
|
||||
validatorLock.Lock()
|
||||
defer validatorLock.Unlock()
|
||||
specValidator = fn
|
||||
}
|
||||
|
||||
// validateSpec validates the Spec using the extneral validator.
|
||||
func validateSpec(raw *cdi.Spec) error {
|
||||
validatorLock.RLock()
|
||||
defer validatorLock.RUnlock()
|
||||
|
||||
if specValidator == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package specs
|
||||
import "os"
|
||||
|
||||
// CurrentVersion is the current version of the Spec.
|
||||
const CurrentVersion = "0.4.0"
|
||||
const CurrentVersion = "0.5.0"
|
||||
|
||||
// Spec is the base configuration for CDI
|
||||
type Spec struct {
|
||||
@@ -31,6 +31,7 @@ type ContainerEdits struct {
|
||||
// DeviceNode represents a device node that needs to be added to the OCI spec.
|
||||
type DeviceNode struct {
|
||||
Path string `json:"path"`
|
||||
HostPath string `json:"hostPath,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Major int64 `json:"major,omitempty"`
|
||||
Minor int64 `json:"minor,omitempty"`
|
||||
|
||||
89
vendor/github.com/containers/podman/v4/pkg/hooks/1.0.0/hook.go
generated
vendored
89
vendor/github.com/containers/podman/v4/pkg/hooks/1.0.0/hook.go
generated
vendored
@@ -1,89 +0,0 @@
|
||||
// Package hook is the 1.0.0 hook configuration structure.
|
||||
package hook
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Version is the hook configuration version defined in this package.
|
||||
const Version = "1.0.0"
|
||||
|
||||
// Hook is the hook configuration structure.
|
||||
type Hook struct {
|
||||
Version string `json:"version"`
|
||||
Hook rspec.Hook `json:"hook"`
|
||||
When When `json:"when"`
|
||||
Stages []string `json:"stages"`
|
||||
}
|
||||
|
||||
// Read reads hook JSON bytes, verifies them, and returns the hook configuration.
|
||||
func Read(content []byte) (hook *Hook, err error) {
|
||||
if err = json.Unmarshal(content, &hook); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hook, nil
|
||||
}
|
||||
|
||||
// Validate performs load-time hook validation.
|
||||
func (hook *Hook) Validate(extensionStages []string) (err error) {
|
||||
if hook == nil {
|
||||
return errors.New("nil hook")
|
||||
}
|
||||
|
||||
if hook.Version != Version {
|
||||
return fmt.Errorf("unexpected hook version %q (expecting %v)", hook.Version, Version)
|
||||
}
|
||||
|
||||
if hook.Hook.Path == "" {
|
||||
return errors.New("missing required property: hook.path")
|
||||
}
|
||||
|
||||
if _, err := os.Stat(hook.Hook.Path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for key, value := range hook.When.Annotations {
|
||||
if _, err = regexp.Compile(key); err != nil {
|
||||
return errors.Wrapf(err, "invalid annotation key %q", key)
|
||||
}
|
||||
if _, err = regexp.Compile(value); err != nil {
|
||||
return errors.Wrapf(err, "invalid annotation value %q", value)
|
||||
}
|
||||
}
|
||||
|
||||
for _, command := range hook.When.Commands {
|
||||
if _, err = regexp.Compile(command); err != nil {
|
||||
return errors.Wrapf(err, "invalid command %q", command)
|
||||
}
|
||||
}
|
||||
|
||||
if hook.Stages == nil {
|
||||
return errors.New("missing required property: stages")
|
||||
}
|
||||
|
||||
validStages := map[string]bool{
|
||||
"createContainer": true,
|
||||
"createRuntime": true,
|
||||
"prestart": true,
|
||||
"poststart": true,
|
||||
"poststop": true,
|
||||
"startContainer": true,
|
||||
}
|
||||
for _, stage := range extensionStages {
|
||||
validStages[stage] = true
|
||||
}
|
||||
|
||||
for _, stage := range hook.Stages {
|
||||
if !validStages[stage] {
|
||||
return fmt.Errorf("unknown stage %q", stage)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
95
vendor/github.com/containers/podman/v4/pkg/hooks/1.0.0/when.go
generated
vendored
95
vendor/github.com/containers/podman/v4/pkg/hooks/1.0.0/when.go
generated
vendored
@@ -1,95 +0,0 @@
|
||||
package hook
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// When holds hook-injection conditions.
|
||||
type When struct {
|
||||
Always *bool `json:"always,omitempty"`
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
Commands []string `json:"commands,omitempty"`
|
||||
HasBindMounts *bool `json:"hasBindMounts,omitempty"`
|
||||
|
||||
// Or enables any-of matching.
|
||||
//
|
||||
// Deprecated: this property is for is backwards-compatibility with
|
||||
// 0.1.0 hooks. It will be removed when we drop support for them.
|
||||
Or bool `json:"-"`
|
||||
}
|
||||
|
||||
// Match returns true if the given conditions match the configuration.
|
||||
func (when *When) Match(config *rspec.Spec, annotations map[string]string, hasBindMounts bool) (match bool, err error) {
|
||||
matches := 0
|
||||
|
||||
if when.Always != nil {
|
||||
if *when.Always {
|
||||
if when.Or {
|
||||
return true, nil
|
||||
}
|
||||
matches++
|
||||
} else if !when.Or {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
if when.HasBindMounts != nil {
|
||||
if *when.HasBindMounts && hasBindMounts {
|
||||
if when.Or {
|
||||
return true, nil
|
||||
}
|
||||
matches++
|
||||
} else if !when.Or {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
for keyPattern, valuePattern := range when.Annotations {
|
||||
match := false
|
||||
for key, value := range annotations {
|
||||
match, err = regexp.MatchString(keyPattern, key)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "annotation key")
|
||||
}
|
||||
if match {
|
||||
match, err = regexp.MatchString(valuePattern, value)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "annotation value")
|
||||
}
|
||||
if match {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if match {
|
||||
if when.Or {
|
||||
return true, nil
|
||||
}
|
||||
matches++
|
||||
} else if !when.Or {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
if config.Process != nil && len(when.Commands) > 0 {
|
||||
if len(config.Process.Args) == 0 {
|
||||
return false, errors.New("process.args must have at least one entry")
|
||||
}
|
||||
command := config.Process.Args[0]
|
||||
for _, cmdPattern := range when.Commands {
|
||||
match, err := regexp.MatchString(cmdPattern, command)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "command")
|
||||
}
|
||||
if match {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return matches > 0, nil
|
||||
}
|
||||
20
vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
generated
vendored
20
vendor/github.com/fsnotify/fsnotify/CHANGELOG.md
generated
vendored
@@ -7,9 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.5.4] - 2022-04-25
|
||||
|
||||
* Windows: add missing defer to `Watcher.WatchList` [#447](https://github.com/fsnotify/fsnotify/pull/447)
|
||||
* go.mod: use latest x/sys [#444](https://github.com/fsnotify/fsnotify/pull/444)
|
||||
* Fix compilation for OpenBSD [#443](https://github.com/fsnotify/fsnotify/pull/443)
|
||||
|
||||
## [1.5.3] - 2022-04-22
|
||||
|
||||
* This version is retracted. An incorrect branch is published accidentally [#445](https://github.com/fsnotify/fsnotify/issues/445)
|
||||
|
||||
## [1.5.2] - 2022-04-21
|
||||
|
||||
* Add a feature to return the directories and files that are being monitored [#374](https://github.com/fsnotify/fsnotify/pull/374)
|
||||
* Fix potential crash on windows if `raw.FileNameLength` exceeds `syscall.MAX_PATH` [#361](https://github.com/fsnotify/fsnotify/pull/361)
|
||||
* Allow build on unsupported GOOS [#424](https://github.com/fsnotify/fsnotify/pull/424)
|
||||
* Don't set `poller.fd` twice in `newFdPoller` [#406](https://github.com/fsnotify/fsnotify/pull/406)
|
||||
* fix go vet warnings: call to `(*T).Fatalf` from a non-test goroutine [#416](https://github.com/fsnotify/fsnotify/pull/416)
|
||||
|
||||
## [1.5.1] - 2021-08-24
|
||||
|
||||
* Revert Add AddRaw to not follow symlinks
|
||||
* Revert Add AddRaw to not follow symlinks [#394](https://github.com/fsnotify/fsnotify/pull/394)
|
||||
|
||||
## [1.5.0] - 2021-08-20
|
||||
|
||||
|
||||
17
vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
generated
vendored
17
vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md
generated
vendored
@@ -48,18 +48,6 @@ fsnotify uses build tags to compile different code on Linux, BSD, macOS, and Win
|
||||
|
||||
Before doing a pull request, please do your best to test your changes on multiple platforms, and list which platforms you were able/unable to test on.
|
||||
|
||||
To aid in cross-platform testing there is a Vagrantfile for Linux and BSD.
|
||||
|
||||
* Install [Vagrant](http://www.vagrantup.com/) and [VirtualBox](https://www.virtualbox.org/)
|
||||
* Setup [Vagrant Gopher](https://github.com/nathany/vagrant-gopher) in your `src` folder.
|
||||
* Run `vagrant up` from the project folder. You can also setup just one box with `vagrant up linux` or `vagrant up bsd` (note: the BSD box doesn't support Windows hosts at this time, and NFS may prompt for your host OS password)
|
||||
* Once setup, you can run the test suite on a given OS with a single command `vagrant ssh linux -c 'cd fsnotify/fsnotify; go test'`.
|
||||
* When you're done, you will want to halt or destroy the Vagrant boxes.
|
||||
|
||||
Notice: fsnotify file system events won't trigger in shared folders. The tests get around this limitation by using the /tmp directory.
|
||||
|
||||
Right now there is no equivalent solution for Windows and macOS, but there are Windows VMs [freely available from Microsoft](http://www.modern.ie/en-us/virtualization-tools#downloads).
|
||||
|
||||
### Maintainers
|
||||
|
||||
Help maintaining fsnotify is welcome. To be a maintainer:
|
||||
@@ -67,11 +55,6 @@ Help maintaining fsnotify is welcome. To be a maintainer:
|
||||
* Submit a pull request and sign the CLA as above.
|
||||
* You must be able to run the test suite on Mac, Windows, Linux and BSD.
|
||||
|
||||
To keep master clean, the fsnotify project uses the "apply mail" workflow outlined in Nathaniel Talbott's post ["Merge pull request" Considered Harmful][am]. This requires installing [hub][].
|
||||
|
||||
All code changes should be internal pull requests.
|
||||
|
||||
Releases are tagged using [Semantic Versioning](http://semver.org/).
|
||||
|
||||
[hub]: https://github.com/github/hub
|
||||
[am]: http://blog.spreedly.com/2014/06/24/merge-pull-request-considered-harmful/#.VGa5yZPF_Zs
|
||||
|
||||
24
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
24
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
@@ -1,12 +1,8 @@
|
||||
# File system notifications for Go
|
||||
|
||||
[](https://godoc.org/github.com/fsnotify/fsnotify) [](https://goreportcard.com/report/github.com/fsnotify/fsnotify)
|
||||
[](https://pkg.go.dev/github.com/fsnotify/fsnotify) [](https://goreportcard.com/report/github.com/fsnotify/fsnotify) [](https://github.com/fsnotify/fsnotify/issues/413)
|
||||
|
||||
fsnotify utilizes [golang.org/x/sys](https://godoc.org/golang.org/x/sys) rather than `syscall` from the standard library. Ensure you have the latest version installed by running:
|
||||
|
||||
```console
|
||||
go get -u golang.org/x/sys/...
|
||||
```
|
||||
fsnotify utilizes [`golang.org/x/sys`](https://pkg.go.dev/golang.org/x/sys) rather than [`syscall`](https://pkg.go.dev/syscall) from the standard library.
|
||||
|
||||
Cross platform: Windows, Linux, BSD and macOS.
|
||||
|
||||
@@ -16,22 +12,20 @@ Cross platform: Windows, Linux, BSD and macOS.
|
||||
| kqueue | BSD, macOS, iOS\* | Supported |
|
||||
| ReadDirectoryChangesW | Windows | Supported |
|
||||
| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) |
|
||||
| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/issues/12) |
|
||||
| fanotify | Linux 2.6.37+ | [Planned](https://github.com/fsnotify/fsnotify/issues/114) |
|
||||
| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/pull/371) |
|
||||
| fanotify | Linux 2.6.37+ | [Maybe](https://github.com/fsnotify/fsnotify/issues/114) |
|
||||
| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) |
|
||||
| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) |
|
||||
|
||||
\* Android and iOS are untested.
|
||||
|
||||
Please see [the documentation](https://godoc.org/github.com/fsnotify/fsnotify) and consult the [FAQ](#faq) for usage information.
|
||||
Please see [the documentation](https://pkg.go.dev/github.com/fsnotify/fsnotify) and consult the [FAQ](#faq) for usage information.
|
||||
|
||||
## API stability
|
||||
|
||||
fsnotify is a fork of [howeyc/fsnotify](https://godoc.org/github.com/howeyc/fsnotify) with a new API as of v1.0. The API is based on [this design document](http://goo.gl/MrYxyA).
|
||||
fsnotify is a fork of [howeyc/fsnotify](https://github.com/howeyc/fsnotify) with a new API as of v1.0. The API is based on [this design document](http://goo.gl/MrYxyA).
|
||||
|
||||
All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based on [Semantic Versioning](http://semver.org/). Further API changes are [planned](https://github.com/fsnotify/fsnotify/milestones), and will be tagged with a new major revision number.
|
||||
|
||||
Go 1.6 supports dependencies located in the `vendor/` folder. Unless you are creating a library, it is recommended that you copy fsnotify into `vendor/github.com/fsnotify/fsnotify` within your project, and likewise for `golang.org/x/sys`.
|
||||
All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based on [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -84,10 +78,6 @@ func main() {
|
||||
|
||||
Please refer to [CONTRIBUTING][] before opening an issue or pull request.
|
||||
|
||||
## Example
|
||||
|
||||
See [example_test.go](https://github.com/fsnotify/fsnotify/blob/master/example_test.go).
|
||||
|
||||
## FAQ
|
||||
|
||||
**When a file is moved to another directory is it still being watched?**
|
||||
|
||||
36
vendor/github.com/fsnotify/fsnotify/fsnotify_unsupported.go
generated
vendored
Normal file
36
vendor/github.com/fsnotify/fsnotify/fsnotify_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows
|
||||
// +build !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows
|
||||
|
||||
package fsnotify
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// Watcher watches a set of files, delivering events to a channel.
|
||||
type Watcher struct{}
|
||||
|
||||
// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events.
|
||||
func NewWatcher() (*Watcher, error) {
|
||||
return nil, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
// Close removes all watches and closes the events channel.
|
||||
func (w *Watcher) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add starts watching the named file or directory (non-recursively).
|
||||
func (w *Watcher) Add(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove stops watching the the named file or directory (non-recursively).
|
||||
func (w *Watcher) Remove(name string) error {
|
||||
return nil
|
||||
}
|
||||
7
vendor/github.com/fsnotify/fsnotify/go.mod
generated
vendored
7
vendor/github.com/fsnotify/fsnotify/go.mod
generated
vendored
@@ -1,7 +0,0 @@
|
||||
module github.com/fsnotify/fsnotify
|
||||
|
||||
go 1.13
|
||||
|
||||
require golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
|
||||
|
||||
retract v1.5.0
|
||||
2
vendor/github.com/fsnotify/fsnotify/go.sum
generated
vendored
2
vendor/github.com/fsnotify/fsnotify/go.sum
generated
vendored
@@ -1,2 +0,0 @@
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
13
vendor/github.com/fsnotify/fsnotify/inotify.go
generated
vendored
13
vendor/github.com/fsnotify/fsnotify/inotify.go
generated
vendored
@@ -163,6 +163,19 @@ func (w *Watcher) Remove(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WatchList returns the directories and files that are being monitered.
|
||||
func (w *Watcher) WatchList() []string {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
entries := make([]string, 0, len(w.watches))
|
||||
for pathname := range w.watches {
|
||||
entries = append(entries, pathname)
|
||||
}
|
||||
|
||||
return entries
|
||||
}
|
||||
|
||||
type watch struct {
|
||||
wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
|
||||
flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
|
||||
|
||||
1
vendor/github.com/fsnotify/fsnotify/inotify_poller.go
generated
vendored
1
vendor/github.com/fsnotify/fsnotify/inotify_poller.go
generated
vendored
@@ -38,7 +38,6 @@ func newFdPoller(fd int) (*fdPoller, error) {
|
||||
poller.close()
|
||||
}
|
||||
}()
|
||||
poller.fd = fd
|
||||
|
||||
// Create epoll fd
|
||||
poller.epfd, errno = unix.EpollCreate1(unix.EPOLL_CLOEXEC)
|
||||
|
||||
13
vendor/github.com/fsnotify/fsnotify/kqueue.go
generated
vendored
13
vendor/github.com/fsnotify/fsnotify/kqueue.go
generated
vendored
@@ -148,6 +148,19 @@ func (w *Watcher) Remove(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WatchList returns the directories and files that are being monitered.
|
||||
func (w *Watcher) WatchList() []string {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
entries := make([]string, 0, len(w.watches))
|
||||
for pathname := range w.watches {
|
||||
entries = append(entries, pathname)
|
||||
}
|
||||
|
||||
return entries
|
||||
}
|
||||
|
||||
// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE)
|
||||
const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME
|
||||
|
||||
|
||||
28
vendor/github.com/fsnotify/fsnotify/windows.go
generated
vendored
28
vendor/github.com/fsnotify/fsnotify/windows.go
generated
vendored
@@ -12,6 +12,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
@@ -96,6 +97,21 @@ func (w *Watcher) Remove(name string) error {
|
||||
return <-in.reply
|
||||
}
|
||||
|
||||
// WatchList returns the directories and files that are being monitered.
|
||||
func (w *Watcher) WatchList() []string {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
entries := make([]string, 0, len(w.watches))
|
||||
for _, entry := range w.watches {
|
||||
for _, watchEntry := range entry {
|
||||
entries = append(entries, watchEntry.path)
|
||||
}
|
||||
}
|
||||
|
||||
return entries
|
||||
}
|
||||
|
||||
const (
|
||||
// Options for AddWatch
|
||||
sysFSONESHOT = 0x80000000
|
||||
@@ -452,8 +468,16 @@ func (w *Watcher) readEvents() {
|
||||
|
||||
// Point "raw" to the event in the buffer
|
||||
raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset]))
|
||||
buf := (*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName))
|
||||
name := syscall.UTF16ToString(buf[:raw.FileNameLength/2])
|
||||
// TODO: Consider using unsafe.Slice that is available from go1.17
|
||||
// https://stackoverflow.com/questions/51187973/how-to-create-an-array-or-a-slice-from-an-array-unsafe-pointer-in-golang
|
||||
// instead of using a fixed syscall.MAX_PATH buf, we create a buf that is the size of the path name
|
||||
size := int(raw.FileNameLength / 2)
|
||||
var buf []uint16
|
||||
sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf))
|
||||
sh.Data = uintptr(unsafe.Pointer(&raw.FileName))
|
||||
sh.Len = size
|
||||
sh.Cap = size
|
||||
name := syscall.UTF16ToString(buf)
|
||||
fullname := filepath.Join(watch.path, name)
|
||||
|
||||
var mask uint64
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user