diff --git a/cloudinit.yaml b/examples/tofu/cloudinit.yaml similarity index 59% rename from cloudinit.yaml rename to examples/tofu/cloudinit.yaml index 96f5f70..db93a98 100644 --- a/cloudinit.yaml +++ b/examples/tofu/cloudinit.yaml @@ -6,3 +6,5 @@ users: groups: wheel plain_text_passwd: abc123 sudo: ["ALL=(ALL) NOPASSWD:ALL"] + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDUz3WF4qPhk01//5QUuNWyHTn8shv86i/qEyRqa1kTF alexander@miku diff --git a/examples/tofu/main.tf b/examples/tofu/main.tf index 2fd3874..a11389f 100644 --- a/examples/tofu/main.tf +++ b/examples/tofu/main.tf @@ -28,6 +28,8 @@ resource "aws_instance" "test-instance-1" { private_ip = "192.168.122.3" + user_data = file("cloudinit.yaml") + tags = { UseCase = "k8s-control-plane" } diff --git a/scripts/create-network-interface.sh b/scripts/create-network-interface.sh new file mode 100644 index 0000000..1b4e1db --- /dev/null +++ b/scripts/create-network-interface.sh @@ -0,0 +1,10 @@ +#!/bin/bash +ifId=$1 +cidr=$2 +broadcast=$3 + +ip link add name "$ifId" type bridge +ip addr add "$cidr" dev "$ifId" broadcast "$broadcast" +ip link set dev "$ifId" up + +# TODO: NAT diff --git a/src/openec2/actions/create_vpc.py b/src/openec2/actions/create_vpc.py index f4b5935..7735023 100644 --- a/src/openec2/actions/create_vpc.py +++ b/src/openec2/actions/create_vpc.py @@ -6,6 +6,7 @@ from openec2.db.user import User from openec2.config import OpenEC2Config from openec2.db import DatabaseDep from openec2.db.vpc import VPC +from openec2.network.vpc import prepare_host_vpc def create_vpc( @@ -14,4 +15,19 @@ def create_vpc( db: DatabaseDep, user: User, ): + # TODO: Check if it already exists cidr_block = params["CidrBlock"] + vpcs = db.exec(select(VPC)).all() + max_interface_num = max(v.bridge_num for v in vpcs) if vpcs else 0 + + # Create the VPC + vpc = VPC( + bridge_num=max_interface_num + 1, + cidr=cidr_block, + owner_id=user.id, + default=False, + ) + prepare_host_vpc(vpc) + + db.add(vpc) + db.commit() diff --git a/src/openec2/actions/describe_instances.py b/src/openec2/actions/describe_instances.py index e0958ed..afb7c77 100644 --- a/src/openec2/actions/describe_instances.py +++ b/src/openec2/actions/describe_instances.py @@ -55,6 +55,7 @@ def describe_instances( code=48, name="terminated", ), + privateIpAddress=instance.privateIPv4, tagSet=[ Tag( key=key, diff --git a/src/openec2/api/create_vpc.py b/src/openec2/api/create_vpc.py new file mode 100644 index 0000000..a7dca36 --- /dev/null +++ b/src/openec2/api/create_vpc.py @@ -0,0 +1 @@ +from pydantic_xml import BaseXmlModel, wrapped, element diff --git a/src/openec2/api/describe_instances.py b/src/openec2/api/describe_instances.py index 73e1139..c56a24b 100644 --- a/src/openec2/api/describe_instances.py +++ b/src/openec2/api/describe_instances.py @@ -11,6 +11,7 @@ class InstanceDescription( instanceId: str = element() imageId: str = element() instanceState: InstanceState = element() + privateIpAddress: str = element() tagSet: list[Tag] = wrapped("tagSet", element(tag="item")) @@ -43,6 +44,7 @@ def describe_instance( instanceId=instance.id, imageId=instance.imageId, instanceState=describe_instance_state(domain), + privateIpAddress=instance.privateIPv4, tagSet=[ Tag( key=key, diff --git a/src/openec2/db/vpc.py b/src/openec2/db/vpc.py index b913e90..faac81b 100644 --- a/src/openec2/db/vpc.py +++ b/src/openec2/db/vpc.py @@ -1,3 +1,5 @@ +from ipaddress import ip_network + from sqlmodel import SQLModel, Field @@ -5,8 +7,28 @@ class VPC(SQLModel, table=True): # ID of the VPC id: str = Field(default=None, primary_key=True) + # Number-suffix of the bridge device + bridge_num: int + # Base IPv4 cidr: str + # Flag indicating whether this VPC is the user's default VPC + default: bool + # Owning user owner_id: int = Field(foreign_key="user.id") + + @property + def virbr(self) -> str: + return f"virbr{self.bridge_num}" + + @property + def gateway(self) -> str: + network = ip_network(self.cidr) + return f"{network[1]}/{network.prefixlen}" + + @property + def broadcast(self) -> str: + network = ip_network(self.cidr) + return f"{network[255]}" diff --git a/src/openec2/network/dhcp.py b/src/openec2/network/dhcp.py new file mode 100644 index 0000000..e69de29 diff --git a/src/openec2/network/vpc.py b/src/openec2/network/vpc.py new file mode 100644 index 0000000..8a73054 --- /dev/null +++ b/src/openec2/network/vpc.py @@ -0,0 +1,13 @@ +import subprocess + +from openec2.db.vpc import VPC + + +def prepare_host_vpc(vpc: VPC): + # Create the bridge + subprocess.call([ + "/home/alexander/Development/Personal/openec2/scripts/create-network-interface.sh", + vpc.virbr, + vpc.gateway, + vpc.broadcast, + ])