All checks were successful
Build And Test / build-and-push (push) Successful in 1m54s
- Add NHNBaseView with authentication_classes = [] - All NHN View classes now inherit from NHNBaseView - Kong already validates JWT, no need for Django to re-validate Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
3005 lines
117 KiB
Python
3005 lines
117 KiB
Python
"""
|
|
NHN Cloud API Views
|
|
|
|
REST API 엔드포인트 정의
|
|
"""
|
|
|
|
import logging
|
|
|
|
from rest_framework import status
|
|
from rest_framework.views import APIView
|
|
from rest_framework.response import Response
|
|
from rest_framework.permissions import AllowAny, IsAuthenticated
|
|
from drf_yasg.utils import swagger_auto_schema
|
|
from drf_yasg import openapi
|
|
|
|
from .serializers import (
|
|
TokenRequestSerializer,
|
|
TokenResponseSerializer,
|
|
ComputeInstanceSerializer,
|
|
VpcSerializer,
|
|
SubnetSerializer,
|
|
NksClusterSerializer,
|
|
NksNodeGroupSerializer,
|
|
NksNodeActionSerializer,
|
|
NksClusterResizeSerializer,
|
|
NksClusterUpgradeSerializer,
|
|
NksAutoscaleConfigSerializer,
|
|
NksNodeGroupUpgradeSerializer,
|
|
NksNodeGroupUpdateSerializer,
|
|
NksUserScriptSerializer,
|
|
NksApiEndpointIpAclSerializer,
|
|
StorageContainerSerializer,
|
|
ErrorResponseSerializer,
|
|
# DNS Plus
|
|
DnsZoneSerializer,
|
|
DnsZoneUpdateSerializer,
|
|
DnsRecordSetSerializer,
|
|
DnsRecordSetUpdateSerializer,
|
|
DnsPoolSerializer,
|
|
DnsPoolUpdateSerializer,
|
|
DnsGslbSerializer,
|
|
DnsGslbUpdateSerializer,
|
|
DnsPoolConnectSerializer,
|
|
DnsHealthCheckSerializer,
|
|
DnsHealthCheckUpdateSerializer,
|
|
DnsIdListSerializer,
|
|
# Load Balancer
|
|
LoadBalancerSerializer,
|
|
LoadBalancerUpdateSerializer,
|
|
LBListenerSerializer,
|
|
LBListenerUpdateSerializer,
|
|
LBPoolSerializer,
|
|
LBPoolUpdateSerializer,
|
|
LBMemberSerializer,
|
|
LBMemberUpdateSerializer,
|
|
LBHealthMonitorSerializer,
|
|
LBHealthMonitorUpdateSerializer,
|
|
LBL7PolicySerializer,
|
|
LBL7PolicyUpdateSerializer,
|
|
LBL7RuleSerializer,
|
|
LBL7RuleUpdateSerializer,
|
|
LBIpAclGroupSerializer,
|
|
LBIpAclGroupUpdateSerializer,
|
|
LBIpAclTargetCreateSerializer,
|
|
)
|
|
from .packages import NHNCloudToken, ApiCompute, ApiVpc, ApiNks, ApiStorageObject, ApiDnsPlus
|
|
from .packages.loadbalancer import ApiLoadBalancer
|
|
from .packages.base import NHNCloudAPIError
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
# ==================== Base View ====================
|
|
|
|
|
|
class NHNBaseView(APIView):
|
|
"""
|
|
NHN Cloud API 베이스 뷰
|
|
Kong이 이미 JWT 인증을 수행하므로 Django에서는 인증을 건너뜀
|
|
"""
|
|
authentication_classes = []
|
|
permission_classes = [AllowAny]
|
|
|
|
|
|
# ==================== Common Headers ====================
|
|
|
|
region_header = openapi.Parameter(
|
|
"X-NHN-Region",
|
|
openapi.IN_HEADER,
|
|
description="NHN Cloud 리전 (kr1: 판교, kr2: 평촌)",
|
|
type=openapi.TYPE_STRING,
|
|
default="kr2",
|
|
)
|
|
|
|
token_header = openapi.Parameter(
|
|
"X-NHN-Token",
|
|
openapi.IN_HEADER,
|
|
description="NHN Cloud API 토큰",
|
|
type=openapi.TYPE_STRING,
|
|
required=True,
|
|
)
|
|
|
|
tenant_header = openapi.Parameter(
|
|
"X-NHN-Tenant-ID",
|
|
openapi.IN_HEADER,
|
|
description="NHN Cloud 테넌트 ID",
|
|
type=openapi.TYPE_STRING,
|
|
required=True,
|
|
)
|
|
|
|
|
|
def get_nhn_headers(request):
|
|
"""요청 헤더에서 NHN Cloud 정보 추출"""
|
|
headers = {
|
|
"region": request.headers.get("X-NHN-Region", "kr2"),
|
|
"token": request.headers.get("X-NHN-Token"),
|
|
"tenant_id": request.headers.get("X-NHN-Tenant-ID"),
|
|
"storage_account": request.headers.get("X-NHN-Storage-Account"),
|
|
}
|
|
# 토큰은 앞 8자리만 로깅 (보안)
|
|
token_preview = headers["token"][:8] + "..." if headers["token"] else "None"
|
|
logger.info(f"[Request Headers] region={headers['region']}, token={token_preview}, tenant_id={headers['tenant_id']}")
|
|
return headers
|
|
|
|
|
|
# ==================== Token API ====================
|
|
|
|
|
|
class TokenCreateView(NHNBaseView):
|
|
"""토큰 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="NHN Cloud API 토큰 생성",
|
|
operation_description="NHN Cloud API 인증 토큰을 생성합니다.",
|
|
request_body=TokenRequestSerializer,
|
|
responses={
|
|
200: TokenResponseSerializer,
|
|
400: ErrorResponseSerializer,
|
|
401: ErrorResponseSerializer,
|
|
},
|
|
)
|
|
def post(self, request):
|
|
logger.info(f"[Token] 토큰 생성 요청 수신 - client_ip={request.META.get('REMOTE_ADDR')}")
|
|
|
|
serializer = TokenRequestSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
logger.warning(f"[Token] 요청 데이터 유효성 검사 실패: {serializer.errors}")
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
tenant_id = serializer.validated_data["tenant_id"]
|
|
username = serializer.validated_data["username"]
|
|
logger.info(f"[Token] 토큰 발급 시도 - tenant_id={tenant_id}, username={username}")
|
|
|
|
try:
|
|
token_manager = NHNCloudToken(
|
|
tenant_id=tenant_id,
|
|
username=username,
|
|
password=serializer.validated_data["password"],
|
|
)
|
|
result = token_manager.create_token()
|
|
|
|
token_preview = result.token[:8] + "..." if result.token else "None"
|
|
logger.info(f"[Token] 토큰 발급 성공 - tenant_id={tenant_id}, token={token_preview}, expires_at={result.expires_at}")
|
|
|
|
return Response(
|
|
{
|
|
"token": result.token,
|
|
"tenant_id": result.tenant_id,
|
|
"expires_at": result.expires_at,
|
|
},
|
|
status=status.HTTP_200_OK,
|
|
)
|
|
except NHNCloudAPIError as e:
|
|
logger.error(f"[Token] 토큰 발급 실패 - tenant_id={tenant_id}, username={username}, error={e.message}, code={e.code}")
|
|
return Response(
|
|
{"error": e.message, "code": e.code},
|
|
status=status.HTTP_401_UNAUTHORIZED,
|
|
)
|
|
|
|
|
|
# ==================== Compute API ====================
|
|
|
|
|
|
class ComputeFlavorListView(NHNBaseView):
|
|
"""Flavor 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Flavor 목록 조회",
|
|
manual_parameters=[region_header, token_header, tenant_header],
|
|
responses={200: "Flavor 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiCompute(headers["region"], headers["tenant_id"], headers["token"])
|
|
return Response(api.get_flavor_list())
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class ComputeKeypairListView(NHNBaseView):
|
|
"""Keypair 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Keypair 목록 조회",
|
|
manual_parameters=[region_header, token_header, tenant_header],
|
|
responses={200: "Keypair 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiCompute(headers["region"], headers["tenant_id"], headers["token"])
|
|
return Response(api.get_keypair_list())
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class ComputeImageListView(NHNBaseView):
|
|
"""이미지 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="이미지 목록 조회",
|
|
manual_parameters=[region_header, token_header, tenant_header],
|
|
responses={200: "이미지 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiCompute(headers["region"], headers["tenant_id"], headers["token"])
|
|
return Response(api.get_image_list())
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class ComputeInstanceListView(NHNBaseView):
|
|
"""인스턴스 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="인스턴스 목록 조회",
|
|
manual_parameters=[region_header, token_header, tenant_header],
|
|
responses={200: "인스턴스 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiCompute(headers["region"], headers["tenant_id"], headers["token"])
|
|
# detail=true 파라미터로 상세 조회 여부 결정
|
|
if request.query_params.get("detail", "true").lower() == "true":
|
|
return Response(api.get_instance_list_detail())
|
|
return Response(api.get_instance_list())
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class ComputeInstanceDetailView(NHNBaseView):
|
|
"""인스턴스 상세/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="인스턴스 상세 조회",
|
|
manual_parameters=[region_header, token_header, tenant_header],
|
|
responses={200: "인스턴스 상세 정보"},
|
|
)
|
|
def get(self, request, server_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiCompute(headers["region"], headers["tenant_id"], headers["token"])
|
|
return Response(api.get_instance_info(server_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="인스턴스 삭제 (비동기)",
|
|
manual_parameters=[region_header, token_header, tenant_header],
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def delete(self, request, server_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
from .tasks import delete_instance_async
|
|
|
|
task = delete_instance_async(
|
|
region=headers["region"],
|
|
tenant_id=headers["tenant_id"],
|
|
token=headers["token"],
|
|
server_id=server_id,
|
|
server_name=request.query_params.get("name", ""),
|
|
)
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "message": "인스턴스 삭제 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception("인스턴스 삭제 작업 시작 실패")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class ComputeInstanceCreateView(NHNBaseView):
|
|
"""인스턴스 생성 API (비동기)"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="인스턴스 생성 (비동기)",
|
|
manual_parameters=[region_header, token_header, tenant_header],
|
|
request_body=ComputeInstanceSerializer,
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = ComputeInstanceSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
from .tasks import create_instance_async
|
|
|
|
# 비동기 작업 시작
|
|
task = create_instance_async(
|
|
region=headers["region"],
|
|
tenant_id=headers["tenant_id"],
|
|
token=headers["token"],
|
|
instance_data=serializer.validated_data,
|
|
)
|
|
|
|
return Response(
|
|
{
|
|
"task_id": str(task.id),
|
|
"status": task.status,
|
|
"message": "인스턴스 생성 작업이 시작되었습니다.",
|
|
},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception("인스턴스 생성 작업 시작 실패")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class ComputeInstanceActionView(NHNBaseView):
|
|
"""인스턴스 액션 API (시작/정지/재부팅) - 비동기"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="인스턴스 액션 (start/stop/reboot) - 비동기",
|
|
manual_parameters=[region_header, token_header, tenant_header],
|
|
request_body=openapi.Schema(
|
|
type=openapi.TYPE_OBJECT,
|
|
properties={
|
|
"action": openapi.Schema(
|
|
type=openapi.TYPE_STRING,
|
|
enum=["start", "stop", "reboot"],
|
|
description="액션 타입",
|
|
),
|
|
},
|
|
required=["action"],
|
|
),
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def post(self, request, server_id):
|
|
headers = get_nhn_headers(request)
|
|
action = request.data.get("action")
|
|
|
|
if action not in ["start", "stop", "reboot"]:
|
|
return Response(
|
|
{"error": "Invalid action. Use: start, stop, reboot"},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
try:
|
|
from .tasks import instance_action_async
|
|
|
|
task = instance_action_async(
|
|
region=headers["region"],
|
|
tenant_id=headers["tenant_id"],
|
|
token=headers["token"],
|
|
server_id=server_id,
|
|
action=action,
|
|
server_name=request.data.get("name", ""),
|
|
hard=request.data.get("hard", False),
|
|
)
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "action": action, "message": f"인스턴스 {action} 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception(f"인스턴스 {action} 작업 시작 실패")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== VPC API ====================
|
|
|
|
|
|
class VpcListView(NHNBaseView):
|
|
"""VPC 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="VPC 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "VPC 목록"},
|
|
)
|
|
def get(self, request):
|
|
logger.info(f"[VPC] VPC 목록 조회 요청")
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiVpc(headers["region"], headers["token"])
|
|
result = api.get_vpc_list()
|
|
vpc_count = len(result.get("vpcs", []))
|
|
logger.info(f"[VPC] VPC 목록 조회 성공 - count={vpc_count}")
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
logger.error(f"[VPC] VPC 목록 조회 실패 - error={e.message}")
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class VpcCreateView(NHNBaseView):
|
|
"""VPC 생성 API (비동기)"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="VPC 생성 (비동기)",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=VpcSerializer,
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = VpcSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
from .tasks import create_vpc_async
|
|
|
|
task = create_vpc_async(
|
|
region=headers["region"],
|
|
token=headers["token"],
|
|
name=serializer.validated_data["name"],
|
|
cidr=serializer.validated_data["cidr"],
|
|
)
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "message": "VPC 생성 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception("VPC 생성 작업 시작 실패")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class VpcDetailView(NHNBaseView):
|
|
"""VPC 상세/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="VPC 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "VPC 상세 정보"},
|
|
)
|
|
def get(self, request, vpc_id):
|
|
logger.info(f"[VPC] VPC 상세 조회 요청 - vpc_id={vpc_id}")
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiVpc(headers["region"], headers["token"])
|
|
result = api.get_vpc_info(vpc_id)
|
|
vpc_name = result.get("vpc", {}).get("name", "unknown")
|
|
logger.info(f"[VPC] VPC 상세 조회 성공 - vpc_id={vpc_id}, name={vpc_name}")
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
logger.error(f"[VPC] VPC 상세 조회 실패 - vpc_id={vpc_id}, error={e.message}")
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="VPC 삭제 (비동기)",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def delete(self, request, vpc_id):
|
|
logger.info(f"[VPC] VPC 삭제 요청 - vpc_id={vpc_id}")
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
from .tasks import delete_vpc_async
|
|
|
|
task = delete_vpc_async(
|
|
region=headers["region"],
|
|
token=headers["token"],
|
|
vpc_id=vpc_id,
|
|
vpc_name=request.query_params.get("name", ""),
|
|
)
|
|
logger.info(f"[VPC] VPC 삭제 작업 시작 - vpc_id={vpc_id}, task_id={task.id}")
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "message": "VPC 삭제 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception(f"[VPC] VPC 삭제 작업 시작 실패 - vpc_id={vpc_id}")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class SubnetListView(NHNBaseView):
|
|
"""서브넷 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="서브넷 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "서브넷 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiVpc(headers["region"], headers["token"])
|
|
return Response(api.get_subnet_list())
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class SubnetCreateView(NHNBaseView):
|
|
"""서브넷 생성 API (비동기)"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="서브넷 생성 (비동기)",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=SubnetSerializer,
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = SubnetSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
from .tasks import create_subnet_async
|
|
|
|
task = create_subnet_async(
|
|
region=headers["region"],
|
|
token=headers["token"],
|
|
vpc_id=serializer.validated_data["vpc_id"],
|
|
cidr=serializer.validated_data["cidr"],
|
|
name=serializer.validated_data["name"],
|
|
)
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "message": "서브넷 생성 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception("서브넷 생성 작업 시작 실패")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class SubnetDetailView(NHNBaseView):
|
|
"""서브넷 상세/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="서브넷 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "서브넷 상세 정보"},
|
|
)
|
|
def get(self, request, subnet_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiVpc(headers["region"], headers["token"])
|
|
return Response(api.get_subnet_info(subnet_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="서브넷 삭제 (비동기)",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def delete(self, request, subnet_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
from .tasks import delete_subnet_async
|
|
|
|
task = delete_subnet_async(
|
|
region=headers["region"],
|
|
token=headers["token"],
|
|
subnet_id=subnet_id,
|
|
subnet_name=request.query_params.get("name", ""),
|
|
)
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "message": "서브넷 삭제 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception("서브넷 삭제 작업 시작 실패")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class FloatingIpListView(NHNBaseView):
|
|
"""Floating IP 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Floating IP 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "Floating IP 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiVpc(headers["region"], headers["token"])
|
|
return Response(api.get_floating_ip_list())
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== Security Group API ====================
|
|
|
|
|
|
class SecurityGroupListView(NHNBaseView):
|
|
"""보안 그룹 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="보안 그룹 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "보안 그룹 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiVpc(headers["region"], headers["token"])
|
|
return Response(api.get_security_group_list())
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== Async Task API ====================
|
|
|
|
|
|
class AsyncTaskListView(NHNBaseView):
|
|
"""비동기 작업 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="비동기 작업 목록 조회",
|
|
responses={200: "작업 목록"},
|
|
)
|
|
def get(self, request):
|
|
from .models import AsyncTask
|
|
|
|
# 최근 100개만 조회
|
|
tasks = AsyncTask.objects.all()[:100]
|
|
data = [
|
|
{
|
|
"id": str(task.id),
|
|
"task_type": task.task_type,
|
|
"status": task.status,
|
|
"resource_name": task.resource_name,
|
|
"resource_id": task.resource_id,
|
|
"error_message": task.error_message,
|
|
"created_at": task.created_at.isoformat(),
|
|
"completed_at": task.completed_at.isoformat() if task.completed_at else None,
|
|
}
|
|
for task in tasks
|
|
]
|
|
return Response({"tasks": data})
|
|
|
|
|
|
class AsyncTaskDetailView(NHNBaseView):
|
|
"""비동기 작업 상세 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="비동기 작업 상태 조회",
|
|
responses={200: "작업 상태"},
|
|
)
|
|
def get(self, request, task_id):
|
|
from .models import AsyncTask
|
|
|
|
try:
|
|
task = AsyncTask.objects.get(id=task_id)
|
|
return Response(
|
|
{
|
|
"id": str(task.id),
|
|
"task_type": task.task_type,
|
|
"status": task.status,
|
|
"resource_name": task.resource_name,
|
|
"resource_id": task.resource_id,
|
|
"request_data": task.request_data,
|
|
"result_data": task.result_data,
|
|
"error_message": task.error_message,
|
|
"created_at": task.created_at.isoformat(),
|
|
"updated_at": task.updated_at.isoformat(),
|
|
"completed_at": task.completed_at.isoformat() if task.completed_at else None,
|
|
}
|
|
)
|
|
except AsyncTask.DoesNotExist:
|
|
return Response({"error": "작업을 찾을 수 없습니다."}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
# ==================== NKS API ====================
|
|
|
|
|
|
class NksSupportsView(NHNBaseView):
|
|
"""NKS 지원 버전 및 작업 종류 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="지원되는 Kubernetes 버전 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "지원 버전 및 작업 종류"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
return Response(api.get_supports())
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksClusterListView(NHNBaseView):
|
|
"""NKS 클러스터 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="NKS 클러스터 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "클러스터 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
return Response(api.get_cluster_list())
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksClusterDetailView(NHNBaseView):
|
|
"""NKS 클러스터 상세/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="NKS 클러스터 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "클러스터 상세 정보"},
|
|
)
|
|
def get(self, request, cluster_name):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
return Response(api.get_cluster_info(cluster_name))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="NKS 클러스터 삭제 (비동기)",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def delete(self, request, cluster_name):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
from .tasks import delete_nks_cluster_async
|
|
|
|
task = delete_nks_cluster_async(
|
|
region=headers["region"],
|
|
token=headers["token"],
|
|
cluster_name=cluster_name,
|
|
)
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "message": "NKS 클러스터 삭제 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception("NKS 클러스터 삭제 작업 시작 실패")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksClusterConfigView(NHNBaseView):
|
|
"""NKS 클러스터 kubeconfig 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="NKS 클러스터 kubeconfig 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "kubeconfig"},
|
|
)
|
|
def get(self, request, cluster_name):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
config = api.get_cluster_config(cluster_name)
|
|
return Response({"config": config})
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksClusterCreateView(NHNBaseView):
|
|
"""NKS 클러스터 생성 API (비동기)"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="NKS 클러스터 생성 (비동기)",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=NksClusterSerializer,
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = NksClusterSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
cluster_data = serializer.validated_data.copy()
|
|
|
|
# Public 클러스터인 경우 External Network/Subnet 자동 조회
|
|
if cluster_data.get("is_public", True):
|
|
vpc_api = ApiVpc(headers["region"], headers["token"])
|
|
external_networks = vpc_api.get_external_network_id()
|
|
networks = external_networks.get("networks", [])
|
|
|
|
if not networks:
|
|
return Response(
|
|
{"error": "External Network를 찾을 수 없습니다."},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
# 첫 번째 External Network 사용
|
|
external_network = networks[0]
|
|
cluster_data["external_network_id"] = external_network.get("id")
|
|
|
|
# External Network의 서브넷 가져오기
|
|
subnets = external_network.get("subnets", [])
|
|
if subnets:
|
|
cluster_data["external_subnet_id"] = subnets[0]
|
|
else:
|
|
return Response(
|
|
{"error": "External Subnet을 찾을 수 없습니다."},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
logger.info(
|
|
f"[NKS] External Network 자동 설정 - network_id={cluster_data['external_network_id']}, "
|
|
f"subnet_id={cluster_data['external_subnet_id']}"
|
|
)
|
|
|
|
from .tasks import create_nks_cluster_async
|
|
|
|
task = create_nks_cluster_async(
|
|
region=headers["region"],
|
|
token=headers["token"],
|
|
cluster_data=cluster_data,
|
|
)
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "message": "NKS 클러스터 생성 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except NHNCloudAPIError as e:
|
|
logger.exception("External Network 조회 실패")
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
except Exception as e:
|
|
logger.exception("NKS 클러스터 생성 작업 시작 실패")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksClusterResizeView(NHNBaseView):
|
|
"""NKS 클러스터 리사이즈 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="NKS 클러스터 노드 수 조정",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=NksClusterResizeSerializer,
|
|
responses={200: "리사이즈 결과"},
|
|
)
|
|
def post(self, request, cluster_name):
|
|
headers = get_nhn_headers(request)
|
|
serializer = NksClusterResizeSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.resize_cluster(cluster_name, serializer.validated_data["node_count"])
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksClusterUpgradeView(NHNBaseView):
|
|
"""NKS 클러스터 업그레이드 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="NKS 클러스터 Kubernetes 버전 업그레이드",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=NksClusterUpgradeSerializer,
|
|
responses={200: "업그레이드 결과"},
|
|
)
|
|
def post(self, request, cluster_name):
|
|
headers = get_nhn_headers(request)
|
|
serializer = NksClusterUpgradeSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.upgrade_cluster(cluster_name, serializer.validated_data["kubernetes_version"])
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksClusterEventsView(NHNBaseView):
|
|
"""NKS 클러스터 작업 이력 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="NKS 클러스터 작업 이력 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "작업 이력 목록"},
|
|
)
|
|
def get(self, request, cluster_uuid):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
return Response(api.get_cluster_events(cluster_uuid))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksClusterEventDetailView(NHNBaseView):
|
|
"""NKS 클러스터 작업 이력 상세 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="NKS 클러스터 작업 이력 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "작업 이력 상세"},
|
|
)
|
|
def get(self, request, cluster_uuid, event_uuid):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
return Response(api.get_cluster_event(cluster_uuid, event_uuid))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksClusterCertificatesView(NHNBaseView):
|
|
"""NKS 클러스터 인증서 갱신 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="NKS 클러스터 인증서 갱신",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "갱신 결과"},
|
|
)
|
|
def post(self, request, cluster_name):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.renew_certificates(cluster_name)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksClusterIpAclView(NHNBaseView):
|
|
"""NKS 클러스터 API 엔드포인트 IP 접근 제어 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="API 엔드포인트 IP 접근 제어 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "IP 접근 제어 설정"},
|
|
)
|
|
def get(self, request, cluster_name):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
return Response(api.get_api_endpoint_ipacl(cluster_name))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="API 엔드포인트 IP 접근 제어 설정",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=NksApiEndpointIpAclSerializer,
|
|
responses={200: "설정 결과"},
|
|
)
|
|
def post(self, request, cluster_name):
|
|
headers = get_nhn_headers(request)
|
|
serializer = NksApiEndpointIpAclSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.set_api_endpoint_ipacl(
|
|
cluster_name,
|
|
serializer.validated_data["enable"],
|
|
serializer.validated_data.get("allowed_cidrs"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== NKS Node Group API ====================
|
|
|
|
|
|
class NksNodeGroupListView(NHNBaseView):
|
|
"""NKS 노드 그룹 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="노드 그룹 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "노드 그룹 목록"},
|
|
)
|
|
def get(self, request, cluster_name):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
return Response(api.get_nodegroup_list(cluster_name))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksNodeGroupCreateView(NHNBaseView):
|
|
"""NKS 노드 그룹 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="노드 그룹 생성",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=NksNodeGroupSerializer,
|
|
responses={200: "생성된 노드 그룹 정보"},
|
|
)
|
|
def post(self, request, cluster_name):
|
|
headers = get_nhn_headers(request)
|
|
serializer = NksNodeGroupSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.create_nodegroup(
|
|
cluster_name=cluster_name,
|
|
nodegroup_name=serializer.validated_data["nodegroup_name"],
|
|
instance_type=serializer.validated_data["instance_type"],
|
|
node_count=serializer.validated_data.get("node_count", 1),
|
|
availability_zone=serializer.validated_data.get("availability_zone"),
|
|
boot_volume_size=serializer.validated_data.get("boot_volume_size", 50),
|
|
boot_volume_type=serializer.validated_data.get("boot_volume_type", "General SSD"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksNodeGroupDetailView(NHNBaseView):
|
|
"""NKS 노드 그룹 상세/삭제/수정 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="노드 그룹 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "노드 그룹 상세 정보"},
|
|
)
|
|
def get(self, request, cluster_name, nodegroup_name):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
return Response(api.get_nodegroup_info(cluster_name, nodegroup_name))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="노드 그룹 삭제",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, cluster_name, nodegroup_name):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.delete_nodegroup(cluster_name, nodegroup_name)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="노드 그룹 설정 변경",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=NksNodeGroupUpdateSerializer,
|
|
responses={200: "변경된 노드 그룹 정보"},
|
|
)
|
|
def patch(self, request, cluster_name, nodegroup_name):
|
|
headers = get_nhn_headers(request)
|
|
serializer = NksNodeGroupUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.update_nodegroup(
|
|
cluster_name=cluster_name,
|
|
nodegroup_name=nodegroup_name,
|
|
instance_type=serializer.validated_data.get("instance_type"),
|
|
node_count=serializer.validated_data.get("node_count"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksNodeGroupUpgradeView(NHNBaseView):
|
|
"""NKS 노드 그룹 업그레이드 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="노드 그룹 Kubernetes 버전 업그레이드",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=NksNodeGroupUpgradeSerializer,
|
|
responses={200: "업그레이드 결과"},
|
|
)
|
|
def post(self, request, cluster_name, nodegroup_name):
|
|
headers = get_nhn_headers(request)
|
|
serializer = NksNodeGroupUpgradeSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.upgrade_nodegroup(
|
|
cluster_name=cluster_name,
|
|
nodegroup_name=nodegroup_name,
|
|
kubernetes_version=serializer.validated_data["kubernetes_version"],
|
|
max_unavailable_worker=serializer.validated_data.get("max_unavailable_worker", 1),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksNodeGroupUserScriptView(NHNBaseView):
|
|
"""NKS 노드 그룹 사용자 스크립트 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="노드 그룹 사용자 스크립트 설정",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=NksUserScriptSerializer,
|
|
responses={200: "설정 결과"},
|
|
)
|
|
def post(self, request, cluster_name, nodegroup_name):
|
|
headers = get_nhn_headers(request)
|
|
serializer = NksUserScriptSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.set_nodegroup_userscript(
|
|
cluster_name=cluster_name,
|
|
nodegroup_name=nodegroup_name,
|
|
userscript=serializer.validated_data["userscript"],
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksNodeStartView(NHNBaseView):
|
|
"""NKS 워커 노드 시작 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="워커 노드 시작",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=NksNodeActionSerializer,
|
|
responses={200: "시작 결과"},
|
|
)
|
|
def post(self, request, cluster_name, nodegroup_name):
|
|
headers = get_nhn_headers(request)
|
|
serializer = NksNodeActionSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.start_node(
|
|
cluster_name=cluster_name,
|
|
nodegroup_name=nodegroup_name,
|
|
node_id=serializer.validated_data["node_id"],
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksNodeStopView(NHNBaseView):
|
|
"""NKS 워커 노드 중지 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="워커 노드 중지",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=NksNodeActionSerializer,
|
|
responses={200: "중지 결과"},
|
|
)
|
|
def post(self, request, cluster_name, nodegroup_name):
|
|
headers = get_nhn_headers(request)
|
|
serializer = NksNodeActionSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.stop_node(
|
|
cluster_name=cluster_name,
|
|
nodegroup_name=nodegroup_name,
|
|
node_id=serializer.validated_data["node_id"],
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class NksAutoscaleConfigView(NHNBaseView):
|
|
"""NKS 오토스케일러 설정 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="오토스케일러 설정 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "오토스케일러 설정"},
|
|
)
|
|
def get(self, request, cluster_name, nodegroup_name):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
return Response(api.get_autoscale_config(cluster_name, nodegroup_name))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="오토스케일러 설정 변경",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=NksAutoscaleConfigSerializer,
|
|
responses={200: "변경된 오토스케일러 설정"},
|
|
)
|
|
def post(self, request, cluster_name, nodegroup_name):
|
|
headers = get_nhn_headers(request)
|
|
serializer = NksAutoscaleConfigSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiNks(headers["region"], headers["token"])
|
|
result = api.set_autoscale_config(
|
|
cluster_name=cluster_name,
|
|
nodegroup_name=nodegroup_name,
|
|
ca_enable=serializer.validated_data["ca_enable"],
|
|
ca_max_node_count=serializer.validated_data.get("ca_max_node_count"),
|
|
ca_min_node_count=serializer.validated_data.get("ca_min_node_count"),
|
|
ca_scale_down_enable=serializer.validated_data.get("ca_scale_down_enable"),
|
|
ca_scale_down_delay_after_add=serializer.validated_data.get("ca_scale_down_delay_after_add"),
|
|
ca_scale_down_unneeded_time=serializer.validated_data.get("ca_scale_down_unneeded_time"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== Storage API ====================
|
|
|
|
storage_account_header = openapi.Parameter(
|
|
"X-NHN-Storage-Account",
|
|
openapi.IN_HEADER,
|
|
description="NHN Cloud Object Storage 계정 (AUTH_...)",
|
|
type=openapi.TYPE_STRING,
|
|
required=True,
|
|
)
|
|
|
|
|
|
class StorageContainerListView(NHNBaseView):
|
|
"""스토리지 컨테이너 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="컨테이너 목록 조회",
|
|
manual_parameters=[region_header, token_header, storage_account_header],
|
|
responses={200: "컨테이너 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiStorageObject(
|
|
headers["region"], headers["token"], headers["storage_account"]
|
|
)
|
|
containers = api.get_container_list()
|
|
return Response({"containers": containers})
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class StorageContainerCreateView(NHNBaseView):
|
|
"""스토리지 컨테이너 생성 API (비동기)"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="컨테이너 생성 (비동기)",
|
|
manual_parameters=[region_header, token_header, storage_account_header],
|
|
request_body=StorageContainerSerializer,
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = StorageContainerSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
from .tasks import create_storage_container_async
|
|
|
|
task = create_storage_container_async(
|
|
region=headers["region"],
|
|
token=headers["token"],
|
|
storage_account=headers["storage_account"],
|
|
container_name=serializer.validated_data["name"],
|
|
)
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "message": "컨테이너 생성 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception("컨테이너 생성 작업 시작 실패")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class StorageContainerDetailView(NHNBaseView):
|
|
"""스토리지 컨테이너 상세/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="컨테이너 오브젝트 목록 조회",
|
|
manual_parameters=[region_header, token_header, storage_account_header],
|
|
responses={200: "오브젝트 목록"},
|
|
)
|
|
def get(self, request, container_name):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiStorageObject(
|
|
headers["region"], headers["token"], headers["storage_account"]
|
|
)
|
|
objects = api.get_object_list(container_name)
|
|
return Response({"objects": objects})
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="컨테이너 삭제 (비동기)",
|
|
manual_parameters=[region_header, token_header, storage_account_header],
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def delete(self, request, container_name):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
from .tasks import delete_storage_container_async
|
|
|
|
task = delete_storage_container_async(
|
|
region=headers["region"],
|
|
token=headers["token"],
|
|
storage_account=headers["storage_account"],
|
|
container_name=container_name,
|
|
)
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "message": "컨테이너 삭제 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception("컨테이너 삭제 작업 시작 실패")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== DNS Plus API ====================
|
|
|
|
appkey_header = openapi.Parameter(
|
|
"X-NHN-Appkey",
|
|
openapi.IN_HEADER,
|
|
description="NHN Cloud 앱키",
|
|
type=openapi.TYPE_STRING,
|
|
required=True,
|
|
)
|
|
|
|
|
|
def get_appkey(request):
|
|
"""요청 헤더에서 앱키 추출"""
|
|
appkey = request.headers.get("X-NHN-Appkey")
|
|
if not appkey:
|
|
raise NHNCloudAPIError("X-NHN-Appkey 헤더가 필요합니다.", code=400)
|
|
return appkey
|
|
|
|
|
|
# ==================== DNS Zone API ====================
|
|
|
|
|
|
class DnsZoneListView(NHNBaseView):
|
|
"""DNS Zone 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="DNS Zone 목록 조회",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "Zone 목록"},
|
|
)
|
|
def get(self, request):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
page = int(request.query_params.get("page", 1))
|
|
limit = int(request.query_params.get("limit", 50))
|
|
search_name = request.query_params.get("search")
|
|
return Response(api.get_zone_list(
|
|
search_zone_name=search_name,
|
|
page=page,
|
|
limit=limit,
|
|
))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DnsZoneCreateView(NHNBaseView):
|
|
"""DNS Zone 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="DNS Zone 생성",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsZoneSerializer,
|
|
responses={200: "생성된 Zone 정보"},
|
|
)
|
|
def post(self, request):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsZoneSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.create_zone(
|
|
zone_name=serializer.validated_data["zone_name"],
|
|
description=serializer.validated_data.get("description"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DnsZoneDetailView(NHNBaseView):
|
|
"""DNS Zone 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="DNS Zone 상세 조회",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "Zone 상세 정보"},
|
|
)
|
|
def get(self, request, zone_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
return Response(api.get_zone(zone_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="DNS Zone 수정",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsZoneUpdateSerializer,
|
|
responses={200: "수정된 Zone 정보"},
|
|
)
|
|
def put(self, request, zone_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsZoneUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.update_zone(zone_id, serializer.validated_data["description"])
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="DNS Zone 삭제",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, zone_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.delete_zones([zone_id])
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== DNS Record Set API ====================
|
|
|
|
|
|
class DnsRecordSetListView(NHNBaseView):
|
|
"""DNS 레코드 세트 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="레코드 세트 목록 조회",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "레코드 세트 목록"},
|
|
)
|
|
def get(self, request, zone_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
page = int(request.query_params.get("page", 1))
|
|
limit = int(request.query_params.get("limit", 50))
|
|
search_name = request.query_params.get("search")
|
|
recordset_type = request.query_params.get("type")
|
|
return Response(api.get_recordset_list(
|
|
zone_id=zone_id,
|
|
recordset_type_list=[recordset_type] if recordset_type else None,
|
|
search_recordset_name=search_name,
|
|
page=page,
|
|
limit=limit,
|
|
))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DnsRecordSetCreateView(NHNBaseView):
|
|
"""DNS 레코드 세트 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="레코드 세트 생성",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsRecordSetSerializer,
|
|
responses={200: "생성된 레코드 세트 정보"},
|
|
)
|
|
def post(self, request, zone_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsRecordSetSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.create_recordset(
|
|
zone_id=zone_id,
|
|
recordset_name=serializer.validated_data["recordset_name"],
|
|
recordset_type=serializer.validated_data["recordset_type"],
|
|
recordset_ttl=serializer.validated_data["recordset_ttl"],
|
|
record_list=serializer.validated_data["record_list"],
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DnsRecordSetDetailView(NHNBaseView):
|
|
"""DNS 레코드 세트 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="레코드 세트 상세 조회",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "레코드 세트 상세 정보"},
|
|
)
|
|
def get(self, request, zone_id, recordset_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
return Response(api.get_recordset(zone_id, recordset_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="레코드 세트 수정",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsRecordSetUpdateSerializer,
|
|
responses={200: "수정된 레코드 세트 정보"},
|
|
)
|
|
def put(self, request, zone_id, recordset_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsRecordSetUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.update_recordset(
|
|
zone_id=zone_id,
|
|
recordset_id=recordset_id,
|
|
recordset_type=serializer.validated_data["recordset_type"],
|
|
recordset_ttl=serializer.validated_data["recordset_ttl"],
|
|
record_list=serializer.validated_data["record_list"],
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="레코드 세트 삭제",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, zone_id, recordset_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.delete_recordsets(zone_id, [recordset_id])
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== DNS Pool API ====================
|
|
|
|
|
|
class DnsPoolListView(NHNBaseView):
|
|
"""DNS Pool 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Pool 목록 조회",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "Pool 목록"},
|
|
)
|
|
def get(self, request):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
page = int(request.query_params.get("page", 1))
|
|
limit = int(request.query_params.get("limit", 50))
|
|
search_name = request.query_params.get("search")
|
|
return Response(api.get_pool_list(
|
|
search_pool_name=search_name,
|
|
page=page,
|
|
limit=limit,
|
|
))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DnsPoolCreateView(NHNBaseView):
|
|
"""DNS Pool 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Pool 생성",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsPoolSerializer,
|
|
responses={200: "생성된 Pool 정보"},
|
|
)
|
|
def post(self, request):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsPoolSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.create_pool(
|
|
pool_name=serializer.validated_data["pool_name"],
|
|
endpoint_list=serializer.validated_data["endpoint_list"],
|
|
pool_disabled=serializer.validated_data.get("pool_disabled", False),
|
|
health_check_id=serializer.validated_data.get("health_check_id"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DnsPoolDetailView(NHNBaseView):
|
|
"""DNS Pool 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Pool 상세 조회",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "Pool 상세 정보"},
|
|
)
|
|
def get(self, request, pool_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
return Response(api.get_pool(pool_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Pool 수정",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsPoolUpdateSerializer,
|
|
responses={200: "수정된 Pool 정보"},
|
|
)
|
|
def put(self, request, pool_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsPoolUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.update_pool(
|
|
pool_id=pool_id,
|
|
pool_name=serializer.validated_data.get("pool_name"),
|
|
endpoint_list=serializer.validated_data.get("endpoint_list"),
|
|
pool_disabled=serializer.validated_data.get("pool_disabled"),
|
|
health_check_id=serializer.validated_data.get("health_check_id"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Pool 삭제",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, pool_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.delete_pools([pool_id])
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== DNS GSLB API ====================
|
|
|
|
|
|
class DnsGslbListView(NHNBaseView):
|
|
"""DNS GSLB 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="GSLB 목록 조회",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "GSLB 목록"},
|
|
)
|
|
def get(self, request):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
page = int(request.query_params.get("page", 1))
|
|
limit = int(request.query_params.get("limit", 50))
|
|
search_name = request.query_params.get("search")
|
|
return Response(api.get_gslb_list(
|
|
search_gslb_name=search_name,
|
|
page=page,
|
|
limit=limit,
|
|
))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DnsGslbCreateView(NHNBaseView):
|
|
"""DNS GSLB 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="GSLB 생성",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsGslbSerializer,
|
|
responses={200: "생성된 GSLB 정보"},
|
|
)
|
|
def post(self, request):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsGslbSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.create_gslb(
|
|
gslb_name=serializer.validated_data["gslb_name"],
|
|
gslb_ttl=serializer.validated_data["gslb_ttl"],
|
|
gslb_routing_rule=serializer.validated_data["gslb_routing_rule"],
|
|
gslb_disabled=serializer.validated_data.get("gslb_disabled", False),
|
|
connected_pool_list=serializer.validated_data.get("connected_pool_list"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DnsGslbDetailView(NHNBaseView):
|
|
"""DNS GSLB 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="GSLB 상세 조회",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "GSLB 상세 정보"},
|
|
)
|
|
def get(self, request, gslb_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
return Response(api.get_gslb(gslb_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="GSLB 수정",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsGslbUpdateSerializer,
|
|
responses={200: "수정된 GSLB 정보"},
|
|
)
|
|
def put(self, request, gslb_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsGslbUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.update_gslb(
|
|
gslb_id=gslb_id,
|
|
gslb_name=serializer.validated_data.get("gslb_name"),
|
|
gslb_ttl=serializer.validated_data.get("gslb_ttl"),
|
|
gslb_routing_rule=serializer.validated_data.get("gslb_routing_rule"),
|
|
gslb_disabled=serializer.validated_data.get("gslb_disabled"),
|
|
connected_pool_list=serializer.validated_data.get("connected_pool_list"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="GSLB 삭제",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, gslb_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.delete_gslbs([gslb_id])
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DnsGslbPoolConnectView(NHNBaseView):
|
|
"""GSLB에 Pool 연결/수정/해제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="GSLB에 Pool 연결",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsPoolConnectSerializer,
|
|
responses={200: "연결 결과"},
|
|
)
|
|
def post(self, request, gslb_id, pool_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsPoolConnectSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.connect_pool(
|
|
gslb_id=gslb_id,
|
|
pool_id=pool_id,
|
|
connected_pool_order=serializer.validated_data["connected_pool_order"],
|
|
connected_pool_region_content=serializer.validated_data.get("connected_pool_region_content"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="연결된 Pool 수정",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsPoolConnectSerializer,
|
|
responses={200: "수정 결과"},
|
|
)
|
|
def put(self, request, gslb_id, pool_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsPoolConnectSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.update_connected_pool(
|
|
gslb_id=gslb_id,
|
|
pool_id=pool_id,
|
|
connected_pool_order=serializer.validated_data["connected_pool_order"],
|
|
connected_pool_region_content=serializer.validated_data.get("connected_pool_region_content"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Pool 연결 해제",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "연결 해제 결과"},
|
|
)
|
|
def delete(self, request, gslb_id, pool_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.disconnect_pools(gslb_id, [pool_id])
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== DNS Health Check API ====================
|
|
|
|
|
|
class DnsHealthCheckListView(NHNBaseView):
|
|
"""DNS Health Check 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Health Check 목록 조회",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "Health Check 목록"},
|
|
)
|
|
def get(self, request):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
page = int(request.query_params.get("page", 1))
|
|
limit = int(request.query_params.get("limit", 50))
|
|
search_name = request.query_params.get("search")
|
|
return Response(api.get_health_check_list(
|
|
search_health_check_name=search_name,
|
|
page=page,
|
|
limit=limit,
|
|
))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DnsHealthCheckCreateView(NHNBaseView):
|
|
"""DNS Health Check 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Health Check 생성",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsHealthCheckSerializer,
|
|
responses={200: "생성된 Health Check 정보"},
|
|
)
|
|
def post(self, request):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsHealthCheckSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.create_health_check(
|
|
health_check_name=serializer.validated_data["health_check_name"],
|
|
health_check_protocol=serializer.validated_data["health_check_protocol"],
|
|
health_check_port=serializer.validated_data["health_check_port"],
|
|
health_check_interval=serializer.validated_data.get("health_check_interval", 30),
|
|
health_check_timeout=serializer.validated_data.get("health_check_timeout", 5),
|
|
health_check_retries=serializer.validated_data.get("health_check_retries", 2),
|
|
health_check_path=serializer.validated_data.get("health_check_path"),
|
|
health_check_expected_codes=serializer.validated_data.get("health_check_expected_codes"),
|
|
health_check_expected_body=serializer.validated_data.get("health_check_expected_body"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class DnsHealthCheckDetailView(NHNBaseView):
|
|
"""DNS Health Check 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Health Check 상세 조회",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "Health Check 상세 정보"},
|
|
)
|
|
def get(self, request, health_check_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
return Response(api.get_health_check(health_check_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Health Check 수정",
|
|
manual_parameters=[appkey_header],
|
|
request_body=DnsHealthCheckUpdateSerializer,
|
|
responses={200: "수정된 Health Check 정보"},
|
|
)
|
|
def put(self, request, health_check_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
serializer = DnsHealthCheckUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.update_health_check(
|
|
health_check_id=health_check_id,
|
|
health_check_name=serializer.validated_data.get("health_check_name"),
|
|
health_check_protocol=serializer.validated_data.get("health_check_protocol"),
|
|
health_check_port=serializer.validated_data.get("health_check_port"),
|
|
health_check_interval=serializer.validated_data.get("health_check_interval"),
|
|
health_check_timeout=serializer.validated_data.get("health_check_timeout"),
|
|
health_check_retries=serializer.validated_data.get("health_check_retries"),
|
|
health_check_path=serializer.validated_data.get("health_check_path"),
|
|
health_check_expected_codes=serializer.validated_data.get("health_check_expected_codes"),
|
|
health_check_expected_body=serializer.validated_data.get("health_check_expected_body"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="Health Check 삭제",
|
|
manual_parameters=[appkey_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, health_check_id):
|
|
try:
|
|
appkey = get_appkey(request)
|
|
api = ApiDnsPlus(appkey)
|
|
result = api.delete_health_checks([health_check_id])
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== Load Balancer API ====================
|
|
|
|
|
|
class LoadBalancerListView(NHNBaseView):
|
|
"""로드밸런서 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="로드밸런서 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "로드밸런서 목록"},
|
|
)
|
|
def get(self, request):
|
|
logger.info(f"[LB] 로드밸런서 목록 조회 요청")
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.get_loadbalancer_list(
|
|
name=request.query_params.get("name"),
|
|
provisioning_status=request.query_params.get("provisioning_status"),
|
|
vip_address=request.query_params.get("vip_address"),
|
|
)
|
|
lb_count = len(result.get("loadbalancers", []))
|
|
logger.info(f"[LB] 로드밸런서 목록 조회 성공 - count={lb_count}")
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
logger.error(f"[LB] 로드밸런서 목록 조회 실패 - error={e.message}")
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LoadBalancerCreateView(NHNBaseView):
|
|
"""로드밸런서 생성 API (비동기)"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="로드밸런서 생성 (비동기)",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LoadBalancerSerializer,
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LoadBalancerSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
from .tasks import create_loadbalancer_async
|
|
|
|
task = create_loadbalancer_async(
|
|
region=headers["region"],
|
|
token=headers["token"],
|
|
lb_data=serializer.validated_data,
|
|
)
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "message": "로드밸런서 생성 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception("로드밸런서 생성 작업 시작 실패")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LoadBalancerDetailView(NHNBaseView):
|
|
"""로드밸런서 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="로드밸런서 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "로드밸런서 상세 정보"},
|
|
)
|
|
def get(self, request, loadbalancer_id):
|
|
logger.info(f"[LB] 로드밸런서 상세 조회 요청 - loadbalancer_id={loadbalancer_id}")
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.get_loadbalancer_info(loadbalancer_id)
|
|
logger.info(f"[LB] 로드밸런서 상세 조회 성공 - loadbalancer_id={loadbalancer_id}")
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
logger.error(f"[LB] 로드밸런서 상세 조회 실패 - loadbalancer_id={loadbalancer_id}, error={e.message}")
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="로드밸런서 수정",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LoadBalancerUpdateSerializer,
|
|
responses={200: "수정된 로드밸런서 정보"},
|
|
)
|
|
def put(self, request, loadbalancer_id):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LoadBalancerUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.update_loadbalancer(
|
|
loadbalancer_id=loadbalancer_id,
|
|
name=serializer.validated_data.get("name"),
|
|
description=serializer.validated_data.get("description"),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="로드밸런서 삭제 (비동기)",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={202: "작업 ID 반환"},
|
|
)
|
|
def delete(self, request, loadbalancer_id):
|
|
logger.info(f"[LB] 로드밸런서 삭제 요청 - loadbalancer_id={loadbalancer_id}")
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
from .tasks import delete_loadbalancer_async
|
|
|
|
task = delete_loadbalancer_async(
|
|
region=headers["region"],
|
|
token=headers["token"],
|
|
loadbalancer_id=loadbalancer_id,
|
|
loadbalancer_name=request.query_params.get("name", ""),
|
|
)
|
|
logger.info(f"[LB] 로드밸런서 삭제 작업 시작 - loadbalancer_id={loadbalancer_id}, task_id={task.id}")
|
|
return Response(
|
|
{"task_id": str(task.id), "status": task.status, "message": "로드밸런서 삭제 작업이 시작되었습니다."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
except Exception as e:
|
|
logger.exception(f"[LB] 로드밸런서 삭제 작업 시작 실패 - loadbalancer_id={loadbalancer_id}")
|
|
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== LB Listener API ====================
|
|
|
|
|
|
class LBListenerListView(NHNBaseView):
|
|
"""리스너 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="리스너 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "리스너 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.get_listener_list(
|
|
loadbalancer_id=request.query_params.get("loadbalancer_id"),
|
|
protocol=request.query_params.get("protocol"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBListenerCreateView(NHNBaseView):
|
|
"""리스너 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="리스너 생성",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBListenerSerializer,
|
|
responses={200: "생성된 리스너 정보"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBListenerSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.create_listener(
|
|
loadbalancer_id=serializer.validated_data["loadbalancer_id"],
|
|
protocol=serializer.validated_data["protocol"],
|
|
protocol_port=serializer.validated_data["protocol_port"],
|
|
name=serializer.validated_data.get("name"),
|
|
description=serializer.validated_data.get("description"),
|
|
default_pool_id=serializer.validated_data.get("default_pool_id"),
|
|
connection_limit=serializer.validated_data.get("connection_limit", -1),
|
|
keepalive_timeout=serializer.validated_data.get("keepalive_timeout", 300),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up", True),
|
|
default_tls_container_ref=serializer.validated_data.get("default_tls_container_ref"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBListenerDetailView(NHNBaseView):
|
|
"""리스너 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="리스너 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "리스너 상세 정보"},
|
|
)
|
|
def get(self, request, listener_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
return Response(api.get_listener_info(listener_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="리스너 수정",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBListenerUpdateSerializer,
|
|
responses={200: "수정된 리스너 정보"},
|
|
)
|
|
def put(self, request, listener_id):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBListenerUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.update_listener(
|
|
listener_id=listener_id,
|
|
name=serializer.validated_data.get("name"),
|
|
description=serializer.validated_data.get("description"),
|
|
default_pool_id=serializer.validated_data.get("default_pool_id"),
|
|
connection_limit=serializer.validated_data.get("connection_limit"),
|
|
keepalive_timeout=serializer.validated_data.get("keepalive_timeout"),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="리스너 삭제",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, listener_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.delete_listener(listener_id)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== LB Pool API ====================
|
|
|
|
|
|
class LBPoolListView(NHNBaseView):
|
|
"""풀 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="풀 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "풀 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.get_pool_list(
|
|
loadbalancer_id=request.query_params.get("loadbalancer_id"),
|
|
protocol=request.query_params.get("protocol"),
|
|
lb_algorithm=request.query_params.get("lb_algorithm"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBPoolCreateView(NHNBaseView):
|
|
"""풀 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="풀 생성",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBPoolSerializer,
|
|
responses={200: "생성된 풀 정보"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBPoolSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.create_pool(
|
|
lb_algorithm=serializer.validated_data["lb_algorithm"],
|
|
protocol=serializer.validated_data["protocol"],
|
|
loadbalancer_id=serializer.validated_data.get("loadbalancer_id"),
|
|
listener_id=serializer.validated_data.get("listener_id"),
|
|
name=serializer.validated_data.get("name"),
|
|
description=serializer.validated_data.get("description"),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up", True),
|
|
session_persistence=serializer.validated_data.get("session_persistence"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBPoolDetailView(NHNBaseView):
|
|
"""풀 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="풀 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "풀 상세 정보"},
|
|
)
|
|
def get(self, request, pool_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
return Response(api.get_pool_info(pool_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="풀 수정",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBPoolUpdateSerializer,
|
|
responses={200: "수정된 풀 정보"},
|
|
)
|
|
def put(self, request, pool_id):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBPoolUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.update_pool(
|
|
pool_id=pool_id,
|
|
name=serializer.validated_data.get("name"),
|
|
description=serializer.validated_data.get("description"),
|
|
lb_algorithm=serializer.validated_data.get("lb_algorithm"),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up"),
|
|
session_persistence=serializer.validated_data.get("session_persistence"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="풀 삭제",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, pool_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.delete_pool(pool_id)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== LB Member API ====================
|
|
|
|
|
|
class LBMemberListView(NHNBaseView):
|
|
"""멤버 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="멤버 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "멤버 목록"},
|
|
)
|
|
def get(self, request, pool_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
return Response(api.get_member_list(pool_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBMemberCreateView(NHNBaseView):
|
|
"""멤버 추가 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="멤버 추가",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBMemberSerializer,
|
|
responses={200: "추가된 멤버 정보"},
|
|
)
|
|
def post(self, request, pool_id):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBMemberSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.create_member(
|
|
pool_id=pool_id,
|
|
address=serializer.validated_data["address"],
|
|
protocol_port=serializer.validated_data["protocol_port"],
|
|
subnet_id=serializer.validated_data.get("subnet_id"),
|
|
weight=serializer.validated_data.get("weight", 1),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up", True),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBMemberDetailView(NHNBaseView):
|
|
"""멤버 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="멤버 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "멤버 상세 정보"},
|
|
)
|
|
def get(self, request, pool_id, member_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
return Response(api.get_member_info(pool_id, member_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="멤버 수정",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBMemberUpdateSerializer,
|
|
responses={200: "수정된 멤버 정보"},
|
|
)
|
|
def put(self, request, pool_id, member_id):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBMemberUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.update_member(
|
|
pool_id=pool_id,
|
|
member_id=member_id,
|
|
weight=serializer.validated_data.get("weight"),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="멤버 삭제",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, pool_id, member_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.delete_member(pool_id, member_id)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== LB Health Monitor API ====================
|
|
|
|
|
|
class LBHealthMonitorListView(NHNBaseView):
|
|
"""헬스 모니터 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="헬스 모니터 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "헬스 모니터 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.get_healthmonitor_list(
|
|
pool_id=request.query_params.get("pool_id"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBHealthMonitorCreateView(NHNBaseView):
|
|
"""헬스 모니터 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="헬스 모니터 생성",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBHealthMonitorSerializer,
|
|
responses={200: "생성된 헬스 모니터 정보"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBHealthMonitorSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.create_healthmonitor(
|
|
pool_id=serializer.validated_data["pool_id"],
|
|
type=serializer.validated_data["type"],
|
|
delay=serializer.validated_data["delay"],
|
|
timeout=serializer.validated_data["timeout"],
|
|
max_retries=serializer.validated_data["max_retries"],
|
|
max_retries_down=serializer.validated_data.get("max_retries_down", 3),
|
|
http_method=serializer.validated_data.get("http_method", "GET"),
|
|
url_path=serializer.validated_data.get("url_path", "/"),
|
|
expected_codes=serializer.validated_data.get("expected_codes", "200"),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up", True),
|
|
host_header=serializer.validated_data.get("host_header"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBHealthMonitorDetailView(NHNBaseView):
|
|
"""헬스 모니터 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="헬스 모니터 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "헬스 모니터 상세 정보"},
|
|
)
|
|
def get(self, request, healthmonitor_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
return Response(api.get_healthmonitor_info(healthmonitor_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="헬스 모니터 수정",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBHealthMonitorUpdateSerializer,
|
|
responses={200: "수정된 헬스 모니터 정보"},
|
|
)
|
|
def put(self, request, healthmonitor_id):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBHealthMonitorUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.update_healthmonitor(
|
|
healthmonitor_id=healthmonitor_id,
|
|
delay=serializer.validated_data.get("delay"),
|
|
timeout=serializer.validated_data.get("timeout"),
|
|
max_retries=serializer.validated_data.get("max_retries"),
|
|
max_retries_down=serializer.validated_data.get("max_retries_down"),
|
|
http_method=serializer.validated_data.get("http_method"),
|
|
url_path=serializer.validated_data.get("url_path"),
|
|
expected_codes=serializer.validated_data.get("expected_codes"),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up"),
|
|
host_header=serializer.validated_data.get("host_header"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="헬스 모니터 삭제",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, healthmonitor_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.delete_healthmonitor(healthmonitor_id)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== LB L7 Policy API ====================
|
|
|
|
|
|
class LBL7PolicyListView(APIView):
|
|
"""L7 정책 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="L7 정책 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "L7 정책 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.get_l7policy_list(
|
|
listener_id=request.query_params.get("listener_id"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBL7PolicyCreateView(APIView):
|
|
"""L7 정책 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="L7 정책 생성",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBL7PolicySerializer,
|
|
responses={200: "생성된 L7 정책 정보"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBL7PolicySerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.create_l7policy(
|
|
listener_id=serializer.validated_data["listener_id"],
|
|
action=serializer.validated_data["action"],
|
|
position=serializer.validated_data.get("position", 1),
|
|
name=serializer.validated_data.get("name"),
|
|
description=serializer.validated_data.get("description"),
|
|
redirect_pool_id=serializer.validated_data.get("redirect_pool_id"),
|
|
redirect_url=serializer.validated_data.get("redirect_url"),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up", True),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBL7PolicyDetailView(APIView):
|
|
"""L7 정책 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="L7 정책 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "L7 정책 상세 정보"},
|
|
)
|
|
def get(self, request, l7policy_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
return Response(api.get_l7policy_info(l7policy_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="L7 정책 수정",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBL7PolicyUpdateSerializer,
|
|
responses={200: "수정된 L7 정책 정보"},
|
|
)
|
|
def put(self, request, l7policy_id):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBL7PolicyUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.update_l7policy(
|
|
l7policy_id=l7policy_id,
|
|
name=serializer.validated_data.get("name"),
|
|
description=serializer.validated_data.get("description"),
|
|
action=serializer.validated_data.get("action"),
|
|
position=serializer.validated_data.get("position"),
|
|
redirect_pool_id=serializer.validated_data.get("redirect_pool_id"),
|
|
redirect_url=serializer.validated_data.get("redirect_url"),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="L7 정책 삭제",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, l7policy_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.delete_l7policy(l7policy_id)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== LB L7 Rule API ====================
|
|
|
|
|
|
class LBL7RuleListView(APIView):
|
|
"""L7 룰 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="L7 룰 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "L7 룰 목록"},
|
|
)
|
|
def get(self, request, l7policy_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
return Response(api.get_l7rule_list(l7policy_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBL7RuleCreateView(APIView):
|
|
"""L7 룰 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="L7 룰 생성",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBL7RuleSerializer,
|
|
responses={200: "생성된 L7 룰 정보"},
|
|
)
|
|
def post(self, request, l7policy_id):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBL7RuleSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.create_l7rule(
|
|
l7policy_id=l7policy_id,
|
|
type=serializer.validated_data["type"],
|
|
compare_type=serializer.validated_data["compare_type"],
|
|
value=serializer.validated_data["value"],
|
|
key=serializer.validated_data.get("key"),
|
|
invert=serializer.validated_data.get("invert", False),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up", True),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBL7RuleDetailView(APIView):
|
|
"""L7 룰 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="L7 룰 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "L7 룰 상세 정보"},
|
|
)
|
|
def get(self, request, l7policy_id, l7rule_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
return Response(api.get_l7rule_info(l7policy_id, l7rule_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="L7 룰 수정",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBL7RuleUpdateSerializer,
|
|
responses={200: "수정된 L7 룰 정보"},
|
|
)
|
|
def put(self, request, l7policy_id, l7rule_id):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBL7RuleUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.update_l7rule(
|
|
l7policy_id=l7policy_id,
|
|
l7rule_id=l7rule_id,
|
|
type=serializer.validated_data.get("type"),
|
|
compare_type=serializer.validated_data.get("compare_type"),
|
|
value=serializer.validated_data.get("value"),
|
|
key=serializer.validated_data.get("key"),
|
|
invert=serializer.validated_data.get("invert"),
|
|
admin_state_up=serializer.validated_data.get("admin_state_up"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="L7 룰 삭제",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, l7policy_id, l7rule_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.delete_l7rule(l7policy_id, l7rule_id)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== LB IP ACL Group API ====================
|
|
|
|
|
|
class LBIpAclGroupListView(NHNBaseView):
|
|
"""IP ACL 그룹 목록 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="IP ACL 그룹 목록 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "IP ACL 그룹 목록"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
return Response(api.get_ipacl_group_list())
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBIpAclGroupCreateView(NHNBaseView):
|
|
"""IP ACL 그룹 생성 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="IP ACL 그룹 생성",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBIpAclGroupSerializer,
|
|
responses={200: "생성된 IP ACL 그룹 정보"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBIpAclGroupSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.create_ipacl_group(
|
|
action=serializer.validated_data["action"],
|
|
name=serializer.validated_data.get("name"),
|
|
description=serializer.validated_data.get("description"),
|
|
ipacl_targets=serializer.validated_data.get("ipacl_targets"),
|
|
loadbalancers=serializer.validated_data.get("loadbalancers"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBIpAclGroupDetailView(NHNBaseView):
|
|
"""IP ACL 그룹 상세/수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="IP ACL 그룹 상세 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "IP ACL 그룹 상세 정보"},
|
|
)
|
|
def get(self, request, ipacl_group_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
return Response(api.get_ipacl_group_info(ipacl_group_id))
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="IP ACL 그룹 수정",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBIpAclGroupUpdateSerializer,
|
|
responses={200: "수정된 IP ACL 그룹 정보"},
|
|
)
|
|
def put(self, request, ipacl_group_id):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBIpAclGroupUpdateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.update_ipacl_group(
|
|
ipacl_group_id=ipacl_group_id,
|
|
name=serializer.validated_data.get("name"),
|
|
description=serializer.validated_data.get("description"),
|
|
loadbalancers=serializer.validated_data.get("loadbalancers"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="IP ACL 그룹 삭제",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, ipacl_group_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.delete_ipacl_group(ipacl_group_id)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== LB IP ACL Target API ====================
|
|
|
|
|
|
class LBIpAclTargetCreateView(NHNBaseView):
|
|
"""IP ACL 타깃 추가 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="IP ACL 타깃 추가",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=LBIpAclTargetCreateSerializer,
|
|
responses={200: "추가된 IP ACL 타깃 정보"},
|
|
)
|
|
def post(self, request):
|
|
headers = get_nhn_headers(request)
|
|
serializer = LBIpAclTargetCreateSerializer(data=request.data)
|
|
if not serializer.is_valid():
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.create_ipacl_target(
|
|
ipacl_group_id=serializer.validated_data["ipacl_group_id"],
|
|
ip_address=serializer.validated_data["ip_address"],
|
|
description=serializer.validated_data.get("description"),
|
|
)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class LBIpAclTargetDetailView(NHNBaseView):
|
|
"""IP ACL 타깃 수정/삭제 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="IP ACL 타깃 수정 (설명만)",
|
|
manual_parameters=[region_header, token_header],
|
|
request_body=openapi.Schema(
|
|
type=openapi.TYPE_OBJECT,
|
|
properties={
|
|
"description": openapi.Schema(type=openapi.TYPE_STRING, description="설명"),
|
|
},
|
|
required=["description"],
|
|
),
|
|
responses={200: "수정된 IP ACL 타깃 정보"},
|
|
)
|
|
def put(self, request, ipacl_target_id):
|
|
headers = get_nhn_headers(request)
|
|
description = request.data.get("description")
|
|
if description is None:
|
|
return Response({"error": "description is required"}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.update_ipacl_target(ipacl_target_id, description)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="IP ACL 타깃 삭제",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "삭제 결과"},
|
|
)
|
|
def delete(self, request, ipacl_target_id):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
result = api.delete_ipacl_target(ipacl_target_id)
|
|
return Response(result)
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
# ==================== LB Quota API ====================
|
|
|
|
|
|
class LBQuotaView(NHNBaseView):
|
|
"""로드밸런서 쿼타 조회 API"""
|
|
|
|
@swagger_auto_schema(
|
|
operation_summary="로드밸런서 쿼타 조회",
|
|
manual_parameters=[region_header, token_header],
|
|
responses={200: "쿼타 정보"},
|
|
)
|
|
def get(self, request):
|
|
headers = get_nhn_headers(request)
|
|
try:
|
|
api = ApiLoadBalancer(headers["region"], headers["token"])
|
|
return Response(api.get_quota())
|
|
except NHNCloudAPIError as e:
|
|
return Response({"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
|