Skip to content

Commit

Permalink
Implement "om daemon lock show" to show cluster locks
Browse files Browse the repository at this point in the history
example 1:
    $ om daemon lock show
    name     id                                    requester  requested
    |- plic  30e7cbfa-341d-44f5-8b80-a0ab936e7374  node-1     1593539586.1547928
    `- ploc  e3c245f3-e363-48e9-8dc2-b43651682669  node-1     1593539586.1605227

example 2:
    $ om daemon lock show --format json
    {
        "plic": {
            "id": "30e7cbfa-341d-44f5-8b80-a0ab936e7374",
            "requested": 1593539586.1547928,
            "requester": "node-1"
        },
        "ploc": {
            "id": "e3c245f3-e363-48e9-8dc2-b43651682669",
            "requested": 1593539586.1605227,
            "requester": "node-1"
        }
    }

example 3:
    $ om daemon lock show --format flat_json
    .plic.id = 30e7cbfa-341d-44f5-8b80-a0ab936e7374
    .plic.requested = 1593539586.1547928
    .plic.requester = node-1
    .ploc.id = e3c245f3-e363-48e9-8dc2-b43651682669
    .ploc.requested = 1593539586.1605227
    .ploc.requester = node-1
  • Loading branch information
cgalibern committed Jul 1, 2020
1 parent 1bf5a67 commit 6955769
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
3 changes: 3 additions & 0 deletions opensvc/commands/daemon/parser.py
Expand Up @@ -42,6 +42,9 @@
"blacklist_clear": {
"msg": "Empty the content of the daemon senders blacklist.",
},
"lock_show": {
"msg": "Show cluster locks.",
},
"lock_release": {
"msg": "Release a lock. Beware locks should be released automatically.",
"options": [
Expand Down
35 changes: 35 additions & 0 deletions opensvc/core/node/node.py
Expand Up @@ -3944,6 +3944,41 @@ def _daemon_status(self, silent=False, refresh=False, server=None, selector=None
)
return data

@formatter
def daemon_lock_show(self):
data = self.daemon_get(
{
"action": "cluster/locks",
},
timeout=DEFAULT_DAEMON_TIMEOUT,
with_result=True,
server=self.options.server
)
status, error, info = self.parse_result(data)
if error:
raise ex.Error(error)
if status != 0:
raise ex.Error("cluster/locks api return status %s" % status)
locks = data['data']
if self.options.format in ("json", "flat_json"):
return locks
from utilities.render.forest import Forest
from utilities.render.color import color
tree = Forest()
node = tree.add_node()
node.add_column("name", color.BOLD)
node.add_column("id", color.BOLD)
node.add_column("requester", color.BOLD)
node.add_column("requested", color.BOLD)
for name in sorted(locks.keys()):
lock_info = locks[name]
leaf = node.add_node()
leaf.add_column(name, color.BROWN)
leaf.add_column(lock_info['id'])
leaf.add_column(lock_info['requester'])
leaf.add_column(lock_info['requested'])
print(tree)

def daemon_lock_release(self):
self._daemon_unlock(self.options.name, self.options.id)

Expand Down
78 changes: 78 additions & 0 deletions opensvc/tests/commands/daemon/test_daemon.py
@@ -1,9 +1,11 @@
import json
import os
import sys
import time

import pytest
import commands.daemon
from core.comm import Crypt, DEFAULT_DAEMON_TIMEOUT

from daemon.main import main as daemon_main

Expand All @@ -13,6 +15,82 @@ def daemon_join(mocker):
return mocker.patch('commands.daemon.Node._daemon_join')


@pytest.fixture(scope='function')
def daemon_get(mocker):
return mocker.patch.object(Crypt,
'daemon_get',
return_value={
"data": {
"ploc": {
"id": "01e4491d-083f-48ba-8cdf-c5c8771e6b92",
"requested": 1593425914.0323133,
"requester": "u2004-1"
},
"plic": {
"id": "01e4491d-083f-48ba-8cdf-c5c8771e6b99",
"requested": 1593425914.0423133,
"requester": "u2004-1"
}
},
"status": 0
})


@pytest.mark.ci
@pytest.mark.usefixtures('osvc_path_tests', 'has_node_config', 'has_euid_0')
class TestDaemonLockShow:
@staticmethod
@pytest.mark.parametrize('server', ['', 'https://u2004-15:1215'])
def test_calls_daemon_get_on_correct_api_path(daemon_get, server):
argv = ["lock", "show"]
if server:
argv += ["--server", server]
assert commands.daemon.main(argv=argv) == 0
daemon_get.assert_called_once_with(
{'action': 'cluster/locks'},
timeout=DEFAULT_DAEMON_TIMEOUT,
server=server,
with_result=True)

@staticmethod
def test_return_non_0_if_daemon_get_status_has_error(daemon_get):
daemon_get.return_value = {"data": {}, "status": 0, "error": "blah"}
assert commands.daemon.main(argv=["lock", "show"]) == 1

@staticmethod
def test_return_non_0_if_daemon_get_status_is_not_0(daemon_get):
daemon_get.return_value = {"data": {}, "status": 1}
assert commands.daemon.main(argv=["lock", "show"]) == 1

@staticmethod
def test_has_correct_default_format_forest(daemon_get, capture_stdout, tmp_file):
with capture_stdout(tmp_file):
commands.daemon.main(argv=["lock", "show"])
if int(sys.version[0]) > 2:
expected_output = '''
name id requester requested
|- plic 01e4491d-083f-48ba-8cdf-c5c8771e6b92 u2004-1 1593425914.0323133
`- ploc 01e4491d-083f-48ba-8cdf-c5c8771e6b99 u2004-1 1593425914.0423133
'''
else:
expected_output = '''
name id requester requested
|- plic 01e4491d-083f-48ba-8cdf-c5c8771e6b92 u2004-1 1593425914.03
`- ploc 01e4491d-083f-48ba-8cdf-c5c8771e6b99 u2004-1 1593425914.04
'''
with open(tmp_file, 'r') as output_file:
'\n' + output_file.read() == expected_output

@staticmethod
def test_output_with_format_json(daemon_get, capture_stdout, tmp_file):
with capture_stdout(tmp_file):
commands.daemon.main(argv=["lock", "show", "--format", "json"])
with open(tmp_file, 'r') as output_file:
assert json.load(output_file) == daemon_get.return_value['data']


@pytest.mark.ci
@pytest.mark.usefixtures('osvc_path_tests', 'has_node_config', 'has_euid_0')
class TestNodemgrDaemonJoin:
Expand Down

0 comments on commit 6955769

Please sign in to comment.