Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions aleph_message/models/execution/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ class NodeRequirements(HashableModel):
node_hash: Optional[ItemHash] = Field(
default=None, description="Hash of the compute resource node that must be used"
)
terms_and_conditions: Optional[ItemHash] = Field(
default=None, description="Terms and conditions of this CRN"
)

class Config:
extra = Extra.forbid
Expand Down
38 changes: 28 additions & 10 deletions aleph_message/models/execution/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,35 @@ class InstanceContent(BaseExecutableContent):
)

@root_validator()
def check_gpu_requirement(cls, values):
if values.get("requirements") and values.get("requirements").gpu:
if (
not values.get("requirements").node
or not values.get("requirements").node.node_hash
):
raise ValueError("Node hash assignment is needed for GPU support")
def check_requirements(cls, values):
if values.get("requirements"):
# GPU filter only supported for QEmu instances with node_hash assigned
if values.get("requirements").gpu:
if (
not values.get("requirements").node
or not values.get("requirements").node.node_hash
):
raise ValueError("Node hash assignment is needed for GPU support")

if (
values.get("environment")
and values.get("environment").hypervisor != HypervisorType.qemu
):
raise ValueError("GPU option is only supported for QEmu hypervisor")

# Terms and conditions filter only supported for stream payments with node_hash assigned
if (
values.get("environment")
and values.get("environment").hypervisor != HypervisorType.qemu
values.get("requirements").node
and values.get("requirements").node.terms_and_conditions
):
raise ValueError("GPU option is only supported for QEmu hypervisor")
if not values.get("requirements").node.node_hash:
raise ValueError(
"Terms_and_conditions field needs a requirements.node.node_hash value"
)

if not values.get("payment").is_stream:
raise ValueError(
"Only PAYG/stream instances can have a terms_and_conditions"
)

