@@ -100,13 +100,18 @@ type RouterOpts struct {
100100 RouterId string `gcfg:"router-id"` // required
101101}
102102
103+ type MetadataOpts struct {
104+ SearchOrder string `gcfg:"search-order"`
105+ }
106+
103107// OpenStack is an implementation of cloud provider Interface for OpenStack.
104108type OpenStack struct {
105- provider * gophercloud.ProviderClient
106- region string
107- lbOpts LoadBalancerOpts
108- bsOpts BlockStorageOpts
109- routeOpts RouterOpts
109+ provider * gophercloud.ProviderClient
110+ region string
111+ lbOpts LoadBalancerOpts
112+ bsOpts BlockStorageOpts
113+ routeOpts RouterOpts
114+ metadataOpts MetadataOpts
110115 // InstanceID of the server where this OpenStack object is instantiated.
111116 localInstanceID string
112117}
@@ -128,6 +133,7 @@ type Config struct {
128133 LoadBalancer LoadBalancerOpts
129134 BlockStorage BlockStorageOpts
130135 Route RouterOpts
136+ Metadata MetadataOpts
131137}
132138
133139func init () {
@@ -181,6 +187,7 @@ func readConfig(config io.Reader) (Config, error) {
181187 // Set default values for config params
182188 cfg .BlockStorage .BSVersion = "auto"
183189 cfg .BlockStorage .TrustDevicePath = false
190+ cfg .Metadata .SearchOrder = fmt .Sprintf ("%s,%s" , configDriveID , metadataID )
184191
185192 err := gcfg .ReadInto (& cfg , config )
186193 return cfg , err
@@ -198,7 +205,7 @@ func (c *Caller) Call(f func()) {
198205 }
199206}
200207
201- func readInstanceID () (string , error ) {
208+ func readInstanceID (searchOrder string ) (string , error ) {
202209 // Try to find instance ID on the local filesystem (created by cloud-init)
203210 const instanceIDFile = "/var/lib/cloud/data/instance-id"
204211 idBytes , err := ioutil .ReadFile (instanceIDFile )
@@ -212,7 +219,7 @@ func readInstanceID() (string, error) {
212219 // Fall through to metadata server lookup
213220 }
214221
215- md , err := getMetadata ()
222+ md , err := getMetadata (searchOrder )
216223 if err != nil {
217224 return "" , err
218225 }
@@ -275,16 +282,19 @@ func newOpenStack(cfg Config) (*OpenStack, error) {
275282 err = openstack .Authenticate (provider , cfg .toAuthOptions ())
276283 }
277284
285+ err = validateMetadataSearchOrder (cfg .Metadata .SearchOrder )
286+
278287 if err != nil {
279288 return nil , err
280289 }
281290
282291 os := OpenStack {
283- provider : provider ,
284- region : cfg .Global .Region ,
285- lbOpts : cfg .LoadBalancer ,
286- bsOpts : cfg .BlockStorage ,
287- routeOpts : cfg .Route ,
292+ provider : provider ,
293+ region : cfg .Global .Region ,
294+ lbOpts : cfg .LoadBalancer ,
295+ bsOpts : cfg .BlockStorage ,
296+ routeOpts : cfg .Route ,
297+ metadataOpts : cfg .Metadata ,
288298 }
289299
290300 err = checkOpenStackOpts (& os )
@@ -539,7 +549,7 @@ func (os *OpenStack) Zones() (cloudprovider.Zones, bool) {
539549}
540550
541551func (os * OpenStack ) GetZone () (cloudprovider.Zone , error ) {
542- md , err := getMetadata ()
552+ md , err := getMetadata (os . metadataOpts . SearchOrder )
543553 if err != nil {
544554 return cloudprovider.Zone {}, err
545555 }
@@ -742,3 +752,27 @@ func (os *OpenStack) volumeService(forceVersion string) (volumeService, error) {
742752 return nil , errors .New (err_txt )
743753 }
744754}
755+
756+ func validateMetadataSearchOrder (order string ) error {
757+ if order == "" {
758+ return errors .New ("Invalid value in section [Metadata] with key `search-order`. Value cannot be empty" )
759+ }
760+
761+ elements := strings .Split (order , "," )
762+ if len (elements ) > 2 {
763+ return errors .New ("Invalid value in section [Metadata] with key `search-order`. Value cannot contain more than 2 elements" )
764+ }
765+
766+ for _ , o := range elements {
767+ switch o {
768+ case configDriveID :
769+ case metadataID :
770+ default :
771+ errTxt := "Invalid element '%s' found in section [Metadata] with key `search-order`." +
772+ "Supported elements include '%s' and '%s'"
773+ return fmt .Errorf (errTxt , o , configDriveID , metadataID )
774+ }
775+ }
776+
777+ return nil
778+ }
0 commit comments