Skip to content

Commit

Permalink
Add new API to support config replace (#125)
Browse files Browse the repository at this point in the history
Why I did it
Sonic host services need to support GCU config replace operation.

How I did it
Add new API for config replace

How did I verify it
Run unit test
  • Loading branch information
ganglyu authored May 15, 2024
1 parent 1a8ff81 commit 10bfa90
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 0 deletions.
30 changes: 30 additions & 0 deletions host_modules/gcu.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,36 @@ def apply_patch_yang(self, patch_text):
break
return result.returncode, msg

@host_service.method(host_service.bus_name(MOD_NAME), in_signature='s', out_signature='is')
def replace_db(self, patch_text):
input_bytes = (patch_text + '\n').encode('utf-8')
cmd = ['/usr/local/bin/config', 'replace', '-f', 'CONFIGDB', '/dev/stdin']

result = subprocess.run(cmd, input=input_bytes, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
msg = ''
if result.returncode:
lines = result.stderr.decode().split('\n')
for line in lines:
if 'Error' in line:
msg = line
break
return result.returncode, msg

@host_service.method(host_service.bus_name(MOD_NAME), in_signature='s', out_signature='is')
def replace_yang(self, patch_text):
input_bytes = (patch_text + '\n').encode('utf-8')
cmd = ['/usr/local/bin/config', 'replace', '-f', 'SONICYANG', '/dev/stdin']

result = subprocess.run(cmd, input=input_bytes, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
msg = ''
if result.returncode:
lines = result.stderr.decode().split('\n')
for line in lines:
if 'Error' in line:
msg = line
break
return result.returncode, msg

@host_service.method(host_service.bus_name(MOD_NAME), in_signature='s', out_signature='is')
def create_checkpoint(self, checkpoint_file):

Expand Down
74 changes: 74 additions & 0 deletions tests/host_modules/gcu_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,80 @@ def test_apply_patch_yang(self, MockInit, MockBusName, MockSystemBus):
assert ret == test_ret, "Return value is wrong"
assert msg == "Error: this is the test message", "Return message is wrong"

@mock.patch("dbus.SystemBus")
@mock.patch("dbus.service.BusName")
@mock.patch("dbus.service.Object.__init__")
def test_replace_db(self, MockInit, MockBusName, MockSystemBus):
with mock.patch("subprocess.run") as mock_run:
res_mock = mock.Mock()
test_ret = 0
test_msg = b"Error: this is the test message\nHello world\n"
attrs = {"returncode": test_ret, "stderr": test_msg}
res_mock.configure_mock(**attrs)
mock_run.return_value = res_mock
patch_text = "{}"
gcu_stub = gcu.GCU(gcu.MOD_NAME)
ret, msg = gcu_stub.replace_db(patch_text)
call_args = mock_run.call_args[0][0]
assert "replace" in call_args
assert "CONFIGDB" in call_args
assert '/dev/stdin' in call_args
assert ret == test_ret, "Return value is wrong"
assert msg == "", "Return message is wrong"
with mock.patch("subprocess.run") as mock_run:
res_mock = mock.Mock()
test_ret = 1
test_msg = b"Error: this is the test message\nHello world\n"
attrs = {"returncode": test_ret, "stderr": test_msg}
res_mock.configure_mock(**attrs)
mock_run.return_value = res_mock
patch_text = "{}"
gcu_stub = gcu.GCU(gcu.MOD_NAME)
ret, msg = gcu_stub.replace_db(patch_text)
call_args = mock_run.call_args[0][0]
assert "replace" in call_args
assert "CONFIGDB" in call_args
assert '/dev/stdin' in call_args
assert ret == test_ret, "Return value is wrong"
assert msg == "Error: this is the test message", "Return message is wrong"

@mock.patch("dbus.SystemBus")
@mock.patch("dbus.service.BusName")
@mock.patch("dbus.service.Object.__init__")
def test_replace_yang(self, MockInit, MockBusName, MockSystemBus):
with mock.patch("subprocess.run") as mock_run:
res_mock = mock.Mock()
test_ret = 0
test_msg = b"Error: this is the test message\nHello world\n"
attrs = {"returncode": test_ret, "stderr": test_msg}
res_mock.configure_mock(**attrs)
mock_run.return_value = res_mock
patch_text = "{}"
gcu_stub = gcu.GCU(gcu.MOD_NAME)
ret, msg = gcu_stub.replace_yang(patch_text)
call_args = mock_run.call_args[0][0]
assert "replace" in call_args
assert "SONICYANG" in call_args
assert '/dev/stdin' in call_args
assert ret == test_ret, "Return value is wrong"
assert msg == "", "Return message is wrong"
with mock.patch("subprocess.run") as mock_run:
res_mock = mock.Mock()
test_ret = 1
test_msg = b"Error: this is the test message\nHello world\n"
attrs = {"returncode": test_ret, "stderr": test_msg}
res_mock.configure_mock(**attrs)
mock_run.return_value = res_mock
patch_text = "{}"
gcu_stub = gcu.GCU(gcu.MOD_NAME)
ret, msg = gcu_stub.replace_yang(patch_text)
call_args = mock_run.call_args[0][0]
assert "replace" in call_args
assert "SONICYANG" in call_args
assert '/dev/stdin' in call_args
assert ret == test_ret, "Return value is wrong"
assert msg == "Error: this is the test message", "Return message is wrong"

@mock.patch("dbus.SystemBus")
@mock.patch("dbus.service.BusName")
@mock.patch("dbus.service.Object.__init__")
Expand Down

0 comments on commit 10bfa90

Please sign in to comment.