Skip to content

Commit be5a697

Browse files
authored
Add new Confidential fields (#137)
* Problem: As a user we cannot create a confidential VM using the SDK. Solution: Implement new confidential VM fields. * Fix: Solve code quality issues. * Fix: Changed `create_instance` method signature to be similar to aleph-message schema.
1 parent 59cc247 commit be5a697

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

src/aleph/sdk/client/abstract.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@
2727
PostMessage,
2828
parse_message,
2929
)
30-
from aleph_message.models.execution.environment import HypervisorType
30+
from aleph_message.models.execution.environment import (
31+
HostRequirements,
32+
HypervisorType,
33+
TrustedExecutionEnvironment,
34+
)
3135
from aleph_message.models.execution.program import Encoding
3236
from aleph_message.status import MessageStatus
3337

@@ -395,10 +399,12 @@ async def create_instance(
395399
internet: bool = True,
396400
aleph_api: bool = True,
397401
hypervisor: Optional[HypervisorType] = None,
402+
trusted_execution: Optional[TrustedExecutionEnvironment] = None,
398403
volumes: Optional[List[Mapping]] = None,
399404
volume_persistence: str = "host",
400405
ssh_keys: Optional[List[str]] = None,
401406
metadata: Optional[Mapping[str, Any]] = None,
407+
requirements: Optional[HostRequirements] = None,
402408
) -> Tuple[AlephMessage, MessageStatus]:
403409
"""
404410
Post a (create) INSTANCE message.
@@ -417,11 +423,14 @@ async def create_instance(
417423
:param allow_amend: Whether the deployed VM image may be changed (Default: False)
418424
:param internet: Whether the VM should have internet connectivity. (Default: True)
419425
:param aleph_api: Whether the VM needs access to Aleph messages API (Default: True)
426+
:param hypervisor: Whether the VM should use as Hypervisor, like QEmu or Firecracker (Default: Qemu)
427+
:param trusted_execution: Whether the VM configuration (firmware and policy) to use for Confidential computing (Default: None)
420428
:param encoding: Encoding to use (Default: Encoding.zip)
421429
:param volumes: Volumes to mount
422430
:param volume_persistence: Where volumes are persisted, can be "host" or "store", meaning distributed across Aleph.im (Default: "host")
423431
:param ssh_keys: SSH keys to authorize access to the VM
424432
:param metadata: Metadata to attach to the message
433+
:param requirements: CRN Requirements needed for the VM execution
425434
"""
426435
raise NotImplementedError(
427436
"Did you mean to import `AuthenticatedAlephHttpClient`?"

src/aleph/sdk/client/authenticated_http.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@
2929
from aleph_message.models.execution.base import Encoding, Payment, PaymentType
3030
from aleph_message.models.execution.environment import (
3131
FunctionEnvironment,
32+
HostRequirements,
3233
HypervisorType,
3334
InstanceEnvironment,
3435
MachineResources,
36+
TrustedExecutionEnvironment,
3537
)
3638
from aleph_message.models.execution.instance import RootfsVolume
3739
from aleph_message.models.execution.program import CodeContent, FunctionRuntime
@@ -522,10 +524,12 @@ async def create_instance(
522524
internet: bool = True,
523525
aleph_api: bool = True,
524526
hypervisor: Optional[HypervisorType] = None,
527+
trusted_execution: Optional[TrustedExecutionEnvironment] = None,
525528
volumes: Optional[List[Mapping]] = None,
526529
volume_persistence: str = "host",
527530
ssh_keys: Optional[List[str]] = None,
528531
metadata: Optional[Mapping[str, Any]] = None,
532+
requirements: Optional[HostRequirements] = None,
529533
) -> Tuple[InstanceMessage, MessageStatus]:
530534
address = address or settings.ADDRESS_TO_USE or self.account.get_address()
531535

@@ -546,6 +550,7 @@ async def create_instance(
546550
internet=internet,
547551
aleph_api=aleph_api,
548552
hypervisor=selected_hypervisor,
553+
trusted_execution=trusted_execution,
549554
),
550555
variables=environment_variables,
551556
resources=MachineResources(
@@ -563,6 +568,7 @@ async def create_instance(
563568
use_latest=True,
564569
),
565570
volumes=[parse_volume(volume) for volume in volumes],
571+
requirements=requirements,
566572
time=time.time(),
567573
authorized_keys=ssh_keys,
568574
metadata=metadata,

tests/unit/test_asynchronous.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@
1414
ProgramMessage,
1515
StoreMessage,
1616
)
17-
from aleph_message.models.execution.environment import HypervisorType, MachineResources
17+
from aleph_message.models.execution.environment import (
18+
HostRequirements,
19+
HypervisorType,
20+
MachineResources,
21+
NodeRequirements,
22+
TrustedExecutionEnvironment,
23+
)
1824
from aleph_message.status import MessageStatus
1925

2026
from aleph.sdk.exceptions import InsufficientFundsError
@@ -163,6 +169,35 @@ async def test_create_instance_no_hypervisor(mock_session_with_post_success):
163169
assert isinstance(instance_message, InstanceMessage)
164170

165171

172+
@pytest.mark.asyncio
173+
async def test_create_confidential_instance(mock_session_with_post_success):
174+
async with mock_session_with_post_success as session:
175+
confidential_instance_message, message_status = await session.create_instance(
176+
rootfs="cafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe",
177+
rootfs_size=1,
178+
channel="TEST",
179+
metadata={"tags": ["test"]},
180+
payment=Payment(
181+
chain=Chain.AVAX,
182+
receiver="0x4145f182EF2F06b45E50468519C1B92C60FBd4A0",
183+
type=PaymentType.superfluid,
184+
),
185+
hypervisor=HypervisorType.qemu,
186+
trusted_execution=TrustedExecutionEnvironment(
187+
firmware="cafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe",
188+
policy=0b1,
189+
),
190+
requirements=HostRequirements(
191+
node=NodeRequirements(
192+
node_hash="cafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe",
193+
)
194+
),
195+
)
196+
197+
assert mock_session_with_post_success.http_session.post.assert_called_once
198+
assert isinstance(confidential_instance_message, InstanceMessage)
199+
200+
166201
@pytest.mark.asyncio
167202
async def test_forget(mock_session_with_post_success):
168203
async with mock_session_with_post_success as session:

0 commit comments

Comments
 (0)