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:
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({}))