From df9d9e0409b452ccf388a823fb8dbc4530ecbb23 Mon Sep 17 00:00:00 2001 From: "Andres D. Molins" Date: Tue, 5 Mar 2024 17:18:16 +0100 Subject: [PATCH 1/8] Problem: Instances with Qemu hypervisor cannot be created. Solution: Implement hypervisor field into create_instance method --- src/aleph/sdk/client/authenticated_http.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/aleph/sdk/client/authenticated_http.py b/src/aleph/sdk/client/authenticated_http.py index cf75d986..cb7854eb 100644 --- a/src/aleph/sdk/client/authenticated_http.py +++ b/src/aleph/sdk/client/authenticated_http.py @@ -30,6 +30,7 @@ from aleph_message.models.execution.environment import ( FunctionEnvironment, MachineResources, + HypervisorType, ) from aleph_message.models.execution.instance import RootfsVolume from aleph_message.models.execution.program import CodeContent, FunctionRuntime @@ -520,6 +521,7 @@ async def create_instance( allow_amend: bool = False, internet: bool = True, aleph_api: bool = True, + hypervisor: Optional[HypervisorType] = None, volumes: Optional[List[Mapping]] = None, volume_persistence: str = "host", ssh_keys: Optional[List[str]] = None, @@ -533,6 +535,7 @@ async def create_instance( timeout_seconds = timeout_seconds or settings.DEFAULT_VM_TIMEOUT payment = payment or Payment(chain=Chain.ETH, type=PaymentType.hold) + hypervisor = hypervisor or HypervisorType.firecracker content = InstanceContent( address=address, @@ -541,6 +544,7 @@ async def create_instance( reproducible=False, internet=internet, aleph_api=aleph_api, + hypervisor=hypervisor, ), variables=environment_variables, resources=MachineResources( From 7757f2093b9560a2a45723aa159d0c378fad680d Mon Sep 17 00:00:00 2001 From: "Andres D. Molins" Date: Tue, 5 Mar 2024 17:44:15 +0100 Subject: [PATCH 2/8] Fix: Add test case for hypervisor field --- tests/unit/test_asynchronous.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_asynchronous.py b/tests/unit/test_asynchronous.py index ef8b67ca..c105bd70 100644 --- a/tests/unit/test_asynchronous.py +++ b/tests/unit/test_asynchronous.py @@ -14,7 +14,7 @@ ProgramMessage, StoreMessage, ) -from aleph_message.models.execution.environment import MachineResources +from aleph_message.models.execution.environment import MachineResources, HypervisorType from aleph_message.status import MessageStatus from aleph.sdk.exceptions import InsufficientFundsError @@ -116,6 +116,7 @@ async def test_create_instance(mock_session_with_post_success): receiver="0x4145f182EF2F06b45E50468519C1B92C60FBd4A0", type=PaymentType.superfluid, ), + hypervisor=HypervisorType.qemu, ) assert mock_session_with_post_success.http_session.post.called_once @@ -144,6 +145,27 @@ async def test_create_instance_no_payment(mock_session_with_post_success): assert isinstance(instance_message, InstanceMessage) +@pytest.mark.asyncio +async def test_create_instance_no_hypervisor(mock_session_with_post_success): + """Test that an instance can be created with no hypervisor specified. + It should in this case default to "firecracker". + """ + async with mock_session_with_post_success as session: + instance_message, message_status = await session.create_instance( + rootfs="cafecafecafecafecafecafecafecafecafecafecafecafecafecafecafecafe", + rootfs_size=1, + rootfs_name="rootfs", + channel="TEST", + metadata={"tags": ["test"]}, + hypervisor=None, + ) + + assert instance_message.content.hypervisor == HypervisorType.firecracker + + assert mock_session_with_post_success.http_session.post.called_once + assert isinstance(instance_message, InstanceMessage) + + @pytest.mark.asyncio async def test_forget(mock_session_with_post_success): async with mock_session_with_post_success as session: From 36dfde5fa081f48deb74067461d2defd7ed60159 Mon Sep 17 00:00:00 2001 From: "Andres D. Molins" Date: Wed, 6 Mar 2024 13:48:42 +0100 Subject: [PATCH 3/8] Fix: Solved code quality issues --- src/aleph/sdk/client/abstract.py | 2 ++ src/aleph/sdk/client/authenticated_http.py | 2 +- src/aleph/sdk/conf.py | 4 +--- src/aleph/sdk/types.py | 12 ++++++++---- src/aleph/sdk/utils.py | 6 ++++-- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/aleph/sdk/client/abstract.py b/src/aleph/sdk/client/abstract.py index b8ce2038..899b405c 100644 --- a/src/aleph/sdk/client/abstract.py +++ b/src/aleph/sdk/client/abstract.py @@ -18,6 +18,7 @@ from aleph_message.models import ( AlephMessage, + HypervisorType, MessagesResponse, MessageType, Payment, @@ -373,6 +374,7 @@ async def create_instance( allow_amend: bool = False, internet: bool = True, aleph_api: bool = True, + hypervisor: Optional[HypervisorType] = None, volumes: Optional[List[Mapping]] = None, volume_persistence: str = "host", ssh_keys: Optional[List[str]] = None, diff --git a/src/aleph/sdk/client/authenticated_http.py b/src/aleph/sdk/client/authenticated_http.py index cb7854eb..f4f89ba1 100644 --- a/src/aleph/sdk/client/authenticated_http.py +++ b/src/aleph/sdk/client/authenticated_http.py @@ -29,8 +29,8 @@ from aleph_message.models.execution.base import Encoding, Payment, PaymentType from aleph_message.models.execution.environment import ( FunctionEnvironment, - MachineResources, HypervisorType, + MachineResources, ) from aleph_message.models.execution.instance import RootfsVolume from aleph_message.models.execution.program import CodeContent, FunctionRuntime diff --git a/src/aleph/sdk/conf.py b/src/aleph/sdk/conf.py index 318536e4..f8d798c6 100644 --- a/src/aleph/sdk/conf.py +++ b/src/aleph/sdk/conf.py @@ -29,9 +29,7 @@ class Settings(BaseSettings): REMOTE_CRYPTO_UNIX_SOCKET: Optional[str] = None ADDRESS_TO_USE: Optional[str] = None - DEFAULT_RUNTIME_ID: str = ( - "f873715dc2feec3833074bd4b8745363a0e0093746b987b4c8191268883b2463" # Debian 12 official runtime - ) + DEFAULT_RUNTIME_ID: str = "f873715dc2feec3833074bd4b8745363a0e0093746b987b4c8191268883b2463" # Debian 12 official runtime DEFAULT_VM_MEMORY: int = 256 DEFAULT_VM_VCPUS: int = 1 DEFAULT_VM_TIMEOUT: float = 30.0 diff --git a/src/aleph/sdk/types.py b/src/aleph/sdk/types.py index 2f57b280..67c0dda3 100644 --- a/src/aleph/sdk/types.py +++ b/src/aleph/sdk/types.py @@ -18,19 +18,23 @@ class Account(Protocol): CURVE: str @abstractmethod - async def sign_message(self, message: Dict) -> Dict: ... + async def sign_message(self, message: Dict) -> Dict: + ... @abstractmethod - def get_address(self) -> str: ... + def get_address(self) -> str: + ... @abstractmethod - def get_public_key(self) -> str: ... + def get_public_key(self) -> str: + ... class AccountFromPrivateKey(Account, Protocol): """Only accounts that are initialized from a private key string are supported.""" - def __init__(self, private_key: bytes): ... + def __init__(self, private_key: bytes): + ... GenericMessage = TypeVar("GenericMessage", bound=AlephMessage) diff --git a/src/aleph/sdk/utils.py b/src/aleph/sdk/utils.py index ab17f44a..72a219b9 100644 --- a/src/aleph/sdk/utils.py +++ b/src/aleph/sdk/utils.py @@ -98,11 +98,13 @@ def check_unix_socket_valid(unix_socket_path: str) -> bool: class AsyncReadable(Protocol[T]): - async def read(self, n: int = -1) -> T: ... + async def read(self, n: int = -1) -> T: + ... class Writable(Protocol[U]): - def write(self, buffer: U) -> int: ... + def write(self, buffer: U) -> int: + ... async def copy_async_readable_to_buffer( From 8106bd89cc49771c2c8feddf556f3d9b0083cea8 Mon Sep 17 00:00:00 2001 From: "Andres D. Molins" Date: Wed, 6 Mar 2024 14:32:29 +0100 Subject: [PATCH 4/8] Fix: Solve code quality issues on tests also --- tests/unit/conftest.py | 6 ++++-- tests/unit/test_asynchronous.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index 7d388e36..5289e9d7 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -158,9 +158,11 @@ def __init__(self, sync: bool): async def __aenter__(self): return self - async def __aexit__(self, exc_type, exc_val, exc_tb): ... + async def __aexit__(self, exc_type, exc_val, exc_tb): + ... - async def raise_for_status(self): ... + async def raise_for_status(self): + ... @property def status(self): diff --git a/tests/unit/test_asynchronous.py b/tests/unit/test_asynchronous.py index c105bd70..557418c4 100644 --- a/tests/unit/test_asynchronous.py +++ b/tests/unit/test_asynchronous.py @@ -14,7 +14,7 @@ ProgramMessage, StoreMessage, ) -from aleph_message.models.execution.environment import MachineResources, HypervisorType +from aleph_message.models.execution.environment import HypervisorType, MachineResources from aleph_message.status import MessageStatus from aleph.sdk.exceptions import InsufficientFundsError From d6ebc3ce5ecbf9fc696a7017dbdbb00b4b5debce Mon Sep 17 00:00:00 2001 From: "Andres D. Molins" Date: Wed, 6 Mar 2024 14:36:18 +0100 Subject: [PATCH 5/8] Fix: Fixed incorrect import on abstract interface --- src/aleph/sdk/client/abstract.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aleph/sdk/client/abstract.py b/src/aleph/sdk/client/abstract.py index 899b405c..34eb74d4 100644 --- a/src/aleph/sdk/client/abstract.py +++ b/src/aleph/sdk/client/abstract.py @@ -24,6 +24,7 @@ Payment, PostMessage, ) +from aleph_message.models.execution.environment import HypervisorType from aleph_message.models.execution.program import Encoding from aleph_message.status import MessageStatus From e5b1527d4db8087246e70bd793856232f8f4697d Mon Sep 17 00:00:00 2001 From: "Andres D. Molins" Date: Wed, 6 Mar 2024 14:39:22 +0100 Subject: [PATCH 6/8] Fix: Fixed incorrect import on abstract interface --- src/aleph/sdk/client/abstract.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/aleph/sdk/client/abstract.py b/src/aleph/sdk/client/abstract.py index 34eb74d4..db98d3ac 100644 --- a/src/aleph/sdk/client/abstract.py +++ b/src/aleph/sdk/client/abstract.py @@ -18,7 +18,6 @@ from aleph_message.models import ( AlephMessage, - HypervisorType, MessagesResponse, MessageType, Payment, From e80bfc70a7b695ed56207a45ff81bcdfb82ecd19 Mon Sep 17 00:00:00 2001 From: "Andres D. Molins" Date: Wed, 6 Mar 2024 14:56:46 +0100 Subject: [PATCH 7/8] Fix: Upgraded black version and refformatted issues --- src/aleph/sdk/conf.py | 4 +++- src/aleph/sdk/types.py | 12 ++++-------- src/aleph/sdk/utils.py | 6 ++---- tests/unit/conftest.py | 6 ++---- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/aleph/sdk/conf.py b/src/aleph/sdk/conf.py index f8d798c6..318536e4 100644 --- a/src/aleph/sdk/conf.py +++ b/src/aleph/sdk/conf.py @@ -29,7 +29,9 @@ class Settings(BaseSettings): REMOTE_CRYPTO_UNIX_SOCKET: Optional[str] = None ADDRESS_TO_USE: Optional[str] = None - DEFAULT_RUNTIME_ID: str = "f873715dc2feec3833074bd4b8745363a0e0093746b987b4c8191268883b2463" # Debian 12 official runtime + DEFAULT_RUNTIME_ID: str = ( + "f873715dc2feec3833074bd4b8745363a0e0093746b987b4c8191268883b2463" # Debian 12 official runtime + ) DEFAULT_VM_MEMORY: int = 256 DEFAULT_VM_VCPUS: int = 1 DEFAULT_VM_TIMEOUT: float = 30.0 diff --git a/src/aleph/sdk/types.py b/src/aleph/sdk/types.py index 67c0dda3..2f57b280 100644 --- a/src/aleph/sdk/types.py +++ b/src/aleph/sdk/types.py @@ -18,23 +18,19 @@ class Account(Protocol): CURVE: str @abstractmethod - async def sign_message(self, message: Dict) -> Dict: - ... + async def sign_message(self, message: Dict) -> Dict: ... @abstractmethod - def get_address(self) -> str: - ... + def get_address(self) -> str: ... @abstractmethod - def get_public_key(self) -> str: - ... + def get_public_key(self) -> str: ... class AccountFromPrivateKey(Account, Protocol): """Only accounts that are initialized from a private key string are supported.""" - def __init__(self, private_key: bytes): - ... + def __init__(self, private_key: bytes): ... GenericMessage = TypeVar("GenericMessage", bound=AlephMessage) diff --git a/src/aleph/sdk/utils.py b/src/aleph/sdk/utils.py index 72a219b9..ab17f44a 100644 --- a/src/aleph/sdk/utils.py +++ b/src/aleph/sdk/utils.py @@ -98,13 +98,11 @@ def check_unix_socket_valid(unix_socket_path: str) -> bool: class AsyncReadable(Protocol[T]): - async def read(self, n: int = -1) -> T: - ... + async def read(self, n: int = -1) -> T: ... class Writable(Protocol[U]): - def write(self, buffer: U) -> int: - ... + def write(self, buffer: U) -> int: ... async def copy_async_readable_to_buffer( diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index 5289e9d7..7d388e36 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -158,11 +158,9 @@ def __init__(self, sync: bool): async def __aenter__(self): return self - async def __aexit__(self, exc_type, exc_val, exc_tb): - ... + async def __aexit__(self, exc_type, exc_val, exc_tb): ... - async def raise_for_status(self): - ... + async def raise_for_status(self): ... @property def status(self): From 7c25ae30eb6f1a3ed9a2fec21b6458d83e240fe1 Mon Sep 17 00:00:00 2001 From: "Andres D. Molins" Date: Wed, 6 Mar 2024 16:01:57 +0100 Subject: [PATCH 8/8] Fix: Solved issue in wrong field to test. --- tests/unit/test_asynchronous.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_asynchronous.py b/tests/unit/test_asynchronous.py index 557418c4..0981ad19 100644 --- a/tests/unit/test_asynchronous.py +++ b/tests/unit/test_asynchronous.py @@ -160,7 +160,7 @@ async def test_create_instance_no_hypervisor(mock_session_with_post_success): hypervisor=None, ) - assert instance_message.content.hypervisor == HypervisorType.firecracker + assert instance_message.content.environment.hypervisor == HypervisorType.firecracker assert mock_session_with_post_success.http_session.post.called_once assert isinstance(instance_message, InstanceMessage)