-
Notifications
You must be signed in to change notification settings - Fork 195
[psud] Refactor PSU object retrieval to improve exception handling #659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
sonic-psud/scripts/psud
Outdated
| if platform_chassis is not None: | ||
| try: | ||
| return platform_chassis.get_psu(psu_index - 1) | ||
| except NotImplementedError: # TODO: Is NotImplementedError sufficient? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log a warning for this exception and return None, Also add a general exception to make the code robust.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
sonic-psud/scripts/psud
Outdated
| def _wrapper_get_psu_presence(psu_index): | ||
| if platform_chassis is not None: | ||
| psu = _wrapper_get_psu(psu_index) | ||
| if not psu: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if psu returned is None here, add exception here to log error and returning false.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
sonic-psud/scripts/psud
Outdated
| try: | ||
| return platform_chassis.get_psu(psu_index - 1) | ||
| except NotImplementedError as e: | ||
| logger.log_warning("get_psu() not implemented by platform chassis: {}".format(str(e))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this something that needs to be logged? Also in its current form, you'll get two conflicting logs. Say you run the wrapper to get presence, this get_psu wrapper will log "get_psu() not implemented by platform chassis: {}" and return none, but now that its none the get_presence will print "Failed to get PSU {} object from platform chassis".
This also seems to deviate from the prior behavior where if the platform_chassis doesn't have the get_psu, it will fallback to the platform_psuutil case. Is it possible that some vendors have not implemented this get_psu on the platform_chassis and still rely on this fallback?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your pointing out.
sonic-psud/scripts/psud
Outdated
| psu = _wrapper_get_psu(psu_index) | ||
| if not psu: | ||
| logger.log_error("Failed to get PSU {} object from platform chassis".format(psu_index)) | ||
| return '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imo this should be a case where it returns the PSU_INFO_KEY_TEMPLATE, not an empty string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
/azpw run |
|
/AzurePipelines run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Signed-off-by: Lin Jin <[email protected]>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Signed-off-by: Lin Jin <[email protected]>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Signed-off-by: Lin Jin <[email protected]>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Signed-off-by: Lin Jin <[email protected]>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Signed-off-by: Lin Jin <[email protected]>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 11 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
sonic-psud/scripts/psud
Outdated
| except NotImplementedError: | ||
| pass | ||
| except Exception as e: | ||
| logger.log_warning("Exception in psu.get_presence() for PSU {}: {}".format(psu_index, str(e))) |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing null check for logger before calling log_warning. This will cause an AttributeError if logger is None. The same pattern is correctly handled on line 143-144 with an if logger: check.
| logger.log_warning("Exception in psu.get_presence() for PSU {}: {}".format(psu_index, str(e))) | |
| if logger: | |
| logger.log_warning("Exception in psu.get_presence() for PSU {}: {}".format(psu_index, str(e))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
sonic-psud/scripts/psud
Outdated
| # some functionality is expectent on returning an expected key even if the psu object itself does not exist | ||
| pass | ||
| except Exception as e: | ||
| return False |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning False in get_psu_key() is inconsistent with the function's purpose. The function should return a string key identifying the PSU. In all other exception paths (NotImplementedError, IndexError), it falls through to return PSU_INFO_KEY_TEMPLATE.format(psu_index) on line 191. This general Exception handler should either return the same default template or be removed to allow the fall-through behavior.
| return False | |
| pass |
Signed-off-by: Lin Jin <[email protected]>
judyjoseph
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Signed-off-by: Lin Jin <[email protected]>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Lin Jin <[email protected]>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # | ||
|
|
||
| def get_psu_key(psu_index): | ||
| if platform_chassis is not None: |
Copilot
AI
Nov 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The get_psu_key function passes None as the logger parameter to _wrapper_get_psu. While this is intentional to avoid logging in this context, the function should include a comment explaining why logging is suppressed here, as this is a deviation from other usages where self (the logger) is passed.
| if platform_chassis is not None: | |
| if platform_chassis is not None: | |
| # Intentionally pass None as the logger to suppress logging in this context, | |
| # as get_psu_key is only used for key generation and not for error reporting. | |
| # This deviates from other usages where a logger is passed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think it’s necessary.
| Get PSU object from platform chassis | ||
| :param logger: Logger instance for error/warning messages | ||
| :param psu_index: PSU index (1-based) | ||
| :return: PSU object if available, None otherwise | ||
Copilot
AI
Nov 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docstring should explicitly mention that this function only attempts to retrieve PSU from platform_chassis and does not fall back to platform_psuutil, as this is a key behavioral difference from other wrapper functions like _wrapper_get_psu_presence and _wrapper_get_psu_status.
| Get PSU object from platform chassis | |
| :param logger: Logger instance for error/warning messages | |
| :param psu_index: PSU index (1-based) | |
| :return: PSU object if available, None otherwise | |
| Get PSU object from platform chassis. | |
| This function only attempts to retrieve the PSU from `platform_chassis` and does not fall back to | |
| `platform_psuutil`, unlike other wrapper functions such as `_wrapper_get_psu_presence` and | |
| `_wrapper_get_psu_status`. | |
| :param logger: Logger instance for error/warning messages | |
| :param psu_index: PSU index (1-based) | |
| :return: PSU object if available, None otherwise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think it’s necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
sonic-psud/tests/test_psud.py
Outdated
| psud.platform_psuutil = mock.MagicMock() | ||
| psud._wrapper_get_num_psus(None) | ||
| assert psud.platform_chassis.get_num_psus.call_count >= 1 | ||
|
|
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing whitespace should be removed for code cleanliness.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
sonic-psud/tests/test_psud.py
Outdated
| mock_logger = mock.MagicMock() | ||
| mock_psu = mock.MagicMock() | ||
| mock_psu.get_presence.return_value = True | ||
|
|
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing whitespace should be removed for code cleanliness.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
sonic-psud/tests/test_psud.py
Outdated
| def test_wrapper_get_psu(): | ||
| mock_logger = mock.MagicMock() | ||
| mock_psu = mock.MagicMock() | ||
|
|
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing whitespace should be removed for code cleanliness.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
sonic-psud/tests/test_psud.py
Outdated
| mock_logger = mock.MagicMock() | ||
| mock_psu = mock.MagicMock() | ||
| mock_psu.get_powergood_status.return_value = True | ||
|
|
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing whitespace should be removed for code cleanliness.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
sonic-psud/tests/test_psud.py
Outdated
| def test_get_psu_key(): | ||
| mock_psu = mock.MagicMock() | ||
| mock_psu.get_name.return_value = "PSU-1" | ||
|
|
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing whitespace should be removed for code cleanliness.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
| Note: | ||
| If logger is None, errors and warnings encountered during execution will not be logged. |
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The docstring mentions that 'logger is None' will suppress logging, but this behavior should be more prominently documented in the parameter description itself, not just in a Note section. Consider updating line 109 to: :param logger: Logger instance for error/warning messages (can be None to suppress logging)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think it’s necessary.
| except Exception: | ||
| pass |
Copilot
AI
Nov 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Catching a bare Exception without logging or handling specific exception types makes debugging harder. The old code caught NotImplementedError and IndexError separately. Consider at minimum adding a comment explaining why all exceptions are silently ignored here, or restore the specific exception handling for clarity.
| except Exception: | |
| pass | |
| except NotImplementedError: | |
| pass | |
| except IndexError: | |
| pass | |
| except Exception as e: | |
| # Unexpected exception; log if logger is available, else silently ignore | |
| # (logger is None here, so we cannot log) | |
| pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think it’s necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, please take care of general comments above
Signed-off-by: Lin Jin <[email protected]>
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
Hi @liamkearney-msft, could you please help review? |
Description
This PR refactors the PSU object retrieval logic in psud by extracting the
platform_chassis.get_psu()call into a dedicated wrapper function_wrapper_get_psu(). In addition, the process no longer exits when platform_psuutil is unavailable. The change improves exception handling consistency and code maintainability by centralizing PSU object retrieval logic.Motivation and Context
The original code had duplicate
platform_chassis.get_psu(psu_index - 1)calls scattered across multiple wrapper functions, making it difficult to maintain consistent exception handling and increasing code duplication.How Has This Been Tested?
Unit tests were extended to test the PSU exception handling features and tested in physical platform.
Additional Information (Optional)