Git Product home page Git Product logo

gofish's People

Contributors

abrander avatar dandann00dle avatar danile71 avatar danjpar avatar dependabot[bot] avatar iamsli avatar iurygregory avatar joelrebel avatar keithwegner avatar kozl avatar krishnan-priyanshu avatar leslie-qiwa avatar leslie-wang avatar lorenzb07 avatar micahhausler avatar muyk33rus avatar ncode avatar nrolans avatar nwaizer avatar pallasscat avatar prajwalpatil25 avatar richardelling avatar riethm avatar sn0rt avatar sosodev avatar stmcginnis avatar sungup avatar treydock avatar vsvastey avatar xflipped avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gofish's Issues

Request to add Name filed into the resources

Hi,

I am ultilizing this lib to construct a prometheus monitoring exporter, so lables with component Name is a good one to distinguish them. but resources such as Memory, drive volume ,PCIeDevice, Ethernetinterfaces ... etc. seems don't have Name field, and it is essential to have thie field to distinguish different type /name of the resource when getting the metrics.

Is there any concerns to add this filed ?

Provide control for cert validation

Commit 44bf7e0 disabled TLS cert validation to make it easier to connect to self-signed hosts. This is a security issue, so is less than ideal.

There may be some internal network environments where cert validation is not needed, especially in lab environments. But for normal production use, we should allow for enforcing certificate validity. Need some config or client creation argument so the consumer of the library has control over what works best for their situation.

OEM Specific Sensor data not available

Hi Sean,

I am curious if you plan to put OEM specific sensor data .

"/redfish/v1/Chassis/1/Oem/Lenovo/Sensors"

Do you plan to implement? Please let us know we can try that out and contribute back.

HostedServices field in ComputerSystem doesn't match Redfish Schema

I'm having difficulty with the redfish.GetComputerSystem() call returning the error:
json: cannot unmarshal object into Go struct field .HostedServices of type string

According to the Redfish Schema for ComputerSystem, the HostedServices field is a complex type. As such, the golang data model generated by openapi-generater from this schema defines HostedServices as follows:

type ComputerSystemV1130ComputerSystem struct { 
        ...
        HostedServices ComputerSystemV1130HostedServices `json:"HostedServices,omitempty"`
}

type ComputerSystemV1130HostedServices struct {
        // The OEM extension.
        Oem map[string]map[string]interface{} `json:"Oem,omitempty"`

        StorageServices OdataV4IdRef `json:"StorageServices,omitempty"`
}

Yet, the gofish library is attempting to unmarshal this object into a string as defined by the ComputerSystem struct:

