Browse Source

add logging of reserve and release events..

main
John-Mark Gurney 4 years ago
parent
commit
0bc61b74fe
2 changed files with 80 additions and 2 deletions
  1. +79
    -1
      bitelab/__init__.py
  2. +1
    -1
      bitelab/testing.py

+ 79
- 1
bitelab/__init__.py View File

@@ -58,6 +58,7 @@ import sqlite3
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
import time
import ucl import ucl
import unittest import unittest
import urllib import urllib
@@ -73,6 +74,26 @@ def new_parse_socket_addr(domain, addr):


tcp_server.parse_socket_addr = new_parse_socket_addr tcp_server.parse_socket_addr = new_parse_socket_addr


async def log_event(tag, board=None, user=None, extra={}):
info = extra.copy()
info['event'] = tag

if board is not None:
info['board_name'] = board.name
else:
info.pop('board_name', None)

if user is not None:
info['user'] = user
else:
info.pop('user', None)

t = time.time()
info['date'] = time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime(t)) + \
'.%03dZ' % (int((t * 1000) % 1000),)

logging.info(json.dumps(info))

class EtherIface(DefROAttribute): class EtherIface(DefROAttribute):
defattrname = 'eiface' defattrname = 'eiface'


@@ -411,6 +432,8 @@ async def reserve_board(board_id_or_class,


await brd.activate() await brd.activate()


await log_event('reserve', user=user, board=brd)

await brd.update() await brd.update()


return brd return brd
@@ -423,6 +446,9 @@ async def release_board(board_id, user: str = Depends(lookup_user),
brd = brdmgr.boards[board_id] brd = brdmgr.boards[board_id]


async with brd.lock: async with brd.lock:
# XXX - how to handle a release error?
await log_event('release', user=user, board=brd)

try: try:
brduser = await data.BoardStatus.objects.get(board=board_id) brduser = await data.BoardStatus.objects.get(board=board_id)
if user != brduser.user: if user != brduser.user:
@@ -660,11 +686,12 @@ class TestBiteLab(unittest.IsolatedAsyncioTestCase):
# and that the error got logged # and that the error got logged
le.assert_called_with('release script failure: board: \'cora-1\', ret: 1, stderr: b\'error\'') le.assert_called_with('release script failure: board: \'cora-1\', ret: 1, stderr: b\'error\'')


@patch('bitelab.log_event')
@patch('bitelab.BoardImpl.deactivate') @patch('bitelab.BoardImpl.deactivate')
@patch('bitelab.BoardImpl.activate') @patch('bitelab.BoardImpl.activate')
@patch('asyncio.create_subprocess_exec') @patch('asyncio.create_subprocess_exec')
@patch('bitelab.snmp.snmpget') @patch('bitelab.snmp.snmpget')
async def test_board_reserve_release(self, sg, cse, biact, bideact):
async def test_board_reserve_release(self, sg, cse, biact, bideact, le):
# that when releasing a board that is not yet reserved # that when releasing a board that is not yet reserved
res = await self.client.post('/board/cora-1/release', res = await self.client.post('/board/cora-1/release',
auth=BiteAuth('anotherlongapikey')) auth=BiteAuth('anotherlongapikey'))
@@ -737,6 +764,10 @@ class TestBiteLab(unittest.IsolatedAsyncioTestCase):
# and that the board was activated # and that the board was activated
biact.assert_called() biact.assert_called()


# and that log_event was called properly
le.assert_called_with('reserve', user='foo',
board=self.brdmgr.boards['cora-1'])

# that another user reserving the board # that another user reserving the board
res = await self.client.post('/board/cora-1/reserve', res = await self.client.post('/board/cora-1/reserve',
auth=BiteAuth('anotherlongapikey')) auth=BiteAuth('anotherlongapikey'))
@@ -781,6 +812,10 @@ class TestBiteLab(unittest.IsolatedAsyncioTestCase):
} }
self.assertEqual(res.json(), info) self.assertEqual(res.json(), info)


# and that log_event was called properly
le.assert_called_with('release', user='foo',
board=self.brdmgr.boards['cora-1'])

env = os.environ.copy() env = os.environ.copy()
env['ip'] = brdinfo['attrs']['ip'] env['ip'] = brdinfo['attrs']['ip']
env['iface'] = brdinfo['attrs']['iface'] env['iface'] = brdinfo['attrs']['iface']
@@ -950,6 +985,49 @@ class TestBoardImpl(unittest.IsolatedAsyncioTestCase):


opt.deactivate.assert_called_with(brd) opt.deactivate.assert_called_with(brd)


class TestLogEvent(unittest.IsolatedAsyncioTestCase):
@patch('time.time')
@patch('logging.info')
async def test_log_event(self, li, tt):
tag = 'eslkjdf'
user = 'weoijsdfkj'
brdname = 'woied'
extra = dict(something=2323, someelse='asdlfkj')
brd = BoardImpl(brdname, {}, [])

tt.return_value = 1607650392.384

await log_event(tag, user=user, board=brd, extra=extra)

res = dict(event=tag, board_name=brdname, user=user,
date='2020-12-11T01:33:12.384Z', **extra)

# that log_event logs the correct data
self.assertEqual(len(li.call_args[0]), 1)

# that the logged data can be parsed as json, and results
# in the correct object
self.assertEqual(json.loads(li.call_args[0][0]), res)

tt.return_value = 1607650393.289

# that log_event handles no board/user
await log_event(tag)

res = json.dumps(dict(event=tag,
date='2020-12-11T01:33:13.289Z'))

li.assert_called_with(res)

# that log_event doesn't allow board/user from extra
await log_event(tag, extra=dict(board_name='sldkfj',
user='sod'))

res = json.dumps(dict(event=tag,
date='2020-12-11T01:33:13.289Z'))

li.assert_called_with(res)

class TestAttrs(unittest.IsolatedAsyncioTestCase): class TestAttrs(unittest.IsolatedAsyncioTestCase):
@patch('asyncio.create_subprocess_exec') @patch('asyncio.create_subprocess_exec')
async def test_serialconsole(self, cse): async def test_serialconsole(self, cse):


+ 1
- 1
bitelab/testing.py View File

@@ -30,5 +30,5 @@


from .snmp import TestSNMPPower, TestSNMPWrapper from .snmp import TestSNMPPower, TestSNMPWrapper
from .data import TestDatabase from .data import TestDatabase
from . import TestBiteLab, TestUnhashLRU, TestAttrs, TestBoardImpl
from . import TestBiteLab, TestUnhashLRU, TestAttrs, TestBoardImpl, TestLogEvent
from .__main__ import TestClient from .__main__ import TestClient

Loading…
Cancel
Save