Skip to content

Commit 1f66948

Browse files
authored
Merge pull request #415 from linode/remove_linode_api_ds
Refactor NodeServer to eliminate Linode API dependency and support isolated driver roles
2 parents 34f29e7 + d36f902 commit 1f66948

21 files changed

+410
-189
lines changed

Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ generate-mock:
158158
mockgen -source=pkg/linode-client/linode_client.go -destination=mocks/mock_linodeclient.go -package=mocks
159159
mockgen -source=pkg/cryptsetup-client/cryptsetup_client.go -destination=mocks/mock_cryptsetupclient.go -package=mocks
160160
mockgen -source=internal/driver/metadata.go -destination=mocks/mock_metadata.go -package=mocks
161+
mockgen -source=pkg/hwinfo/hwinfo.go -destination=mocks/mock_hwinfo.go -package=mocks
161162

162163
.PHONY: test
163164
test:

deploy/kubernetes/base/ds-csi-linode-node.yaml

+2-11
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,8 @@ spec:
5454
env:
5555
- name: CSI_ENDPOINT
5656
value: unix:///csi/csi.sock
57-
- name: LINODE_URL
58-
value: https://api.linode.com/v4
59-
- name: NODE_NAME
60-
valueFrom:
61-
fieldRef:
62-
fieldPath: spec.nodeName
63-
- name: LINODE_TOKEN
64-
valueFrom:
65-
secretKeyRef:
66-
name: linode
67-
key: token
57+
- name: DRIVER_ROLE
58+
value: nodeserver
6859
imagePullPolicy: "Always"
6960
securityContext:
7061
# This container must run as privileged due to the requirement for bidirectional mount propagation

deploy/kubernetes/base/ss-csi-linode-controller.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ spec:
8787
value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock
8888
- name: LINODE_URL
8989
value: https://api.linode.com/v4
90+
- name: DRIVER_ROLE
91+
value: controller
9092
- name: LINODE_BS_PREFIX
9193
- name: NODE_NAME
9294
valueFrom:

devbox.lock

