github.com/gophercloud/gophercloud@v1.11.0/openstack/baremetalintrospection/v1/introspection/results.go (about) 1 package introspection 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "time" 7 8 "github.com/gophercloud/gophercloud" 9 "github.com/gophercloud/gophercloud/pagination" 10 ) 11 12 type introspectionResult struct { 13 gophercloud.Result 14 } 15 16 // Extract interprets any introspectionResult as an Introspection, if possible. 17 func (r introspectionResult) Extract() (*Introspection, error) { 18 var s Introspection 19 err := r.ExtractInto(&s) 20 return &s, err 21 } 22 23 // ExtractInto will extract a response body into an Introspection struct. 24 func (r introspectionResult) ExtractInto(v interface{}) error { 25 return r.Result.ExtractIntoStructPtr(v, "") 26 } 27 28 // ExtractIntrospectionsInto will extract a collection of introspectResult pages into a 29 // slice of Introspection entities. 30 func ExtractIntrospectionsInto(r pagination.Page, v interface{}) error { 31 return r.(IntrospectionPage).Result.ExtractIntoSlicePtr(v, "introspection") 32 } 33 34 // ExtractIntrospections interprets the results of a single page from a 35 // ListIntrospections() call, producing a slice of Introspection entities. 36 func ExtractIntrospections(r pagination.Page) ([]Introspection, error) { 37 var s []Introspection 38 err := ExtractIntrospectionsInto(r, &s) 39 return s, err 40 } 41 42 // IntrospectionPage abstracts the raw results of making a ListIntrospections() 43 // request against the Inspector API. As OpenStack extensions may freely alter 44 // the response bodies of structures returned to the client, you may only safely 45 // access the data provided through the ExtractIntrospections call. 46 type IntrospectionPage struct { 47 pagination.LinkedPageBase 48 } 49 50 // Introspection represents an introspection in the OpenStack Bare Metal Introspector API. 51 type Introspection struct { 52 // Whether introspection is finished 53 Finished bool `json:"finished"` 54 55 // State of the introspection 56 State string `json:"state"` 57 58 // Error message, can be null; "Canceled by operator" in case introspection was aborted 59 Error string `json:"error"` 60 61 // UUID of the introspection 62 UUID string `json:"uuid"` 63 64 // UTC ISO8601 timestamp 65 StartedAt time.Time `json:"-"` 66 67 // UTC ISO8601 timestamp or null 68 FinishedAt time.Time `json:"-"` 69 70 // Link to the introspection URL 71 Links []interface{} `json:"links"` 72 } 73 74 // IsEmpty returns true if a page contains no Introspection results. 75 func (r IntrospectionPage) IsEmpty() (bool, error) { 76 if r.StatusCode == 204 { 77 return true, nil 78 } 79 80 s, err := ExtractIntrospections(r) 81 return len(s) == 0, err 82 } 83 84 // NextPageURL uses the response's embedded link reference to navigate to the 85 // next page of results. 86 func (r IntrospectionPage) NextPageURL() (string, error) { 87 var s struct { 88 Links []gophercloud.Link `json:"introspection_links"` 89 } 90 err := r.ExtractInto(&s) 91 if err != nil { 92 return "", err 93 } 94 return gophercloud.ExtractNextURL(s.Links) 95 } 96 97 // UnmarshalJSON trie to convert values for started_at and finished_at from the 98 // json response into RFC3339 standard. Since Introspection API can remove the 99 // Z from the format, if the conversion fails, it falls back to an RFC3339 100 // with no Z format supported by gophercloud. 101 func (r *Introspection) UnmarshalJSON(b []byte) error { 102 type tmp Introspection 103 var s struct { 104 tmp 105 StartedAt string `json:"started_at"` 106 FinishedAt string `json:"finished_at"` 107 } 108 109 err := json.Unmarshal(b, &s) 110 if err != nil { 111 return err 112 } 113 114 *r = Introspection(s.tmp) 115 116 if s.StartedAt != "" { 117 t, err := time.Parse(time.RFC3339, s.StartedAt) 118 if err != nil { 119 t, err = time.Parse(gophercloud.RFC3339NoZ, s.StartedAt) 120 if err != nil { 121 return err 122 } 123 } 124 r.StartedAt = t 125 } 126 127 if s.FinishedAt != "" { 128 t, err := time.Parse(time.RFC3339, s.FinishedAt) 129 if err != nil { 130 t, err = time.Parse(gophercloud.RFC3339NoZ, s.FinishedAt) 131 if err != nil { 132 return err 133 } 134 } 135 r.FinishedAt = t 136 } 137 138 return nil 139 } 140 141 // GetIntrospectionStatusResult is the response from a GetIntrospectionStatus operation. 142 // Call its Extract method to interpret it as an Introspection. 143 type GetIntrospectionStatusResult struct { 144 introspectionResult 145 } 146 147 // StartResult is the response from a StartIntrospection operation. 148 // Call its ExtractErr method to determine if the call succeeded or failed. 149 type StartResult struct { 150 gophercloud.ErrResult 151 } 152 153 // AbortResult is the response from an AbortIntrospection operation. 154 // Call its ExtractErr method to determine if the call succeeded or failed. 155 type AbortResult struct { 156 gophercloud.ErrResult 157 } 158 159 // Data represents the full introspection data collected. 160 // The format and contents of the stored data depends on the ramdisk used 161 // and plugins enabled both in the ramdisk and in inspector itself. 162 // This structure has been provided for basic compatibility but it 163 // will need extensions 164 type Data struct { 165 AllInterfaces map[string]BaseInterfaceType `json:"all_interfaces"` 166 BootInterface string `json:"boot_interface"` 167 CPUArch string `json:"cpu_arch"` 168 CPUs int `json:"cpus"` 169 Error string `json:"error"` 170 Interfaces map[string]BaseInterfaceType `json:"interfaces"` 171 Inventory InventoryType `json:"inventory"` 172 IPMIAddress string `json:"ipmi_address"` 173 LocalGB int `json:"local_gb"` 174 MACs []string `json:"macs"` 175 MemoryMB int `json:"memory_mb"` 176 RootDisk RootDiskType `json:"root_disk"` 177 Extra ExtraHardwareDataType `json:"extra"` 178 NUMATopology NUMATopology `json:"numa_topology"` 179 RawLLDP map[string][]LLDPTLVType `json:"lldp_raw"` 180 } 181 182 // Sub Types defined under Data and deeper in the structure 183 184 type BaseInterfaceType struct { 185 ClientID string `json:"client_id"` 186 IP string `json:"ip"` 187 MAC string `json:"mac"` 188 PXE bool `json:"pxe"` 189 LLDPProcessed map[string]interface{} `json:"lldp_processed"` 190 } 191 192 type BootInfoType struct { 193 CurrentBootMode string `json:"current_boot_mode"` 194 PXEInterface string `json:"pxe_interface"` 195 } 196 197 type CPUType struct { 198 Architecture string `json:"architecture"` 199 Count int `json:"count"` 200 Flags []string `json:"flags"` 201 Frequency string `json:"frequency"` 202 ModelName string `json:"model_name"` 203 } 204 205 type LLDPTLVType struct { 206 Type int 207 Value string 208 } 209 210 type InterfaceType struct { 211 BIOSDevName string `json:"biosdevname"` 212 ClientID string `json:"client_id"` 213 HasCarrier bool `json:"has_carrier"` 214 IPV4Address string `json:"ipv4_address"` 215 IPV6Address string `json:"ipv6_address"` 216 // Deprecated, see Data.RawLLDP 217 LLDP []LLDPTLVType `json:"lldp"` 218 MACAddress string `json:"mac_address"` 219 Name string `json:"name"` 220 Product string `json:"product"` 221 SpeedMbps int `json:"speed_mbps"` 222 Vendor string `json:"vendor"` 223 } 224 225 type InventoryType struct { 226 BmcAddress string `json:"bmc_address"` 227 Boot BootInfoType `json:"boot"` 228 CPU CPUType `json:"cpu"` 229 Disks []RootDiskType `json:"disks"` 230 Interfaces []InterfaceType `json:"interfaces"` 231 Memory MemoryType `json:"memory"` 232 SystemVendor SystemVendorType `json:"system_vendor"` 233 Hostname string `json:"hostname"` 234 } 235 236 type MemoryType struct { 237 PhysicalMb int `json:"physical_mb"` 238 Total int `json:"total"` 239 } 240 241 type RootDiskType struct { 242 Hctl string `json:"hctl"` 243 Model string `json:"model"` 244 Name string `json:"name"` 245 ByPath string `json:"by_path"` 246 Rotational bool `json:"rotational"` 247 Serial string `json:"serial"` 248 Size int64 `json:"size"` 249 Vendor string `json:"vendor"` 250 Wwn string `json:"wwn"` 251 WwnVendorExtension string `json:"wwn_vendor_extension"` 252 WwnWithExtension string `json:"wwn_with_extension"` 253 } 254 255 type SystemFirmwareType struct { 256 Version string `json:"version"` 257 BuildDate string `json:"build_date"` 258 Vendor string `json:"vendor"` 259 } 260 261 type SystemVendorType struct { 262 Manufacturer string `json:"manufacturer"` 263 ProductName string `json:"product_name"` 264 SerialNumber string `json:"serial_number"` 265 Firmware SystemFirmwareType `json:"firmware"` 266 } 267 268 type ExtraHardwareData map[string]interface{} 269 270 type ExtraHardwareDataSection map[string]ExtraHardwareData 271 272 type ExtraHardwareDataType struct { 273 CPU ExtraHardwareDataSection `json:"cpu"` 274 Disk ExtraHardwareDataSection `json:"disk"` 275 Firmware ExtraHardwareDataSection `json:"firmware"` 276 IPMI ExtraHardwareDataSection `json:"ipmi"` 277 Memory ExtraHardwareDataSection `json:"memory"` 278 Network ExtraHardwareDataSection `json:"network"` 279 System ExtraHardwareDataSection `json:"system"` 280 } 281 282 type NUMATopology struct { 283 CPUs []NUMACPU `json:"cpus"` 284 NICs []NUMANIC `json:"nics"` 285 RAM []NUMARAM `json:"ram"` 286 } 287 288 type NUMACPU struct { 289 CPU int `json:"cpu"` 290 NUMANode int `json:"numa_node"` 291 ThreadSiblings []int `json:"thread_siblings"` 292 } 293 294 type NUMANIC struct { 295 Name string `json:"name"` 296 NUMANode int `json:"numa_node"` 297 } 298 299 type NUMARAM struct { 300 NUMANode int `json:"numa_node"` 301 SizeKB int `json:"size_kb"` 302 } 303 304 // UnmarshalJSON interprets an LLDP TLV [key, value] pair as an LLDPTLVType structure 305 func (r *LLDPTLVType) UnmarshalJSON(data []byte) error { 306 var list []interface{} 307 if err := json.Unmarshal(data, &list); err != nil { 308 return err 309 } 310 311 if len(list) != 2 { 312 return fmt.Errorf("Invalid LLDP TLV key-value pair") 313 } 314 315 fieldtype, ok := list[0].(float64) 316 if !ok { 317 return fmt.Errorf("LLDP TLV key is not number") 318 } 319 320 value, ok := list[1].(string) 321 if !ok { 322 return fmt.Errorf("LLDP TLV value is not string") 323 } 324 325 r.Type = int(fieldtype) 326 r.Value = value 327 return nil 328 } 329 330 // Extract interprets any IntrospectionDataResult as IntrospectionData, if possible. 331 func (r DataResult) Extract() (*Data, error) { 332 var s Data 333 err := r.ExtractInto(&s) 334 return &s, err 335 } 336 337 // DataResult represents the response from a GetIntrospectionData operation. 338 // Call its Extract method to interpret it as a Data. 339 type DataResult struct { 340 gophercloud.Result 341 } 342 343 // ApplyDataResult is the response from an ApplyData operation. 344 // Call its ExtractErr method to determine if the call succeeded or failed. 345 type ApplyDataResult struct { 346 gophercloud.ErrResult 347 }