return values
69 changes: 69 additions & 0 deletions aleph_message/tests/messages/instance_content.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"sender": "0x3E1aba4ad853Dd7Aa531aB59F10bd9f4d89aebaF",
"chain": "ETH",
"signature": "0x5ff79fb62190455b485e6a891d7bbee3a992ca8d0361bbd55f12a18176d9f668692601a75c3344cb880a479fc5920efc53036450bce8e891e13b9aa5618b2aba1b",
"type": "INSTANCE",
"item_content": "{\"address\":\"0x3E1aba4ad853Dd7Aa531aB59F10bd9f4d89aebaF\",\"time\":1732118563.2142403,\"allow_amend\":false,\"metadata\":{\"name\":\"test-payg-base\"},\"authorized_keys\":[\"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQVOxf7uOhIlt7GbPD1XnnSGPvj4t9cdjzB2AYRt3jlPT5w9gcUr2WYj+EPYDXig+imDYELtZNx6Pvg5jruKjFaAtugV3ta0NHPamGNIVPxSNdwx+teLIEs/A9FPT3jeohvU+JpjrKLjBtsfyVJ9iBf/Iswm2rcc/33k4LumwFgkpgNswIc4Da6L1K7EHrlkSbdtdBMdlxLGaU2eFp140JwOTCBBF4rL0JNzPDCzLdkKsj2hQOWg6IIwhQzg3B6o1lY2xoGrVWL4+s+TKSgv1VQY0I1Fmyw+33bWYw/sZlhEpflFYp565Nh2+n3nbYNvmouH4RTLwNUF4z2vvG3J3HVlkd5Q0SCNvPk6FAkAgZ2oXK2P79enlglL+NcFr21QInbacclAtESpPop3dSdLNbR8NvQwh53eELcBPtGFQLRPP9ZfOwtG1hZhVinCeb6fpgcOsBXn0Xo11DQ3XNgfMho632FPqujQtggkyZt/2a53oGEbrrfGgDhiLCGswUM1k= root@rpi\"],\"environment\":{\"internet\":true,\"aleph_api\":true,\"hypervisor\":\"qemu\",\"reproducible\":false,\"shared_cache\":false},\"resources\":{\"vcpus\":1,\"memory\":2048,\"seconds\":30},\"payment\":{\"chain\":\"BASE\",\"receiver\":\"0xFeF2b33478f906eDE5ee96110b2342861cF1569A\",\"type\":\"superfluid\"},\"requirements\":{\"node\":{\"node_hash\":\"2cdb78cf561c6f0f839edb817395d3b5ece20d89125c5afba658f9170d6932c8\"}},\"volumes\":[],\"rootfs\":{\"parent\":{\"ref\":\"b6ff5c3a8205d1ca4c7c3369300eeafff498b558f71b851aa2114afd0a532717\",\"use_latest\":true},\"persistence\":\"host\",\"size_mib\":10240}}",
"item_type": "inline",
"item_hash": "b28fa9a9ede14c9bbd6fde8959be07cfd25a3358d08e01405301adc5a1a2b2c8",
"time": "2024-11-20T16:02:43.214390+00:00",
"channel": "ALEPH-CLOUDSOLUTIONS",
"content": {
"address": "0x3E1aba4ad853Dd7Aa531aB59F10bd9f4d89aebaF",
"time": 1732118563.2142403,
"allow_amend": false,
"metadata": {
"name": "test-payg-base"
},
"authorized_keys": [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQVOxf7uOhIlt7GbPD1XnnSGPvj4t9cdjzB2AYRt3jlPT5w9gcUr2WYj+EPYDXig+imDYELtZNx6Pvg5jruKjFaAtugV3ta0NHPamGNIVPxSNdwx+teLIEs/A9FPT3jeohvU+JpjrKLjBtsfyVJ9iBf/Iswm2rcc/33k4LumwFgkpgNswIc4Da6L1K7EHrlkSbdtdBMdlxLGaU2eFp140JwOTCBBF4rL0JNzPDCzLdkKsj2hQOWg6IIwhQzg3B6o1lY2xoGrVWL4+s+TKSgv1VQY0I1Fmyw+33bWYw/sZlhEpflFYp565Nh2+n3nbYNvmouH4RTLwNUF4z2vvG3J3HVlkd5Q0SCNvPk6FAkAgZ2oXK2P79enlglL+NcFr21QInbacclAtESpPop3dSdLNbR8NvQwh53eELcBPtGFQLRPP9ZfOwtG1hZhVinCeb6fpgcOsBXn0Xo11DQ3XNgfMho632FPqujQtggkyZt/2a53oGEbrrfGgDhiLCGswUM1k= root@rpi"
],
"variables": null,
"environment": {
"internet": true,
"aleph_api": true,
"hypervisor": "qemu",
"trusted_execution": null,
"reproducible": false,
"shared_cache": false
},
"resources": {
"vcpus": 1,
"memory": 2048,
"seconds": 30,
"published_ports": null
},
"payment": {
"chain": "BASE",
"receiver": "0xFeF2b33478f906eDE5ee96110b2342861cF1569A",
"type": "superfluid"
},
"requirements": {
"cpu": null,
"node": {
"owner": null,
"address_regex": null,
"node_hash": "2cdb78cf561c6f0f839edb817395d3b5ece20d89125c5afba658f9170d6932c8",
"terms_and_conditions": "2cdb78cf561c6f0f839edb817395d3b5ece20d89125c5afba658f9170d6932c8"
}
},
"volumes": [],
"replaces": null,
"rootfs": {
"parent": {
"ref": "b6ff5c3a8205d1ca4c7c3369300eeafff498b558f71b851aa2114afd0a532717",
"use_latest": true
},
"persistence": "host",
"size_mib": 10240
}
},
"confirmed": true,
"confirmations": [
{
"chain": "ETH",
"height": 21230293,
"hash": "0x8bd25e2384dbb2da8c516880c47148304ed9ee1b7dfff8a327f8ccfa97ea29f4"
}
]
}
35 changes: 35 additions & 0 deletions aleph_message/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from aleph_message.models import (
AggregateMessage,
ForgetMessage,
InstanceContent,
InstanceMessage,
ItemType,
MessagesResponse,
Expand Down Expand Up @@ -402,3 +403,37 @@ def test_messages_from_disk():
console.print(message_dict)
console.print_json(e.json())
raise


def test_terms_and_conditions_only_for_payg_instances():
"""Ensure that only instance with PAYG and a node_hash can have a terms_and_conditions"""
path = os.path.abspath(os.path.join(__file__, "../messages/instance_content.json"))
with open(path) as fd:
message_dict = json.load(fd)

# this one is valid
instance_message = create_message_from_json(
json.dumps(message_dict), factory=InstanceMessage
)

assert isinstance(instance_message.content, InstanceContent)
assert (
instance_message.content.payment and instance_message.content.payment.is_stream
)

message_dict["content"]["payment"]["type"] = "hold"

# can't have a terms_and_conditions with hold
with pytest.raises(ValueError):
instance_message = create_message_from_json(
json.dumps(message_dict), factory=InstanceMessage
)

message_dict["content"]["payment"]["type"] = "superfluid"

# a node_hash is needed for a terms_and_conditions
del message_dict["content"]["requirements"]["node"]["node_hash"]
with pytest.raises(ValueError):
instance_message = create_message_from_json(
json.dumps(message_dict), factory=InstanceMessage
)