type ComputerSystem struct {
...
	// HostedServices shall describe services supported by this computer system.
	HostedServices string

Changing the openapi-generated definition of HostedServices to a string in my Redfish API service resolves this error. Any explanation for this mismatch?

How to use the Settings object

Resource annotations such as "@Redfish.Settings" provide additional information about a property or a resource. See here for more details.

I am writing an application using gofish to configure the server BIOS attributes. In order to do that, I need to find the @Redfish.Settings term in this resource, and if it is found, then makes requests to change BIOS settings by modifying the resource identified by the @Redfish.Settings term.

I see the Settings object defined in types.go, but it is not part of the BIOS struct

Read rawData for an entity

Would it be reasonable to add a function to get a copy of the rawData for an entity? I've noticed that I often need to get some OEM specific data that gofish does not parse and I have to manually re-request and parse the entity JSON. I'd be glad to open a PR if you think this is reasonable 👍

cannot unmarshal object into Go struct field .SupportedLinkCapabilities of type []redfish.SupportedLinkCapabilities

Hi Sean,

Was trying to collect network port data but hit with below exception.

error: unable to get network adapter info: json: cannot unmarshal object into Go struct field .SupportedLinkCapabilities of type []redfish.SupportedLinkCapabilities

Dummy code we used:

func (r *RedfishConn) GetAdapterNetworkAddresses() (map[string][]interface{}, error) {	service := r.Client.Service
	// Query the chassis data using the session token
	chassis, err := service.Chassis()
	if err != nil {
		return nil, err
	}
	NetworkAdapterInfo := make(map[string][]interface{})	
for _, ch := range chassis {
		adapterNetworkAddresses, err := ch.NetworkAdapters()
		if err != nil {
			return nil, err
		}
		for _, networkAddresses := range adapterNetworkAddresses {
			Addresses, err := networkAddresses.NetworkPorts()
			if err != nil {
				return nil, err
			}			for _, address := range Addresses {
				info := make(map[string]string)
				info["AssociatedNetworkAddresses"] = address.AssociatedNetworkAddresses[0]
				info["PhysicalPortNumber"] = address.PhysicalPortNumber
				info["Type"] = string(address.ActiveLinkTechnology)
				NetworkAdapterInfo[networkAddresses.ID] = append(NetworkAdapterInfo[networkAddresses.ID], info)
			}
		}
	}	return NetworkAdapterInfo, err
}

Tried to debug the gofish lib. and found slice of SupportedLinkCapabilities is causing the problem.

Problematic piece of code: https://pkg.go.dev/github.com/stmcginnis/gofish/redfish#NetworkPort

type NetworkPort struct {
SupportedLinkCapabilities []SupportedLinkCapabilities
} 

I tried without slice and it worked for me.

type NetworkPort struct {
SupportedLinkCapabilities SupportedLinkCapabilities
}

Please have a look, if any more info is need let us know.

Error when creating a user using ManagerAccount

Hi Sean,

I tried creating a user using ManagerAccount and I got an error. Here is the code

func main() {
  config := gosih.ClientConfig{
    Endpoint: "BMC_IP",
    Username: "username",
    Password: "password",
    Insecure: true,
  }

  c, _ := gofish.Connect(config)
  defer c.Logout()

  mgr := &redfish.ManagerAccount{
    UserName: "new user",
    Password: "password",
    Enabled: true,
    RoleID: "Administrator",
  }
  mgr.ODataID = "/redfish/v1/AccoutService/Accounts/3"
  mgr.SetClient(c)

  if err := mgr.Update(); err != nil {
    fmt.Println("Error:", err)
  }
}

Error is "RoleID field is read only". It turns out, it will fail here https://github.com/stmcginnis/gofish/blob/main/redfish/manageraccount.go#L137 during comparison at https://github.com/stmcginnis/gofish/blob/main/common/types.go#L82

"RoleId" should be "RoleID".
I can create a PR for this and add a test if it is Ok with you.

regards,
Ferdinand

Data type for ReadingCelsius

Hi
I found that the type of ReadingCelsius may be not suitable.
I get the return value from Lenovo SR850, the value is a "ReadingCelsius": -42.8, it should be a float

....
{
      "UpperThresholdFatal": null,
      "PhysicalContext": "CPU",
      "LowerThresholdFatal": null,
      "UpperThresholdCritical": null,
      "RelatedItem": [
        {
          "@odata.id": "/redfish/v1/Systems/1/"
        },
        {
          "@odata.id": "/redfish/v1/Chassis/1/"
        },
        {
          "@odata.id": "/redfish/v1/Systems/1/Processors/4"
        }
      ],
      "Status": {
        "State": "Enabled"
      },
      "SensorNumber": 238,
      "Name": "CPU 4 DTS",
      "MaxReadingRangeTemp": 0,
      "UpperThresholdNonCritical": null,
      "@odata.id": "/redfish/v1/Chassis/1/Thermal/#/Temperatures/7",
      "@odata.type": "#Thermal.v1_3_0.Temperature",
      "MinReadingRangeTemp": -51,
      "MemberId": "CPU_4_DTS",
      "LowerThresholdNonCritical": null,
      "LowerThresholdCritical": null,
      "ReadingCelsius": -42.8
    },
....
		chassisThermal, err := chasssis.Thermal()
		if err !=nil {
			log.Fatalf("Errors Getting  Thermal from chassis : %s",err)
		}

so I got following error

Errors Getting   Thermal from chassis : json: cannot unmarshal number -42.8 into Go struct field .ReadingCelsius of type int  source="chassis_collector.go:164"

Created a pull request for this #12

Several json unmarshal errors

Hi @stmcginnis , from my project redfish-exporter some users reported some json unmarshal error

  1. Processor.Metrics on Lenovo SR630, our definition is a string, but on his device it is a link
{
    "ProcessorArchitecture": "x86",
    "Metrics": {
        "@odata.id": "/redfish/v1/Systems/1/Processors/1/ProcessorMetrics"
    },
  1. Memory.Location, our definition is a string, but on his device it is a map
    "Location": {
        "PartLocation": {
            "LocationType": "Slot",
            "ServiceLabel": "DIMM 5",
            "LocationOrdinalValue": 4
        }
    },

but from https://redfish.dmtf.org/redfish/mockups/v1/922#, we can use
MemoryLocation for memory, instead of big changes of Location as it may exist else where

    "MemoryLocation": {
        "Channel": 0,
        "MemoryController": 0,
        "Slot": 5,
        "Socket": 1
    },

currently Location exist in Chassis and Memory

Capability of adding custom headers in HTTP calls

Hello Sean,

I've been thinking for a while about an issue that we could face regarding including headers using the different methods this library has (Get, Post, PostMultipart, Put, Patch, Delete, runRequest and runRequestWithMultipartPayload).

All of above method eventually use runRawRequest method to perform the call to the server.

It turns out that runRawRequest has an argument in its signature called contentType and that allow to set the header Content Type to whatever. But what if I need to set a different header (custom one)? Current implementation doesn't allow to do this.

Would you be open to modify current implementation to add an argument to all above methods so it allows adding custom headers to the different HTTP requests? I.e:

func (c *APIClient) Post(url string, payload interface{}, customHeaders map[string]string) (*http.Response, error) {
	return c.runRequest(http.MethodPost, url, payload)
}

I need this because, I'm trying to create a Resource in our Terraform project that upgrades firmware. In order to do so, before using PostMultipart to upload the package, we need to get the Etag from the Firmware/Software repository, and then do a PostMultipart with a custom header with "If-Match" as key and the Etag value as value.

What do you think?
Thanks!
/Miguel

Scripted import of schema

Sean, I started looking at importing the full schema from dmtf.org for redfish. I cleaned up some issues with the .py script around legitimate identifiers in the output code, but source.go doesn't appear to match up well with the code already in the library. Is that expected, or does source.go need a bunch of updates?
Stuff yet to do:

  1. lots of redeclaration issues (ex: OemActions, Links)
  2. serialinterface and switch objects have some identifier issues on import to be dealt with

Oh and....small world, eh?

Basic Auth

How do I use Basic Auth with this library?

Flatten module structure

Due to some earlier design ideas, all schema objects were placed under a "school" directory. This really isn't needed now. Most code aliases school to gofish anyway, so the school directory level should just go away and move the schema objects up a level.

Request add OEM object under redfish computesystem to fetch metrics for BMC

Hi,
request to add OEM object under redfish computesystem, as under oem, I can see that redfish expose all metrics data /redfish/v1/Systems/1/Oem/Lenovo/Metrics/

{
  "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/",
  "[email protected]": 16,
  "@odata.context": "/redfish/v1/$metadata#LenovoHistoryMetricValueContainerCollection.LenovoHistoryMetricValueContainerCollection",
  "Members": [
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/SystemInputPower"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/SystemOutputPower"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/CPUSubsystemPower"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/MemorySubsystemPower"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/PowerSupplyInputPower1"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/PowerSupplyInputPower2"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/PowerSupplyOutputPower1"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/PowerSupplyOutputPower2"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/SystemPerformance"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/CPUSubsystemPerformance"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/MemorySubsystemPerformance"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/IOSubsystemPerformance"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/InletAirTemp"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/OutletAirTemp"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/ExpansionInletAirTemp"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/ExpansionOutletAirTemp"
    }
  ],
  "@odata.type": "#LenovoHistoryMetricValueContainerCollection.LenovoHistoryMetricValueContainerCollection",
  "[email protected]": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/Members",
  "@odata.etag": "W/\"3782fe24455209818097e08bdd8f76d5\"",
  "Name": "Historical Metrics",
  "Description": "A Collection of HistoryMetricValueContainer resource instances."
}

we can get the merics root uri via

curl -u user:pass https://10.36.48.23/redfish/v1/Systems/1/|  jq .Oem[].Metrics
{
  "@odata.id": "/redfish/v1/Systems/1/Oem/Lenovo/Metrics/"
}

Default Paths are not respected by different vendors

Hello @stmcginnis,

I've started running the gofish against all of our vendors and I found out (sadly but kinda expected) that they don't respect the "Default.Path". So we would need to update the values that are constants today to become variables, or stick to the "ListReferenced." to retrieve all objects that you are doing already. I've started working the second approach, so I would like to double check if you agree with that.

I've added to screenshots that reflect that on the session path, but I'm also seeing it against other paths.

Sessions
SessionServiceSessions

Relicense to BSD 3-Clause license

There is some talk underway of moving this library to either SNIA or DMTF to be an official project hosted there. Nothing would really change, other than that both organizations require the use of the BSD 3-Clause license for any of their open source projects. This would be relicensing Gofish before then.

At a high level, the main difference between Apache 2 and BSD 3-Clause is the implicit patent grant. More details and a comparison can be found here:

https://choosealicense.com/appendix/

@ncode and @mike-pittelko, since you both have contributed code to this library, it would be great to get your ack on this to know if you are good with the license change, or if there are any concerns you have about doing so.

pass context throughout

Hey, great library! thanks so much for all the hard work!

I was wondering if you'd be open to a PR to add context throughout? It'd obviously be a pretty breaking change as most of the function/method signatures would need to be changed.

Make unexported Storage.volumes string exportable

Hello Sean,

I'm trying to create a volume in a raid disk controller using the API, and I'm wondering the following:
It turns out that in the redfish.Storage struct, you have an unexported field (Storage.volumes string) where you keep the @OData link reference to the volumes endpoint for that particular Disk controller. Since it is unexported, I cannot get it and can't perform volume creation for a particular disk controller.

I've been looking and I didn't find any way in the API to get the link to the volumes endpoint for a particular disk controller (storage struct).

Is it possible to make this field exportable? (change volumes by Volumes), something like below:

type Storage struct {
	common.Entity
	...
	
	// Volumes is a collection that indicates all the volumes produced by the
	// storage controllers that this resource represents.
	Volumes string
	
	...
}

If there are other ways of getting the volumes endpoint for a particular disk controller, I'd appreciate you mention it please 😄

Thanks!
/Miguel

APIClient.Delete method just return error and not the HTTP response itself

Hello Sean,

I've noticed that the *APIClient.Delete() method just returns an error interface saying if there was any issue with that call. The rest of HTTP method calls return also the a *http.Response object.
I think having also the *http.Response object returned from the Delete method is also very useful. Let me highlight that with an example. Please see the image below:

deletemethod

I'm trying to get rid of a virtual disk. To do that, I need to perform a Delete onto /redfish/v1/Systems/<ComputerSystem-Id>/Storage/<Storage-Id>/Volumes.

The operation is not done rightaway. In my case, the iDRAC, which is the controller that implements the RedfishAPI, creates a job. Then I need to record the job completion status, to see if that was ok or not.
In the Delete response headers, you can see the Location header, which is a link to that. I need to get that for checking the job status. Unfortunately in the current implementation I cannot get that because the Delete() method only returns an error.

Would you be open to accept a PR where apart from the error status also returns a *http.Response object?

Many thanks!
/Miguel

Type errors and missing items

Hi,

from real test, found found type errors

  1. power votage type error, most of them are float not int, so need to change to float32
  2. power metrcs also are float for watts, so also need to change to float32
  3. Redundancy. RedundancySet should be common.Links not string
  4. not sure why common.Entity is removed from chassis objects, such as temperature/fan/power....

some resources are not exporter in computerSyste

Hi,

the struct ComputerSystem has some resources referenced but not exporter, for example
memory,processor, bios,ethernetInterfaces , networkInterfaces , pcieDevices , pcieFunctions .
so it is impossible to retrive the these resource.

I understood that we already have defined Memory in other place, but here we can use a MemoryLink or just Memories to refer to this resource, as they are actually links.

for example here is the data retrieved from a commputersystem resource

"NetworkInterfaces": {
    "@odata.id": "/redfish/v1/Systems/1/NetworkInterfaces/"
  },
  "Storage": {
    "@odata.id": "/redfish/v1/Systems/1/Storage/"
  },
  "PartNumber": null,
  "Bios": {
    "@odata.id": "/redfish/v1/Systems/1/Bios/"
  },
  "EthernetInterfaces": {
    "@odata.id": "/redfish/v1/Systems/1/EthernetInterfaces/"
  },
"PCIeFunctions": [
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeFunctions/ob_1.00"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeFunctions/slot_2.00"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeFunctions/slot_2.01"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeFunctions/slot_7.00"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeFunctions/slot_7.01"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeFunctions/slot_8.00"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeFunctions/slot_8.01"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeFunctions/slot_9.00"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeFunctions/slot_9.01"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeFunctions/slot_10.00"
    }
  ],