+4
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@
193193
}
194194
}
195195
},
196+
"github:NixOS/nixpkgs/nixpkgs-unstable": {
197+
"last_modified": "2025-04-17T05:47:26Z",
198+
"resolved": "github:NixOS/nixpkgs/ebe4301cbd8f81c4f8d3244b3632338bbeb6d49c?lastModified=1744868846&narHash=sha256-5RJTdUHDmj12Qsv7XOhuospjAjATNiTMElplWnJE9Hs%3D"
199+
},
196200
"go@1.23.1": {
197201
"last_modified": "2024-09-10T15:01:03Z",
198202
"resolved": "github:NixOS/nixpkgs/5ed627539ac84809c78b2dd6d26a5cebeb5ae269#go_1_23",

docs/deployment.md

+15-1
Original file line numberDiff line numberDiff line change
@@ -164,5 +164,19 @@ kubectl apply -f https://raw.githubusercontent.com/linode/linode-blockstorage-cs
164164
- The CSI driver supports offline volume resizing. This means that the volume must be unmounted from all nodes before resizing.
165165
- To resize a volume, update the `spec.resources.requests.storage` field in the PersistentVolumeClaim (PVC) manifest and apply the changes.
166166
- The CSI driver will automatically resize the underlying Linode Block Storage Volume to match the new size specified in the PVC.
167-
- The volume must be unmounted from all nodes before resizing.
167+
- The volume must be unmounted from all nodes before resizing.
168168
It could be unmounted by deleting the pod using the volume or by using the `kubectl delete pod <pod-name>` command.
169+
170+
5. Driver Role Configuration
171+
172+
Set the `DRIVER_ROLE` environment variable to control which CSI components load:
173+
174+
- **controller**
175+
- **Prerequisite**: `LINODE_TOKEN` **must** be defined.
176+
- **Behavior**: Boots the CSI Controller service.
177+
- **API**: Actively calls the Linode API to provision, attach and manage volumes.
178+
179+
- **nodeserver**
180+
- **Prerequisite**: `LINODE_TOKEN` **not required**.
181+
- **Behavior**: Launches only the NodeServer endpoint.
182+
- **API**: Operates entirely offline—no Linode API interactions.

go.mod

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ require (
88
github.com/golang/mock v1.6.0
99
github.com/google/uuid v1.6.0
1010
github.com/ianschenck/envflag v0.0.0-20140720210342-9111d830d133
11+
github.com/jaypipes/ghw v0.16.0
1112
github.com/linode/go-metadata v0.2.1
1213
github.com/linode/linodego v1.49.0
1314
github.com/martinjungblut/go-cryptsetup v0.0.0-20220520180014-fd0874fd07a6
@@ -33,13 +34,15 @@ require (
3334
)
3435

3536
require (
37+
github.com/StackExchange/wmi v1.2.1 // indirect
3638
github.com/beorn7/perks v1.0.1 // indirect
3739
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
3840
github.com/cespare/xxhash/v2 v2.3.0 // indirect
3941
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
4042
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
4143
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
4244
github.com/go-logr/stdr v1.2.2 // indirect
45+
github.com/go-ole/go-ole v1.2.6 // indirect
4346
github.com/go-openapi/jsonpointer v0.21.0 // indirect
4447
github.com/go-openapi/jsonreference v0.20.2 // indirect
4548
github.com/go-openapi/swag v0.23.0 // indirect
@@ -51,9 +54,11 @@ require (
5154
github.com/google/go-querystring v1.1.0 // indirect
5255
github.com/google/gofuzz v1.2.0 // indirect
5356
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
57+
github.com/jaypipes/pcidb v1.0.1 // indirect
5458
github.com/josharian/intern v1.0.0 // indirect
5559
github.com/json-iterator/go v1.1.12 // indirect
5660
github.com/mailru/easyjson v0.7.7 // indirect
61+
github.com/mitchellh/go-homedir v1.1.0 // indirect
5762
github.com/moby/sys/mountinfo v0.7.2 // indirect
5863
github.com/moby/sys/userns v0.1.0 // indirect
5964
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@@ -79,6 +84,7 @@ require (
7984
gopkg.in/inf.v0 v0.9.1 // indirect
8085
gopkg.in/ini.v1 v1.66.6 // indirect
8186
gopkg.in/yaml.v3 v3.0.1 // indirect
87+
howett.net/plist v1.0.0 // indirect
8288
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
8389
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
8490
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect

go.sum

+16
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
2+
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
13
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
24
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
35
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
@@ -20,6 +22,9 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
2022
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
2123
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
2224
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
25+
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
26+
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
27+
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
2328
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
2429
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
2530
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
@@ -59,6 +64,11 @@ github.com/ianschenck/envflag v0.0.0-20140720210342-9111d830d133 h1:h6FO/Da7rdYq
5964
github.com/ianschenck/envflag v0.0.0-20140720210342-9111d830d133/go.mod h1:pyYc5lldRtL0l5YitYVv1dLKuC0qhMfAfiR7BLsN2pA=
6065
github.com/jarcoal/httpmock v1.3.1 h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww=
6166
github.com/jarcoal/httpmock v1.3.1/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
67+
github.com/jaypipes/ghw v0.16.0 h1:3HurCTS38VNpeQLo5fIdZsySuo/qAfpPSJ5t05QBFPM=
68+
github.com/jaypipes/ghw v0.16.0/go.mod h1:In8SsaDqlb1oTyrbmTC14uy+fbBMvp+xdqX51MidlD8=
69+
github.com/jaypipes/pcidb v1.0.1 h1:WB2zh27T3nwg8AE8ei81sNRb9yWBii3JGNJtT7K9Oic=
70+
github.com/jaypipes/pcidb v1.0.1/go.mod h1:6xYUz/yYEyOkIkUt2t2J2folIuZ4Yg6uByCGFXMCeE4=
71+
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
6272
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
6373
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
6474
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -84,6 +94,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
8494
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
8595
github.com/martinjungblut/go-cryptsetup v0.0.0-20220520180014-fd0874fd07a6 h1:YDjLk3wsL5ZLhLC4TIwIvT2NkSCAdAV6pzzZaRfj4jk=
8696
github.com/martinjungblut/go-cryptsetup v0.0.0-20220520180014-fd0874fd07a6/go.mod h1:gZoZ0+POlM1ge/VUxWpMmZVNPzzMJ7l436CgkQ5+qzU=
97+
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
98+
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
8799
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
88100
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
89101
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
@@ -181,6 +193,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
181193
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
182194
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
183195
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
196+
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
184197
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
185198
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
186199
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -224,9 +237,12 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
224237
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
225238
gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
226239
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
240+
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
227241
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
228242
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
229243
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
244+
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
245+
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
230246
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
231247
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
232248
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=

hack/generate-yaml.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ fi
1919

2020
cd $(dirname "$0")/../
2121
file=./deploy/kubernetes/overlays/release/kustomization.yaml
22-
CSI_VERSION=$TAG CSI_IMAGE_NAME=$IMAGE_NAME envsubst < "$file.template" > $file
22+
CSI_VERSION=$TAG CSI_IMAGE_NAME=$IMAGE_NAME envsubst <"$file.template" >$file
2323

2424
kustomize build "$(dirname $file)"

helm-chart/csi-driver/templates/csi-linode-controller.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ spec:
111111
value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock
112112
- name: LINODE_URL
113113
value: https://api.linode.com
114+
- name: DRIVER_ROLE
115+
value: controller
114116
- name: LINODE_VOLUME_LABEL_PREFIX
115117
value: {{ .Values.volumeLabelPrefix | default "" | quote }}
116118
- name: NODE_NAME

helm-chart/csi-driver/templates/daemonset.yaml

+2-11
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,8 @@ spec:
4949
env:
5050
- name: CSI_ENDPOINT
5151
value: unix:///csi/csi.sock
52-
- name: LINODE_URL
53-
value: https://api.linode.com
54-
- name: NODE_NAME
55-
valueFrom:
56-
fieldRef:
57-
fieldPath: spec.nodeName
58-
- name: LINODE_TOKEN
59-
valueFrom:
60-
secretKeyRef:
61-
name: {{ if .Values.secretRef }}{{ .Values.secretRef.name | default "linode" }}{{ else }}"linode"{{ end }}
62-
key: {{ if .Values.secretRef }}{{ .Values.secretRef.apiTokenRef | default "token" }}{{ else }}"token"{{ end }}
52+
- name: DRIVER_ROLE
53+
value: nodeserver
6354
- name: ENABLE_METRICS
6455
value: {{ .Values.enableMetrics | quote}}
6556
- name: METRICS_PORT

internal/driver/driver.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"google.golang.org/grpc/status"
2828

2929
devicemanager "github.com/linode/linode-blockstorage-csi-driver/pkg/device-manager"
30+
"github.com/linode/linode-blockstorage-csi-driver/pkg/hwinfo"
3031
linodeclient "github.com/linode/linode-blockstorage-csi-driver/pkg/linode-client"
3132
"github.com/linode/linode-blockstorage-csi-driver/pkg/logger"
3233
mountmanager "github.com/linode/linode-blockstorage-csi-driver/pkg/mount-manager"
@@ -121,7 +122,9 @@ func (linodeDriver *LinodeDriver) SetupLinodeDriver(
121122
linodeDriver.volumeLabelPrefix = volumeLabelPrefix
122123

123124
log.V(2).Info("Setting up RPC Servers")
124-
linodeDriver.ns, err = NewNodeServer(ctx, linodeDriver, mounter, deviceUtils, linodeClient, metadata, encrypt, resizeFs)
125+
126+
hw := hwinfo.NewHardwareInfo()
127+
linodeDriver.ns, err = NewNodeServer(ctx, linodeDriver, mounter, deviceUtils, metadata, encrypt, resizeFs, hw)
125128
if err != nil {
126129
return fmt.Errorf("new node server: %w", err)
127130
}

internal/driver/limits.go

+23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package driver
22

3+
import (
4+
"strings"
5+
6+
"github.com/linode/linode-blockstorage-csi-driver/pkg/hwinfo"
7+
)
8+
39
// maxVolumeAttachments returns the maximum number of block storage volumes
410
// that can be attached to a Linode instance, given the amount of memory the
511
// instance has.
@@ -29,3 +35,20 @@ const (
2935
// a single Linode instance.
3036
maxAttachments = 64
3137
)
38+
39+
func attachedVolumeCount(hw hwinfo.HardwareInfo) (int, error) {
40+
bdev, err := hw.Block()
41+
if err != nil {
42+
return 0, err
43+
}
44+
count := 0
45+
for _, disk := range bdev.Disks {
46+
driveType := strings.ToLower(disk.DriveType.String())
47+
controllerType := strings.ToLower(disk.StorageController.String())
48+
if driveType == "virtual" || driveType == "cdrom" || controllerType == "loop" || controllerType == "unknown" {
49+
continue
50+
}
51+
count++
52+
}
53+
return count, nil
54+
}

internal/driver/limits_test.go

+123
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,21 @@ package driver
33
import (
44
"fmt"
55
"testing"
6+
7+
"github.com/jaypipes/ghw"
8+
"github.com/jaypipes/ghw/pkg/block"
9+
"go.uber.org/mock/gomock"
10+
11+
"github.com/linode/linode-blockstorage-csi-driver/mocks"
12+
)
13+
14+
const (
15+
DRIVE_TYPE_UNKNOWN = iota
16+
DRIVE_TYPE_HDD
17+
DRIVE_TYPE_FDD
18+
DRIVE_TYPE_ODD
19+
DRIVE_TYPE_SSD
20+
DRIVE_TYPE_VIRTUAL
621
)
722

823
func TestMaxVolumeAttachments(t *testing.T) {
@@ -37,3 +52,111 @@ func TestMaxVolumeAttachments(t *testing.T) {
3752
})
3853
}
3954
}
55+
56+
func TestAttachedVolumeCount(t *testing.T) {
57+
t.Parallel()
58+
59+
tests := []struct {
60+
name string
61+
expectedVolumeCount int
62+
expectedError error
63+
blkInfo *ghw.BlockInfo
64+
}{
65+
{
66+
name: "AllLoopDevices",
67+
expectedVolumeCount: 0,
68+
blkInfo: &ghw.BlockInfo{
69+
Disks: []*ghw.Disk{
70+
{
71+
DriveType: DRIVE_TYPE_VIRTUAL,
72+
StorageController: block.StorageControllerUnknown,
73+
IsRemovable: false,
74+
Partitions: []*ghw.Partition{
75+
{
76+
Name: "vd1p1",
77+
MountPoint: "/mnt/virtual1",
78+
SizeBytes: 1024 * 1024 * 1024,
79+
},
80+
},
81+
},
82+
{
83+
DriveType: DRIVE_TYPE_VIRTUAL,
84+
StorageController: block.StorageControllerLoop,
85+
IsRemovable: false,
86+
Partitions: []*ghw.Partition{
87+
{
88+
Name: "loop1",
89+
MountPoint: "/mnt/virtual1",
90+
SizeBytes: 1024 * 1024 * 1024,
91+
},
92+
},
93+
},
94+
},
95+
},
96+
},
97+
{
98+
name: "OneDisk",
99+
expectedVolumeCount: 1,
100+
blkInfo: &ghw.BlockInfo{
101+
Disks: []*ghw.Disk{
102+
{
103+
DriveType: DRIVE_TYPE_VIRTUAL,
104+
IsRemovable: false,
105+
StorageController: block.StorageControllerUnknown,
106+
Partitions: []*ghw.Partition{
107+
{
108+
Name: "vd1p1",
109+
MountPoint: "/mnt/virtual1",
110+
SizeBytes: 1024 * 1024 * 1024,
111+
},
112+
},
113+
},
114+
{
115+
DriveType: DRIVE_TYPE_VIRTUAL,
116+
IsRemovable: false,
117+
StorageController: block.StorageControllerLoop,
118+
Partitions: []*ghw.Partition{
119+
{
120+
Name: "loop1",
121+
MountPoint: "/foo",
122+
SizeBytes: 1024 * 1024 * 1024,
123+
},
124+
},
125+
},
126+
{
127+
DriveType: DRIVE_TYPE_SSD,
128+
IsRemovable: false,
129+
StorageController: block.StorageControllerSCSI,
130+
Partitions: []*ghw.Partition{
131+
{
132+
Name: "nvme0n1",
133+
MountPoint: "/foo",
134+
SizeBytes: 1024 * 1024 * 1024,
135+
},
136+
},
137+
},
138+
},
139+
},
140+
},
141+
}
142+
143+
for _, tt := range tests {
144+
tt := tt // capture range variable
145+
t.Run(tt.name, func(t *testing.T) {
146+
t.Parallel()
147+
ctrl := gomock.NewController(t)
148+
defer ctrl.Finish()
149+
150+
mockHW := mocks.NewMockHardwareInfo(ctrl)
151+
mockHW.EXPECT().Block().Return(tt.blkInfo, nil)
152+
153+
count, err := attachedVolumeCount(mockHW)
154+
if err != nil {
155+
t.Fatalf("unexpected error: %v", err)
156+
}
157+
if count != tt.expectedVolumeCount {
158+
t.Errorf("expected %d, got %d", tt.expectedVolumeCount, count)
159+
}
160+
})
161+
}
162+
}

0 commit comments

Comments
 (0)