aetherscale

[unmaintained] code for a cloud provider tutorial
Log | Files | Refs | README | LICENSE

commit 6ac8212a30496653447ff3829bd3c927ecd48b96
parent f7263b94dd7ebc1ccb1b6054b0b3f2b84f3b37a7
Author: Stefan Koch <programming@stefan-koch.name>
Date:   Sat,  6 Feb 2021 17:12:46 +0100

add endpoint for VM details

Diffstat:
Maetherscale/api/rest.py | 12++++++++++++
Maetherscale/computing.py | 21+++++++++++++++++++++
Mtests/test_api_rest.py | 7+++++++
Mtests/test_computing.py | 4++++
4 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/aetherscale/api/rest.py b/aetherscale/api/rest.py @@ -24,6 +24,18 @@ def list_vms(): return flask.jsonify(result) +@app.route('/vm/<vm_id>', methods=['GET']) +def vm_info(vm_id): + handler: ComputingHandler = flask.g.handler + + try: + result = list(handler.vm_info({'vm-id': vm_id}))[0] + except RuntimeError: + return 'VM does not exist', 400 + + return flask.jsonify(result) + + @app.route('/vm', methods=['POST']) def create_vm(): options = flask.request.json diff --git a/aetherscale/computing.py b/aetherscale/computing.py @@ -146,6 +146,27 @@ class ComputingHandler: yield vms + def vm_info(self, options: Dict[str, Any]) -> Iterator[Dict[str, str]]: + try: + vm_id = options['vm-id'] + except KeyError: + raise ValueError('VM ID not specified') + + unit_name = systemd_unit_name_for_vm(vm_id) + if not self.service_manager.service_exists(unit_name): + raise RuntimeError('VM does not exist') + + # TODO: Distinguish better between status, define good lifecycle + if self.service_manager.service_is_running(unit_name): + status = 'running' + else: + status = 'stopped' + + yield { + 'vm-id': vm_id, + 'status': status, + } + def create_vm(self, options: Dict[str, Any]) -> Iterator[Dict[str, str]]: vm_id = ''.join( random.choice(string.ascii_lowercase) for _ in range(8)) diff --git a/tests/test_api_rest.py b/tests/test_api_rest.py @@ -23,6 +23,13 @@ def test_list_vms(handler, client): @mock.patch('aetherscale.api.rest.ComputingHandler') +def test_show_vm_info(handler, client): + handler.return_value.vm_info.return_value = [{'vm-id': 'abc123'}] + rv = client.get('/vm/abc123') + assert rv.json['vm-id'] == 'abc123' + + +@mock.patch('aetherscale.api.rest.ComputingHandler') def test_create_vm(handler, client): client.post( '/vm', data=json.dumps({'image': 'dummy-image'}), diff --git a/tests/test_computing.py b/tests/test_computing.py @@ -49,6 +49,10 @@ def test_vm_lifecycle(tmppath, mock_service_manager: ServiceManager): assert mock_service_manager.service_is_running(service_name) assert list_results[0][0]['vm-id'] == vm_id + vm_info = list(handler.vm_info({'vm-id': vm_id}))[0] + assert vm_info['vm-id'] == vm_id + assert vm_info['status'] == 'running' + # TODO: Test graceful stop, needs mock of QemuMonitor results = list(handler.stop_vm({'vm-id': vm_id, 'kill': True})) list_results = list(handler.list_vms({}))