test build
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-09-28 11:55:15 +10:00
parent 46f151f599
commit 95a48a89a6
25 changed files with 2358 additions and 12 deletions

2
go.mod
View File

@@ -19,3 +19,5 @@ require (
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect google.golang.org/protobuf v1.30.0 // indirect
) )
replace github.com/dnaeon/go-ucs => ./local/go-ucs

View File

@@ -15,13 +15,14 @@ type UcsmTemperaturesCollector struct {
ctx context.Context ctx context.Context
} }
/*
type ComputeMbTempStats struct { type ComputeMbTempStats struct {
XMLName xml.Name `xml:"computeMbTempStats"` XMLName xml.Name `xml:"computeMbTempStats"`
Dn string `xml:"dn,attr,omitempty"` Dn string `xml:"dn,attr,omitempty"`
FmTempSenIo string `xml:"fmTempSenIo,attr,omitempty"` FmTempSenIo string `xml:"fmTempSenIo,attr,omitempty"`
FmTempSenRear string `xml:"fmTempSenRear,attr,omitempty"` FmTempSenRear string `xml:"fmTempSenRear,attr,omitempty"`
} }
*/
func NewUcsmTemperatureCollector(client *api.Client, ctx context.Context) *UcsmTemperaturesCollector { func NewUcsmTemperatureCollector(client *api.Client, ctx context.Context) *UcsmTemperaturesCollector {
return &UcsmTemperaturesCollector{ return &UcsmTemperaturesCollector{
ucsClient: client, ucsClient: client,
@@ -52,7 +53,7 @@ func (u *UcsmTemperaturesCollector) Collect(ch chan<- prometheus.Metric) {
type temps struct { type temps struct {
XMLName xml.Name XMLName xml.Name
Temperatures []ComputeMbTempStats `xml:"computeMbTempStats"` Temperatures []mo.ComputeMbTempStats `xml:"computeMbTempStats"`
} }
bladeRequest := api.ConfigResolveClassRequest{ bladeRequest := api.ConfigResolveClassRequest{
@@ -74,6 +75,7 @@ func (u *UcsmTemperaturesCollector) Collect(ch chan<- prometheus.Metric) {
log.Printf("%s:\n", blade.Dn) log.Printf("%s:\n", blade.Dn)
boardDn := "^" + blade.Dn + "/board/" boardDn := "^" + blade.Dn + "/board/"
//boardDn := blade.Dn + "/board/"
log.Printf("%s:\n", boardDn) log.Printf("%s:\n", boardDn)
log.Printf("\tNumber of CPUs: %d\n", blade.NumOfCpus) log.Printf("\tNumber of CPUs: %d\n", blade.NumOfCpus)
@@ -100,10 +102,12 @@ func (u *UcsmTemperaturesCollector) Collect(ch chan<- prometheus.Metric) {
var tempList temps var tempList temps
log.Printf("Retrieving temperatures for this blade\n") log.Printf("Retrieving temperatures for this blade\n")
/*
if err := u.ucsClient.ConfigResolveClass(u.ctx, tempReq, &tempList); err != nil { if err := u.ucsClient.ConfigResolveClass(u.ctx, tempReq, &tempList); err != nil {
log.Fatalf("Unable to retrieve `computeMbTempStats` managed object: %s", err) log.Fatalf("Unable to retrieve `computeMbTempStats` managed object: %s", err)
} }
*/
u.ucsClient.ConfigResolveClass(u.ctx, tempReq, &tempList)
log.Printf("Front Temperature: %v\n", tempList) log.Printf("Front Temperature: %v\n", tempList)
} }

30
local/go-ucs/.gitignore vendored Normal file
View File

@@ -0,0 +1,30 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
# Ignore Emacs backup files
*~
# Vim swap files
*.swp

21
local/go-ucs/Gopkg.lock generated Executable file
View File

@@ -0,0 +1,21 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
branch = "master"
name = "golang.org/x/net"
packages = ["context"]
revision = "5f9ae10d9af5b1c89ae6904293b14b064d4ada23"
[[projects]]
branch = "master"
name = "golang.org/x/time"
packages = ["rate"]
revision = "fbb02b2291d28baffd63558aa44b4b56f178d650"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "95c0627ec50dce844f8d1485f7dad5ed1d321aaae8cd00bb303cc7709e89fd4d"
solver-name = "gps-cdcl"
solver-version = 1

34
local/go-ucs/Gopkg.toml Executable file
View File

@@ -0,0 +1,34 @@
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true
[[constraint]]
branch = "master"
name = "golang.org/x/time"
[prune]
go-tests = true
unused-packages = true

24
local/go-ucs/LICENSE Executable file
View File

@@ -0,0 +1,24 @@
Copyright (c) 2017-2018 Marin Atanasov Nikolov <dnaeon@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer
in this position and unchanged.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

27
local/go-ucs/README.md Executable file
View File

@@ -0,0 +1,27 @@
## go-ucs: Go library for the Cisco UCS API
[![GoDoc](https://godoc.org/github.com/dnaeon/go-ucs?status.svg)](https://godoc.org/github.com/dnaeon/go-ucs)
`go-ucs` is a Go library for interfacing with the Cisco UCS API.
## Documentation
The API documentation is available [here](https://godoc.org/github.com/dnaeon/go-ucs).
## Installation
In order to install `go-ucs` execute the following command.
```
go get -v github.com/dnaeon/go-ucs
```
## Tests
```bash
go test -v ./...
```
## Examples
Check the included examples from this repository.

326
local/go-ucs/api/api.go Executable file
View File

@@ -0,0 +1,326 @@
package api
import (
"encoding/xml"
"errors"
"fmt"
"github.com/dnaeon/go-ucs/version"
)
// The remote API endpoint to which we POST requests.
const apiEndpoint = "nuova"
// The UserAgent that we use for our requests.
const userAgent = "go-ucs/" + version.Version
// BaseResponse contains the base attributes as returned in a response from a
// Cisco UCS API endpoint.
type BaseResponse struct {
Cookie string `xml:"cookie,attr"`
Response string `xml:"response,attr"`
ErrorCode string `xml:"errorCode,attr,omitempty"`
InvocationResult string `xml:"invocationResult,attr,omitempty"`
ErrorDescription string `xml:"errorDescr,attr,omitempty"`
}
// IsError returns a boolean indicating whether the response contains errors.
func (b *BaseResponse) IsError() bool {
return b.ErrorCode != ""
}
// Error implements the error interface.
func (b *BaseResponse) Error() string {
return fmt.Sprintf("%s: %s (code %s)", b.ErrorDescription, b.InvocationResult, b.ErrorCode)
}
// ToError creates a new error.Error from the error response fields.
func (b *BaseResponse) ToError() error {
return errors.New(b.Error())
}
// AaaLoginRequest is the type which is sent during initial login
// in order to obtain authentication cookie.
type AaaLoginRequest struct {
XMLName xml.Name `xml:"aaaLogin"`
InName string `xml:"inName,attr"`
InPassword string `xml:"inPassword,attr"`
}
// AaaLoginResponse represents the response after a successful login to UCS manager.
type AaaLoginResponse struct {
BaseResponse
XMLName xml.Name `xml:"aaaLogin"`
OutCookie string `xml:"outCookie,attr,omitempty"`
OutRefreshPeriod int `xml:"outRefreshPeriod,attr,omitempty"`
OutPriv string `xml:"outPriv,attr,omitempty"`
OutDomains string `xml:"outDomains,attr,omitempty"`
OutChannel string `xml:"outChannel,attr,omitempty"`
OutEvtChannel string `xml:"outEvtChannel,attr,omitempty"`
OutName string `xml:"outName,attr,omitempty"`
OutVersion string `xml:"outVersion,attr,omitempty"`
OutSessionId string `xml:"outSessionId,attr,omitempty"`
}
// AaaRefreshRequest type is used for sending a request to the remote API endpoint for
// refreshing a session using the 47-character cookie obtained from a previous refresh
// or during the initial authentication as returned in a AaaLoginResponse.
type AaaRefreshRequest struct {
XMLName xml.Name `xml:"aaaRefresh"`
InName string `xml:"inName,attr"`
InPassword string `xml:"inPassword,attr"`
InCookie string `xml:"inCookie,attr"`
}
// AaaRefreshResponse is the response associated to a AaaRefreshRequest.
type AaaRefreshResponse struct {
XMLName xml.Name `xml:"aaaRefresh"`
AaaLoginResponse
}
// AaaLogoutRequest type is used for sending a request to invalidate an existing
// authentication cookie.
type AaaLogoutRequest struct {
XMLName xml.Name `xml:"aaaLogout"`
InCookie string `xml:"inCookie,attr"`
}
// AaaLogoutResponse represents the type that is returned after a call to aaaLogout method.
type AaaLogoutResponse struct {
BaseResponse
XMLName xml.Name `xml:"aaaLogout"`
OutStatus string `xml:"outStatus,attr,omitempty"`
}
// AaaKeepAliveRequest type is used for sending a request for keeping a session active
// until the default session time expires.
type AaaKeepAliveRequest struct {
XMLName xml.Name `xml:"aaaKeepAlive"`
Cookie string `xml:"cookie,attr"`
}
// AaaKeepAliveResponse is the response type associated with a AaaKeepAliveRequest.
type AaaKeepAliveResponse struct {
BaseResponse
XMLName xml.Name `xml:"aaaKeepAlive"`
Cookie string `xml:"cookie,attr"`
}
// ConfigResolveDnRequest type is used for constructing requests that retrieve a
// single managed object with the given DN.
type ConfigResolveDnRequest struct {
XMLName xml.Name `xml:"configResolveDn"`
Cookie string `xml:"cookie,attr"`
Dn string `xml:"dn,attr"`
InHierarchical string `xml:"inHierarchical,attr,omitempty"`
}
// ConfigResolveDnResponse is the type associated with a ConfigResolveDnRequest type.
// Specific classes contained within OutConfig should be xml.Unmarshal'ed first.
type ConfigResolveDnResponse struct {
BaseResponse
XMLName xml.Name `xml:"configResolveDn"`
Dn string `xml:"dn,attr"`
OutConfig InnerXml `xml:"outConfig"`
}
// Dn represents a single managed object DN.
type Dn struct {
XMLName xml.Name `xml:"dn"`
Value string `xml:"value,attr"`
}
// NewDn creates a new DN value.
func NewDn(value string) Dn {
dn := Dn{
Value: value,
}
return dn
}
// ConfigResolveDnsRequest type is used for constructing requests that retrieve
// managed objects for a list of given DNs.
type ConfigResolveDnsRequest struct {
XMLName xml.Name `xml:"configResolveDns"`
Cookie string `xml:"cookie,attr"`
InHierarchical string `xml:"inHierarchical,attr,omitempty"`
InDns []Dn `xml:"inDns>dn"`
}
// ConfigResolveDnsResponse is the response type associated with a ConfigResolveDnsRequest.
// The managed objects within OutConfigs field should be xml.Unmarshal'ed.
type ConfigResolveDnsResponse struct {
BaseResponse
XMLName xml.Name `xml:"configResolveDns"`
OutUnresolved []Dn `xml:"outUnresolved>dn"`
OutConfigs InnerXml `xml:"outConfigs"`
}
// InnerXml represents a generic configuration retrieved by the various query methods.
// After a successful result from a query method a client should unmarshal the data
// contained within an InnerXml to the specific managed object.
type InnerXml struct {
XMLName xml.Name
Inner []byte `xml:",innerxml"`
}
// ConfigResolveClassRequest type is used for constructing requests that retrieve
// managed objects of a given class.
type ConfigResolveClassRequest struct {
XMLName xml.Name `xml:"configResolveClass"`
Cookie string `xml:"cookie,attr"`
ClassId string `xml:"classId,attr"`
InHierarchical string `xml:"inHierarchical,attr,omitempty"`
InFilter FilterAny `xml:"inFilter>any,omitempty"`
}
// ConfigResolveClassResponse is the type associated with a ConfigResolveClassRequest.
// Specific classes contained within OutConfigs should be xml.Unmarshal'ed first.
type ConfigResolveClassResponse struct {
BaseResponse
XMLName xml.Name `xml:"configResolveClass"`
OutConfigs InnerXml `xml:"outConfigs"`
}
// Id represents an ID of a class.
type Id struct {
XMLName xml.Name `xml:"Id"`
Value string `xml:"value,attr"`
}
// NewId creates a new class id.
func NewId(value string) Id {
id := Id{
Value: value,
}
return id
}
// ConfigResolveClassesRequest type is used for constructing requests that retrieve managed
// objects in several classes.
type ConfigResolveClassesRequest struct {
XMLName xml.Name `xml:"configResolveClasses"`
Cookie string `xml:"cookie,attr"`
InHierarchical string `xml:"inHierarchical,attr,omitempty"`
InIds []Id `xml:"inIds>Id"`
}
// ConfigResolveClassesResponse is the response type associated with a ConfigResolveClassesRequest.
type ConfigResolveClassesResponse struct {
BaseResponse
XMLName xml.Name `xml:"configResolveClasses"`
OutConfigs InnerXml `xml:"outConfigs"`
}
// ConfigResolveChildren type is used for constructing requests that retrieve
// children of managed objects under a specified DN. A filter can be used to
// reduce the number of children being returned.
type ConfigResolveChildrenRequest struct {
XMLName xml.Name `xml:"configResolveChildren"`
Cookie string `xml:"cookie,attr"`
ClassId string `xml:"classId,attr"`
InDn string `xml:"inDn,attr"`
InHierarchical string `xml:"inHierarchical,attr"`
InFilter FilterAny `xml:"inFilter>any,omitempty"`
}
// ConfigResolveChildrenResponse is the response type associated with a ConfigResolveChildrenRequest.
type ConfigResolveChildrenResponse struct {
BaseResponse
XMLName xml.Name `xml:"configResolveChildren"`
OutConfigs InnerXml `xml:"outConfigs"`
}
// FilterAny represents any valid filter.
type FilterAny interface{}
// FilterProperty represents a Property Filter.
type FilterProperty struct {
Class string `xml:"class,attr"`
Property string `xml:"property,attr"`
Value string `xml:"value,attr"`
}
// FilterEq represents an Equality Filter.
type FilterEq struct {
XMLName xml.Name `xml:"eq"`
FilterProperty
}
// FilterNe represents a Not Equal Filter.
type FilterNe struct {
XMLName xml.Name `xml:"ne"`
FilterProperty
}
// FilterGt represents a Greater Than Filter.
type FilterGt struct {
XMLName xml.Name `xml:"gt"`
FilterProperty
}
// FilterGe represents a Greater Than Or Equal To Filter.
type FilterGe struct {
XMLName xml.Name `xml:"ge"`
FilterProperty
}
// FilterLt represents a Less Than Filter.
type FilterLt struct {
XMLName xml.Name `xml:"lt"`
FilterProperty
}
// FilterLe represents a Less Than Or Equal To Filter.
type FilterLe struct {
XMLName xml.Name `xml:"le"`
FilterProperty
}
// FilterWildcard represents a Wildcard Filter.
// The wildcard filter uses standard regular expression syntax.
type FilterWildcard struct {
XMLName xml.Name `xml:"wcard"`
FilterProperty
}
// FilterAnyBits represents an Any Bits Filter.
type FilterAnyBits struct {
XMLName xml.Name `xml:"anybit"`
FilterProperty
}
// FilterAllBits represents an All Bits Filter.
type FilterAllBits struct {
XMLName xml.Name `xml:"allbits"`
FilterProperty
}
// FilterAnd represents a composite AND Filter.
type FilterAnd struct {
XMLName xml.Name `xml:"and"`
Filters []FilterAny
}
// FilterOr represents a composite OR Filter.
type FilterOr struct {
XMLName xml.Name `xml:"or"`
Filters []FilterAny
}
// FilterNot represents a NOT Modifier Filter.
type FilterNot struct {
XMLName xml.Name `xml:"not"`
Filters []FilterAny
}
// FilterBetween represents a Between Filter.
type FilterBetween struct {
XMLName xml.Name `xml:"bw"`
Class string `xml:"class,attr"`
Property string `xml:"property,attr"`
FirstVault string `xml:"firstValue,attr"`
SecondValue string `xml:"secondValue,attr"`
}

341
local/go-ucs/api/client.go Executable file
View File

@@ -0,0 +1,341 @@
package api
import (
"bytes"
"context"
"encoding/xml"
"fmt"
"io"
"net/http"
"net/url"
"time"
"github.com/dnaeon/go-ucs/mo"
"golang.org/x/time/rate"
)
// RateLimit limits the number of requests per second that a Client
// can send to a remote Cisco UCS API endpoint using a rate.Limiter
// token bucket configured with the provided requests per seconds and
// burst. A request will wait for up to the given wait time.
type RateLimit struct {
// RequestsPerSecond defines the allowed number of requests per second.
RequestsPerSecond float64
// Burst is the maximum burst size.
Burst int
// Wait defines the maximum time a request will wait for a token to be consumed.
Wait time.Duration
}
// Config type contains the setting used by the Client.
type Config struct {
// HttpClient is the HTTP client to use for sending requests.
// If nil then we use http.DefaultClient for all requests.
HttpClient *http.Client
// Endpoint is the base URL to the remote Cisco UCS Manager endpoint.
Endpoint string
// Username to use when authenticating to the remote endpoint.
Username string
// Password to use when authenticating to the remote endpoint.
Password string
// RateLimit is used for limiting the number of requests per second
// against the remote Cisco UCS API endpoint using a token bucket.
RateLimit *RateLimit
}
// Client is used for interfacing with the remote Cisco UCS API endpoint.
type Client struct {
config *Config
apiUrl *url.URL
limiter *rate.Limiter
// Cookie is the authentication cookie currently in use.
// It's value is set by the AaaLogin and AaaRefresh methods.
Cookie string
}
// NewClient creates a new API client from the given config.
func NewClient(config Config) (*Client, error) {
if config.HttpClient == nil {
config.HttpClient = http.DefaultClient
}
baseUrl, err := url.Parse(config.Endpoint)
if err != nil {
return nil, err
}
apiUrl, err := url.Parse(apiEndpoint)
if err != nil {
return nil, err
}
var limiter *rate.Limiter
if config.RateLimit != nil {
rps := rate.Limit(config.RateLimit.RequestsPerSecond)
limiter = rate.NewLimiter(rps, config.RateLimit.Burst)
}
client := &Client{
config: &config,
apiUrl: baseUrl.ResolveReference(apiUrl),
limiter: limiter,
}
return client, nil
}
// Hostname returns the host portion of the remote UCS API endpoint without any port number.
func (c *Client) Hostname() string {
return c.apiUrl.Host
}
// AaaLogin performs the initial authentication to the remote Cisco UCS API endpoint.
func (c *Client) AaaLogin(ctx context.Context) (*AaaLoginResponse, error) {
req := AaaLoginRequest{
InName: c.config.Username,
InPassword: c.config.Password,
}
var resp AaaLoginResponse
if err := c.Request(ctx, req, &resp); err != nil {
return nil, err
}
if resp.IsError() {
return nil, resp.ToError()
}
// Set authentication cookie for future re-use when needed.
c.Cookie = resp.OutCookie
return &resp, nil
}
// AaaRefresh refreshes the current session by requesting a new authentication cookie.
func (c *Client) AaaRefresh(ctx context.Context) (*AaaRefreshResponse, error) {
req := AaaRefreshRequest{
InName: c.config.Username,
InPassword: c.config.Password,
InCookie: c.Cookie,
}
var resp AaaRefreshResponse
if err := c.Request(ctx, req, &resp); err != nil {
return nil, err
}
if resp.IsError() {
return nil, resp.ToError()
}
// Set new authentication cookie
c.Cookie = resp.OutCookie
return &resp, nil
}
// AaaKeepAlive sends a request to keep the current session active using the same cookie.
func (c *Client) AaaKeepAlive(ctx context.Context) (*AaaKeepAliveResponse, error) {
req := AaaKeepAliveRequest{
Cookie: c.Cookie,
}
var resp AaaKeepAliveResponse
if err := c.Request(ctx, req, &resp); err != nil {
return nil, err
}
if resp.IsError() {
return nil, resp.ToError()
}
return &resp, nil
}
// AaaLogout invalidates the current client session.
func (c *Client) AaaLogout(ctx context.Context) (*AaaLogoutResponse, error) {
req := AaaLogoutRequest{
InCookie: c.Cookie,
}
var resp AaaLogoutResponse
if err := c.Request(ctx, req, &resp); err != nil {
return nil, err
}
if resp.IsError() {
return nil, resp.ToError()
}
c.Cookie = ""
return &resp, nil
}
// doRequest sends a request to the remote Cisco UCS API endpoint.
func (c *Client) doRequest(ctx context.Context, in, out interface{}) error {
data, err := xmlMarshalWithSelfClosingTags(in)
if err != nil {
return err
}
fmt.Println("doRequest sending following XML request:")
fmt.Println(string(data[:]))
r, err := http.NewRequest("POST", c.apiUrl.String(), bytes.NewBuffer(data))
if err != nil {
return err
}
req := r.WithContext(ctx)
req.Header.Set("User-Agent", userAgent)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := c.config.HttpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
fmt.Println("doRequest received following response:")
fmt.Println(string(body[:]))
return xml.Unmarshal(body, &out)
}
// Request sends a POST request to the remote Cisco UCS API endpoint.
func (c *Client) Request(ctx context.Context, in, out interface{}) error {
// Rate limit requests if we are using a limiter
if c.limiter != nil {
ctxWithTimeout, cancel := context.WithTimeout(ctx, c.config.RateLimit.Wait)
defer cancel()
if err := c.limiter.Wait(ctxWithTimeout); err != nil {
return err
}
}
return c.doRequest(ctx, in, out)
}
// RequestNow sends a POST request to the remote Cisco UCS API endpoint immediately.
// This bypasses any rate limiter configuration that may be used and is
// meant to be used for priority requests, e.g. refreshing a token, logging out, etc.
func (c *Client) RequestNow(ctx context.Context, in, out interface{}) error {
return c.doRequest(ctx, in, out)
}
// ConfigResolveDn retrieves a single managed object for a specified DN.
func (c *Client) ConfigResolveDn(ctx context.Context, in ConfigResolveDnRequest, out mo.Any) error {
var resp ConfigResolveDnResponse
if err := c.Request(ctx, in, &resp); err != nil {
return err
}
if resp.IsError() {
return resp.ToError()
}
// The requested managed object is contained within the inner XML document,
// which we need to unmarshal first into the given concrete type.
return xml.Unmarshal(resp.OutConfig.Inner, &out)
}
// ConfigResolveDns retrieves managed objects for a specified list of DNs.
func (c *Client) ConfigResolveDns(ctx context.Context, in ConfigResolveDnsRequest, out mo.Any) (*ConfigResolveDnsResponse, error) {
var resp ConfigResolveDnsResponse
if err := c.Request(ctx, in, &resp); err != nil {
return nil, err
}
if resp.IsError() {
return nil, resp.ToError()
}
inner, err := xml.Marshal(resp.OutConfigs)
if err != nil {
return nil, err
}
if err := xml.Unmarshal(inner, &out); err != nil {
return nil, err
}
return &resp, nil
}
// ConfigResolveClass retrieves managed objects of the specified class.
func (c *Client) ConfigResolveClass(ctx context.Context, in ConfigResolveClassRequest, out mo.Any) error {
var resp ConfigResolveClassResponse
if err := c.Request(ctx, in, &resp); err != nil {
return err
}
if resp.IsError() {
return resp.ToError()
}
inner, err := xml.Marshal(resp.OutConfigs)
if err != nil {
return err
}
// The requested managed objects are contained within the inner XML document,
// which we need to unmarshal first into the given concrete type.
return xml.Unmarshal(inner, &out)
}
// ConfigResolveClasses retrieves managed objects from the specified list of classes.
func (c *Client) ConfigResolveClasses(ctx context.Context, in ConfigResolveClassesRequest, out mo.Any) error {
var resp ConfigResolveClassesResponse
if err := c.Request(ctx, in, &resp); err != nil {
return err
}
if resp.IsError() {
return resp.ToError()
}
inner, err := xml.Marshal(resp.OutConfigs)
if err != nil {
return err
}
// The requested managed objects are contained within the inner XML document,
// which we need to unmarshal first into the given concrete type.
return xml.Unmarshal(inner, &out)
}
// ConfigResolveChildren retrieves children of managed objects under a specified DN.
func (c *Client) ConfigResolveChildren(ctx context.Context, in ConfigResolveChildrenRequest, out mo.Any) error {
var resp ConfigResolveChildrenResponse
if err := c.Request(ctx, in, &resp); err != nil {
return err
}
if resp.IsError() {
return resp.ToError()
}
inner, err := xml.Marshal(resp.OutConfigs)
if err != nil {
return err
}
// The requested managed objects are contained within the inner XML document,
// which we need to unmarshal first into the given concrete type.
return xml.Unmarshal(inner, &out)
}

2
local/go-ucs/api/doc.go Executable file
View File

@@ -0,0 +1,2 @@
// Package api provides types and methods for interfacing with a Cisco UCS API endpoint.
package api

View File

@@ -0,0 +1,73 @@
package api_test
import (
"context"
"crypto/tls"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/dnaeon/go-ucs/api"
)
func Example_aaaKeepAlive() {
// The following example shows how to keep a session alive.
// Skip SSL certificate verification of remote endpoint.
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
httpClient := &http.Client{Transport: tr}
// Create a new Cisco UCS API client
config := api.Config{
Endpoint: "https://ucs01.example.org/",
Username: "admin",
Password: "password",
HttpClient: httpClient,
}
client, err := api.NewClient(config)
if err != nil {
log.Fatalf("Unable to create API client: %s", err)
}
ctx := context.Background()
// Authenticate to the remote API endpoint and obtain authentication cookie
log.Printf("Logging in to %s\n", config.Endpoint)
if _, err := client.AaaLogin(ctx); err != nil {
log.Fatalf("Unable to authenticate: %s", err)
}
defer client.AaaLogout(ctx)
log.Printf("Got authentication cookie: %s\n", client.Cookie)
// Channel on which the shutdown signal is sent
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
// Send a KeepAlive request every minute
ticker := time.NewTicker(1 * time.Minute)
L:
for {
select {
case <-quit:
log.Println("Keyboard interrupt detected, terminating.")
break L
case <-ticker.C:
log.Println("Sending KeepAlive request ...")
resp, err := client.AaaKeepAlive(ctx)
if err != nil {
log.Printf("Unable to keep session alive: %s\n", err)
break L
}
log.Printf("Got response with cookie: %s\n", resp.Cookie)
}
}
}

View File

@@ -0,0 +1,44 @@
package api_test
import (
"context"
"crypto/tls"
"log"
"net/http"
"github.com/dnaeon/go-ucs/api"
)
func Example_aaaLogin() {
// The following example shows how to login and logout from a Cisco UCS API endpoint
// Skip SSL certificate verification of remote endpoint.
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
httpClient := &http.Client{Transport: tr}
// Create a new Cisco UCS API client
config := api.Config{
Endpoint: "https://ucs01.example.org/",
Username: "admin",
Password: "password",
HttpClient: httpClient,
}
client, err := api.NewClient(config)
if err != nil {
log.Fatalf("Unable to create API client: %s\n", err)
}
// Authenticate to the remote API endpoint and obtain authentication cookie
log.Printf("Logging in to %s\n", config.Endpoint)
ctx := context.Background()
if _, err := client.AaaLogin(ctx); err != nil {
log.Fatalf("Unable to authenticate: %s", err)
}
defer client.AaaLogout(ctx)
log.Printf("Got authentication cookie: %s\n", client.Cookie)
}

View File

@@ -0,0 +1,51 @@
package api_test
import (
"context"
"crypto/tls"
"log"
"net/http"
"github.com/dnaeon/go-ucs/api"
)
func Example_aaaRefresh() {
// The following example shows how to refresh an existing session.
// Skip SSL certificate verification of remote endpoint.
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
httpClient := &http.Client{Transport: tr}
// Create a new Cisco UCS API client
config := api.Config{
Endpoint: "https://ucs01.example.org/",
Username: "admin",
Password: "password",
HttpClient: httpClient,
}
client, err := api.NewClient(config)
if err != nil {
log.Fatalf("Unable to create API client: %s", err)
}
ctx := context.Background()
// Authenticate to the remote API endpoint and obtain authentication cookie
log.Printf("Logging in to %s\n", config.Endpoint)
if _, err := client.AaaLogin(ctx); err != nil {
log.Fatalf("Unable to authenticate: %s", err)
}
defer client.AaaLogout(ctx)
log.Printf("Got authentication cookie: %s\n", client.Cookie)
log.Println("Refreshing session")
if _, err := client.AaaRefresh(ctx); err != nil {
log.Fatalf("Unable to refresh session: %s\n", err)
}
log.Printf("New authentication cookie is: %s\n", client.Cookie)
}

View File

@@ -0,0 +1,96 @@
package api_test
import (
"context"
"crypto/tls"
"encoding/xml"
"log"
"net/http"
"github.com/dnaeon/go-ucs/api"
"github.com/dnaeon/go-ucs/mo"
)
func Example_compositeFilter() {
// The following example shows how to use a composite AND property filter.
// Skip SSL certificate verification of remote endpoint.
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
httpClient := &http.Client{Transport: tr}
// Create a new Cisco UCS API client
config := api.Config{
Endpoint: "https://ucs01.example.org/",
Username: "admin",
Password: "password",
HttpClient: httpClient,
}
client, err := api.NewClient(config)
if err != nil {
log.Fatalf("Unable to create API client: %s", err)
}
ctx := context.Background()
log.Printf("Logging in to %s\n", config.Endpoint)
if _, err := client.AaaLogin(ctx); err != nil {
log.Fatalf("Unable to login: %s\n", err)
}
defer client.AaaLogout(ctx)
log.Printf("Got authentication cookie: %s\n", client.Cookie)
// The type into which we unmarshal the result data
type blades struct {
XMLName xml.Name
Blades []mo.ComputeBlade `xml:"computeBlade"`
}
// Create a composite AND property filter, which will find all blades,
// which have total memory greater than or equal to 2048 MB and are in chassis 3.
filter := api.FilterAnd{
Filters: []api.FilterAny{
api.FilterGe{
FilterProperty: api.FilterProperty{
Class: "computeBlade",
Property: "totalMemory",
Value: "2048",
},
},
api.FilterEq{
FilterProperty: api.FilterProperty{
Class: "computeBlade",
Property: "chassisId",
Value: "3",
},
},
},
}
req := api.ConfigResolveClassRequest{
Cookie: client.Cookie,
InHierarchical: "false",
ClassId: "computeBlade",
InFilter: filter,
}
var out blades
log.Println("Retrieving managed objects with class `computeBlade`")
if err := client.ConfigResolveClass(ctx, req, &out); err != nil {
log.Fatalf("Unable to retrieve `computeBlade` managed object: %s", err)
}
log.Printf("Retrieved %d compute blades\n", len(out.Blades))
for _, blade := range out.Blades {
log.Printf("%s:\n", blade.Dn)
log.Printf("\tNumber of CPUs: %d\n", blade.NumOfCpus)
log.Printf("\tTotal Memory: %d\n", blade.TotalMemory)
log.Printf("\tModel: %s\n", blade.Model)
log.Printf("\tChassis ID: %d\n", blade.ChassisId)
log.Printf("\tVendor: %s\n", blade.Vendor)
}
}

View File

@@ -0,0 +1,73 @@
package api_test
import (
"context"
"crypto/tls"
"encoding/xml"
"log"
"net/http"
"github.com/dnaeon/go-ucs/api"
"github.com/dnaeon/go-ucs/mo"
)
func Example_configResolveClass() {
// The following example shows how to retrieve all compute blades.
// Skip SSL certificate verification of remote endpoint.
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
httpClient := &http.Client{Transport: tr}
// Create a new Cisco UCS API client
config := api.Config{
Endpoint: "https://ucs01.example.org/",
Username: "admin",
Password: "password",
HttpClient: httpClient,
}
client, err := api.NewClient(config)
if err != nil {
log.Fatalf("Unable to create API client: %s", err)
}
ctx := context.Background()
log.Printf("Logging in to %s\n", config.Endpoint)
if _, err := client.AaaLogin(ctx); err != nil {
log.Fatalf("Unable to login: %s\n", err)
}
defer client.AaaLogout(ctx)
log.Printf("Got authentication cookie: %s\n", client.Cookie)
// The type into which we unmarshal the result data
type blades struct {
XMLName xml.Name
Blades []mo.ComputeBlade `xml:"computeBlade"`
}
req := api.ConfigResolveClassRequest{
Cookie: client.Cookie,
ClassId: "computeBlade",
InHierarchical: "false",
}
var out blades
log.Println("Retrieving managed objects with class `computeBlade`")
if err := client.ConfigResolveClass(ctx, req, &out); err != nil {
log.Fatalf("Unable to retrieve `computeBlade` managed object: %s", err)
}
log.Printf("Retrieved %d compute blades\n", len(out.Blades))
for _, blade := range out.Blades {
log.Printf("%s:\n", blade.Dn)
log.Printf("\tNumber of CPUs: %d\n", blade.NumOfCpus)
log.Printf("\tTotal Memory: %d\n", blade.TotalMemory)
log.Printf("\tModel: %s\n", blade.Model)
log.Printf("\tVendor: %s\n", blade.Vendor)
}
}

View File

@@ -0,0 +1,81 @@
package api_test
import (
"context"
"crypto/tls"
"log"
"net/http"
"github.com/dnaeon/go-ucs/api"
"github.com/dnaeon/go-ucs/mo"
)
func Example_configResolveClasses() {
// The following example shows how to retrieve managed objects from different classes.
// In the example below we will retrieve the managed objects of `computeBlade` and `computeRackUnit` classes.
// Skip SSL certificate verification of remote endpoint.
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
httpClient := &http.Client{Transport: tr}
// Create a new Cisco UCS API client
config := api.Config{
Endpoint: "https://ucs01.example.org/",
Username: "admin",
Password: "password",
HttpClient: httpClient,
}
client, err := api.NewClient(config)
if err != nil {
log.Fatalf("Unable to create API client: %s", err)
}
ctx := context.Background()
log.Printf("Logging in to %s\n", config.Endpoint)
if _, err := client.AaaLogin(ctx); err != nil {
log.Fatalf("Unable to login: %s\n", err)
}
defer client.AaaLogout(ctx)
log.Printf("Got authentication cookie: %s\n", client.Cookie)
req := api.ConfigResolveClassesRequest{
Cookie: client.Cookie,
InHierarchical: "false",
InIds: []api.Id{
api.NewId("computeBlade"),
api.NewId("computeRackUnit"),
},
}
// ComputeItem is a container for all physical compute items.
var out mo.ComputeItem
log.Println("Retrieving managed objects with classes `computeBlade` and `computeRackUnit`")
if err := client.ConfigResolveClasses(ctx, req, &out); err != nil {
log.Fatalf("Unable to retrieve `computeBlade` and `computeRackUnit` managed object: %s", err)
}
log.Printf("Retrieved %d compute blades\n", len(out.Blades))
log.Printf("Retrieved %d compute rack units\n", len(out.RackUnits))
for _, blade := range out.Blades {
log.Printf("%s:\n", blade.Dn)
log.Printf("\tNumber of CPUs: %d\n", blade.NumOfCpus)
log.Printf("\tTotal Memory: %d\n", blade.TotalMemory)
log.Printf("\tModel: %s\n", blade.Model)
log.Printf("\tVendor: %s\n", blade.Vendor)
}
for _, blade := range out.RackUnits {
log.Printf("%s:\n", blade.Dn)
log.Printf("\tNumber of CPUs: %d\n", blade.NumOfCpus)
log.Printf("\tTotal Memory: %d\n", blade.TotalMemory)
log.Printf("\tModel: %s\n", blade.Model)
log.Printf("\tVendor: %s\n", blade.Vendor)
}
}

View File

@@ -0,0 +1,63 @@
package api_test
import (
"context"
"crypto/tls"
"log"
"net/http"
"github.com/dnaeon/go-ucs/api"
"github.com/dnaeon/go-ucs/mo"
)
func Example_configResolveDn() {
// The following example shows how to retrieve a single managed object for a specified DN.
// Skip SSL certificate verification of remote endpoint.
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
httpClient := &http.Client{Transport: tr}
// Create a new Cisco UCS API client
config := api.Config{
Endpoint: "https://ucs01.example.org/",
Username: "admin",
Password: "password",
HttpClient: httpClient,
}
client, err := api.NewClient(config)
if err != nil {
log.Fatalf("Unable to create API client: %s", err)
}
ctx := context.Background()
log.Printf("Logging in to %s\n", config.Endpoint)
if _, err := client.AaaLogin(ctx); err != nil {
log.Fatalf("Unable to login: %s\n", err)
}
defer client.AaaLogout(ctx)
log.Printf("Got authentication cookie: %s\n", client.Cookie)
// Retrieve the `sys` DN, which is of type mo.TopSystem
log.Println("Retrieving `sys` managed object")
req := api.ConfigResolveDnRequest{
Cookie: client.Cookie,
Dn: "sys",
InHierarchical: "false",
}
var sys mo.TopSystem
if err := client.ConfigResolveDn(ctx, req, &sys); err != nil {
log.Fatalf("Unable to retrieve DN: %s", err)
}
log.Printf("Address: %s\n", sys.Address)
log.Printf("Current time: %s\n", sys.CurrentTime)
log.Printf("Dn: %s\n", sys.Dn)
log.Printf("Mode: %s\n", sys.Mode)
log.Printf("Uptime: %s\n", sys.SystemUptime)
}

View File

@@ -0,0 +1,80 @@
package api_test
import (
"context"
"crypto/tls"
"encoding/xml"
"log"
"net/http"
"strings"
"github.com/dnaeon/go-ucs/api"
"github.com/dnaeon/go-ucs/mo"
)
func Example_configResolveDns() {
// The following example shows how to retrieve a list of managed objects by specifying their DNs.
// Skip SSL certificate verification of remote endpoint.
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
httpClient := &http.Client{Transport: tr}
// Create a new Cisco UCS API client
config := api.Config{
Endpoint: "https://ucs01.example.org/",
Username: "admin",
Password: "password",
HttpClient: httpClient,
}
client, err := api.NewClient(config)
if err != nil {
log.Fatalf("Unable to create API client: %s", err)
}
ctx := context.Background()
log.Printf("Logging in to %s\n", config.Endpoint)
if _, err := client.AaaLogin(ctx); err != nil {
log.Fatalf("Unable to login: %s\n", err)
}
defer client.AaaLogout(ctx)
log.Printf("Got authentication cookie: %s\n", client.Cookie)
// A type to contain the instances of the retrieved DNs.
type outConfigs struct {
XMLName xml.Name
Sys mo.TopSystem `xml:"topSystem"`
Version mo.VersionApplication `xml:"versionApplication"`
}
var out outConfigs
// Retrieve the list of DNs
log.Println("Retrieving managed objects using configResolveDns query method")
req := api.ConfigResolveDnsRequest{
Cookie: client.Cookie,
InHierarchical: "false",
InDns: []api.Dn{
api.NewDn("sys"),
api.NewDn("sys/version/application"),
api.NewDn("no/such/dn"),
},
}
resp, err := client.ConfigResolveDns(ctx, req, &out)
if err != nil {
log.Fatalf("Unable to retrieve DNs: %s", err)
}
log.Printf("%s is at version %s\n", out.Sys.Name, out.Version.Version)
unresolved := make([]string, 0)
for _, dn := range resp.OutUnresolved {
unresolved = append(unresolved, dn.Value)
}
log.Printf("Unresolved DNs: %s", strings.Join(unresolved, ", "))
}

View File

@@ -0,0 +1,88 @@
package api_test
import (
"context"
"crypto/tls"
"log"
"net/http"
"sync"
"time"
"github.com/dnaeon/go-ucs/api"
"github.com/dnaeon/go-ucs/mo"
)
func Example_rateLimiter() {
// The following example shows how to rate limit requests again the remote
// Cisco UCS API endpoint using a token bucket rate limiter.
// https://en.wikipedia.org/wiki/Token_bucket
// Skip SSL certificate verification of remote endpoint.
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
httpClient := &http.Client{Transport: tr}
// Create a new Cisco UCS API client.
// Set maximum allowed requests per second to 1 with a burst size of 1.
// A request will wait up to 1 minute for a token.
config := api.Config{
Endpoint: "https://ucs01.example.org/",
Username: "admin",
Password: "password",
HttpClient: httpClient,
RateLimit: &api.RateLimit{
RequestsPerSecond: 1.0,
Burst: 1,
Wait: time.Duration(1 * time.Minute),
},
}
client, err := api.NewClient(config)
if err != nil {
log.Fatalf("Unable to create API client: %s", err)
}
ctx := context.Background()
log.Printf("Logging in to %s\n", config.Endpoint)
if _, err := client.AaaLogin(ctx); err != nil {
log.Fatalf("Unable to login: %s\n", err)
}
defer client.AaaLogout(ctx)
log.Printf("Got authentication cookie: %s\n", client.Cookie)
// Start a few concurrent requests to the remote API endpoint.
// Requests will be executed one at a time, because of how the limiter is configured.
var wg sync.WaitGroup
for i := 1; i < 10; i++ {
wg.Add(1)
// Our worker function will retrieve the `sys` DN from the remote Cisco UCS API.
// We will start a few of these in separate goroutines.
worker := func(id int) {
defer wg.Done()
// Retrieve the `sys` DN, which is of type mo.TopSystem
log.Printf("Worker #%d: Retrieving `sys` managed object\n", id)
req := api.ConfigResolveDnRequest{
Cookie: client.Cookie,
Dn: "sys",
InHierarchical: "false",
}
var sys mo.TopSystem
if err := client.ConfigResolveDn(ctx, req, &sys); err != nil {
log.Printf("Worker #%d: Unable to retrieve DN: %s\n", id, err)
return
}
log.Printf("Worker #%d: successfully retrieved `sys` managed object\n", id)
}
go worker(i)
}
wg.Wait()
}

54
local/go-ucs/api/xml.go Executable file
View File

@@ -0,0 +1,54 @@
package api
import (
"encoding/xml"
"regexp"
)
// xmlMarshalWithSelfClosingTags post-processes results from xml.Marshal into XML
// document where empty XML elements use self-closing tags.
//
// The XML standard states that self-closing tags are permitted.
//
// https://www.w3.org/TR/REC-xml/#dt-empty
// https://www.w3.org/TR/REC-xml/#d0e2480
//
// According to the XML standard an empty element with a start and end tag is
// semantically the same as an empty element with a self-closing tag.
//
// Unfortunately not all XML parsers can understand both. Such is the
// case with Cisco UCS Manager API, which expects empty elements to use
// self-closing tags only.
//
// As of now XML marshaling in Go always uses start and end tags,
// which results in XML elements like the one below.
//
// <Person name="me"></Person>
//
// Above XML elements cannot be parsed by the remote Cisco UCS API endpoint,
// and such API calls result in parse error returned to the client.
//
// Currently the Go team is considering implementing XML self-closing tags,
// which progress can be tracked in the issue below.
//
// https://github.com/golang/go/issues/21399
//
// Until support for XML self-closing tags (if ever) becomes real in Go
// we need to ensure compatibility with the Cisco UCS API by doing that ourselves.
//
// In a separate thread @rsc also suggested a similar approach by using
// strings.Replace(), even though such thing is not ideal and should
// hopefully one day make into the language as a feature.
//
// https://groups.google.com/forum/#!topic/golang-nuts/guG6iOCRu08
func xmlMarshalWithSelfClosingTags(in interface{}) ([]byte, error) {
data, err := xml.Marshal(in)
if err != nil {
return nil, err
}
re := regexp.MustCompile(`<([^/][\w\s\"\=\-\/]*)>\s*<(\/\w*)>`)
newData := re.ReplaceAllString(string(data), "<$1/>")
return []byte(newData), nil
}

64
local/go-ucs/api/xml_test.go Executable file
View File

@@ -0,0 +1,64 @@
package api
import (
"encoding/xml"
"testing"
)
type Person struct {
XMLName xml.Name `xml:"person"`
Name string `xml:"name,attr,omitempty"`
Place *Location `xml:"place,omitempty"`
}
type Location struct {
Country string `xml:"country,omitempty"`
City string `xml:"city,omitempty"`
}
type PersonEmbedded struct {
XMLName xml.Name `xml:"personEmbedded"`
Person
Location
}
type NilStruct *Person
func TestXmlMarshalWithSelfClosingTags(t *testing.T) {
var tests = []struct {
value interface{}
expect string
}{
// Nil values
{value: nil, expect: ``},
{value: new(NilStruct), expect: ``},
// Values
{value: Person{}, expect: `<person/>`},
{value: Person{Name: "John Doe"}, expect: `<person name="John Doe"/>`},
{
value: Person{Name: "Jane Doe", Place: &Location{Country: "unknown", City: "unknown"}},
expect: `<person name="Jane Doe"><place><country>unknown</country><city>unknown</city></place></person>`,
},
{
value: &PersonEmbedded{Person: Person{Name: "John Doe"}, Location: Location{Country: "unknown"}},
expect: `<personEmbedded name="John Doe"><country>unknown</country></personEmbedded>`,
},
// Pointers to values
{value: &Person{}, expect: `<person/>`},
{value: &Person{Name: "John Doe"}, expect: `<person name="John Doe"/>`},
}
for _, test := range tests {
data, err := xmlMarshalWithSelfClosingTags(test.value)
if err != nil {
t.Fatalf("Cannot marshal %+v: %s", test.value, err)
}
got := string(data)
if got != test.expect {
t.Fatalf("Got XML '%s', expect '%s'", got, test.expect)
}
}
}

11
local/go-ucs/go.mod Executable file
View File

@@ -0,0 +1,11 @@
module local/go-ucs
go 1.21.0
require (
golang.org/x/net v0.0.0-20180420171651-5f9ae10d9af5
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2
)
replace github.com/dnaeon/go-ucs/mo => ./local/go-ucs/mo
replace github.com/dnaeon/go-ucs/version => ./local/go-ucs/version
replace github.com/dnaeon/go-ucs/api => ./local/go-ucs/api

2
local/go-ucs/mo/doc.go Executable file
View File

@@ -0,0 +1,2 @@
// Package mo provides Go types for the Cisco UCS Managed Objects types.
package mo

750
local/go-ucs/mo/mo.go Executable file
View File

@@ -0,0 +1,750 @@
package mo
import (
"encoding/xml"
"net"
)
// Any represents any valid managed object.
type Any interface{}
// TopSystem provides general information about the system, such as the
// name, IP address and current time.
type TopSystem struct {
XMLName xml.Name `xml:"topSystem"`
Address net.IP `xml:"address,attr,omitempty"`
CurrentTime string `xml:"currentTime,attr,omitempty"`
Description string `xml:"descr,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
Ipv6Addr string `xml:"ipv6Addr,attr,omitempty"`
Mode string `xml:"mode,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
Owner string `xml:"owner,attr,omitempty"`
Site string `xml:"site,attr,omitempty"`
SystemUptime string `xml:"systemUpTime,attr,omitempty"`
VersionEp VersionEp `xml:"versionEp"`
CommServiceEp CommServiceEp `xml:"commSvcEp"`
EquipmentChassis []EquipmentChassis `xml:"equipmentChassis"`
ComputeRackUnits []ComputeRackUnit `xml:"computeRackUnit"`
}
// CommServiceEp contains configuration for various services.
type CommServiceEp struct {
FiniteStateMachineTask
XMLName xml.Name `xml:"commSvcEp"`
ConfigState string `xml:"configState,attr,omitempty"`
ConfigStatusMessage string `xml:"configStatusMessage,attr,omitempty"`
Description string `xml:"descr,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
IntId string `xml:"intId,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
PolicyLevel int `xml:"policyLevel,attr,omitempty"`
PolicyOwner string `xml:"policyOwner,attr,omitempty"`
CommDns CommDns `xml:"commDns"`
}
// CommDns contains the DNS settings of the UCS system.
type CommDns struct {
XMLName xml.Name `xml:"commDns"`
AdminState string `xml:"adminState,attr,omitempty"`
Description string `xml:"descr,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
Domain string `xml:"domain,attr,omitempty"`
IntId string `xml:"intId,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
OperationalPort int `xml:"operPort,attr,omitempty"`
PolicyLevel int `xml:"policyLevel,attr,omitempty"`
PolicyOwner string `xml:"policyOwner,attr,omitempty"`
Port int `xml:"port,attr,omitempty"`
Proto string `xml:"proto,attr,omitempty"`
Providers []CommDnsProvider `xml:"commDnsProvider"`
}
// CommDnsProvider represents a DNS service provider.
type CommDnsProvider struct {
XMLName xml.Name `xml:"commDnsProvider"`
AdminState string `xml:"adminState,attr,omitempty"`
Description string `xml:"descr,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
Hostname string `xml:"hostname,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
}
// VersionEp contains version information.
type VersionEp struct {
XMLName xml.Name `xml:"versionEp"`
ChildAction string `xml:"childAction,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
Application VersionApplication `xml:"versionApplication,omitempty"`
}
// VersionApplication contains the application version.
type VersionApplication struct {
XMLName xml.Name `xml:"versionApplication"`
ChildAction string `xml:"childAction,attr,omitempty"`
Detail string `xml:"detail,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
Time string `xml:"time,attr,omitempty"`
Version string `xml:"version,attr,omitempty"`
}
// EquipmentChassis represents a physical unit that can accomodate multiple blade servers.
// For example, the Cisco UCS 5108 Blade Server Chassis is six rack units (6RU) high,
// can mount in an industry-standard 19-inch rack and uses front-to-back cooling.
type EquipmentChassis struct {
FiniteStateMachineTask
XMLName xml.Name `xml:"equipmentChassis"`
AckProgressIndicator string `xml:"ackProgressIndicator,attr,omitempty"`
AdminState string `xml:"adminState,attr,omitempty"`
AssignedToDn string `xml:"assignedToDn,attr,omitempty"`
Association string `xml:"association,attr,omitempty"`
Availability string `xml:"availability,attr,omitempty"`
ConfigState string `xml:"configState,attr,omitempty"`
ConnPath string `xml:"connPath,attr,omitempty"`
ConnStatus string `xml:"connStatus,attr,omitempty"`
Discovery string `xml:"discovery,attr,omitempty"`
DiscoveryStatus string `xml:"discoveryStatus,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
FabricEpDn string `xml:"fabricEpDn,attr,omitempty"`
FltAggr int `xml:"fltAggr,attr,omitempty"`
Id string `xml:"id,attr,omitempty"`
LcTimestamp string `xml:"lcTs,attr,omitempty"`
LicGP int `xml:"licGP,attr,omitempty"`
LicState string `xml:"licState,attr,omitempty"`
ManagingInstance string `xml:"managingInst,attr,omitempty"`
ManufacturingTime string `xml:"mfgTime,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
OperationalQualifier string `xml:"operQualifier,attr,omitempty"`
OperationalQualifierReason string `xml:"operQualifierReason,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
PartNumber string `xml:"partNumber,attr,omitempty"`
Power string `xml:"power,attr,omitempty"`
Presence string `xml:"presence,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
SeepromOperationalState string `xml:"seepromOperState,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
ServiceState string `xml:"serviceState,attr,omitempty"`
Thermal string `xml:"thermal,attr,omitempty"`
ThermalStateQualifier string `xml:"thermalStateQualifier,attr,omitempty"`
UserLabel string `xml:"usrLbl,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
VersionHolder string `xml:"versionHolder,attr,omitempty"`
Vid string `xml:"vid,attr,omitempty"`
ComputeBlades []ComputeBlade `xml:"computeBlade"`
FanModules []EquipmentFanModule `xml:"equipmentFanModule"`
}
// ComputePhysical represents a physical specification of an abstract compute item.
// Serves as the base of physical compute nodes (e.g. blade, stand-alone computer or server).
type ComputePhysical struct {
FiniteStateMachineTask
AdminPower string `xml:"adminPower,attr,omitempty"`
AdminState string `xml:"adminState,attr,omitempty"`
AssignedToDn string `xml:"assignedToDn,attr,omitempty"`
Association string `xml:"association,attr,omitempty"`
Availability string `xml:"availability,attr,omitempty"`
AvailableMemory int `xml:"availableMemory,attr,omitempty"`
ChassisId string `xml:"chassisId,attr,omitempty"`
CheckPoint string `xml:"checkPoint,attr,omitempty"`
ConnPath string `xml:"connPath,attr,omitempty"`
ConnStatus string `xml:"connStatus,attr,omitempty"`
Description string `xml:"descr,attr,omitempty"`
Discovery string `xml:"discovery,attr,omitempty"`
DiscoveryStatus string `xml:"discoveryStatus,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
FltAggr int `xml:"fltAggr,attr,omitempty"`
IntId string `xml:"intId,attr,omitempty"`
Lc string `xml:"lc,attr,omitempty"`
LcTimestamp string `xml:"lcTs,attr,omitempty"`
LocalId string `xml:"localId,attr,omitempty"`
LowVoltageMemory string `xml:"lowVoltageMemory,attr,omitempty"`
ManagingInstance string `xml:"managingInst,attr,omitempty"`
MemorySpeed string `xml:"memorySpeed,attr,omitempty"`
ManufacturingTime string `xml:"mfgTime,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
NumOf40GAdaptorsWithOldFirmware int `xml:"numOf40GAdaptorsWithOldFw,attr,omitempty"`
NumOf40GAdaptorsWithUnknownFirmware int `xml:"numOf40GAdaptorsWithUnknownFw,attr,omitempty"`
NumOfAdaptors int `xml:"numOfAdaptors,attr,omitempty"`
NumOfCores int `xml:"numOfCores,attr,omitempty"`
NumOfCoresEnabled int `xml:"numOfCoresEnabled,attr,omitempty"`
NumOfCpus int `xml:"numOfCpus,attr,omitempty"`
NumOfEthHostInterfaces int `xml:"numOfEthHostIfs,attr,omitempty"`
NumOfFcHostInterfaces int `xml:"numOfFcHostIfs,attr,omitempty"`
NumOfThreads int `xml:"numOfThreads,attr,omitempty"`
OperationalPower string `xml:"operPower,attr,omitempty"`
OperationalPowerTransitionSource string `xml:"operPwrTransSrc,attr,omitempty"`
OperationalQualifier string `xml:"operQualifier,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
OriginalUuid string `xml:"originalUuid,attr,omitempty"`
PartNumber string `xml:"partNumber,attr,omitempty"`
PolicyLevel int `xml:"policyLevel,attr,omitempty"`
PolicyOwner string `xml:"policyOwner,attr,omitempty"`
Presence string `xml:"presence,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
ScaledMode string `xml:"scaledMode,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
ServerId string `xml:"serverId,attr,omitempty"`
SlotId int `xml:"slotId,attr,omitempty"`
TotalMemory int `xml:"totalMemory,attr,omitempty"`
UserLabel string `xml:"usrLbl,attr,omitempty"`
Uuid string `xml:"uuid,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
Vid string `xml:"vid,attr,omitempty"`
ComputeBoard ComputeBoard `xml:"computeBoard"`
AdaptorUnits []AdaptorUnit `xml:"adaptorUnit"`
ManagementController ManagementController `xml:"mgmtController"`
FirmwareStatus FirmwareStatus `xml:"firmwareStatus"`
BiosUnit BiosUnit `xml:"biosUnit"`
}
// ComputeBlade represents a physical compute blade.
// Physical compute item in blade form factor.
type ComputeBlade struct {
XMLName xml.Name `xml:"computeBlade"`
ComputePhysical
}
// ComputeRackUnit represents a physical compute RackUnit.
// Physical compute item representing a Rack mountable unit.
type ComputeRackUnit struct {
XMLName xml.Name `xml:"computeRackUnit"`
ComputePhysical
}
// ComputeServerUnit represents a server instance on a cartridge.
type ComputeServerUnit struct {
XMLName xml.Name `xml:"computeServerUnit"`
ComputePhysical
}
// ComputeItem type represents a container for all compute items,
// which include blades, rack units and stand-alone servers.
type ComputeItem struct {
XMLName xml.Name
Blades []ComputeBlade `xml:"computeBlade"`
RackUnits []ComputeRackUnit `xml:"computeRackUnit"`
ServerUnits []ComputeServerUnit `xml:"computeServerUnit"`
}
// ComputeBoard represents a motherboard contained by physical compute item.
type ComputeBoard struct {
XMLName xml.Name `xml:"computeBoard"`
CmosVoltage string `xml:"cmosVoltage,attr,omitempty"`
CpuTypeDescription string `xml:"cpuTypeDescription,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
FaultQualifier string `xml:"faultQualifier,attr,omitempty"`
Id int `xml:"id,attr,omitempty"`
LocationDn string `xml:"locationDn,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
OperationalPower string `xml:"operPower,attr,omitempty"`
OperationalQualifierReason string `xml:"operQualifierReason,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
Perf string `xml:"perf,attr,omitempty"`
Power string `xml:"power,attr,omitempty"`
PowerUsage string `xml:"powerUsage,attr,omitempty"`
Presence string `xml:"presence,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
Thermal string `xml:"thermal,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
Voltage string `xml:"voltage,attr,omitempty"`
MemoryArray MemoryArray `xml:"memoryArray"`
ProcessorUnits []ProcessorUnit `xml:"processorUnit"`
StorageController StorageController `xml:"storageController"`
}
// ComputeMbTempStats represents temperature values added by Nathan
// Properties are incomplete
type ComputeMbTempStats struct {
XMLName xml.Name `xml:"computeMbTempStats"`
Dn string `xml:"dn,attr,omitempty"`
FmTempSenIo string `xml:"fmTempSenIo,attr,omitempty"`
FmTempSenRear string `xml:"fmTempSenRear,attr,omitempty"`
}
// MemoryArray represents an array of memory units.
type MemoryArray struct {
XMLName xml.Name `xml:"memoryArray"`
ChildAction string `xml:"childAction,attr,omitempty"`
CpuId int `xml:"cpuId,attr,omitempty"`
CurrentCapacity int `xml:"currCapacity,attr,omitempty"`
ErrorCorrectionn string `xml:"errorCorrection,attr,omitempty"`
Id int `xml:"id,attr,omitempty"`
LocationDn string `xml:"locationDn,attr,omitempty"`
MaxCapacity int `xml:"maxCapacity,attr,omitempty"`
MaxDevices int `xml:"maxDevices,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
OperationalQualifierReason string `xml:"operQualifierReason,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
Perf string `xml:"perf,attr,omitempty"`
Populated int `xml:"populated,attr,omitempty"`
Power string `xml:"power,attr,omitempty"`
Presence string `xml:"presence,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
Thermal string `xml:"thermal,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
Voltage string `xml:"voltage,attr,omitempty"`
Units []MemoryUnit `xml:"memoryUnit"`
}
// MemoryUnit represents a single memory unit in a memory array.
type MemoryUnit struct {
XMLName xml.Name `xml:"memoryUnit"`
AdminState string `xml:"adminState,attr,omitempty"`
Array int `xml:"array,attr,omitempty"`
Bank int `xml:"bank,attr,omitempty"`
Capacity string `xml:"capacity,attr,omitempty"`
ChildAction string `xml:"childAction,attr,omitempty"`
Clock string `xml:"clock,attr,omitempty"`
FormFactor string `xml:"formFactor,attr,omitempty"`
Id int `xml:"id,attr,omitempty"`
Latency string `xml:"latency,attr,omitempty"`
Location string `xml:"location,attr,omitempty"`
LocationDn string `xml:"locationDn,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
OperationalQualifier string `xml:"operQualifier,attr,omitempty"`
OperationalQualifierReason string `xml:"operQualifierReason,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
Perf string `xml:"perf,attr,omitempty"`
Power string `xml:"power,attr,omitempty"`
Presence string `xml:"presence,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
Set int `xml:"set,attr,omitempty"`
Speed string `xml:"speed,attr,omitempty"`
Thermal string `xml:"thermal,attr,omitempty"`
Type string `xml:"type,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
Visibility string `xml:"visibility,attr,omitempty"`
Voltage string `xml:"voltage,attr,omitempty"`
Width string `xml:"width,attr,omitempty"`
}
// ProcessorUnit represents a single processor unit.
type ProcessorUnit struct {
XMLName xml.Name `xml:"processorUnit"`
Arch string `xml:"arch,attr,omitempty"`
ChildAction string `xml:"childAction,attr,omitempty"`
Cores int `xml:"cores,attr,omitempty"`
CoresEnabled int `xml:"coresEnabled,attr,omitempty"`
Id int `xml:"id,attr,omitempty"`
LocationDn string `xml:"locationDn,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
OperationalQualifierReason string `xml:"operQualifierReason,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
Perf string `xml:"perf,attr,omitempty"`
Power string `xml:"power,attr,omitempty"`
Presence string `xml:"presence,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
SocketDesignation string `xml:"socketDesignation,attr,omitempty"`
Speed string `xml:"speed,attr,omitempty"`
Stepping int `xml:"stepping,attr,omitempty"`
Thermal string `xml:"thermal,attr,omitempty"`
Threads int `xml:"threads,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
Visibility string `xml:"visibility,attr,omitempty"`
Voltage string `xml:"voltage,attr,omitempty"`
}
// AdaptorUnit is a managed object representing a network adaptor unit such as a
// card that has NIC and/or HBA, SCSI functionality.
type AdaptorUnit struct {
XMLName xml.Name `xml:"adaptorUnit"`
AdminPowerState string `xml:"adminPowerState,attr,omitempty"`
BaseMac string `xml:"baseMac,attr,omitempty"`
BladeId int `xml:"bladeId,attr,omitempty"`
CartridgeId int `xml:"cartridgeId,attr,omitempty"`
ChassisId string `xml:"chassisId,attr,omitempty"`
ChildAction string `xml:"childAction,attr,omitempty"`
ConnPath string `xml:"connPath,attr,omitempty"`
ConnStatus string `xml:"connStatus,attr,omitempty"`
DiscoveryStatus string `xml:"discoveryStatus,attr,omitempty"`
FltAggr int `xml:"fltAggr,attr,omitempty"`
Id int `xml:"id,attr,omitempty"`
Integrated string `xml:"integrated,attr,omitempty"`
LocationDn string `xml:"locationDn,attr,omitempty"`
ManagingInstance string `xml:"managingInst,attr,omitempty"`
ManufacturingTime string `xml:"mfgTime,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
OperationalQualifierReason string `xml:"operQualifierReason,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
PartNumber string `xml:"partNumber,attr,omitempty"`
PciAddress string `xml:"pciAddr,attr,omitempty"`
PciSlot string `xml:"pciSlot,attr,omitempty"`
Perf string `xml:"perf,attr,omitempty"`
Power string `xml:"power,attr,omitempty"`
Presence string `xml:"presence,attr,omitempty"`
Reachability string `xml:"reachability,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
Thermal string `xml:"thermal,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
Vid string `xml:"vid,attr,omitempty"`
Voltage string `xml:"voltage,attr,omitempty"`
AdaptorHostEthernetInterfaces []AdaptorHostEthernetInterface `xml:"adaptorHostEthIf"`
ManagementController ManagementController `xml:"mgmtController"`
}
// AdaptorHostEthernetInterface is a representation of a host-facing Ethernet interface
// on a server adaptor. A server adaptor has network facing interfaces (NIF), which
// provide network connectivity to the network (through the IO Module for UCS blades) and
// server facing interfaces (SIF), which are visible by the Operating System.
type AdaptorHostEthernetInterface struct {
FiniteStateMachineTask
XMLName xml.Name `xml:"adaptorHostEthIf"`
AdminState string `xml:"adminState,attr,omitempty"`
BootDev string `xml:"bootDev,attr,omitempty"`
CdnName string `xml:"cdnName,attr,omitempty"`
ChassisId string `xml:"chassisId,attr,omitempty"`
ChildAction string `xml:"childAction,attr,omitempty"`
Discovery string `xml:"discovery,attr,omitempty"`
EpDn string `xml:"epDn,attr,omitempty"`
FltAggr int `xml:"fltAggr,attr,omitempty"`
HostPort string `xml:"hostPort,attr,omitempty"`
Id int `xml:"id,attr,omitempty"`
InterfaceRole string `xml:"ifRole,attr,omitempty"`
InterfaceType string `xml:"ifType,attr,omitempty"`
Lc string `xml:"lc,attr,omitempty"`
LinkState string `xml:"linkState,attr,omitempty"`
Locale string `xml:"locale,attr,omitempty"`
Mac string `xml:"mac,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
Mtu int `xml:"mtu,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
OperationalQualifierReason string `xml:"operQualifierReason,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
Order int `xml:"order,attr,omitempty"`
OriginalMac string `xml:"originaMac,attr,omitempty"`
PciAddress string `xml:"pciAddr,attr,omitempty"`
PciFunc int `xml:"pciFunc,attr,omitempty"`
PciSlot int `xml:"pciSlot,attr,omitempty"`
PeerChassisId string `xml:"peerChassisId,attr,omitempty"`
PeerDn string `xml:"peerDn,attr,omitempty"`
PeerPortId int `xml:"peerPortId,attr,omitempty"`
PeerSlotId int `xml:"peerSlotId,attr,omitempty"`
Perf string `xml:"perf,attr,omitempty"`
PfDn string `xml:"pfDn,attr,omitempty"`
PortId int `xml:"portId,attr,omitempty"`
Power string `xml:"power,attr,omitempty"`
Presence string `xml:"presence,attr,omitempty"`
Purpose string `xml:"purpose,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
Side string `xml:"side,attr,omitempty"`
SlotId int `xml:"slotId,attr,omitempty"`
SwitchId string `xml:"switchId,attr,omitempty"`
Thermal string `xml:"thermal,attr,omitempty"`
Transport string `xml:"transport,attr,omitempty"`
Type string `xml:"type,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
VirtualizationPreference string `xml:"virtualizationPreference,attr,omitempty"`
VnicDn string `xml:"vnicDn,attr,omitempty"`
Voltage string `xml:"voltage,attr,omitempty"`
ManagementInterfaces []ManagementInterface `xml:"mgmtIf"`
}
// ManagementInterface encapsulates the configuration of a CIMC management interface.
type ManagementInterface struct {
FiniteStateMachineTask
XMLName xml.Name `xml:"mgmtIf"`
Access string `xml:"access,attr,omitempty"`
AdminState string `xml:"adminState,attr,omitempty"`
AggrPortId int `xml:"aggrPortId,attr,omitempty"`
ChassisId string `xml:"chassisId,attr,omitempty"`
ChildAction string `xml:"childAction,attr,omitempty"`
Discovery string `xml:"discovery,attr,omitempty"`
EpDn string `xml:"epDn,attr,omitempty"`
ExtBroadcast net.IP `xml:"extBroadcast,attr,omitempty"`
ExtGateway net.IP `xml:"extGw,attr,omitempty"`
ExtIp net.IP `xml:"extIp,attr,omitempty"`
ExtNetmask net.IP `xml:"extMask,attr,omitempty"`
Id int `xml:"id,attr,omitempty"`
InterfaceRole string `xml:"ifRole,attr,omitempty"`
InterfaceType string `xml:"ifType,attr,omitempty"`
InstanceId int `xml:"instanceId,attr,omitempty"`
Locale string `xml:"locale,attr,omitempty"`
Ip net.IP `xml:"ip,attr,omitempty"`
Mac string `xml:"mac,attr,omitempty"`
Netmask net.IP `xml:"mask,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
PeerAggrPortId int `xml:"peerAggrPortId,attr,omitempty"`
PeerChassisId string `xml:"peerChassisId,attr,omitempty"`
PeerDn string `xml:"peerDn,attr,omitempty"`
PeerPortId int `xml:"peerPortId,attr,omitempty"`
PeerSlotId int `xml:"peerSlotId,attr,omitempty"`
PortId int `xml:"portId,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
SlotId int `xml:"slotId,attr,omitempty"`
StateQual string `xml:"stateQual,attr,omitempty"`
Subject string `xml:"subject,attr,omitempty"`
SwitchId string `xml:"switchId,attr,omitempty"`
Transport string `xml:"transport,attr,omitempty"`
Type string `xml:"type,attr,omitempty"`
Vnet int `xml:"vnet,attr,omitempty"`
}
// EquipmentFanModule represents an inventoried Fan module.
// This object is created implicitly when a Fan module is detected during equipment discovery.
type EquipmentFanModule struct {
XMLName xml.Name `xml:"equipmentFanModule"`
ChildAction string `xml:"childAction,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
FltAggr int `xml:"fltAggr,attr,omitempty"`
Id int `xml:"id,attr,omitempty"`
ManufacturingTime string `xml:"mfgTime,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
OperationalQualifier string `xml:"operQualifier,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
PartNumber string `xml:"partNumber,attr,omitempty"`
Perf string `xml:"perf,attr,omitempty"`
Power string `xml:"power,attr,omitempty"`
Presence string `xml:"presence,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
Thermal string `xml:"thermal,attr,omitempty"`
Tray int `xml:"tray,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
Vid string `xml:"vid,attr,omitempty"`
Voltage string `xml:"voltage,attr,omitempty"`
Fans []EquipmentFan `xml:"equipmentFan"`
}
// EquipmentFan represents a fan in a Fan module.
type EquipmentFan struct {
XMLName xml.Name `xml:"equipmentFan"`
ChildAction string `xml:"childAction,attr,omitempty"`
FanSpeedPolicyAdminState string `xml:"fanSpeedPolicyAdminState,attr,omitempty"`
FanSpeedPolicyOperationalState string `xml:"fanSpeedPolicyOperState,attr,omitempty"`
FltAggr int `xml:"fltAggr,attr,omitempty"`
Id int `xml:"id,attr,omitempty"`
InternalType string `xml:"intType,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
Module int `xml:"module,attr,omitempty"`
OperationalQualifierReason string `xml:"operQualifierReason,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
Perf string `xml:"perf,attr,omitempty"`
Power string `xml:"power,attr,omitempty"`
Presence string `xml:"presence,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
Thermal string `xml:"thermal,attr,omitempty"`
Tray int `xml:"tray,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
Voltage string `xml:"voltage,attr,omitempty"`
}
// FiniteStateMachineTask represents the result of an FSM task.
type FiniteStateMachineTask struct {
FsmDescription string `xml:"fsmDescr,attr,omitempty"`
FsmFlags string `xml:"fsmFlags,attr,omitempty"`
FsmPrev string `xml:"fsmPrev,attr,omitempty"`
FsmProgress int `xml:"fsmProgr,attr,omitempty"`
FsmRemoteInvErrCode string `xml:"fsmRmtInvErrCode,attr,omitempty"`
FsmRemoteInvErrDescription string `xml:"fsmRmtInvErrDescr,attr,omitempty"`
FsmRemoteInvResult string `xml:"fsmRmtInvRslt,attr,omitempty"`
FsmStageDescription string `xml:"fsmStageDescr,attr,omitempty"`
FsmTimestamp string `xml:"fsmStamp,attr,omitempty"`
FsmStatus string `xml:"fsmStatus,attr,omitempty"`
FsmTry int `xml:"fsmTry,attr,omitempty"`
}
// FirmwareRunning is a representation of the primary firmware image (currently running).
type FirmwareRunning struct {
XMLName xml.Name `xml:"firmwareRunning"`
Deployment string `xml:"deployment,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
InvTag string `xml:"invTag,attr,omitempty"`
PackageVersion string `xml:"packageVersion,attr,omitempty"`
Type string `xml:"type,attr,omitempty"`
Version string `xml:"version,attr,omitempty"`
}
// FirmwareUpdatable is a representation of a backup firmware image for the chassis components
// that supports backup image (CMC, BMC, BIOS, Adaptor, etc).
type FirmwareUpdatable struct {
XMLName xml.Name `xml:"firmwareUpdatable"`
AdminState string `xml:"adminState,attr,omitempty"`
ChildAction string `xml:"childAction,attr,omitempty"`
Deployment string `xml:"deployment,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
OperationalStateQualifier string `xml:"operStateQual,attr,omitempty"`
PreviousVersion string `xml:"prevVersion,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
Version string `xml:"version,attr,omitempty"`
}
// FirmwareStatus represents a registered client for monitoring firmware update progress.
type FirmwareStatus struct {
XMLName xml.Name `xml:"firmwareStatus"`
ChildAction string `xml:"childAction,attr,omitempty"`
CimcVersion string `xml:"cimcVersion,attr,omitempty"`
FirmwareState string `xml:"firmwareState,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
PackageVersion string `xml:"packageVersion,attr,omitempty"`
PldVersion string `xml:"pldVersion,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
}
// StorageController represents a storage controller.
type StorageController struct {
XMLName xml.Name `xml:"storageController"`
AdminAction string `xml:"adminAction,attr,omitempty"`
AdminActionTrigger string `xml:"adminActionTrigger,attr,omitempty"`
ConfigState string `xml:"configState,attr,omitempty"`
ControllerOperations string `xml:"controllerOps,attr,omitempty"`
ControllerStatus string `xml:"controllerStatus,attr,omitempty"`
DefaultStripSize string `xml:"defaultStripSize,attr,omitempty"`
DeviceRaidSupport string `xml:"deviceRaidSupport,attr,omitempty"`
DiskOperations string `xml:"diskOps,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
FaultMonitoring string `xml:"faultMonitoring,attr,omitempty"`
HardwareRevision string `xml:"hwRevision,attr,omitempty"`
Id int `xml:"id,attr,omitempty"`
IdCount string `xml:"idCount,attr,omitempty"`
Lc string `xml:"lc,attr,omitempty"`
LocationDn string `xml:"locationDn,attr,omitempty"`
Mode string `xml:"mode,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
OnBoardMemoryPresent string `xml:"onBoardMemoryPresent,attr,omitempty"`
OnBoardMemorySize string `xml:"onBoardMemorySize,attr,omitempty"`
OobControllerId string `xml:"oobControllerId,attr,omitempty"`
OobInterfaceSupported string `xml:"oobInterfaceSupported,attr,omitempty"`
OperationalQualifierReason string `xml:"operQualifierReason,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
OpromBootStatus string `xml:"opromBootStatus,attr,omitempty"`
PartNumber string `xml:"partNumber,attr,omitempty"`
PciAddress string `xml:"pciAddr,attr,omitempty"`
PciSlot string `xml:"pciSlot,attr,omitempty"`
PciSlotRawName string `xml:"pciSlotRawName,attr,omitempty"`
Perf string `xml:"perf,attr,omitempty"`
PinnedCacheStatus string `xml:"pinnedCacheStatus,attr,omitempty"`
Power string `xml:"power,attr,omitempty"`
Presence string `xml:"presence,attr,omitempty"`
RaidBatteryOperations string `xml:"raidBatteryOps,attr,omitempty"`
RaidSupport string `xml:"raidSupport,attr,omitempty"`
RebuildRate string `xml:"rebuildRate,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
SubOemId string `xml:"subOemId,attr,omitempty"`
SupportedStripSizes string `xml:"supportedStripSizes,attr,omitempty"`
Thermal string `xml:"thermal,attr,omitempty"`
Type string `xml:"type,attr,omitempty"`
VariantType string `xml:"variantType,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
Vid string `xml:"vid,attr,omitempty"`
VirtualDriveOperations string `xml:"virtualDriveops,attr,omitempty"`
Voltage string `xml:"voltage,attr,omitempty"`
ManagementController ManagementController `xml:"mgmtController"`
FirmwareRunning []FirmwareRunning `xml:"firmwareRunning"`
}
// BiosUnit represents a BIOS unit.
type BiosUnit struct {
XMLName xml.Name `xml:"biosUnit"`
ChildAction string `xml:"childAction,attr,omitempty"`
InitSequence string `xml:"initSeq,attr,omitempty"`
InitTimestamp string `xml:"initTs,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
FirmwareRunning FirmwareRunning `xml:"firmwareRunning"`
FirmwareUpdatable FirmwareUpdatable `xml:"firmwareUpdatable"`
}
// ManagementController represents an instance of a management controller.
type ManagementController struct {
FiniteStateMachineTask
XMLName xml.Name `xml:"mgmtController"`
DesiredMaintenanceMode string `xml:"desiredMaintenanceMode,attr,omitempty"`
DimmBlackListingOperationalState string `xml:"dimmBlacklistingOperState,attr,omitempty"`
DiskZoningState string `xml:"diskZoningState,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
Guid string `xml:"guid,attr,omitempty"`
Id string `xml:"id,attr,omitempty"`
LastRebootReason string `xml:"lastRebootReason,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
OperationalConnection string `xml:"operConn,attr,omitempty"`
PowerFanSpeedPolicySupported string `xml:"powerFanSpeedPolicySupported,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
StorageOobConfigSupported string `xml:"storageOobConfigSupported,attr,omitempty"`
StorageOobInterfaceSupported string `xml:"storageOobInterfaceSupported,attr,omitempty"`
StorageSubsystemState string `xml:"storageSubsystemState,attr,omitempty"`
Subject string `xml:"subject,attr,omitempty"`
SupportedCapability string `xml:"supportedCapability,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
FirmwareRunning []FirmwareRunning `xml:"firmwareRunning"`
FirmwareUpdatable FirmwareUpdatable `xml:"firmwareUpdatable"`
ManagementInterfaces []ManagementInterface `xml:"mgmtIf"`
}
// StorageItem represents a storage item.
type StorageItem struct {
XMLName xml.Name `xml:"storageItem"`
AlarmType string `xml:"alarmType,attr,omitempty"`
ChildAction string `xml:"childAction,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
OperationalState string `xml:"operState,attr,omitempty"`
Rn string `xml:"rn,attr,omitempty"`
Size int `xml:"size,attr,omitempty"`
Used int `xml:"used,attr,omitempty"`
}
// NetworkElement represents a physical network element, such as a Fabric Interconnect.
type NetworkElement struct {
XMLName xml.Name `xml:"networkElement"`
AdminEvacState string `xml:"adminEvacState,attr,omitempty"`
AdminInbandInterfaceState string `xml:"adminInbandIfState,attr,omitempty"`
ChildAction string `xml:"childAction,attr,omitempty"`
DiffMemory int `xml:"diffMemory,attr,omitempty"`
Dn string `xml:"dn,attr,omitempty"`
ExpectedMemory int `xml:"expectedMemory,attr,omitempty"`
FltAggr int `xml:"fltAggr,attr,omitempty"`
ForceEvac string `xml:"forceEvac,attr,omitempty"`
Id string `xml:"id,attr,omitempty"`
InbandInterfaceGateway net.IP `xml:"inbandIfGw,attr,omitempty"`
InbandInterfaceIp net.IP `xml:"inbandIfIp,attr,omitempty"`
InbandInterfaceNetmask net.IP `xml:"inbandIfMask,attr,omitempty"`
InbandInterfaceVnet int `xml:"inbandIfVnet,attr,omitempty"`
InventoryStatus string `xml:"inventoryStatus,attr,omitempty"`
MinActiveFan int `xml:"minActiveFan,attr,omitempty"`
Model string `xml:"model,attr,omitempty"`
OobInterfaceGateway net.IP `xml:"oobIfGw,attr,omitempty"`
OobInterfaceIp net.IP `xml:"oobIfIp,attr,omitempty"`
OobInterfaceNetmask net.IP `xml:"oobIfMask,attr,omitempty"`
OobInterfaceMac string `xml:"oobIfMac,attr,omitempty"`
OperEvacState string `xml:"operEvacState,attr,omitempty"`
Operability string `xml:"operability,attr,omitempty"`
Revision string `xml:"revision,attr,omitempty"`
Serial string `xml:"serial,attr,omitempty"`
ShutdownFanRemoval string `xml:"shutdownFanRemoveal,attr,omitempty"`
Thermal string `xml:"thermal,attr,omitempty"`
TotalMemory int `xml:"totalMemory,attr,omitempty"`
Vendor string `xml:"vendor,attr,omitempty"`
FanModules []EquipmentFanModule `xml:"equipmentFanModule"`
ManagementController ManagementController `xml:"mgmtController"`
StorageItems []StorageItem `xml:"storageItem"`
}

View File

@@ -0,0 +1,5 @@
// Package version provides information about the current version of the API library.
package version
// Version is the version of the Cisco UCS API library.
const Version = "0.1.0"