dell / iDRAC-Redfish-Scripting

Python and PowerShell scripting for Dell EMC PowerEdge iDRAC REST API with DMTF Redfish
GNU General Public License v2.0
584 stars 273 forks source link

Python GetIdracLcLogsREDFISH output as real JSON #270

Closed jgranduel closed 8 months ago

jgranduel commented 9 months ago

Hi,

what is the best way to parse Redfish Python output ? Shouldn't it be canonical JSON as what curl or PowerShell return? It cannot be piped into jq for instance.

I have also noticed a surprising multiline output:

$ python GetIdracLcLogsREDFISH.py -ip <IP> -u <user> -p <password> --get-severity critical
[...]
 'Members@odata.count': 66,
 'Members@odata.nextLink': '/redfish/v1/Managers/iDRAC.Embedded.1/Logs/Lclog?$filter=Severity '
                           "eq 'Critical'&$top=50&$skip=50",
 'Name': 'Log Entry Collection'}

which breaks any JSON-like parsing.

Is it expected? Thx

texroemer commented 9 months ago

Hi @jgranduel

Thanks for pointing out these concerns, script was originally returning python objects not JSON. I updated the script to now dump the output into a file in JSON format (screen output still in python) which you can then parse. I also fixed the issue when skip URI is detected (iDRAC is only able to report 50 entries at a time, reason for skip URI needed), script will now cycle through these URIs to get the data.

See example below running new script which i'm able to use jq command to parse the file.

[root@SCPexport opt]# python3 GetIdracLcLogsREDFISH.py -ip 192.168.0.120 -u root -p calvin --dump-to-json-file --get-severity critical

- INFO, this may take 30 seconds to 1 minute to collect all iDRAC LC logs depending on log file size
[{'@odata.context': '/redfish/v1/$metadata#LogEntryCollection.LogEntryCollection',
  '@odata.id': '/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries',
  '@odata.type': '#LogEntryCollection.LogEntryCollection',
  'Description': 'LC Logs for this manager',
  'Members': [{'@odata.id': '/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries/10265',
               '@odata.type': '#LogEntry.v1_15_0.LogEntry',
               'Created': '2023-09-26T10:06:49-05:00',
               'Description': 'Log Entry 10265',
               'EntryType': 'Oem',
               'Id': '10265',
               'Links': {},
               'Message': 'Fault detected on drive 0 in disk drive bay 0.',
               'MessageArgs': ['0', '0'],
               'MessageArgs@odata.count': 2,
               'MessageId': 'IDRAC.2.9.PDR1001',
               'Name': 'Log Entry 10265',
               'Oem': {'Dell': {'@odata.type': '#DellLCLogEntry.v1_1_0.DellLCLogEntry',
                                'Category': 'SystemHealth',
                                'Comment': None,
                                'LastUpdatedByUser': None}},
               'OemRecordFormat': 'Dell',
               'Severity': 'Critical'},
              {'@odata.id': '/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries/10262',
               '@odata.type': '#LogEntry.v1_15_0.LogEntry',
               'Created': '2023-09-26T10:06:42-05:00',
               'Description': 'Log Entry 10262',
               'EntryType': 'Oem',
               'Id': '10262',
               'Links': {},
               'Message': 'Fault detected on drive 0 in disk drive bay 0.',
               'MessageArgs': ['0', '0'],
               'MessageArgs@odata.count': 2,
               'MessageId': 'IDRAC.2.9.PDR1001',
               'Name': 'Log Entry 10262',
               'Oem': {'Dell': {'@odata.type': '#DellLCLogEntry.v1_1_0.DellLCLogEntry',
                                'Category': 'SystemHealth',
                                'Comment': None,
                                'LastUpdatedByUser': None}},
               'OemRecordFormat': 'Dell',
               'Severity': 'Critical'}],
  'Members@odata.count': 2,
  'Name': 'Log Entry Collection'}]

- INFO, JSON dump log files copied to directory 192.168.0.120_LC_log_JSON_files

[root@SCPexport opt]# ls -la 192.168.0.120_LC_log_JSON_files/
total 8
drwxr-xr-x   2 root root   34 Sep 26 12:55 .
drwxr-xr-x. 16 root root 4096 Sep 26 12:55 ..
-rw-r--r--   1 root root 1596 Sep 26 12:55 lclog_entries_1.json

