Skip to content

Commit

Permalink
[sonic_installer]: Improve exception handling: introduce notes. (soni…
Browse files Browse the repository at this point in the history
…c-net#3029)

Signed-off-by: Nazarii Hnydyn <nazariig@nvidia.com>
  • Loading branch information
nazariig authored Nov 20, 2023
1 parent 3610ce9 commit 8ebc56a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
9 changes: 7 additions & 2 deletions sonic_installer/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,15 @@ def run_command_or_raise(argv, raise_exception=True, capture=True):

stdout = subprocess.PIPE if capture else None
proc = subprocess.Popen(argv, text=True, stdout=stdout)
out, _ = proc.communicate()
out, err = proc.communicate()

if proc.returncode != 0 and raise_exception:
raise SonicRuntimeException("Failed to run command '{0}'".format(argv))
sre = SonicRuntimeException("Failed to run command '{0}'".format(argv))
if out:
sre.add_note("\nSTDOUT:\n{}".format(out.rstrip("\n")))
if err:
sre.add_note("\nSTDERR:\n{}".format(err.rstrip("\n")))
raise sre

if out is not None:
out = out.rstrip("\n")
Expand Down
13 changes: 12 additions & 1 deletion sonic_installer/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,15 @@
class SonicRuntimeException(Exception):
"""SONiC Runtime Excpetion class used to report SONiC related errors
"""
pass
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.notes = []

def __str__(self):
msg = super().__str__()
if self.notes:
msg += "\n" + "\n".join(self.notes)
return msg

def add_note(self, note):
self.notes.append(note)
15 changes: 15 additions & 0 deletions tests/test_sonic_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,18 @@ def test_set_fips(get_bootloader):
mock_bootloader.get_fips = Mock(return_value=True)
result = runner.invoke(sonic_installer.commands["get-fips"], [next_image])
assert "FIPS is enabled" in result.output

@patch("sonic_installer.common.subprocess.Popen")
def test_runtime_exception(mock_popen):
""" This test covers the "sonic-installer" exception handling. """

mock_popen.return_value.returncode = 1
mock_popen.return_value.communicate.return_value = ('Running', 'Failed')

with pytest.raises(sonic_installer_common.SonicRuntimeException) as sre:
sonic_installer_common.run_command_or_raise(["test.sh"])

assert '\nSTDOUT:\nRunning' in sre.value.notes, "Invalid STDOUT"
assert '\nSTDERR:\nFailed' in sre.value.notes, "Invalid STDERR"

assert all(v in str(sre.value) for v in ['test.sh', 'Running', 'Failed']), "Invalid message"

0 comments on commit 8ebc56a

Please sign in to comment.