diff --git a/bitelab/__init__.py b/bitelab/__init__.py index f16dc0d..bf5da2b 100644 --- a/bitelab/__init__.py +++ b/bitelab/__init__.py @@ -50,6 +50,7 @@ from .mocks import * import asyncio import contextlib import json +import logging import orm import os import socket @@ -356,8 +357,18 @@ async def release_board(board_id, user: str = Depends(lookup_user), settings.setup_script, 'release', brd.name, user, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = await sub.communicate() - if sub.returncode: - raise RuntimeError(sub.returncode, stderr) + retcode = sub.returncode + if retcode: + logging.error('release script failure: ' + + 'board: %s, ret: %s, stderr: %s' % (repr(brd.name), + retcode, repr(stderr))) + raise BITEError( + status_code=HTTP_500_INTERNAL_SERVER_ERROR, + errobj=Error(error= + 'Failed to release board, ret: %d, stderr: %s' % + (retcode, repr(stderr)), + board=Board.from_orm(brd)), + ) await data.BoardStatus.delete(brduser) await brd.release() @@ -509,6 +520,47 @@ class TestBiteLab(unittest.IsolatedAsyncioTestCase): self.assertEqual(res.json(), { 'cora-z7s': BoardClassInfo(**{ 'arch': 'arm-armv7', 'clsname': 'cora-z7s', }) }) + @patch('asyncio.create_subprocess_exec') + @patch('bitelab.snmp.snmpget') + @patch('logging.error') + async def test_board_release_script_fail(self, le, sg, cse): + # that when snmpget returns False + sg.return_value = False + + # that when the setup script will fail + wrap_subprocess_exec(cse, stderr=b'error', retcode=1) + + # that the cora-1 board is reserved + data = self.data + brd = self.brdmgr.boards['cora-1'] + async with brd.lock: + await brd.reserve() + obrdreq = await data.BoardStatus.objects.create( + board='cora-1', user='foo') + + # that when the correct user releases the board + res = await self.client.post('/board/cora-1/release', + auth=BiteAuth('thisisanapikey')) + + # it fails + self.assertEqual(res.status_code, HTTP_500_INTERNAL_SERVER_ERROR) + + # and returns the correct data + info = Error(error='Failed to release board, ret: 1, stderr: b\'error\'', + board=Board(name='cora-1', + brdclass='cora-z7s', + reserved=True, + ), + ).dict() + self.assertEqual(res.json(), info) + + # and that it called the release script + cse.assert_called_with(self.settings.setup_script, 'release', + 'cora-1', 'foo', stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + # and that the error got logged + le.assert_called_with('release script failure: board: \'cora-1\', ret: 1, stderr: b\'error\'') + @patch('asyncio.create_subprocess_exec') @patch('bitelab.snmp.snmpget') async def test_board_reserve_release(self, sg, cse):