diff --git a/backend/src/interfaces/aleph.py b/backend/src/interfaces/aleph.py index f4b4137..9f3cfb7 100644 --- a/backend/src/interfaces/aleph.py +++ b/backend/src/interfaces/aleph.py @@ -6,3 +6,12 @@ class AlephVolume(BaseModel): mount: str ref: str use_latest: bool + + +class AlephNodeInfo: + def __init__(self, **kwargs): + self.data = kwargs.get("data", {}) + self.nodes = self.data.get("corechannel", {}).get("resource_nodes", []) + self.nodes.sort(key=lambda x: x.get("score", 0), reverse=True) + self.core_node = self.data.get("corechannel", {}).get("nodes", []) + self.core_node.sort(key=lambda x: x.get("score", 0), reverse=True) diff --git a/backend/src/main.py b/backend/src/main.py index 068a672..86c048b 100644 --- a/backend/src/main.py +++ b/backend/src/main.py @@ -7,7 +7,9 @@ import paramiko from aleph.sdk import AuthenticatedAlephHttpClient from aleph.sdk.chains.ethereum import ETHAccount -from aleph_message.models import Chain, Payment, PaymentType +from aleph.sdk.conf import settings +from aleph_message.models import Chain, Payment, PaymentType, StoreMessage +from aleph_message.models.execution.environment import HypervisorType from fastapi import FastAPI, File, Form, HTTPException, UploadFile from libertai_utils.chains.index import is_signature_valid from libertai_utils.interfaces.subscription import Subscription @@ -26,6 +28,7 @@ UpdateAgentResponse, ) from src.utils.agent import fetch_agents +from src.utils.aleph import fetch_instance_ip from src.utils.message import get_view_agent_secret_message from src.utils.ssh import generate_ssh_key_pair @@ -52,19 +55,35 @@ async def setup(body: SetupAgentBody) -> None: encrypted_secret = encrypt(secret, config.ALEPH_SENDER_PK) private_key, public_key = generate_ssh_key_pair() - encrypted_private_key = encrypt(private_key, config.ALEPH_SENDER_SK) + encrypted_private_key = encrypt(private_key, config.ALEPH_SENDER_PK) + + rootfs = settings.UBUNTU_22_QEMU_ROOTFS_ID aleph_account = ETHAccount(config.ALEPH_SENDER_SK) async with AuthenticatedAlephHttpClient( account=aleph_account, api_server=config.ALEPH_API_URL ) as client: + rootfs_message: StoreMessage = await client.get_message( + item_hash=rootfs, message_type=StoreMessage + ) + rootfs_size = ( + rootfs_message.content.size + if rootfs_message.content.size is not None + else settings.DEFAULT_ROOTFS_SIZE + ) + instance_message, _status = await client.create_instance( - rootfs="TODO", - rootfs_size=0, + rootfs=rootfs, + rootfs_size=rootfs_size, + hypervisor=HypervisorType.qemu, payment=Payment(chain=Chain.ETH, type=PaymentType.hold, receiver=None), channel=config.ALEPH_CHANNEL, address=config.ALEPH_OWNER, ssh_keys=[public_key], + metadata={"name": agent_id}, + vcpus=settings.DEFAULT_VM_VCPUS, + memory=settings.DEFAULT_INSTANCE_MEMORY, + sync=True, ) agent = Agent( @@ -182,6 +201,9 @@ async def update( ssh_private_key = decrypt(agent.encrypted_ssh_key, config.ALEPH_SENDER_SK) # TODO: get hostname using instance_hash + scheduler_response = fetch_instance_ip(agent.instance_hash) + print(scheduler_response) + return UpdateAgentResponse(instance_hash="TODO") hostname = "2a01:240:ad00:2100:3:89cf:401:4871" # TODO: store link elsewhere, use main version and take as optional parameter in route diff --git a/backend/src/utils/__init__.py b/backend/src/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/src/utils/aleph.py b/backend/src/utils/aleph.py new file mode 100644 index 0000000..c2e2006 --- /dev/null +++ b/backend/src/utils/aleph.py @@ -0,0 +1,29 @@ +import aiohttp +from aleph.sdk import AlephHttpClient +from aleph_message.models import InstanceMessage + +from src.config import config + + +async def fetch_instance_ip(item_hash) -> str: + """ + Fetches IPv6 of an allocated instance given a message hash. + + Args: + item_hash: Instance message hash. + Returns: + IPv6 address + """ + async with AlephHttpClient(api_server=config.ALEPH_API_URL) as client: + message = await client.get_message(item_hash, InstanceMessage) + + async with aiohttp.ClientSession() as session: + try: + async with session.get( + f"https://scheduler.api.aleph.cloud/api/v0/allocation/{message.item_hash}" + ) as resp: + resp.raise_for_status() + allocation = await resp.json() + return allocation["vm_ipv6"] + except (aiohttp.ClientResponseError, aiohttp.ClientConnectorError): + raise ValueError()