@@ -17,16 +17,17 @@ package sas
1717
1818import (
1919 "context"
20+ "encoding/json"
2021 "fmt"
2122 "io/ioutil"
2223 "os"
24+ "os/exec"
2325
2426 "errors"
2527 "path"
2628 "path/filepath"
2729 "strings"
2830
29- "github.com/go-logr/logr"
3031 "k8s.io/klog/v2"
3132)
3233
@@ -39,11 +40,13 @@ type ioHandler interface {
3940
4041//Connector provides a struct to hold all of the needed parameters to make our SAS connection
4142type Connector struct {
42- VolumeName string
43- TargetWWNs []string
44- Lun string
45- WWIDs []string
46- io ioHandler
43+ VolumeName string `json:"volume_name"`
44+ TargetWWNs []string `json:"target_wwns"`
45+ Lun string `json:"lun"`
46+ WWIDs []string `json:"wwids"`
47+ Multipath bool `json:"multipath"`
48+ DevicePath string `json:"device_path"`
49+ IoHandler ioHandler
4750}
4851
4952//OSioHandler is a wrapper that includes all the necessary io functions used for (Should be used as default io handler)
@@ -60,13 +63,15 @@ func Attach(ctx context.Context, c Connector, io ioHandler) (string, error) {
6063 }
6164
6265 logger .V (1 ).Info ("Attaching SAS volume" )
63- devicePath , err := searchDisk (& logger , c , io )
66+ devicePath , err := searchDisk (logger , c , io )
6467
6568 if err != nil {
6669 logger .V (1 ).Info ("unable to find disk given WWNN or WWIDs" )
6770 return "" , err
6871 }
6972
73+ c .DevicePath = devicePath
74+
7075 return devicePath , nil
7176}
7277
@@ -98,10 +103,10 @@ func Detach(ctx context.Context, devicePath string, io ioHandler) error {
98103 var lastErr error
99104
100105 for _ , device := range devices {
101- err := detachFCDisk ( & logger , device , io )
106+ err := detachSasDisk ( logger , device , io )
102107 if err != nil {
103- logger .Error (err , "sas: detachFCDisk failed" , "device" , device )
104- lastErr = fmt .Errorf ("sas: detachFCDisk failed. device: %v err: %v" , device , err )
108+ logger .Error (err , "sas: detachSasDisk failed" , "device" , device )
109+ lastErr = fmt .Errorf ("sas: detachSasDisk failed. device: %v err: %v" , device , err )
105110 }
106111 }
107112
@@ -113,6 +118,50 @@ func Detach(ctx context.Context, devicePath string, io ioHandler) error {
113118 return nil
114119}
115120
121+ // Persist persists the Connector to the specified file (ie /var/lib/pfile/myConnector.json)
122+ func (c * Connector ) Persist (ctx context.Context , filePath string ) error {
123+ logger := klog .FromContext (ctx )
124+ f , err := os .Create (filePath )
125+ if err != nil {
126+ logger .Error (err , "Could not create file" , "filePath" , filePath )
127+ return fmt .Errorf ("error creating iSCSI persistence file %s: %s" , filePath , err )
128+ }
129+ defer f .Close ()
130+ encoder := json .NewEncoder (f )
131+ if err = encoder .Encode (c ); err != nil {
132+ logger .Error (err , "Could not encode the connector" )
133+ return fmt .Errorf ("error encoding connector: %v" , err )
134+ }
135+ return nil
136+ }
137+
138+ // GetConnectorFromFile attempts to create a Connector using the specified json file (ie /var/lib/pfile/myConnector.json)
139+ func GetConnectorFromFile (filePath string ) (* Connector , error ) {
140+ f , err := ioutil .ReadFile (filePath )
141+ if err != nil {
142+ return nil , err
143+ }
144+ c := Connector {}
145+ err = json .Unmarshal ([]byte (f ), & c )
146+ if err != nil {
147+ return nil , err
148+ }
149+
150+ return & c , nil
151+ }
152+
153+ // ResizeMultipathDevice: resize a multipath device based on its underlying devices
154+ func ResizeMultipathDevice (ctx context.Context , devicePath string ) error {
155+ logger := klog .FromContext (ctx )
156+ logger .V (1 ).Info ("Resizing multipath device" , "device" , devicePath )
157+
158+ if output , err := exec .Command ("multipathd" , "resize" , "map" , devicePath ).CombinedOutput (); err != nil {
159+ return fmt .Errorf ("could not resize multipath device: %s (%v)" , output , err )
160+ }
161+
162+ return nil
163+ }
164+
116165// PRIVATE
117166
118167//ReadDir calls the ReadDir function from ioutil package
@@ -174,7 +223,7 @@ func findDeviceForPath(path string, io ioHandler) (string, error) {
174223 return "" , errors .New ("Illegal path for device " + devicePath )
175224}
176225
177- func scsiHostRescan (logger * logr .Logger , io ioHandler ) {
226+ func scsiHostRescan (logger klog .Logger , io ioHandler ) {
178227 scsiPath := "/sys/class/scsi_host/"
179228 logger .V (4 ).Info ("scsi host rescan" , "scsiPath" , scsiPath )
180229 if dirs , err := io .ReadDir (scsiPath ); err == nil {
@@ -187,7 +236,7 @@ func scsiHostRescan(logger *logr.Logger, io ioHandler) {
187236 }
188237}
189238
190- func searchDisk (logger * logr .Logger , c Connector , io ioHandler ) (string , error ) {
239+ func searchDisk (logger klog .Logger , c Connector , io ioHandler ) (string , error ) {
191240 var diskIds []string
192241 var disk string
193242 var dm string
@@ -198,7 +247,10 @@ func searchDisk(logger *logr.Logger, c Connector, io ioHandler) (string, error)
198247 diskIds = c .WWIDs
199248 }
200249
250+ c .Multipath = false
251+
201252 rescaned := false
253+
202254 // two-phase search:
203255 // first phase, search existing device path, if a multipath dm is found, exit loop
204256 // otherwise, in second phase, rescan scsi bus and search again, return with any findings
@@ -234,6 +286,7 @@ func searchDisk(logger *logr.Logger, c Connector, io ioHandler) (string, error)
234286
235287 // if multipath devicemapper device is found, use it; otherwise use raw disk
236288 if dm != "" {
289+ c .Multipath = true
237290 logger .V (1 ).Info ("multipath device was discovered" , "dm" , dm )
238291 return dm , nil
239292 }
@@ -242,8 +295,7 @@ func searchDisk(logger *logr.Logger, c Connector, io ioHandler) (string, error)
242295}
243296
244297// given a wwn and lun, find the device and associated devicemapper parent
245- func findDisk (logger * logr.Logger , wwn , lun string , io ioHandler ) (string , string ) {
246- // FcPath := "-fc-0x" + wwn + "-lun-" + lun
298+ func findDisk (logger klog.Logger , wwn , lun string , io ioHandler ) (string , string ) {
247299 logger .V (4 ).Info ("find disk" , "wwn" , wwn , "lun" , lun )
248300 wwnPath := "wwn-0x" + wwn
249301 DevPath := "/dev/disk/by-id/"
@@ -267,7 +319,7 @@ func findDisk(logger *logr.Logger, wwn, lun string, io ioHandler) (string, strin
267319}
268320
269321// given a wwid, find the device and associated devicemapper parent
270- func findDiskWWIDs (logger * logr .Logger , wwid string , io ioHandler ) (string , string ) {
322+ func findDiskWWIDs (logger klog .Logger , wwid string , io ioHandler ) (string , string ) {
271323 // Example wwid format:
272324 // 3600508b400105e210000900000490000
273325 // <VENDOR NAME> <IDENTIFIER NUMBER>
@@ -319,8 +371,8 @@ func FindSlaveDevicesOnMultipath(dm string, io ioHandler) []string {
319371 return devices
320372}
321373
322- // detachFCDisk removes scsi device file such as /dev/sdX from the node.
323- func detachFCDisk (logger * logr .Logger , devicePath string , io ioHandler ) error {
374+ // detachSasDisk removes scsi device file such as /dev/sdX from the node.
375+ func detachSasDisk (logger klog .Logger , devicePath string , io ioHandler ) error {
324376 // Remove scsi device from the node.
325377 if ! strings .HasPrefix (devicePath , "/dev/" ) {
326378 return fmt .Errorf ("sas detach disk: invalid device name: %s" , devicePath )
@@ -332,7 +384,7 @@ func detachFCDisk(logger *logr.Logger, devicePath string, io ioHandler) error {
332384}
333385
334386// Removes a scsi device based upon /dev/sdX name
335- func removeFromScsiSubsystem (logger * logr .Logger , deviceName string , io ioHandler ) {
387+ func removeFromScsiSubsystem (logger klog .Logger , deviceName string , io ioHandler ) {
336388 fileName := "/sys/block/" + deviceName + "/device/delete"
337389 logger .Info ("sas: remove device from scsi-subsystem" , "path" , fileName )
338390 data := []byte ("1" )
0 commit comments