Fix XML responses

This commit is contained in:
PapaTutuWawa 2025-03-30 22:57:54 +02:00
parent 6b4eaa6448
commit 97f3a12617
10 changed files with 131 additions and 96 deletions

View File

@ -5,7 +5,7 @@ from fastapi.datastructures import QueryParams
from sqlmodel import select
from openec2.libvirt import LibvirtSingleton
from openec2.api.describe_instances import InstanceDescription, DescribeInstancesResponse, DescribeInstancesResponseReservationSet, describe_instance
from openec2.api.describe_instances import InstanceDescription, DescribeInstancesResponse, DescribeInstancesResponseReservationSet, ReservationSet, ReservationSetInstancesSet, describe_instance
from openec2.api.shared import InstanceState
from openec2.config import OpenEC2Config
from openec2.db import DatabaseDep
@ -30,7 +30,14 @@ def describe_instances(
DescribeInstancesResponse(
request_id=uuid.uuid4().hex,
reservation_set=DescribeInstancesResponseReservationSet(
item=response_items,
item=[
ReservationSet(
reservationId=instance.instance_id,
instancesSet=ReservationSetInstancesSet(
item=[instance],
),
) for instance in response_items
],
),
).to_xml(),
media_type="application/xml",

View File

@ -2,7 +2,7 @@ import base64
from typing import cast
import uuid
from fastapi import HTTPException
from fastapi import HTTPException, Response
from fastapi.datastructures import QueryParams
from sqlmodel import select
@ -161,9 +161,12 @@ def run_instances(
description = describe_instance(instance, domain)
db.commit()
return RunInstanceResponse(
request_id=uuid.uuid4().hex,
instance_set=RunInstanceInstanceSet(
item=[description],
),
).to_xml()
return Response(
RunInstanceResponse(
request_id=uuid.uuid4().hex,
instance_set=RunInstanceInstanceSet(
item=[description],
),
).to_xml(),
media_type="application/xml",
)

View File

@ -1,6 +1,6 @@
import uuid
from fastapi import HTTPException
from fastapi import HTTPException, Response
from fastapi.datastructures import QueryParams
from sqlmodel import select
@ -9,7 +9,9 @@ from openec2.config import OpenEC2Config
from openec2.db import DatabaseDep
from openec2.db.instance import Instance
from openec2.utils.array import parse_array_plain
from openec2.api.start_instances import InstanceState, StartInstancesResponseInstancesSetInstance, StartInstancesResponse, StartInstancesResponseInstancesSet
from openec2.api.shared import InstanceInfo, InstancesSet
from openec2.api.describe_instances import describe_instance_state
from openec2.api.start_instances import StartInstancesResponse
def start_instances(
@ -18,7 +20,7 @@ def start_instances(
db: DatabaseDep,
):
conn = LibvirtSingleton.of().connection
instances: list[StartInstancesResponseInstancesSetInstance] = []
instances: list[InstanceInfo] = []
for instance_id in parse_array_plain("InstanceId", params):
instance = db.exec(select(Instance).where(Instance.id == instance_id)).first()
if instance is None:
@ -26,30 +28,25 @@ def start_instances(
dom = conn.lookupByName(instance_id)
running = dom.isActive()
prev_state = InstanceState(
code=16 if running else 80,
name="running" if running else "stopped",
)
prev_state = describe_instance_state(dom)
if not dom.isActive():
dom.create()
running = dom.isActive()
current_state = InstanceState(
code=16 if running else 80,
name="running" if running else "stopped",
)
current_state = describe_instance_state(dom)
instances.append(
StartInstancesResponseInstancesSetInstance(
instance_id=instance_id,
previous_state=prev_state,
current_state=current_state,
InstanceInfo(
instanceId=instance_id,
previousState=prev_state,
currentState=current_state,
),
)
return StartInstancesResponse(
request_id=uuid.uuid4().hex,
instances_set=StartInstancesResponseInstancesSet(
item=instances,
),
).to_xml()
return Response(
StartInstancesResponse(
request_id=uuid.uuid4().hex,
instancesSet=InstancesSet(
item=instances,
),
).to_xml(),
media_type="application/xml",
)

View File

@ -1,6 +1,6 @@
import uuid
from fastapi import HTTPException
from fastapi import HTTPException, Response
from fastapi.datastructures import QueryParams
from sqlmodel import select
@ -9,8 +9,9 @@ from openec2.config import OpenEC2Config
from openec2.db import DatabaseDep
from openec2.db.instance import Instance
from openec2.utils.array import parse_array_plain
from openec2.api.shared import InstanceState
from openec2.api.stop_instances import StopInstancesResponse, StopInstancesResponseInstancesSet, StopInstancesResponseInstancesSetInstance
from openec2.api.shared import InstanceInfo, InstancesSet
from openec2.api.describe_instances import describe_instance_state
from openec2.api.stop_instances import StopInstancesResponse
def stop_instances(
@ -19,7 +20,7 @@ def stop_instances(
db: DatabaseDep,
):
conn = LibvirtSingleton.of().connection
instances: list[StopInstancesResponseInstancesSetInstance] = []
instances: list[InstanceInfo] = []
for instance_id in parse_array_plain("InstanceId", params):
instance = db.exec(select(Instance).where(Instance.id == instance_id)).first()
if instance is None:
@ -27,29 +28,26 @@ def stop_instances(
dom = conn.lookupByName(instance_id)
running = dom.isActive()
prev_state = InstanceState(
code=16 if running else 80,
name="running" if running else "stopped",
)
prev_state = describe_instance_state(dom)
if running:
dom.shutdown()
running = dom.isActive()
current_state = InstanceState(
code=16 if running else 80,
name="running" if running else "stopped",
)
current_state = describe_instance_state(dom)
instances.append(
StopInstancesResponseInstancesSetInstance(
instance_id=instance_id,
previous_state=prev_state,
current_state=current_state,
InstanceInfo(
instanceId=instance_id,
previousState=prev_state,
currentState=current_state,
),
)
return StopInstancesResponse(
request_id=uuid.uuid4().hex,
instances_set=StopInstancesResponseInstancesSet(
item=instances,
),
).to_xml()
return Response(
StopInstancesResponse(
requestId=uuid.uuid4().hex,
instancesSet=InstancesSet(
item=instances,
),
).to_xml(),
media_type="application/xml",
)

View File

@ -1,6 +1,7 @@
import logging
import uuid
from fastapi import HTTPException
from fastapi import HTTPException, Response
from fastapi.datastructures import QueryParams
from sqlmodel import select
@ -11,6 +12,8 @@ from openec2.db.instance import Instance
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.describe_instances import describe_instance_state
from openec2.api.terminate_instances import TerminateInstancesResponse, InstancesSet
logger = logging.getLogger()
@ -20,18 +23,31 @@ def terminate_instances(
config: OpenEC2Config,
db: DatabaseDep,
):
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:
raise HTTPException(status_code=404, detail="Unknown instance")
continue
#raise HTTPException(status_code=404, detail="Unknown instance")
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
@ -47,4 +63,12 @@ def terminate_instances(
for image_id in image_ids:
garbage_collect_image(image_id, db)
return "OK"
return Response(
TerminateInstancesResponse(
requestId=uuid.uuid4().hex,
instancesSet=InstancesSet(
item=instances,
),
).to_xml(),
media_type="application/xml",
)

View File

@ -21,11 +21,19 @@ class InstanceDescription(
instance_state: InstanceState = element(tag="instanceState")
tag_set: InstanceTagSet = element(tag="tagSet")
class ReservationSetInstancesSet(BaseXmlModel):
item: list[InstanceDescription] = element()
class ReservationSet(BaseXmlModel):
reservationId: str = element()
instancesSet: ReservationSetInstancesSet = element()
class DescribeInstancesResponseReservationSet(
BaseXmlModel,
tag="reservationSet",
):
item: list[InstanceDescription] = element()
item: list[ReservationSet] = element("")
class DescribeInstancesResponse(
BaseXmlModel,
@ -36,15 +44,18 @@ class DescribeInstancesResponse(
reservation_set: DescribeInstancesResponseReservationSet = element("reservationSet")
def describe_instance(instance: Instance, domain: libvirt.virDomain) -> InstanceDescription:
def describe_instance_state(domain: libvirt.virDomain) -> InstanceState:
running = domain.isActive()
return InstanceState(
code=16 if running else 80,
name="running" if running else "stopped",
)
def describe_instance(instance: Instance, domain: libvirt.virDomain) -> InstanceDescription:
return InstanceDescription(
instance_id=instance.id,
image_id=instance.imageId,
instance_state=InstanceState(
code=16 if running else 80,
name="running" if running else "stopped",
),
instance_state=describe_instance_state(domain),
tag_set=InstanceTagSet(
item=[
InstanceTag(

View File

@ -4,3 +4,13 @@ from pydantic_xml import BaseXmlModel, element
class InstanceState(BaseXmlModel):
code: int = element()
name: str = element()
class InstanceInfo(BaseXmlModel):
instanceId: str = element()
currentState: InstanceState = element()
previousState: InstanceState = element()
class InstancesSet(BaseXmlModel, tag="instancesSet"):
item: list[InstanceInfo] = element()

View File

@ -1,26 +1,12 @@
from pydantic_xml import BaseXmlModel, element
from openec2.api.shared import InstanceState
from openec2.api.shared import InstancesSet
class StartInstancesResponseInstancesSetInstance(
BaseXmlModel,
tag="item",
):
instance_id: str = element(tag="instanceId")
previous_state: InstanceState = element("previousState")
current_state: InstanceState = element("currentState")
class StartInstancesResponseInstancesSet(
BaseXmlModel,
tag="instancesSet",
):
item: list[StartInstancesResponseInstancesSetInstance] = element()
class StartInstancesResponse(
BaseXmlModel,
tag="StartInstancesResponse",
nsmap={"": "http://ec2.amazonaws.com/doc/2016-11-15/"}
):
request_id: str = element(tag="requestId")
instances_set: StartInstancesResponseInstancesSet
instancesSet: InstancesSet = element()

View File

@ -1,26 +1,12 @@
from pydantic_xml import BaseXmlModel, element
from openec2.api.shared import InstanceState
from openec2.api.shared import InstancesSet
class StopInstancesResponseInstancesSetInstance(
BaseXmlModel,
tag="item",
):
instance_id: str = element(tag="instanceId")
previous_state: InstanceState = element("previousState")
current_state: InstanceState = element("currentState")
class StopInstancesResponseInstancesSet(
BaseXmlModel,
tag="instancesSet",
):
item: list[StopInstancesResponseInstancesSetInstance] = element()
class StopInstancesResponse(
BaseXmlModel,
tag="StopInstancesResponse",
nsmap={"": "http://ec2.amazonaws.com/doc/2016-11-15/"}
):
request_id: str = element(tag="requestId")
instances_set: StopInstancesResponseInstancesSet
requestId: str = element(tag="requestId")
instancesSet: InstancesSet = element()

View File

@ -0,0 +1,13 @@
from pydantic_xml import BaseXmlModel, element
from openec2.api.shared import InstancesSet
class TerminateInstancesResponse(
BaseXmlModel,
tag="TerminateInstancesResponse",
nsmap={"": "http://ec2.amazonaws.com/doc/2016-11-15/"},
):
requestId: str = element()
instancesSet: InstancesSet = element()