github.com/leeclow-ops/gophercloud@v1.2.1/openstack/baremetalintrospection/v1/introspection/results.go (about) 1 package introspection 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "time" 7 8 "github.com/leeclow-ops/gophercloud" 9 "github.com/leeclow-ops/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 } 180 181 // Sub Types defined under Data and deeper in the structure 182 183 type BaseInterfaceType struct { 184 ClientID string `json:"client_id"` 185 IP string `json:"ip"` 186 MAC string `json:"mac"` 187 PXE bool `json:"pxe"` 188 LLDPProcessed map[string]interface{} `json:"lldp_processed"` 189 } 190 191 type BootInfoType struct { 192 CurrentBootMode string `json:"current_boot_mode"` 193 PXEInterface string `json:"pxe_interface"` 194 } 195 196 type CPUType struct { 197 Architecture string `json:"architecture"` 198 Count int `json:"count"` 199 Flags []string `json:"flags"` 200 Frequency string `json:"frequency"` 201 ModelName string `json:"model_name"` 202 } 203 204 type LLDPTLVType struct { 205 Type int 206 Value string 207 } 208 209 type InterfaceType struct { 210 BIOSDevName string `json:"biosdevname"` 211 ClientID string `json:"client_id"` 212 HasCarrier bool `json:"has_carrier"` 213 IPV4Address string `json:"ipv4_address"` 214 IPV6Address string `json:"ipv6_address"` 215 LLDP []LLDPTLVType `json:"lldp"` 216 MACAddress string `json:"mac_address"` 217 Name string `json:"name"` 218 Product string `json:"product"` 219 Vendor string `json:"vendor"` 220 } 221 222 type InventoryType struct { 223 BmcAddress string `json:"bmc_address"` 224 Boot BootInfoType `json:"boot"` 225 CPU CPUType `json:"cpu"` 226 Disks []RootDiskType `json:"disks"` 227 Interfaces []InterfaceType `json:"interfaces"` 228 Memory MemoryType `json:"memory"` 229 SystemVendor SystemVendorType `json:"system_vendor"` 230 Hostname string `json:"hostname"` 231 } 232 233 type MemoryType struct { 234 PhysicalMb int `json:"physical_mb"` 235 Total int `json:"total"` 236 } 237 238 type RootDiskType struct { 239 Hctl string `json:"hctl"` 240 Model string `json:"model"` 241 Name string `json:"name"` 242 ByPath string `json:"by_path"` 243 Rotational bool `json:"rotational"` 244 Serial string `json:"serial"` 245 Size int64 `json:"size"` 246 Vendor string `json:"vendor"` 247 Wwn string `json:"wwn"` 248 WwnVendorExtension string `json:"wwn_vendor_extension"` 249 WwnWithExtension string `json:"wwn_with_extension"` 250 } 251 252 type SystemVendorType struct { 253 Manufacturer string `json:"manufacturer"` 254 ProductName string `json:"product_name"` 255 SerialNumber string `json:"serial_number"` 256 } 257 258 type ExtraHardwareData map[string]interface{} 259 260 type ExtraHardwareDataSection map[string]ExtraHardwareData 261 262 type ExtraHardwareDataType struct { 263 CPU ExtraHardwareDataSection `json:"cpu"` 264 Disk ExtraHardwareDataSection `json:"disk"` 265 Firmware ExtraHardwareDataSection `json:"firmware"` 266 IPMI ExtraHardwareDataSection `json:"ipmi"` 267 Memory ExtraHardwareDataSection `json:"memory"` 268 Network ExtraHardwareDataSection `json:"network"` 269 System ExtraHardwareDataSection `json:"system"` 270 } 271 272 type NUMATopology struct { 273 CPUs []NUMACPU `json:"cpus"` 274 NICs []NUMANIC `json:"nics"` 275 RAM []NUMARAM `json:"ram"` 276 } 277 278 type NUMACPU struct { 279 CPU int `json:"cpu"` 280 NUMANode int `json:"numa_node"` 281 ThreadSiblings []int `json:"thread_siblings"` 282 } 283 284 type NUMANIC struct { 285 Name string `json:"name"` 286 NUMANode int `json:"numa_node"` 287 } 288 289 type NUMARAM struct { 290 NUMANode int `json:"numa_node"` 291 SizeKB int `json:"size_kb"` 292 } 293 294 // UnmarshalJSON interprets an LLDP TLV [key, value] pair as an LLDPTLVType structure 295 func (r *LLDPTLVType) UnmarshalJSON(data []byte) error { 296 var list []interface{} 297 if err := json.Unmarshal(data, &list); err != nil { 298 return err 299 } 300 301 if len(list) != 2 { 302 return fmt.Errorf("Invalid LLDP TLV key-value pair") 303 } 304 305 fieldtype, ok := list[0].(float64) 306 if !ok { 307 return fmt.Errorf("LLDP TLV key is not number") 308 } 309 310 value, ok := list[1].(string) 311 if !ok { 312 return fmt.Errorf("LLDP TLV value is not string") 313 } 314 315 r.Type = int(fieldtype) 316 r.Value = value 317 return nil 318 } 319 320 // Extract interprets any IntrospectionDataResult as IntrospectionData, if possible. 321 func (r DataResult) Extract() (*Data, error) { 322 var s Data 323 err := r.ExtractInto(&s) 324 return &s, err 325 } 326 327 // DataResult represents the response from a GetIntrospectionData operation. 328 // Call its Extract method to interpret it as a Data. 329 type DataResult struct { 330 gophercloud.Result 331 } 332 333 // ApplyDataResult is the response from an ApplyData operation. 334 // Call its ExtractErr method to determine if the call succeeded or failed. 335 type ApplyDataResult struct { 336 gophercloud.ErrResult 337 }