openec2/src/openec2/actions/terminate_instances.py

85 lines
2.5 KiB
Python

import logging
import uuid
from fastapi import HTTPException, Response
from fastapi.datastructures import QueryParams
from sqlmodel import select
from openec2.libvirt import LibvirtSingleton
from openec2.config import OpenEC2Config
from openec2.db import DatabaseDep
from openec2.db.instance import Instance
from openec2.db.user import User
from openec2.utils.array import parse_array_plain
from openec2.images import garbage_collect_image
from openec2.ipam import remove_instance_dhcp_mapping
from openec2.api.shared import InstanceInfo
from openec2.api.describe_instances import describe_instance_state
from openec2.api.terminate_instances import TerminateInstancesResponse, InstancesSet
logger = logging.getLogger()
def terminate_instances(
params: QueryParams,
config: OpenEC2Config,
db: DatabaseDep,
user: User,
):
instances: list[InstanceInfo] = []
conn = LibvirtSingleton.of().connection
image_ids: set[str] = set()
for instance_id in parse_array_plain("InstanceId", params):
instance = db.exec(select(Instance).where(Instance.id == instance_id)).first()
if instance is None:
continue
# raise HTTPException(status_code=404, detail="Unknown instance")
# Check for permission issues
if instance.owner_id != user.id:
# TODO: Add the error to the response
continue
dom = conn.lookupByName(instance_id)
prev_state = describe_instance_state(dom)
if dom.isActive():
dom.shutdown()
current_state = describe_instance_state(dom)
dom.undefine()
instances.append(
InstanceInfo(
instanceId=instance.id,
currentState=current_state,
previousState=prev_state,
),
)
# Delete files
logger.debug(f"Removing {config.instances.location / instance_id}")
instance_disk = config.instances.location / instance_id
instance_disk.unlink()
image_ids.add(instance.imageId)
remove_instance_dhcp_mapping(
instance.id, instance.interfaceMac, instance.privateIPv4, db
)
db.delete(instance)
db.commit()
# Garbage collect AMIs
for image_id in image_ids:
garbage_collect_image(image_id, db)
return Response(
TerminateInstancesResponse(
requestId=uuid.uuid4().hex,
instancesSet=InstancesSet(
item=instances,
),
).to_xml(),
media_type="application/xml",
)