55 "fmt"
66 "io"
77 "os"
8+ "os/exec"
9+ "path/filepath"
810 "strconv"
911 "strings"
1012
@@ -21,15 +23,18 @@ import (
2123)
2224
2325const (
24- ospHostMetaDataDir = "/host/var/config/openstack/2018-08-27"
25- ospMetaDataDir = "/var/config/openstack/2018-08-27"
26- ospMetaDataBaseURL = "http://169.254.169.254/openstack/2018-08-27"
27- ospNetworkDataJSON = "network_data.json"
28- ospMetaDataJSON = "meta_data.json"
29- ospHostNetworkDataFile = ospHostMetaDataDir + "/" + ospNetworkDataJSON
30- ospHostMetaDataFile = ospHostMetaDataDir + "/" + ospMetaDataJSON
31- ospNetworkDataURL = ospMetaDataBaseURL + "/" + ospNetworkDataJSON
32- ospMetaDataURL = ospMetaDataBaseURL + "/" + ospMetaDataJSON
26+ varConfigPath = "/var/config"
27+ ospMetaDataBaseDir = "/openstack/2018-08-27"
28+ ospMetaDataDir = varConfigPath + ospMetaDataBaseDir
29+ ospMetaDataBaseURL = "http://169.254.169.254" + ospMetaDataBaseDir
30+ ospNetworkDataJSON = "network_data.json"
31+ ospMetaDataJSON = "meta_data.json"
32+ ospNetworkDataURL = ospMetaDataBaseURL + "/" + ospNetworkDataJSON
33+ ospMetaDataURL = ospMetaDataBaseURL + "/" + ospMetaDataJSON
34+ // Config drive is defined as an iso9660 or vfat (deprecated) drive
35+ // with the "config-2" label.
36+ //https://docs.openstack.org/nova/latest/user/config-drive.html
37+ configDriveLabel = "config-2"
3338)
3439
3540var (
@@ -109,9 +114,10 @@ func New(hostManager host.HostManagerInterface) OpenstackInterface {
109114}
110115
111116// GetOpenstackData gets the metadata and network_data
112- func getOpenstackData (useHostPath bool ) (metaData * OSPMetaData , networkData * OSPNetworkData , err error ) {
113- metaData , networkData , err = getOpenstackDataFromConfigDrive (useHostPath )
117+ func getOpenstackData (mountConfigDrive bool ) (metaData * OSPMetaData , networkData * OSPNetworkData , err error ) {
118+ metaData , networkData , err = getOpenstackDataFromConfigDrive (mountConfigDrive )
114119 if err != nil {
120+ log .Log .Error (err , "GetOpenStackData(): non-fatal error getting OpenStack data from config drive" )
115121 metaData , networkData , err = getOpenstackDataFromMetadataService ()
116122 if err != nil {
117123 return metaData , networkData , fmt .Errorf ("GetOpenStackData(): error getting OpenStack data: %w" , err )
@@ -153,46 +159,109 @@ func getOpenstackData(useHostPath bool) (metaData *OSPMetaData, networkData *OSP
153159 return metaData , networkData , err
154160}
155161
162+ // getConfigDriveDevice returns the config drive device which was found
163+ func getConfigDriveDevice () (string , error ) {
164+ dev := "/dev/disk/by-label/" + configDriveLabel
165+ if _ , err := os .Stat (dev ); os .IsNotExist (err ) {
166+ out , err := exec .Command (
167+ "blkid" , "-l" ,
168+ "-t" , "LABEL=" + configDriveLabel ,
169+ "-o" , "device" ,
170+ ).CombinedOutput ()
171+ if err != nil {
172+ return "" , fmt .Errorf ("unable to run blkid: %v" , err )
173+ }
174+ dev = strings .TrimSpace (string (out ))
175+ }
176+ log .Log .Info ("found config drive device" , "device" , dev )
177+ return dev , nil
178+ }
179+
180+ // mountConfigDriveDevice mounts the config drive and return the path
181+ func mountConfigDriveDevice (device string ) (string , error ) {
182+ if device == "" {
183+ return "" , fmt .Errorf ("device is empty" )
184+ }
185+ tmpDir , err := os .MkdirTemp ("" , "sriov-configdrive" )
186+ if err != nil {
187+ return "" , fmt .Errorf ("error creating temp directory: %w" , err )
188+ }
189+ cmd := exec .Command ("mount" , "-o" , "ro" , "-t" , "auto" , device , tmpDir )
190+ if err := cmd .Run (); err != nil {
191+ return "" , fmt .Errorf ("error mounting config drive: %w" , err )
192+ }
193+ log .Log .V (2 ).Info ("mounted config drive device" , "device" , device , "path" , tmpDir )
194+ return tmpDir , nil
195+ }
196+
197+ // ummountConfigDriveDevice ummounts the config drive device
198+ func ummountConfigDriveDevice (path string ) error {
199+ if path == "" {
200+ return fmt .Errorf ("path is empty" )
201+ }
202+ cmd := exec .Command ("umount" , path )
203+ if err := cmd .Run (); err != nil {
204+ return fmt .Errorf ("error umounting config drive: %w" , err )
205+ }
206+ log .Log .V (2 ).Info ("umounted config drive" , "path" , path )
207+ return nil
208+ }
209+
156210// getOpenstackDataFromConfigDrive reads the meta_data and network_data files
157- func getOpenstackDataFromConfigDrive (useHostPath bool ) (metaData * OSPMetaData , networkData * OSPNetworkData , err error ) {
211+ func getOpenstackDataFromConfigDrive (mountConfigDrive bool ) (metaData * OSPMetaData , networkData * OSPNetworkData , err error ) {
158212 metaData = & OSPMetaData {}
159213 networkData = & OSPNetworkData {}
214+ var configDrivePath string
160215 log .Log .Info ("reading OpenStack meta_data from config-drive" )
161216 var metadataf * os.File
162217 ospMetaDataFilePath := ospMetaDataFile
163- if useHostPath {
164- ospMetaDataFilePath = ospHostMetaDataFile
218+ if mountConfigDrive {
219+ configDriveDevice , err := getConfigDriveDevice ()
220+ if err != nil {
221+ return metaData , networkData , fmt .Errorf ("error finding config drive device: %w" , err )
222+ }
223+ configDrivePath , err = mountConfigDriveDevice (configDriveDevice )
224+ if err != nil {
225+ return metaData , networkData , fmt .Errorf ("error mounting config drive device: %w" , err )
226+ }
227+ defer func () {
228+ if e := ummountConfigDriveDevice (configDrivePath ); err == nil && e != nil {
229+ err = fmt .Errorf ("error umounting config drive device: %w" , e )
230+ }
231+ if e := os .Remove (configDrivePath ); err == nil && e != nil {
232+ err = fmt .Errorf ("error removing temp directory %s: %w" , configDrivePath , e )
233+ }
234+ }()
235+ ospMetaDataFilePath = filepath .Join (configDrivePath , ospMetaDataBaseDir , ospMetaDataJSON )
236+ ospNetworkDataFile = filepath .Join (configDrivePath , ospMetaDataBaseDir , ospNetworkDataJSON )
165237 }
166238 metadataf , err = os .Open (ospMetaDataFilePath )
167239 if err != nil {
168- return metaData , networkData , fmt .Errorf ("error opening file %s: %w" , ospHostMetaDataFile , err )
240+ return metaData , networkData , fmt .Errorf ("error opening file %s: %w" , ospMetaDataFilePath , err )
169241 }
170242 defer func () {
171243 if e := metadataf .Close (); err == nil && e != nil {
172- err = fmt .Errorf ("error closing file %s: %w" , ospHostMetaDataFile , e )
244+ err = fmt .Errorf ("error closing file %s: %w" , ospMetaDataFilePath , e )
173245 }
174246 }()
175247 if err = json .NewDecoder (metadataf ).Decode (& metaData ); err != nil {
176- return metaData , networkData , fmt .Errorf ("error unmarshalling metadata from file %s: %w" , ospHostMetaDataFile , err )
248+ return metaData , networkData , fmt .Errorf ("error unmarshalling metadata from file %s: %w" , ospMetaDataFilePath , err )
177249 }
178250
179251 log .Log .Info ("reading OpenStack network_data from config-drive" )
180252 var networkDataf * os.File
181253 ospNetworkDataFilePath := ospNetworkDataFile
182- if useHostPath {
183- ospNetworkDataFilePath = ospHostNetworkDataFile
184- }
185254 networkDataf , err = os .Open (ospNetworkDataFilePath )
186255 if err != nil {
187- return metaData , networkData , fmt .Errorf ("error opening file %s: %w" , ospHostNetworkDataFile , err )
256+ return metaData , networkData , fmt .Errorf ("error opening file %s: %w" , ospNetworkDataFilePath , err )
188257 }
189258 defer func () {
190259 if e := networkDataf .Close (); err == nil && e != nil {
191- err = fmt .Errorf ("error closing file %s: %w" , ospHostNetworkDataFile , e )
260+ err = fmt .Errorf ("error closing file %s: %w" , ospNetworkDataFilePath , e )
192261 }
193262 }()
194263 if err = json .NewDecoder (networkDataf ).Decode (& networkData ); err != nil {
195- return metaData , networkData , fmt .Errorf ("error unmarshalling metadata from file %s: %w" , ospHostNetworkDataFile , err )
264+ return metaData , networkData , fmt .Errorf ("error unmarshalling metadata from file %s: %w" , ospNetworkDataFilePath , err )
196265 }
197266 return metaData , networkData , err
198267}
0 commit comments