Skip to content

Commit

Permalink
Merge pull request #102 from DMTF/Fix101-Better-Collection-Handling
Browse files Browse the repository at this point in the history
Updated collection handling for systems, managers, and chassis to differentiate between HTTP 404 from other non-successful responses
  • Loading branch information
mraineri authored Jun 16, 2023
2 parents 3252bfe + 5c4921b commit 011ba23
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 49 deletions.
55 changes: 55 additions & 0 deletions redfish_utilities/collections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#! /usr/bin/python
# Copyright Notice:
# Copyright 2019-2023 DMTF. All rights reserved.
# License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/Redfish-Tacklebox/blob/main/LICENSE.md

"""
Collections Module
File : collections.py
Brief : This file contains the definitions and functionalities for performing
operations with resource collections
"""

from .messages import verify_response

class RedfishCollectionNotFoundError( Exception ):
"""
Raised when the specified collection is not found (HTTP Status = 404)
"""
pass

class RedfishCollectionMemberNotFoundError( Exception ):
"""
Raised when the specified member is not found (HTTP Status = 404)
"""
pass

def get_collection_ids( context, collection_uri ):
"""
Iterates over a collection and returns the identifiers of all members
Args:
context: The Redfish client object with an open session
collection_uri: The URI of the collection to process
Returns:
A list of identifiers of the members of the collection
"""

# Get the collection and iterate through its collection
avail_members = []
collection = context.get( collection_uri )
if collection.status == 404:
raise RedfishCollectionNotFoundError( "Service does not contain a collection at URI {}".format( collection_uri ) )
verify_response( collection )
while True:
for member in collection.dict["Members"]:
avail_members.append( member["@odata.id"].strip( "/" ).split( "/" )[-1] )
if "[email protected]" not in collection.dict:
break
collection = context.get( collection.dict["[email protected]"] )
verify_response( collection )

return avail_members
13 changes: 3 additions & 10 deletions redfish_utilities/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import warnings
import xlsxwriter
from .collections import get_collection_ids
from .messages import verify_response
from . import config

Expand Down Expand Up @@ -406,16 +407,8 @@ def get_chassis_ids( context ):
# Get the service root to find the chassis collection
service_root = context.get( "/redfish/v1/" )
if "Chassis" not in service_root.dict:
# No system collection
# No chassis collection
raise RedfishChassisNotFoundError( "Service does not contain a chassis collection" )

# Get the chassis collection and iterate through its collection
avail_chassis = []
chassis_col = context.get( service_root.dict["Chassis"]["@odata.id"] )
while True:
for chassis_member in chassis_col.dict["Members"]:
avail_chassis.append( chassis_member["@odata.id"].strip( "/" ).split( "/" )[-1] )
if "[email protected]" not in chassis_col.dict:
break
chassis_col = context.get( chassis_col.dict["[email protected]"] )
return avail_chassis
return get_collection_ids( context, service_root.dict["Chassis"]["@odata.id"] )
35 changes: 9 additions & 26 deletions redfish_utilities/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
with the managers collection for a given Redfish service
"""

from .collections import get_collection_ids
from .messages import verify_response
from .resets import reset_types

Expand Down Expand Up @@ -51,15 +52,7 @@ def get_manager_ids( context ):
raise RedfishManagerNotFoundError( "Service does not contain a manager collection" )

# Get the manager collection and iterate through its collection
avail_managers = []
manager_col = context.get( service_root.dict["Managers"]["@odata.id"] )
while True:
for manager_member in manager_col.dict["Members"]:
avail_managers.append( manager_member["@odata.id"].strip( "/" ).split( "/" )[-1] )
if "[email protected]" not in manager_col.dict:
break
manager_col = context.get( manager_col.dict["[email protected]"] )
return avail_managers
return get_collection_ids( context, service_root.dict["Managers"]["@odata.id"] )

def get_manager( context, manager_id = None ):
"""
Expand Down Expand Up @@ -88,12 +81,11 @@ def get_manager( context, manager_id = None ):
raise RedfishManagerNotFoundError( "Service does not contain exactly one manager; a target manager needs to be specified: {}".format( ", ".join( avail_managers ) ) )

