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  }