"[email protected]": 10,
  "Processors": {
    "@odata.id": "/redfish/v1/Systems/1/Processors/"
  },
"PCIeDevices": [
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/ob_1"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/slot_2"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/slot_7"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/slot_8"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/slot_9"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/slot_10"
    }
  ],
"[email protected]": "/redfish/v1/Systems/1/PCIeDevices",
  "[email protected]": 6,
  "[email protected]": "/redfish/v1/Systems/1/PCIeFunctions",
  "LogServices": {
    "@odata.id": "/redfish/v1/Systems/1/LogServices/"
  },

  "Memory": {
    "@odata.id": "/redfish/v1/Systems/1/Memory/"
  }

Can't ge PCIDevices from function ListReferencedPCIeDevices()

Hi
I am tring to get all pcidevices via ListReferencedPCIeDevices(s.redfishClient, pciDevicesLink), with pciDevicesLink=/redfish/v1/Systems/1/PCIeDevices but got empty response.
but actually have pcidevices return via curl

 curl -k  -u 'user:pass'  https://10.36.48.23/redfish/v1/Systems/1/PCIeDevices|jq .
{
  "value": [
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/ob_1"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/ob_2"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/ob_3"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/ob_4"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/slot_1"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/slot_2"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/PCIeDevices/slot_4"
    }
  ]
}