[root@SCPexport opt]# jq . 192.168.0.120_LC_log_JSON_files/lclog_entries_1.json
{
  "@odata.context": "/redfish/v1/$metadata#LogEntryCollection.LogEntryCollection",
  "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries",
  "@odata.type": "#LogEntryCollection.LogEntryCollection",
  "Description": "LC Logs for this manager",
  "Members": [
    {
      "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries/10265",
      "@odata.type": "#LogEntry.v1_15_0.LogEntry",
      "Created": "2023-09-26T10:06:49-05:00",
      "Description": "Log Entry 10265",
      "EntryType": "Oem",
      "Id": "10265",
      "Links": {},
      "Message": "Fault detected on drive 0 in disk drive bay 0.",
      "MessageArgs": [
        "0",
        "0"
      ],
      "MessageArgs@odata.count": 2,
      "MessageId": "IDRAC.2.9.PDR1001",
      "Name": "Log Entry 10265",
      "Oem": {
        "Dell": {
          "@odata.type": "#DellLCLogEntry.v1_1_0.DellLCLogEntry",
          "Category": "SystemHealth",
          "Comment": null,
          "LastUpdatedByUser": null
        }
      },
      "OemRecordFormat": "Dell",
      "Severity": "Critical"
    },
    {
      "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries/10262",
      "@odata.type": "#LogEntry.v1_15_0.LogEntry",
      "Created": "2023-09-26T10:06:42-05:00",
      "Description": "Log Entry 10262",
      "EntryType": "Oem",
      "Id": "10262",
      "Links": {},
      "Message": "Fault detected on drive 0 in disk drive bay 0.",
      "MessageArgs": [
        "0",
        "0"
      ],
      "MessageArgs@odata.count": 2,
      "MessageId": "IDRAC.2.9.PDR1001",
      "Name": "Log Entry 10262",
      "Oem": {
        "Dell": {
          "@odata.type": "#DellLCLogEntry.v1_1_0.DellLCLogEntry",
          "Category": "SystemHealth",
          "Comment": null,
          "LastUpdatedByUser": null
        }
      },
      "OemRecordFormat": "Dell",
      "Severity": "Critical"
    }
  ],
  "Members@odata.count": 2,
  "Name": "Log Entry Collection"
}
[root@SCPexport opt]#

Thanks Tex

jgranduel commented 9 months ago

Thank you very much !

jgranduel commented 9 months ago

Would it be possible to ouput JSON to stdout without the need of creating a file for a quick iDRAC query? Thanks!

texroemer commented 9 months ago

File creation is needed because of skip parameter causing format issues to parse the JSON returned directly to the screen. Dumping all LC logs to the screen where skip parameter gets called (skip will run when over 50 entries are detected) will throw JSON errors. For now you'll need to parse each log file to get specific JSON data.

Thanks Tex

jgranduel commented 9 months ago

Thanks for you answer. As under the hood, if am not wrong, there is an OData REST API call which is also directly queryable by curl for instance, why is there a physical limit of 50 returned items ? I tried using curl with $skip=100 but indeed got 50 results in Members array. Does it change a lot of the server charge? Or is it a constant defined in DMTF Redfish API?

Thanks for any precisions.

texroemer commented 9 months ago

Hi @jgranduel

Only returning 50 members at a time is an iDRAC limitation not a DMTF standard and $skip will need to be leveraged to see the next 50 Members. But there are plans to improve iDRAC behavior and remove this limitation in a future release.

LC log example GET on URI "redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries" “Members@odata.count” property reports 362 entries, you'll need to run GET on these URIs to get the complete LC logs:

redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries?$skip=50 redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries?$skip=100 redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries?$skip=150 redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries?$skip=200 redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries?$skip=250 redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries?$skip=300 redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries?$skip=350

Thanks Tex

jgranduel commented 8 months ago

Hi, I've been trying to use curl (seems faster than Python/PowerShell). The query doesn't return Members@odata.count property, as far as I can tell: Is it only available in version 9 ?

curl -k -uroot 'https://<IP>/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries' | jq
{
  "@odata.context": "/redfish/v1/$metadata#LogService.LogService",
  "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog",
  "@odata.type": "#LogService.v1_1_0.LogService",
  "DateTime": "2023-11-02T13:45:19-05:00",
  "DateTimeLocalOffset": "-05:00",
  "Description": "LifeCycle Controller Log Service",
  "Entries": {
    "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/Logs/Lclog"
  },
  "Id": "LC",
  "LogEntryType": "OEM",
  "MaxNumberOfRecords": 500000,
  "Name": "LifeCycle Controller Log Service",
  "OverWritePolicy": "WrapsWhenFull",
  "ServiceEnabled": true
}

and using $skip=x returns an error:

> curl -s -k -uroot 'https://<IP>/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries?$skip=50' | jq
{
  "error": {
    "code": "Base.1.0.GeneralError",
    "message": "A general error has occurred. See ExtendedInfo for more information.",
    "@Message.ExtendedInfo": [
      {
        "@odata.type": "#Message.v1_0_0.Message",
        "MessageId": "Base.1.0.InternalError",
        "Message": "not supported, Query parameter skip not supported"
      }
    ]
  }
}
texroemer commented 8 months ago

Hi @jgranduel

Members@odata.count is supported on iDRAC8 but you must use URI "redfish/v1/Managers/iDRAC.Embedded.1/Logs/Lclog" to get iDRAC LC logs and this property will be reported. On iDRAC9 use "redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries" to get iDRAC LC logs.

If your environment has both iDRAC8 and iDRAC9 servers you'll need to add code to check the iDRAC version first, then use the correct URI based off the iDRAC version detected.

Thanks Tex

jgranduel commented 8 months ago

Thanks ! Sorry, I got confused with the 2 URIs as there are 2 differences between them and I spotted only Entries.

iDRAC v8: redfish/v1/Managers/iDRAC.Embedded.1/Logs/Lclog iDRAC v9: redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Lclog/Entries