zioinfo-mail/workspace/guardia-itsm/routers/multicloud.py
DESKTOP-TKLFCPR\ython b8faec44e0 feat(advanced): GUARDiA 고급 확장 구현 — 20 routers + 754 endpoints
CMDB 자동 발견 (4개):
- autodiscovery.py: SSH 네트워크 스캔 + CMDB 자동 등록
- snmp_discovery.py: SNMP v2c/v3 장비 자동 발견
- dependency_map.py: 서비스 의존성 자동 매핑 (netstat)
- config_inventory.py: 서버 인벤토리 자동 수집 (SSH)

NL 쿼리 엔진 (3개):
- nlquery.py: Text-to-SQL (SELECT 전용, DML 차단)
- op_assistant.py: Multi-turn 대화형 운영 어시스턴트
- query_history.py: 쿼리 이력·즐겨찾기·공유

구성 드리프트 (3개):
- drift_detection.py: 골든 구성 vs 실제 비교·SR 자동 생성
- golden_config.py: 내장 CSAP 템플릿 + 버전 관리
- auto_remediation.py: 승인 기반 자동 교정 + 롤백

멀티클라우드 (4개):
- multicloud.py: 통합 관제 (NCloud+AWS+KT)
- aws_connector.py: AWS SigV4 직접 서명 연동
- cost_optimizer.py: AI 비용 최적화 권고
- cloud_migration.py: On-prem→K-Cloud 체크리스트

공공기관 특화 (6개):
- narasajang.py: 나라장터 OpenAPI 연동
- public_api_hub.py: data.go.kr KISA·기상청 허브
- isp_support.py: ISP 수립 지원 + AI 보고서
- network_zone.py: 행정망/인터넷망 분리 관리
- k_cloud.py: 정부 K-Cloud 전환 자동화
- e_procurement.py: 전자조달 계약·검수·납품

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 14:33:41 +09:00

118 lines
5.1 KiB
Python

"""
멀티클라우드 통합 관제 — NCloud + AWS + 기타
엔드포인트:
GET /api/multicloud/providers — 등록된 프로바이더 목록
POST /api/multicloud/providers — 프로바이더 등록
DELETE /api/multicloud/providers/{id}— 프로바이더 삭제
GET /api/multicloud/resources — 전체 클라우드 리소스 통합
GET /api/multicloud/costs — 전체 비용 통합
GET /api/multicloud/summary — 멀티클라우드 현황 요약
"""
from __future__ import annotations
import json, logging
from datetime import datetime
from typing import Optional
import httpx
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from core.auth import get_current_user, require_admin_role
from database import get_db
from models import User, MultiCloudConfig
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/multicloud", tags=["멀티클라우드"])
SUPPORTED_PROVIDERS = ["ncloud", "aws", "gcp", "azure", "kt_cloud", "naver_cloud"]
class ProviderCreate(BaseModel):
name: str
provider_type: str = Field(..., description="ncloud|aws|gcp|azure|kt_cloud")
region: str = "kr-1"
access_key: str
secret_key: str
extra_config: Optional[dict] = None
@router.post("/providers")
async def add_provider(req: ProviderCreate, db: AsyncSession = Depends(get_db), user: User = Depends(require_admin_role)):
if req.provider_type not in SUPPORTED_PROVIDERS:
raise HTTPException(400, f"미지원 프로바이더: {req.provider_type}")
cfg = MultiCloudConfig(
tenant_id=user.tenant_id, name=req.name,
provider_type=req.provider_type, region=req.region,
access_key=req.access_key,
secret_key_enc=req.secret_key, # TODO: AES-256-GCM
extra_config=json.dumps(req.extra_config or {}),
is_active=True, created_at=datetime.utcnow(),
)
db.add(cfg); await db.commit(); await db.refresh(cfg)
return {"ok": True, "id": cfg.id}
@router.get("/providers")
async def list_providers(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
rows = await db.execute(select(MultiCloudConfig).where(MultiCloudConfig.tenant_id == user.tenant_id, MultiCloudConfig.is_active == True))
return [{"id": c.id, "name": c.name, "type": c.provider_type, "region": c.region} for c in rows.scalars().all()]
@router.delete("/providers/{config_id}")
async def delete_provider(config_id: int, db: AsyncSession = Depends(get_db), user: User = Depends(require_admin_role)):
row = await db.execute(select(MultiCloudConfig).where(MultiCloudConfig.id == config_id, MultiCloudConfig.tenant_id == user.tenant_id))
cfg = row.scalar_one_or_none()
if not cfg: raise HTTPException(404)
cfg.is_active = False; await db.commit()
return {"ok": True}
@router.get("/resources")
async def list_all_resources(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
rows = await db.execute(select(MultiCloudConfig).where(MultiCloudConfig.tenant_id == user.tenant_id, MultiCloudConfig.is_active == True))
cfgs = rows.scalars().all()
all_resources = []
for cfg in cfgs:
# NCloud 경유 실제 조회 (다른 프로바이더는 설정 완료 후 활성화)
if cfg.provider_type in ("ncloud", "naver_cloud"):
try:
from routers.ncloud import list_servers as ncloud_list
# 기존 ncloud.py 재활용
resources = await _get_ncloud_resources(cfg)
for r in resources:
r["provider"] = cfg.name
r["provider_type"] = cfg.provider_type
all_resources.extend(resources)
except Exception as e:
logger.warning(f"NCloud 조회 실패: {e}")
else:
all_resources.append({"provider": cfg.name, "provider_type": cfg.provider_type, "note": "설정 후 활성화"})
return {"resources": all_resources, "total": len(all_resources)}
async def _get_ncloud_resources(cfg: MultiCloudConfig) -> list[dict]:
try:
from routers.ncloud import _ncloud_request
data = await _ncloud_request(cfg, "GET", "/vserver/v2/getServerInstanceList")
if data:
return [{"id": s.get("serverInstanceNo"), "name": s.get("serverName"),
"status": s.get("serverInstanceStatus", {}).get("codeName"),
"ip": s.get("publicIp")} for s in data.get("getServerInstanceListResponse", {}).get("serverInstanceList", [])]
except Exception: pass
return []
@router.get("/summary")
async def multicloud_summary(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
rows = await db.execute(select(MultiCloudConfig).where(MultiCloudConfig.tenant_id == user.tenant_id, MultiCloudConfig.is_active == True))
cfgs = rows.scalars().all()
return {
"provider_count": len(cfgs),
"providers": [{"name": c.name, "type": c.provider_type} for c in cfgs],
"last_checked": datetime.utcnow(),
}