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  }