after further examination, we found that resouces such Chassis, ComputerSystem,Memory,Processor,Storage,Voume that is collection , which has a field Name in json output, and it is a single URI in parent resource

 curl -k  -u 'user:pass' https://10.36.48.23/redfish/v1/Systems/1/Processors/|jq .
{
  "@odata.id": "/redfish/v1/Systems/1/Processors/",
  "[email protected]": 2,
  "@odata.context": "/redfish/v1/$metadata#ProcessorCollection.ProcessorCollection",
  "Members": [
    {
      "@odata.id": "/redfish/v1/Systems/1/Processors/1"
    },
    {
      "@odata.id": "/redfish/v1/Systems/1/Processors/2"
    }
  ],
  "Oem": {
    "Lenovo": {
      "HistoryCPUMetric": {
        "@odata.id": "/redfish/v1/Systems/1/Processors/Oem/Lenovo/HistoryCPUMetric"
      }
    }
  },
  "@odata.type": "#ProcessorCollection.ProcessorCollection",
  "[email protected]": "/redfish/v1/Systems/1/Processors/Members",
  "@odata.etag": "W/\"91e56b139d17a1bb56e7c8fb0eb840ed\"",
  "Name": "ProcessorCollection",
  "Description": "A Collection of Processor resource instances."
}

