@@ -33,33 +33,45 @@ import (
3333)
3434
3535const (
36- // metadataUrl is URL to OpenStack metadata server. It's hardcoded IPv4
37- // link-local address as documented in "OpenStack Cloud Administrator Guide",
38- // chapter Compute - Networking with nova-network.
36+ // metadataUrlTemplate allows building an OpenStack Metadata service URL.
37+ // It's a hardcoded IPv4 link-local address as documented in "OpenStack Cloud
38+ // Administrator Guide", chapter Compute - Networking with nova-network.
3939 // https://docs.openstack.org/admin-guide/compute-networking-nova.html#metadata-service
40- metadataUrl = "http://169.254.169.254/openstack/2012-08-10/meta_data.json"
40+ defaultMetadataVersion = "2012-08-10"
41+ metadataUrlTemplate = "http://169.254.169.254/openstack/%s/meta_data.json"
4142
4243 // metadataID is used as an identifier on the metadata search order configuration.
4344 metadataID = "metadataService"
4445
4546 // Config drive is defined as an iso9660 or vfat (deprecated) drive
4647 // with the "config-2" label.
4748 // http://docs.openstack.org/user-guide/cli-config-drive.html
48- configDriveLabel = "config-2"
49- configDrivePath = "openstack/2012-08-10 /meta_data.json"
49+ configDriveLabel = "config-2"
50+ configDrivePathTemplate = "openstack/%s /meta_data.json"
5051
5152 // configDriveID is used as an identifier on the metadata search order configuration.
5253 configDriveID = "configDrive"
5354)
5455
55- var ErrBadMetadata = errors .New ("Invalid OpenStack metadata, got empty uuid" )
56+ var ErrBadMetadata = errors .New ("invalid OpenStack metadata, got empty uuid" )
57+
58+ // There are multiple device types. To keep it simple, we're using a single structure
59+ // for all device metadata types.
60+ type DeviceMetadata struct {
61+ Type string `json:"type"`
62+ Bus string `json:"bus,omitempty"`
63+ Serial string `json:"serial,omitempty"`
64+ Address string `json:"address,omitempty"`
65+ // .. and other fields.
66+ }
5667
5768// Assumes the "2012-08-10" meta_data.json format.
5869// See http://docs.openstack.org/user-guide/cli_config_drive.html
5970type Metadata struct {
60- Uuid string `json:"uuid"`
61- Name string `json:"name"`
62- AvailabilityZone string `json:"availability_zone"`
71+ Uuid string `json:"uuid"`
72+ Name string `json:"name"`
73+ AvailabilityZone string `json:"availability_zone"`
74+ Devices []DeviceMetadata `json:"devices,omitempty"`
6375 // .. and other fields we don't care about. Expand as necessary.
6476}
6577
@@ -79,7 +91,15 @@ func parseMetadata(r io.Reader) (*Metadata, error) {
7991 return & metadata , nil
8092}
8193
82- func getMetadataFromConfigDrive () (* Metadata , error ) {
94+ func getMetadataUrl (metadataVersion string ) string {
95+ return fmt .Sprintf (metadataUrlTemplate , metadataVersion )
96+ }
97+
98+ func getConfigDrivePath (metadataVersion string ) string {
99+ return fmt .Sprintf (configDrivePathTemplate , metadataVersion )
100+ }
101+
102+ func getMetadataFromConfigDrive (metadataVersion string ) (* Metadata , error ) {
83103 // Try to read instance UUID from config drive.
84104 dev := "/dev/disk/by-label/" + configDriveLabel
85105 if _ , err := os .Stat (dev ); os .IsNotExist (err ) {
@@ -89,8 +109,7 @@ func getMetadataFromConfigDrive() (*Metadata, error) {
89109 "-o" , "device" ,
90110 ).CombinedOutput ()
91111 if err != nil {
92- glog .V (2 ).Infof ("Unable to run blkid: %v" , err )
93- return nil , err
112+ return nil , fmt .Errorf ("unable to run blkid: %v" , err )
94113 }
95114 dev = strings .TrimSpace (string (out ))
96115 }
@@ -109,37 +128,35 @@ func getMetadataFromConfigDrive() (*Metadata, error) {
109128 err = mounter .Mount (dev , mntdir , "vfat" , []string {"ro" })
110129 }
111130 if err != nil {
112- glog .Errorf ("Error mounting configdrive %s: %v" , dev , err )
113- return nil , err
131+ return nil , fmt .Errorf ("error mounting configdrive %s: %v" , dev , err )
114132 }
115133 defer mounter .Unmount (mntdir )
116134
117135 glog .V (4 ).Infof ("Configdrive mounted on %s" , mntdir )
118136
137+ configDrivePath := getConfigDrivePath (metadataVersion )
119138 f , err := os .Open (
120139 filepath .Join (mntdir , configDrivePath ))
121140 if err != nil {
122- glog .Errorf ("Error reading %s on config drive: %v" , configDrivePath , err )
123- return nil , err
141+ return nil , fmt .Errorf ("error reading %s on config drive: %v" , configDrivePath , err )
124142 }
125143 defer f .Close ()
126144
127145 return parseMetadata (f )
128146}
129147
130- func getMetadataFromMetadataService () (* Metadata , error ) {
131- // Try to get JSON from metdata server.
148+ func getMetadataFromMetadataService (metadataVersion string ) (* Metadata , error ) {
149+ // Try to get JSON from metadata server.
150+ metadataUrl := getMetadataUrl (metadataVersion )
132151 glog .V (4 ).Infof ("Attempting to fetch metadata from %s" , metadataUrl )
133152 resp , err := http .Get (metadataUrl )
134153 if err != nil {
135- glog .V (3 ).Infof ("Cannot read %s: %v" , metadataUrl , err )
136- return nil , err
154+ return nil , fmt .Errorf ("error fetching %s: %v" , metadataUrl , err )
137155 }
138156 defer resp .Body .Close ()
139157
140158 if resp .StatusCode != http .StatusOK {
141- err = fmt .Errorf ("Unexpected status code when reading metadata from %s: %s" , metadataUrl , resp .Status )
142- glog .V (3 ).Infof ("%v" , err )
159+ err = fmt .Errorf ("unexpected status code when reading metadata from %s: %s" , metadataUrl , resp .Status )
143160 return nil , err
144161 }
145162
@@ -159,9 +176,9 @@ func getMetadata(order string) (*Metadata, error) {
159176 id = strings .TrimSpace (id )
160177 switch id {
161178 case configDriveID :
162- md , err = getMetadataFromConfigDrive ()
179+ md , err = getMetadataFromConfigDrive (defaultMetadataVersion )
163180 case metadataID :
164- md , err = getMetadataFromMetadataService ()
181+ md , err = getMetadataFromMetadataService (defaultMetadataVersion )
165182 default :
166183 err = fmt .Errorf ("%s is not a valid metadata search order option. Supported options are %s and %s" , id , configDriveID , metadataID )
167184 }
0 commit comments