stmcginnis / gofish

Gofish is a Golang client library for DMTF Redfish and SNIA Swordfish interaction.
BSD 3-Clause "New" or "Revised" License
211 stars 113 forks source link

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

Closed SupriyoSahana07 closed 5 months ago

SupriyoSahana07 commented 3 years ago

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.

stmcginnis commented 3 years ago

Thanks @SupriyoSahana07. It looks like either the spec documentation is not correct, or the implementation on your platform is not following the spec.

It is defined as "type": "array" here:

                "SupportedLinkCapabilities": {
                    "description": "The link capabilities of this port.",
                    "items": {
                        "$ref": "#/definitions/SupportedLinkCapabilities"
                    },
                    "longDescription": "This property shall describe the static capabilities of the port, irrespective of transient conditions such as cabling, interface module presence, or remote link partner status or configuration.",
                    "type": "array"
                },

Looking at the definition of SupportedLinkCapabilities though, I don't really see why this property would be an array, so it very well may be that the spec docs are inaccurate in this case.

If possible, it would be great to get the JSON output if you can curl (or even go in a web browser) the chassis network info. Then I could use that to add unit test coverage. It would be something like curl https://example.com/redfish/v1/Chassis/[chassis_id]/NetworkAdapters/[adapter_id]

stmcginnis commented 3 years ago

Hmm, they do clearly call out it is an array in the full schema guide: http://redfish.dmtf.org/schemas/DSP2046_2020.4.html

If you search for SupportedLinkCapabilities there, you will see they show it is an array of items. So it looks like your system is not fully compliant with the spec. Maybe check if there are any firmware upgrades in case your vendor has fixed this issue in a newer release. Otherwise it might be worth pointing out to them that they have an error in their implementation.

If you can still get an example output from your system, I may be able to use that to figure out a way to hide the fact that it is not following the spec.

SupriyoSahana07 commented 3 years ago

Hi Sean,

Thanks for response. Please find below o/p for REST /redfish/v1/Chassis/1/NetworkAdapters/slot-3/NetworkPorts

{
  "SerialNumber": "XXXXXX",
  "SKU": "XXXX",
  "NetworkDeviceFunctions": {
    "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters/slot-3/NetworkDeviceFunctions"
  },
  "Id": "slot-3",
  "Status": {
    "State": "Enabled",
    "Health": "OK"
  },
  "PartNumber": "XXXXX",
  "Name": "Broadcom 57414 10/25GbE SFP28 2-port PCIe Ethernet Adapter",
  "NetworkPorts": {
    "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters/slot-3/NetworkPorts"
  },
  "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters/slot-3",
  "Oem": {
    "Lenovo": {
      "@odata.type": "#LenovoDeviceInfo.v1_0_0.LenovoDeviceInfo",
      "UUID": "XXXXX"
    }
  },
  "@odata.type": "#NetworkAdapter.v1_3_1.NetworkAdapter",
  "Controllers": [
    {
      "ControllerCapabilities": {
        "NetworkDeviceFunctionCount": 2,
        "NetworkPortCount": 2
      },
      "FirmwarePackageVersion": "214.0.241.0",
      "Location": {
        "PartLocation": {
          "LocationType": "Slot",
          "ServiceLabel": "PCIe 3",
          "LocationOrdinalValue": 3
        },
        "InfoFormat": "Slot X",
        "Info": "Slot 3",
        "Info@Redfish.Deprecated": "The property is deprecated. Please use PartLocation instead.",
        "InfoFormat@Redfish.Deprecated": "The property is deprecated. Please use PartLocation instead."
      },
      "Links": {
        "NetworkPorts": [
          {
            "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters/slot-3/NetworkPorts/1"
          },
          {
            "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters/slot-3/NetworkPorts/2"
          }
        ],
        "NetworkDeviceFunctions": [
          {
            "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters/slot-3/NetworkDeviceFunctions/1.1"
          },
          {
            "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters/slot-3/NetworkDeviceFunctions/2.1"
          }
        ],
        "PCIeDevices": [
          {
            "@odata.id": "/redfish/v1/Chassis/1/PCIeDevices/slot_3"
          }
        ]
      },
      "PCIeInterface": {
        "LanesInUse": 8,
        "MaxPCIeType": "Gen3",
        "MaxLanes": 8,
        "PCIeType": "Gen3"
      }
    }
  ],
  "Manufacturer": "Broadcom Limited",
  "@odata.etag": "\"c50841373f702d25c0666\"",
  "Model": "XXXX",
  "Description": "A NetworkAdapter represents the physical network adapter capable of connecting to a computer network."
}

Even posting o/p for REST redfish/v1/Chassis/1/NetworkAdapters/slot-3/NetworkPorts/2

{
  "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters/slot-3/NetworkPorts/2",
  "CurrentLinkSpeedMbps": 25000,
  "NetDevFuncMaxBWAlloc": [
    {
      "MaxBWAllocPercent": 100,
      "NetworkDeviceFunction": {
        "@odata.id": "/redfish/v1/Chassis/1/NetworkAdapters/slot-3/NetworkDeviceFunctions/2.1"
      }
    }
  ],
  "Id": "2",
  "Status": {
    "State": "Enabled",
    "Health": "OK",
    "HealthRollup": "OK"
  },
  "Description": "A Network Port represents a discrete physical port capable of connecting to a network.",
  "Name": "Phyical Port 2",
  "PortMaximumMTU": 72000,
  "AssociatedNetworkAddresses": [
    "XXXX"
  ],
  "Oem": {
    "Lenovo": {
      "PortMaxSpeedbps": 26843545600
    }
  },
  "@odata.type": "#NetworkPort.v1_2_4.NetworkPort",
  "SupportedLinkCapabilities": {
    "CapableLinkSpeedMbps": [
      26843545600
    ]
  },
  "LinkStatus": "Up",
  "ActiveLinkTechnology": "Ethernet",
  "@odata.etag": "\"5353f739b2c7272c17e\"",
  "PhysicalPortNumber": "2"
}
stmcginnis commented 3 years ago

Thanks! That will be tricky to handle. It looks like they have inverted the array from what the spec states. Rather than having an array of SupportedLinkCapabilities, they have a single SupportLinkCapability structure with an array of its values:

"SupportedLinkCapabilities": {
    "CapableLinkSpeedMbps": [
      26843545600
    ]
  },

This may need to be addressed with Lenovo so they can fix their conformance to the spec.

SupriyoSahana07 commented 3 years ago

Hey Sean, Thanks for your valuable inputs. Indeed will take it to Lenovo and see if they can provide some fix in later versions. Thanks again...

stmcginnis commented 3 years ago

I'll also think about this a bit and see if there's a way to work around things. It would make the unmarshalling a little odd, but then make it a lot easier for users if the library if this is a common issue.

stmcginnis commented 5 months ago

Looks like this was a Lenovo implementation issue. Going to close, but let me know if there is anything more that can be done from the gofish side to make this better.