Skip to content

Commit d50c807

Browse files
committed
Test new endpoint, add fix for non prepared Execution
1 parent ebef745 commit d50c807

File tree

3 files changed

+153
-4
lines changed

3 files changed

+153
-4
lines changed

src/aleph/vm/orchestrator/resources.py

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
)
2222

2323

24+
2425
class Period(BaseModel):
2526
datetime: datetime
2627

src/aleph/vm/orchestrator/views/__init__.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,12 @@ async def list_executions_v2(request: web.Request) -> web.Response:
183183
{
184184
item_hash: {
185185
"networking": {
186-
"ipv4": execution.vm.tap_interface.ip_network,
187-
"ipv6": execution.vm.tap_interface.ipv6_network,
188-
},
186+
"ipv4_network": execution.vm.tap_interface.ip_network,
187+
"ipv6_network": execution.vm.tap_interface.ipv6_network,
188+
"ipv6_ip": execution.vm.tap_interface.guest_ipv6.ip,
189+
}
190+
if execution.vm and execution.vm.tap_interface
191+
else {},
189192
"status": execution.times,
190193
"running": execution.is_controller_running,
191194
}

tests/supervisor/test_views.py

+146-1
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,39 @@
1111
from pytest_mock import MockerFixture
1212

1313
from aleph.vm.conf import settings
14+
from aleph.vm.models import VmExecution
1415
from aleph.vm.orchestrator.supervisor import setup_webapp
1516
from aleph.vm.pool import VmPool
1617
from aleph.vm.sevclient import SevClient
1718

1819

20+
@pytest.fixture()
21+
def mock_instance_content():
22+
fake = {
23+
"address": "0x101d8D16372dBf5f1614adaE95Ee5CCE61998Fc9",
24+
"time": 1713874241.800818,
25+
"allow_amend": False,
26+
"metadata": None,
27+
"authorized_keys": None,
28+
"variables": None,
29+
"environment": {"reproducible": False, "internet": True, "aleph_api": True, "shared_cache": False},
30+
"resources": {"vcpus": 1, "memory": 256, "seconds": 30, "published_ports": None},
31+
"payment": {"type": "superfluid", "chain": "BASE"},
32+
"requirements": None,
33+
"replaces": None,
34+
"rootfs": {
35+
"parent": {"ref": "63f07193e6ee9d207b7d1fcf8286f9aee34e6f12f101d2ec77c1229f92964696"},
36+
"ref": "63f07193e6ee9d207b7d1fcf8286f9aee34e6f12f101d2ec77c1229f92964696",
37+
"use_latest": True,
38+
"comment": "",
39+
"persistence": "host",
40+
"size_mib": 1000,
41+
},
42+
}
43+
44+
return fake
45+
46+
1947
@pytest.mark.asyncio
2048
async def test_allocation_fails_on_invalid_item_hash(aiohttp_client):
2149
"""Test that the allocation endpoint fails when an invalid item_hash is provided."""
@@ -137,6 +165,124 @@ def get_persistent_executions(self):
137165
assert await response.json() == {"success": True, "successful": [], "failing": [], "errors": {}}
138166

139167