# Check the response and return the manager if the response is good
try:
verify_response( manager )
except:
if manager.status == 404:
if avail_managers is None:
avail_managers = get_manager_ids( context )
raise RedfishManagerNotFoundError( "Service does not contain a manager called {}; valid managers: {}".format( manager_id, ", ".join( avail_managers ) ) ) from None
raise RedfishManagerNotFoundError( "Service does not contain a manager called {}; valid managers: {}".format( manager_id, ", ".join( avail_managers ) ) )
verify_response( manager )
return manager

def print_manager( manager ):
Expand Down Expand Up @@ -230,15 +222,7 @@ def get_manager_ethernet_interface_ids( context, manager_id = None ):
raise RedfishManagerEthIntNotFoundError( "Manager {} does not contain an Ethernet interface collection".format( manager.dict["Id"] ) )

# Get the Ethernet interface collection and iterate through its collection
avail_interfaces = []
interface_col = context.get( manager.dict["EthernetInterfaces"]["@odata.id"] )
while True:
for interface_member in interface_col.dict["Members"]:
avail_interfaces.append( interface_member["@odata.id"].strip( "/" ).split( "/" )[-1] )
if "[email protected]" not in interface_col.dict:
break
interface_col = context.get( interface_col.dict["[email protected]"] )
return avail_interfaces
return get_collection_ids( context, manager.dict["EthernetInterfaces"]["@odata.id"] )

def get_manager_ethernet_interface( context, manager_id = None, interface_id = None ):
"""
Expand Down Expand Up @@ -273,12 +257,11 @@ def get_manager_ethernet_interface( context, manager_id = None, interface_id = N
raise RedfishManagerEthIntNotFoundError( "Manager {} does not contain exactly one Ethernet interface; a target Ethernet interface needs to be specified: {}".format( manager_id, ", ".join( avail_interfaces ) ) )

# Check the response and return the Ethernet interface if the response is good
try:
verify_response( interface )
except:
if interface.status == 404:
if avail_interfaces is None:
avail_interfaces = get_manager_ethernet_interface_ids( context, manager_id )
raise RedfishManagerEthIntNotFoundError( "Manager {} does not contain an Ethernet interface called {}; valid Ethernet interfaces: {}".format( manager_id, interface_id, ", ".join( avail_interfaces ) ) ) from None
raise RedfishManagerEthIntNotFoundError( "Manager {} does not contain an Ethernet interface called {}; valid Ethernet interfaces: {}".format( manager_id, interface_id, ", ".join( avail_interfaces ) ) )
verify_response( interface )
return interface

def set_manager_ethernet_interface( context, manager_id = None, interface_id = None, vlan = None, ipv4_addresses = None, dhcpv4 = None, ipv6_addresses = None, ipv6_gateways = None, dhcpv6 = None ):
Expand Down
18 changes: 5 additions & 13 deletions redfish_utilities/systems.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import warnings
import sys
from .collections import get_collection_ids
from .messages import verify_response
from .resets import reset_types
from . import config
Expand Down Expand Up @@ -77,15 +78,7 @@ def get_system_ids( context ):
raise RedfishSystemNotFoundError( "Service does not contain a system collection" )

# Get the system collection and iterate through its collection
avail_systems = []
system_col = context.get( service_root.dict["Systems"]["@odata.id"] )
while True:
for system_member in system_col.dict["Members"]:
avail_systems.append( system_member["@odata.id"].strip( "/" ).split( "/" )[-1] )
if "[email protected]" not in system_col.dict:
break
system_col = context.get( system_col.dict["[email protected]"] )
return avail_systems
return get_collection_ids( context, service_root.dict["Systems"]["@odata.id"] )

def get_system( context, system_id = None ):
"""
Expand Down Expand Up @@ -114,12 +107,11 @@ def get_system( context, system_id = None ):
raise RedfishSystemNotFoundError( "Service does not contain exactly one system; a target system needs to be specified: {}".format( ", ".join( avail_systems ) ) )

# Check the response and return the system if the response is good
try:
verify_response( system )
except:
if system.status == 404:
if avail_systems is None:
avail_systems = get_system_ids( context )
raise RedfishSystemNotFoundError( "Service does not contain a system called {}; valid systems: {}".format( system_id, ", ".join( avail_systems ) ) ) from None
raise RedfishSystemNotFoundError( "Service does not contain a system called {}; valid systems: {}".format( system_id, ", ".join( avail_systems ) ) )
verify_response( system )
return system

def get_system_boot( context, system_id = None ):
Expand Down

0 comments on commit 011ba23

Please sign in to comment.