Skip to content

Commit

Permalink
cli: retry grabbing the lock
Browse files Browse the repository at this point in the history
This helps when the timer job is running in the background and a cli
command happens to collide with it. The timer job is usually over
quickly, so retrying several times with a small sleep time should be
sufficient.
  • Loading branch information
orndorffgrant committed Nov 15, 2023
1 parent d2f1185 commit 02063c1
Show file tree
Hide file tree
Showing 6 changed files with 16 additions and 7 deletions.
2 changes: 1 addition & 1 deletion uaclient/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def assert_lock_file(lock_holder=None):
def wrapper(f):
@wraps(f)
def new_f(*args, cfg, **kwargs):
with lock.SingleAttemptLock(cfg=cfg, lock_holder=lock_holder):
with lock.SpinLock(cfg=cfg, lock_holder=lock_holder, sleep_time=1):
retval = f(*args, cfg=cfg, **kwargs)
return retval

Expand Down
4 changes: 3 additions & 1 deletion uaclient/cli/tests/test_cli_attach.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,12 @@ def test_already_attached(self, capsys, FakeConfig, event):
}
assert expected == json.loads(capsys.readouterr()[0])

@mock.patch("time.sleep")
@mock.patch("uaclient.system.subp")
def test_lock_file_exists(
self,
m_subp,
m_sleep,
capsys,
FakeConfig,
event,
Expand All @@ -189,7 +191,7 @@ def test_lock_file_exists(
cfg.write_cache("lock", "123:pro disable")
with pytest.raises(LockHeldError) as exc_info:
action_attach(mock.MagicMock(), cfg=cfg)
assert [mock.call(["ps", "123"])] == m_subp.call_args_list
assert [mock.call(["ps", "123"])] * 12 == m_subp.call_args_list
assert (
"Unable to perform: pro attach.\n"
"Operation in progress: pro disable (pid:123)"
Expand Down
4 changes: 3 additions & 1 deletion uaclient/cli/tests/test_cli_detach.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,12 @@ def test_unattached_error_message(
}
assert expected == json.loads(capsys.readouterr()[0])

@mock.patch("time.sleep")
@mock.patch("uaclient.system.subp")
def test_lock_file_exists(
self,
m_subp,
m_sleep,
m_prompt,
FakeConfig,
capsys,
Expand All @@ -118,7 +120,7 @@ def test_lock_file_exists(
cfg.write_cache("lock", "123:pro enable")
with pytest.raises(exceptions.LockHeldError) as err:
action_detach(args, cfg=cfg)
assert [mock.call(["ps", "123"])] == m_subp.call_args_list
assert [mock.call(["ps", "123"])] * 12 == m_subp.call_args_list
expected_error_msg = messages.E_LOCK_HELD_ERROR.format(
lock_request="pro detach", lock_holder="pro enable", pid="123"
)
Expand Down
4 changes: 3 additions & 1 deletion uaclient/cli/tests/test_cli_disable.py
Original file line number Diff line number Diff line change
Expand Up @@ -532,10 +532,12 @@ def test_unattached_error_message(
expected["errors"][0]["additional_info"] = expected_info
assert expected == json.loads(fake_stdout.getvalue())

@mock.patch("time.sleep")
@mock.patch("uaclient.system.subp")
def test_lock_file_exists(
self,
m_subp,
m_sleep,
FakeConfig,
event,
):
Expand All @@ -549,7 +551,7 @@ def test_lock_file_exists(
with pytest.raises(exceptions.LockHeldError) as err:
args.service = ["esm-infra"]
action_disable(args, cfg)
assert [mock.call(["ps", "123"])] == m_subp.call_args_list
assert [mock.call(["ps", "123"])] * 12 == m_subp.call_args_list
assert expected_error.msg == err.value.msg

args.assume_yes = True
Expand Down
4 changes: 3 additions & 1 deletion uaclient/cli/tests/test_cli_enable.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,12 @@ def test_non_root_users_are_rejected(
}
assert expected == json.loads(capsys.readouterr()[0])

@mock.patch("time.sleep")
@mock.patch("uaclient.system.subp")
def test_lock_file_exists(
self,
m_subp,
m_sleep,
_refresh,
capsys,
event,
Expand All @@ -147,7 +149,7 @@ def test_lock_file_exists(

with pytest.raises(exceptions.LockHeldError) as err:
action_enable(args, cfg=cfg)
assert [mock.call(["ps", "123"])] == m_subp.call_args_list
assert [mock.call(["ps", "123"])] * 12 == m_subp.call_args_list

expected_message = messages.E_LOCK_HELD_ERROR.format(
lock_request="pro enable", lock_holder="pro disable", pid="123"
Expand Down
5 changes: 3 additions & 2 deletions uaclient/cli/tests/test_cli_refresh.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,15 @@ def test_not_attached_errors(
else:
action_refresh(mock.MagicMock(target=target), cfg=cfg)

@mock.patch("time.sleep")
@mock.patch("uaclient.system.subp")
def test_lock_file_exists(self, m_subp, FakeConfig):
def test_lock_file_exists(self, m_subp, m_sleep, FakeConfig):
"""Check inability to refresh if operation holds lock file."""
cfg = FakeConfig().for_attached_machine()
cfg.write_cache("lock", "123:pro disable")
with pytest.raises(exceptions.LockHeldError) as err:
action_refresh(mock.MagicMock(), cfg=cfg)
assert [mock.call(["ps", "123"])] == m_subp.call_args_list
assert [mock.call(["ps", "123"])] * 12 == m_subp.call_args_list
assert (
"Unable to perform: pro refresh.\n"
"Operation in progress: pro disable (pid:123)"
Expand Down

0 comments on commit 02063c1

Please sign in to comment.