62 lines
2.1 KiB
Python
62 lines
2.1 KiB
Python
from sqlmodel import select
|
|
import libvirt
|
|
|
|
from openec2.libvirt import LibvirtSingleton
|
|
from openec2.db import DatabaseDep
|
|
from openec2.db.ipam import IPAMEntry
|
|
from openec2.utils.ip import ipv4_to_int, int_to_ipv4
|
|
|
|
|
|
def _libvirt_host_update(instance_id: str, mac: str, ipv4: str) -> str:
|
|
return f"<host name='{instance_id}' mac='{mac}' ip='{ipv4}' />"
|
|
|
|
|
|
def add_instance_dhcp_mapping(instance_id: str, mac: str, ipv4: str, db: DatabaseDep):
|
|
"""
|
|
Adds a DHCP entry for the network to give the instance a static
|
|
private IPv4 address.
|
|
"""
|
|
entry = IPAMEntry(
|
|
ipv4_addr_raw=ipv4_to_int(ipv4),
|
|
instance_id=instance_id,
|
|
# TODO
|
|
vpc_id="default",
|
|
)
|
|
db.add(entry)
|
|
|
|
# Tell libvirt about this mapping
|
|
conn = LibvirtSingleton.of().connection
|
|
conn.networkLookupByName("default").update(
|
|
libvirt.VIR_NETWORK_UPDATE_COMMAND_ADD_LAST,
|
|
libvirt.VIR_NETWORK_SECTION_IP_DHCP_HOST,
|
|
0,
|
|
_libvirt_host_update(instance_id, mac, ipv4),
|
|
flags=libvirt.VIR_NETWORK_UPDATE_AFFECT_LIVE,
|
|
)
|
|
|
|
def remove_instance_dhcp_mapping(instance_id: str, mac: str ,ipv4: str, db: DatabaseDep):
|
|
i = ipv4_to_int(ipv4)
|
|
entry = db.exec(select(IPAMEntry).where(IPAMEntry.ipv4_addr_raw == i, IPAMEntry.instance_id == instance_id)).first()
|
|
db.delete(entry)
|
|
|
|
# Tell libvirt about this mapping
|
|
conn = LibvirtSingleton.of().connection
|
|
conn.networkLookupByName("default").update(
|
|
libvirt.VIR_NETWORK_UPDATE_COMMAND_DELETE,
|
|
libvirt.VIR_NETWORK_SECTION_IP_DHCP_HOST,
|
|
0,
|
|
_libvirt_host_update(instance_id, mac, ipv4),
|
|
flags=libvirt.VIR_NETWORK_UPDATE_AFFECT_LIVE,
|
|
)
|
|
|
|
def is_ipv4_available(ipv4: str, db: DatabaseDep) -> bool:
|
|
i = ipv4_to_int(ipv4)
|
|
return db.exec(select(IPAMEntry).where(IPAMEntry.ipv4_addr_raw == i)).first() is None
|
|
|
|
def get_available_ipv4(db: DatabaseDep) -> str:
|
|
entries = db.exec(select(IPAMEntry)).all()
|
|
# TODO: Use the VPC's subnet
|
|
max_ip = max(e.ipv4_addr_raw for e in entries) if entries else ipv4_to_int("192.168.122.2")
|
|
# TODO: Check if we're still inside the subnet
|
|
return int_to_ipv4(max_ip + 1)
|