k8s.io/kubernetes@v1.29.3/pkg/volume/fc/fc_util_test.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package fc 18 19 import ( 20 "os" 21 "reflect" 22 "testing" 23 "time" 24 25 "k8s.io/kubernetes/pkg/volume/util" 26 ) 27 28 type fakeFileInfo struct { 29 name string 30 } 31 32 func (fi *fakeFileInfo) Name() string { 33 return fi.name 34 } 35 36 func (fi *fakeFileInfo) Size() int64 { 37 return 0 38 } 39 40 func (fi *fakeFileInfo) Mode() os.FileMode { 41 return 777 42 } 43 44 func (fi *fakeFileInfo) ModTime() time.Time { 45 return time.Now() 46 } 47 func (fi *fakeFileInfo) IsDir() bool { 48 return false 49 } 50 51 func (fi *fakeFileInfo) Sys() interface{} { 52 return nil 53 } 54 55 type fakeIOHandler struct{} 56 57 func (handler *fakeIOHandler) ReadDir(dirname string) ([]os.FileInfo, error) { 58 switch dirname { 59 case "/dev/disk/by-path/": 60 f1 := &fakeFileInfo{ 61 name: "pci-0000:41:00.0-fc-0x500a0981891b8dc5-lun-0", 62 } 63 f2 := &fakeFileInfo{ 64 name: "fc-0x5005076810213b32-lun-2", 65 } 66 f3 := &fakeFileInfo{ 67 name: "abc-0000:41:00.0-fc-0x5005076810213404-lun-0", 68 } 69 f4 := &fakeFileInfo{ 70 name: "pci-0000:41:00.0-fc-0x500a0981891b8dc5-lun-12", 71 } 72 f5 := &fakeFileInfo{ 73 name: "pci-0000:41:00.0-fc-0x500a0981891b8dc5-lun-1", 74 } 75 f6 := &fakeFileInfo{ 76 name: "fc-0x5005076810213b32-lun-25", 77 } 78 return []os.FileInfo{f4, f5, f6, f1, f2, f3}, nil 79 case "/sys/block/": 80 f := &fakeFileInfo{ 81 name: "dm-1", 82 } 83 return []os.FileInfo{f}, nil 84 case "/dev/disk/by-id/": 85 f := &fakeFileInfo{ 86 name: "scsi-3600508b400105e210000900000490000", 87 } 88 return []os.FileInfo{f}, nil 89 } 90 return nil, nil 91 } 92 93 func (handler *fakeIOHandler) Lstat(name string) (os.FileInfo, error) { 94 return nil, nil 95 } 96 97 func (handler *fakeIOHandler) EvalSymlinks(path string) (string, error) { 98 switch path { 99 case "/dev/disk/by-path/pci-0000:41:00.0-fc-0x500a0981891b8dc5-lun-0": 100 return "/dev/sda", nil 101 case "/dev/disk/by-path/pci-0000:41:00.0-fc-0x500a0981891b8dc5-lun-1": 102 return "/dev/sdb", nil 103 case "/dev/disk/by-path/fc-0x5005076810213b32-lun-2": 104 return "/dev/sdc", nil 105 case "/dev/disk/by-path/pci-0000:41:00.0-fc-0x500a0981891b8dc5-lun-12": 106 return "/dev/sdl", nil 107 case "/dev/disk/by-path/fc-0x5005076810213b32-lun-25": 108 return "/dev/sdx", nil 109 case "/dev/disk/by-id/scsi-3600508b400105e210000900000490000": 110 return "/dev/sdd", nil 111 } 112 return "", nil 113 } 114 115 func (handler *fakeIOHandler) WriteFile(filename string, data []byte, perm os.FileMode) error { 116 return nil 117 } 118 119 func TestSearchDisk(t *testing.T) { 120 tests := []struct { 121 name string 122 wwns []string 123 lun string 124 disk string 125 expectError bool 126 }{ 127 { 128 name: "PCI disk 0", 129 wwns: []string{"500a0981891b8dc5"}, 130 lun: "0", 131 disk: "/dev/sda", 132 }, 133 { 134 name: "PCI disk 1", 135 wwns: []string{"500a0981891b8dc5"}, 136 lun: "1", 137 disk: "/dev/sdb", 138 }, 139 { 140 name: "Non PCI disk", 141 wwns: []string{"5005076810213b32"}, 142 lun: "2", 143 disk: "/dev/sdc", 144 }, 145 { 146 name: "Invalid Storage Controller", 147 wwns: []string{"5005076810213404"}, 148 lun: "0", 149 expectError: true, 150 }, 151 { 152 name: "Non existing disk", 153 wwns: []string{"500507681fffffff"}, 154 lun: "0", 155 expectError: true, 156 }, 157 } 158 159 for _, test := range tests { 160 t.Run(test.name, func(t *testing.T) { 161 fakeMounter := fcDiskMounter{ 162 fcDisk: &fcDisk{ 163 wwns: test.wwns, 164 lun: test.lun, 165 io: &fakeIOHandler{}, 166 }, 167 deviceUtil: util.NewDeviceHandler(util.NewIOHandler()), 168 } 169 devicePath, err := searchDisk(fakeMounter) 170 if test.expectError && err == nil { 171 t.Errorf("expected error but got none") 172 } 173 if !test.expectError && err != nil { 174 t.Errorf("got unexpected error: %s", err) 175 } 176 // if no disk matches input wwn and lun, exit 177 if devicePath == "" && !test.expectError { 178 t.Errorf("no fc disk found") 179 } 180 if devicePath != test.disk { 181 t.Errorf("matching wrong disk, expected: %s, actual: %s", test.disk, devicePath) 182 } 183 }) 184 } 185 } 186 187 func TestSearchDiskWWID(t *testing.T) { 188 fakeMounter := fcDiskMounter{ 189 fcDisk: &fcDisk{ 190 wwids: []string{"3600508b400105e210000900000490000"}, 191 io: &fakeIOHandler{}, 192 }, 193 deviceUtil: util.NewDeviceHandler(util.NewIOHandler()), 194 } 195 devicePath, error := searchDisk(fakeMounter) 196 // if no disk matches input wwid, exit 197 if devicePath == "" || error != nil { 198 t.Errorf("no fc disk found") 199 } 200 } 201 202 func TestParsePDName(t *testing.T) { 203 tests := []struct { 204 name string 205 path string 206 wwns []string 207 lun int32 208 wwids []string 209 expectError bool 210 }{ 211 { 212 name: "single WWID", 213 path: "/var/lib/kubelet/plugins/kubernetes.io/fc/60050763008084e6e0000000000001ae", 214 wwids: []string{"60050763008084e6e0000000000001ae"}, 215 }, 216 { 217 name: "multiple WWID", 218 path: "/var/lib/kubelet/plugins/kubernetes.io/fc/60050763008084e6e0000000000001ae-60050763008084e6e0000000000001af", 219 wwids: []string{"60050763008084e6e0000000000001ae", "60050763008084e6e0000000000001af"}, 220 }, 221 { 222 name: "single WWN", 223 path: "/var/lib/kubelet/plugins/kubernetes.io/fc/50050768030539b6-lun-0", 224 wwns: []string{"50050768030539b6"}, 225 lun: 0, 226 }, 227 { 228 name: "multiple WWNs", 229 path: "/var/lib/kubelet/plugins/kubernetes.io/fc/50050768030539b6-50050768030539b7-lun-0", 230 wwns: []string{"50050768030539b6", "50050768030539b7"}, 231 lun: 0, 232 }, 233 { 234 name: "no WWNs", 235 path: "/var/lib/kubelet/plugins/kubernetes.io/fc/lun-0", 236 expectError: true, 237 }, 238 { 239 name: "invalid lun", 240 path: "/var/lib/kubelet/plugins/kubernetes.io/fc/50050768030539b6-lun-x", 241 expectError: true, 242 }, 243 } 244 245 for _, test := range tests { 246 t.Run(test.name, func(t *testing.T) { 247 wwns, lun, wwids, err := parsePDName(test.path) 248 if test.expectError && err == nil { 249 t.Errorf("expected error but got none") 250 } 251 if !test.expectError && err != nil { 252 t.Errorf("got unexpected error: %s", err) 253 } 254 if !reflect.DeepEqual(wwns, test.wwns) { 255 t.Errorf("expected WWNs %+v, got %+v", test.wwns, wwns) 256 } 257 if lun != test.lun { 258 t.Errorf("expected lun %d, got %d", test.lun, lun) 259 } 260 if !reflect.DeepEqual(wwids, test.wwids) { 261 t.Errorf("expected WWIDs %+v, got %+v", test.wwids, wwids) 262 } 263 }) 264 } 265 }