168+
@pytest.mark.asyncio
169+
async def test_v2_executions_list_one_vm(aiohttp_client, mock_app_with_pool, mock_instance_content):
170+
web_app = await mock_app_with_pool
171+
pool = web_app["vm_pool"]
172+
message = InstanceContent.model_validate(mock_instance_content)
173+
174+
hash = "decadecadecadecadecadecadecadecadecadecadecadecadecadecadecadeca"
175+
176+
execution = VmExecution(
177+
vm_hash=hash,
178+
message=message,
179+
original=message,
180+
persistent=False,
181+
snapshot_manager=None,
182+
systemd_manager=None,
183+
)
184+
pool.executions = {hash: execution}
185+
client = await aiohttp_client(web_app)
186+
response: web.Response = await client.get(
187+
"/v2/about/executions/list",
188+
)
189+
assert response.status == 200
190+
assert await response.json() == {
191+
"decadecadecadecadecadecadecadecadecadecadecadecadecadecadecadeca": {
192+
"networking": {},
193+
"status": {
194+
"defined_at": str(execution.times.defined_at),
195+
"preparing_at": None,
196+
"prepared_at": None,
197+
"starting_at": None,
198+
"started_at": None,
199+
"stopping_at": None,
200+
"stopped_at": None,
201+
},
202+
"running": None,
203+
}
204+
}
205+
206+
207+
@pytest.mark.asyncio
208+
async def test_v2_executions_list_vm_network(aiohttp_client, mocker, mock_app_with_pool, mock_instance_content):
209+
"Test locally but do not create"
210+
web_app = await mock_app_with_pool
211+
pool = web_app["vm_pool"]
212+
message = InstanceContent.model_validate(mock_instance_content)
213+
214+
vm_hash = "decadecadecadecadecadecadecadecadecadecadecadecadecadecadecadeca"
215+
216+
execution = VmExecution(
217+
vm_hash=hash,
218+
message=message,
219+
original=message,
220+
persistent=False,
221+
snapshot_manager=None,
222+
systemd_manager=None,
223+
)
224+
vm_id = 3
225+
from aleph.vm.network.hostnetwork import Network, make_ipv6_allocator
226+
227+
network = Network(
228+
vm_ipv4_address_pool_range=settings.IPV4_ADDRESS_POOL,
229+
vm_network_size=settings.IPV4_NETWORK_PREFIX_LENGTH,
230+
external_interface=settings.NETWORK_INTERFACE,
231+
ipv6_allocator=make_ipv6_allocator(
232+
allocation_policy=settings.IPV6_ALLOCATION_POLICY,
233+
address_pool=settings.IPV6_ADDRESS_POOL,
234+
subnet_prefix=settings.IPV6_SUBNET_PREFIX,
235+
),
236+
use_ndp_proxy=False,
237+
ipv6_forwarding_enabled=False,
238+
)
239+
network.setup()
240+
241+
from aleph.vm.vm_type import VmType
242+
243+
vm_type = VmType.from_message_content(message)
244+
tap_interface = await network.prepare_tap(vm_id, vm_hash, vm_type)
245+
# await network.create_tap(vm_id, tap_interface)
246+
execution.vm = mocker.Mock()
247+
execution.vm.tap_interface = tap_interface
248+
249+
pool.executions = {vm_hash: execution}
250+
client = await aiohttp_client(web_app)
251+
response: web.Response = await client.get(
252+
"/v2/about/executions/list",
253+
)
254+
assert response.status == 200
255+
assert await response.json() == {
256+
"decadecadecadecadecadecadecadecadecadecadecadecadecadecadecadeca": {
257+
"networking": {
258+
"ipv4_network": "172.16.3.0/24",
259+
"ipv6_network": "fc00:1:2:3:3:deca:deca:dec0/124",
260+
"ipv6_ip": "fc00:1:2:3:3:deca:deca:dec1",
261+
},
262+
"status": {
263+
"defined_at": str(execution.times.defined_at),
264+
"preparing_at": None,
265+
"prepared_at": None,
266+
"starting_at": None,
267+
"started_at": None,
268+
"stopping_at": None,
269+
"stopped_at": None,
270+
},
271+
"running": None,
272+
}
273+
}
274+
275+
276+
@pytest.mark.asyncio
277+
async def test_v2_executions_list_empty(aiohttp_client, mock_app_with_pool):
278+
client = await aiohttp_client(await mock_app_with_pool)
279+
response: web.Response = await client.get(
280+
"/v2/about/executions/list",
281+
)
282+
assert response.status == 200
283+
assert await response.json() == {}
284+
285+
140286
@pytest.mark.asyncio
141287
async def test_about_certificates_missing_setting(aiohttp_client):
142288
"""Test that the certificates system endpoint returns an error if the setting isn't enabled"""
@@ -268,7 +414,6 @@ def mock_is_kernel_enabled_gpu(pci_host: str) -> bool:
268414
)
269415

270416
mocker.patch.object(settings, "ENABLE_GPU_SUPPORT", True)
271-
loop = asyncio.new_event_loop()
272417
pool = VmPool()
273418
await pool.setup()
274419
app = setup_webapp(pool=pool)

0 commit comments

Comments
 (0)