but for pciedevice and pciefunction , it is not a collection,so common.GetCollection() will return nothing

BUG: CreateFormFile method expects just filename, not full filepath

Hey Sean,

I was trying to implement SimpleUpdate in our terraform provider and, when uploading FW packages to the FW inventory, I found out that the API was returning a 500 error with no error description (favorite developer kind of issue 😆 ). It was driving me crazy but after a while I saw the following (please check line 387):

gofish/client.go

Lines 385 to 389 in f20250a

if file, ok := reader.(*os.File); ok {
// Add a file stream
if partWriter, err = payloadWriter.CreateFormFile(key, file.Name()); err != nil {
return nil, err
}

As per current implementation, on CreateFormFile method, we use as filename the file.Name() method, which actually returns the whole path of the file.

To solve this, we need to just grab the filename from the path, using for instance filepath.Base() method. Something like this

if file, ok := reader.(*os.File); ok {
			// Add a file stream
			if partWriter, err = payloadWriter.CreateFormFile(key, filepath.Base(file.Name())); err != nil {
				return nil, err
			}

I will send a PR that implements that, just wanted to open this issue for reference, just in case anyone else faces the same in the future.

Thanks!
/Miguel

Local channel connection?

Using this lib, is it possible to connect to the local BMC without a network connection? For example, ilorest uses ilorest_chif.so to communicate without need for an IP.

If not implemented, any thoughts on how difficult it'd be? I've not seen specs for how HPE communicates, though I'm not sure whether that's because it is proprietary or if I merely haven't looked hard enough.

Access links object for manager, ethernet interfaces, etc

Need access links object to further retrieve more information. For example, need to retrieve dell OEM attributes through manager API.

  "Links": {
    "Oem": {
      "Dell": {
        "DellAttributes": [
          {
            "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/Attributes"
          },
          {
            "@odata.id": "/redfish/v1/Managers/System.Embedded.1/Attributes"
          },
          {
            "@odata.id": "/redfish/v1/Managers/LifecycleController.Embedded.1/Attributes"
          }
        ],

PowerSupply.EfficiencyPercent is a float on Dell iDRAC

Hello,

I have a problem using https://github.com/jenningsloy318/redfish_exporter on Dell servers. It crashes because it can't unmarshal a float number into an integer field.

The problem is EfficiencyPercent, which is int. In my case, Redfish returns a float of 0.920000016689301.

Looking at https://redfish.dmtf.org/schemas/v1/Power.v1_6_0.json, this number is suppose to be between 0 and 100 and unit is %. So the Dell's answer is not OK.

Is this something that could be fixed on the gofish side or should I try my luck with Dell?

Release v0.10.0 ?

Hi @stmcginnis

Could you please tag a new version (v0.10.0) to start using the new *WithHeaders methods from the library?

Many thanks 😄
/Miguel

Able to get NetworkAdapter ID

Based on https://redfish.dmtf.org/schemas/v1/NetworkAdapter.v1_5_0.json, each network adapter has ID field to identify the adapter. Seems like current NetworkAdapter doesn't have the member variable.

        "NetworkAdapter": {
...
            "properties": {
                "@odata.context": {
                    "$ref": "http://redfish.dmtf.org/schemas/v1/odata-v4.json#/definitions/context"
                },
                "@odata.etag": {
                    "$ref": "http://redfish.dmtf.org/schemas/v1/odata-v4.json#/definitions/etag"
                },
                "@odata.id": {
                    "$ref": "http://redfish.dmtf.org/schemas/v1/odata-v4.json#/definitions/id"
                },
...
                "Id": {
                    "$ref": "http://redfish.dmtf.org/schemas/v1/Resource.json#/definitions/Id",
                    "readonly": true
                },

Session auth failed

Hi
I use following code for auth similar with example but still failed.

url := fmt.Sprintf("https://%s", host)

	// skip ssl verification
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}

	httpClient := &http.Client{Transport: tr}

	log.Infof(url)
	// Create a new instance of gofish client
	 redfishClient,err := gofish.APIClient(url,httpClient)
	 if  err != nil {
		log.Fatalf("Errors occours when Creating redfish client: %s",err)
		return redfishClient, false
	}

	 service, err := gofish.ServiceRoot(redfishClient)
	 if err != nil {
		log.Fatalf("Errors occours when Getting Services: %s",err)
		return redfishClient, false
	}

	// Generates a authenticated session
	auth, err := service.CreateSession(username, password)

	if err != nil {
		log.Fatalf("Errors occours when creating sessions: %s",err)
		return redfishClient, false
	}

	// Assign the token back to our gofish client
	redfishClient.Token = auth.Token	
	 
	return redfishClient,true

the error message

INFO[0095] auth %!s(*redfish.AuthToken=<nil>)            source="exporter.go:185"
FATA[0095] Errors occours when creating sessions: 401: {"error":{"@Message.ExtendedInfo":[{"Resolution":"You are required to log on Web Server with valid credentials first.","@odata.type":"#Message.v1_0_5.Message","Severity":"Critical","Message":"The request requires user authentication which has not yet been provided or invalid.","RelatedProperties":[],"MessageId":"StandardError.1.1.Unauthorized","MessageArgs":[]}],"code":"Base.1.1.GeneralError","message":"A general error has occurred. See ExtendedInfo for
more information."}}  source="exporter.go:188"

Add session management

I'm currently developing a Redfish-based Icinga check and would like to avoid spamming my iLO event log with "admin connection" entries - and I think this would go towards avoiding problems like in #75, too. The idea is to get a session token once and preserve it in-between plugin invocations by writing it to a session file, performing as new login only if the old one should have timed out. To do this, I'd need APIClient.auth exported though. At least that's how I hacked it for now - although that way I have to basically duplicate the second part of gofish.Connect(); perhaps it would be better to add an Auth member to ClientConfig and check in Connect() whether this or a username has been provided.

Tag v0.9.0 version

Hi Sean,

Could you please tag main branch with v0.9.0 please?

It's been implemented new features I'd like since two months ago. I'd really appreciate it 😄

Have a nice day!
/Miguel

Creation a Session does not conform to DMTF Specification

Hey,

So we're running into a weird issue on about 20 or so SuperMicro devices where the redfish endpoint /redfish/v1/SessionService/Sessions is returning a 401 unauthorized (It returns a 401 even when using an admin user). This seems to be preventing a redfish client from being created. Below is the code used to create a gofish/redfish client.

func newRedfishClient(host string, username string, password string) (*gofish.APIClient, error) {

	url := fmt.Sprintf("https://%s", host)

	config := gofish.ClientConfig{
		Endpoint: url,
		Username: username,
		Password: password,
		Insecure: true,
	}
	redfishClient, err := gofish.Connect(config)
	if err != nil {
		return nil, err
	}
	return redfishClient, nil
}

Is there any workaround?

Client not set for child objects

Most objects contain links to use to fetch child objects. There are a few (at least PowerSupply and Thermal) that include the full object in the returned JSON. Since these objects are not fetched directly, they never have their client references set. This means if someone then tries to call Update() or any action methods on the object it will fail when trying to use the client to send the update.

The workaround is to use the object.ODataID to fetch the object directly from the system, then operating on that object to update. This is less than ideal though.

One approach may be to change these to private fields of the parent struct, then provide an access method to call to get them. This would be similar behavior to how linked objects are handled. We could then set the client reference prior to returning the objects through this call.

Another option may be to handle these child objects in the UnmarshalJSON calls of the parent object and set the client reference at that point.

Error: The maximum number of user sessions is reached

Got this error when I play around with one server. I did have defer client.Logout(), but not sure where the problem is. Can someone please help?

[LOG][7/2 - 22:49:05]: 503: {"error":{"@Message.ExtendedInfo":[{"Message":"The maximum number of user sessions is reached.","MessageArgs":[],"[email protected]":0,"MessageId":"IDRAC.2.1.RAC0218","RelatedProperties":[],"[email protected]":0,"Resolution":"Close one or more sessions before opening another session.","Severity":"Informational"}],"code":"Base.1.5.GeneralError","message":"A general error has occurred. See ExtendedInfo for more information"}}

Need ability to create new user accounts and roles

There is currently no way to create new objects, other than figuring out the correct URL to use and crafting the JSON content to POST directly to the service through the client object. This should be handled in gofish in a nicer, more user friendly way.

Way gofish.Service is retrieved

Hello Sean,

Just writing you this issue because I wanted to know if it makes sense the change down below before going right away and create a PR.

The Service struct is retrieved once you have an APIClient created. Actually the field Service in API client is exportable and you get it like (where client is an instance of (*gofish.APIClient)):

service := client.Service

Since I'm thinking about the possibility of mocking the client and use it for testing across our Terraform provider project, I don't know if it makes sense the following:

On common.Client interface, add a method like GetRootService() *gofish.Service (or whatever name that describes that better):

type Client interface {
	Get(url string) (*http.Response, error)
	Post(url string, payload interface{}) (*http.Response, error)
	Patch(url string, payload interface{}) (*http.Response, error)
	Put(url string, payload interface{}) (*http.Response, error)
	Delete(url string) (*http.Response, error)
        GetRootService()(*gofish.Service)
}

Then, on gofish.APIClient, make Service unexported, and create a method that retrieves it:

func (c *APIClient) GetRootService() *gofish.Service{
    return c.service
}

I think that would give us the possibility of using a mocked object across our code to test the different functions. So far is impossible because the client interface does not provide any signature to get the Service struct.

I know it is a significant change on the API, but I think it's worth the discussion 😄

Unable to execute request, no target provided error

I am getting an ‘Unable to execute request, no target provided’ error when using a ClientConfig in gofish.Connect(). This seems to be happening when trying to create a Redfish session. From what I can tell in doing a little debugging in serviceroot.go the serviceroot.sessions is an empty string.

My Redfish host is using href in the Links object (ServiceRoot.1.0.0):

Capture

If I change serviceroot.go to this it works for me:

Links struct {
Sessions struct {
Href string json:"href"
}
}

Unable to list BIOS attributes?

Hi guys,

I'm trying to list BIOS attribute but it seems that I'm missing something.

	config := gofish.ClientConfig{
		Endpoint: "https://" + credentials.DriverInfo.IpmiAddress,
		Username: credentials.DriverInfo.IpmiUsername,
		Password: credentials.DriverInfo.IpmiPassword,
		Insecure: true,
	}
	c, err := gofish.Connect(config)
	if err != nil {
		fmt.Print(err)
	}
	service := c.Service
	systems, _ := service.Systems()

	for _, system := range systems {
		bios, _ := system.Bios()
		fmt.Print(bios)
	}

I got this output but no attributes.

&{{Bios BIOS Configuration Current Settings 0xc000dc6870} /redfish/v1/$metadata#Bios.Bios  /redfish/v1/Systems/System.Embedded.1/Bios #Bios.v1_0_2.Bios BiosAttributeRegistry.v1_0_0 BIOS Configuration Current Settings /redfish/v1/Systems/System.Embedded.1/Bios/Actions/Bios.ChangePassword /redfish/v1/Systems/System.Embedded.1/Bios/Actions/Bios.ResetBios}

How can I display the content of BIOS Configuration Current Settings ?
Using a simple curl display what I expect.

Error structure in 400 reply

When the request could not be processed because it contains missing or invalid information (such as validation error on an input field, a missing required value, and so on), redfish will return an extended error in the response body, as defined in clause Error Responses. To help client make smart decision, it is better that the package can detect and return the error if possible.

refer
http://redfish.dmtf.org/schemas/DSP0266_1.0.html#status-codes
http://redfish.dmtf.org/schemas/DSP0266_1.0.html#error-responses

RedFish - Power MemberID & Processor MaxMHz Invalid

Hey so I'm currently using the RedFish prometheus exporter which uses this library for interacting with the RedFish API. During scraping of targets I get the below errors:

2020/11/24 15:35:14 error error getting power data from chassis Chassis=Self app=redfish_exporter collector=ChassisCollector error=json: cannot unmarshal number into Go struct field PowerControl.PowerControl.MemberId of type string operation=chassis.Power() target=

2020/11/24 15:35:28 error error getting processor data from system System=Self app=redfish_exporter collector=SystemCollector error=json: cannot unmarshal string into Go struct field .MaxSpeedMHz of type int operation=system.Processors() target=

Upon further investigation of the data returned by the Dell hardware it seems that the MemberID field isn't always a string and is sometimes cast to a number. Also looks like our specific models are not capturing the MaxSpeedMHz of the processors and are just returning an empty string.

https://gist.github.com/RyanW8/42803cee457e5ebe6d198a2141224be6 This is for PowerControl Grabbed using https://<host_ip>/redfish/v1/Chassis/Self/Power. Looks to be that some MemberIDs are strings and some are numbers

https://gist.github.com/RyanW8/74c4904706b486e0862703d96c5f9235 This is the CPU information. Grabbed using https://<host_ip>/redfish/v1/System/Self/Processors/1 & https://<host_ip>/redfish/v1/System/Self/Processors/2. Looks like MaxSpeedMHz isn't set.

Would it be possible to add in fixes into this library?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.