diff --git a/FARMQ_ADMIN_MACHINE_NAME_FIX_PLAN.md b/FARMQ_ADMIN_MACHINE_NAME_FIX_PLAN.md new file mode 100644 index 0000000..b2392af --- /dev/null +++ b/FARMQ_ADMIN_MACHINE_NAME_FIX_PLAN.md @@ -0,0 +1,289 @@ +# FarmQ Admin 머신 이름 표시 문제 해결 계획 + +## 📋 문제 상황 + +현재 FarmQ Admin의 머신 관리 페이지에서 **머신 이름이 hostname으로만 표시**되고 있어, Magic DNS에서 사용되는 실제 노드 이름(`given_name`)과 일치하지 않는 문제가 발생하고 있습니다. + +## 🔍 문제 분석 + +### 1. 현재 상황 + +**Headscale CLI API 실제 데이터:** +```json +{ + "id": 1, + "name": "0bin-Ubuntu-VM", // ❌ 실제 Magic DNS에서 사용되는 이름 + "given_name": "0bin-ubuntu-vm", // ✅ Magic DNS 접두어 (pev.headscale.local) + "ip_addresses": ["100.64.0.1"], + "user": {"name": "myuser"}, + "online": true +} +``` + +**FarmQ Admin 현재 표시:** +```html +{{ machine_data.machine_name or machine_data.hostname }} +
{{ machine_data.hostname }}
+``` + +### 2. 문제의 근본 원인 + +#### A. 데이터베이스 스키마 불일치 + +**Headscale 모델:** +```python +# models/headscale_models.py +class Node: + hostname = Column(String) # 시스템 호스트명 (0bin-Ubuntu-VM) + given_name = Column(String) # 사용자 지정 이름 (0bin-ubuntu-vm) - Magic DNS용 +``` + +**FarmQ 모델:** +```python +# models/farmq_models.py +class MachineProfile: + hostname = Column(String) # hostname으로 복사됨 + machine_name = Column(String) # hostname으로 중복 저장됨 ❌ +``` + +#### B. 동기화 로직 문제 + +```python +# utils/database_new.py (line 343) +machine_data = { + 'hostname': node.hostname, # "0bin-Ubuntu-VM" + 'machine_name': node.hostname, # ❌ hostname 중복! given_name이어야 함 + 'tailscale_ip': node.ipv4, +} +``` + +#### C. 템플릿 표시 문제 + +```html + +{{ machine_data.machine_name or machine_data.hostname }} + + +``` + +## ✅ 해결 방안 + +### 1. 즉시 수정 (Quick Fix) + +#### A. 데이터베이스 동기화 로직 수정 +```python +# farmq-admin/utils/database_new.py +def get_all_machines_with_details(): + machine_data = { + 'hostname': node.hostname, # 시스템 호스트명 + 'machine_name': node.given_name, # ✅ Magic DNS 이름으로 변경 + 'display_name': node.given_name or node.hostname, # 표시용 이름 + 'tailscale_ip': node.ipv4, + } +``` + +#### B. FarmQ 모델 동기화 수정 +```python +# models/farmq_models.py - sync_machine_from_headscale +machine = MachineProfile( + hostname=headscale_node_data.get('hostname'), + machine_name=headscale_node_data.get('given_name'), # ✅ given_name 사용 + tailscale_ip=headscale_node_data.get('ipv4'), +) +``` + +#### C. 템플릿 표시 개선 +```html + +{{ machine_data.machine_name or machine_data.hostname }} +
+ {{ machine_data.machine_name }}.headscale.local +
+
+ {{ machine_data.hostname }} +
+``` + +### 2. 근본적 개선 (Long-term) + +#### A. 필드 명칭 명확화 +```python +class MachineProfile: + system_hostname = Column(String) # 시스템 호스트명 (0bin-Ubuntu-VM) + headscale_name = Column(String) # Headscale given_name (0bin-ubuntu-vm) + magic_dns_name = Column(String) # Magic DNS 전체 이름 (0bin-ubuntu-vm.headscale.local) + display_name = Column(String) # 사용자 표시용 이름 +``` + +#### B. Magic DNS 정보 표시 강화 +```html +
+
{{ machine.display_name }}
+
+ {{ machine.magic_dns_name }} + +
+
+ 시스템: {{ machine.system_hostname }} +
+
+``` + +## 🚀 구현 단계 + +### Phase 1: 긴급 수정 (1-2시간) + +1. **데이터 동기화 로직 수정** + ```bash + # 파일: farmq-admin/utils/database_new.py + # 라인: 343 + 'machine_name': node.given_name, # hostname → given_name + ``` + +2. **템플릿 표시 개선** + ```bash + # 파일: farmq-admin/templates/machines/list.html + # Magic DNS 정보 추가 표시 + ``` + +3. **동기화 함수 수정** + ```bash + # 파일: farmq-admin/models/farmq_models.py + # sync_machine_from_headscale 함수 수정 + ``` + +### Phase 2: 표시 개선 (2-3시간) + +1. **Magic DNS 정보 강화 표시** + - `.headscale.local` 접미사 자동 표시 + - 클립보드 복사 기능 + - 연결 테스트 기능 + +2. **필터링 기능 추가** + - Magic DNS 이름으로 검색 + - 온라인/오프라인 필터 + - 사용자별 필터 + +### Phase 3: 구조적 개선 (4-6시간) + +1. **데이터베이스 스키마 개선** + - 필드명 명확화 + - Magic DNS 전용 필드 추가 + - 인덱스 최적화 + +2. **API 통합 개선** + - Headscale CLI 응답 캐싱 + - 실시간 상태 업데이트 + - WebSocket을 통한 실시간 알림 + +## 📊 예상 결과 + +### Before (현재) +``` +머신 이름: 0bin-Ubuntu-VM # hostname (시스템명) +호스트명: 0bin-Ubuntu-VM # 중복 정보 +Magic DNS: 사용불가 ❌ # given_name 정보 부족 +``` + +### After (수정 후) +``` +머신 이름: 0bin-ubuntu-vm # given_name (Magic DNS용) +Magic DNS: 0bin-ubuntu-vm.headscale.local ✅ +시스템명: 0bin-Ubuntu-VM # hostname (참고 정보) +IP 주소: 100.64.0.1 # 현재와 동일 +``` + +## 🧪 테스트 계획 + +### 1. 데이터 검증 +```python +# 테스트 스크립트 +def test_machine_name_mapping(): + nodes = headscale_session.query(Node).all() + for node in nodes: + print(f"ID: {node.id}") + print(f"Hostname: {node.hostname}") # 0bin-Ubuntu-VM + print(f"Given Name: {node.given_name}") # 0bin-ubuntu-vm + print(f"Magic DNS: {node.given_name}.headscale.local") + print("---") +``` + +### 2. Magic DNS 연결 테스트 +```bash +# 각 노드별 Magic DNS 테스트 +ping 0bin-ubuntu-vm.headscale.local +ping pev.headscale.local +ping pqserver.headscale.local +``` + +### 3. UI 표시 확인 +- 머신 목록에서 올바른 이름 표시 +- Magic DNS 주소 복사 기능 +- 연결 상태와 일치성 확인 + +## 📝 체크리스트 + +### 코드 수정 +- [ ] `farmq-admin/utils/database_new.py` - 동기화 로직 수정 +- [ ] `farmq-admin/models/farmq_models.py` - 모델 동기화 수정 +- [ ] `farmq-admin/templates/machines/list.html` - 표시 개선 +- [ ] `farmq-admin/templates/machines/detail.html` - 상세 페이지 수정 + +### 테스트 +- [ ] 데이터베이스 동기화 테스트 +- [ ] Magic DNS 이름 표시 확인 +- [ ] UI 표시 정상성 확인 +- [ ] 기존 기능 호환성 테스트 + +### 문서화 +- [ ] 변경사항 README 업데이트 +- [ ] API 문서 갱신 +- [ ] 사용자 가이드 수정 + +## 🔧 구현 파일 목록 + +### 수정할 파일들 +1. **`farmq-admin/utils/database_new.py`** (라인 343) + - `machine_name` 필드를 `given_name`으로 변경 + +2. **`farmq-admin/models/farmq_models.py`** (라인 445) + - 동기화 시 `given_name` 사용 + +3. **`farmq-admin/templates/machines/list.html`** (라인 115-119) + - Magic DNS 정보 추가 표시 + +4. **`farmq-admin/templates/machines/detail.html`** + - 상세 페이지 Magic DNS 정보 개선 + +### 새로 추가할 기능 +- Magic DNS 주소 클립보드 복사 +- 연결 테스트 버튼 +- 실시간 온라인 상태 표시 + +## 💡 장기적 개선사항 + +### 1. Headscale API 직접 통합 +현재 CLI 기반 → REST API 직접 호출로 전환하여 성능 개선 + +### 2. 실시간 모니터링 +WebSocket을 통한 실시간 노드 상태 업데이트 + +### 3. Magic DNS 관리 기능 +- 노드 이름 변경 +- Magic DNS 도메인 설정 +- DNS 해석 테스트 도구 + +## 📅 구현 일정 + +| 단계 | 작업 | 소요시간 | 완료일 | +|------|------|---------|---------| +| Phase 1 | 긴급 수정 | 2시간 | 당일 | +| Phase 2 | 표시 개선 | 3시간 | 1일 | +| Phase 3 | 구조 개선 | 6시간 | 2-3일 | + +--- + +**작성일:** 2025년 9월 13일 +**업데이트:** FarmQ Admin 머신 이름 표시 문제 분석 및 해결 계획 수립 완료 \ No newline at end of file diff --git a/farmq-admin/models/farmq_models.py b/farmq-admin/models/farmq_models.py index ccdcbfc..54b2c99 100644 --- a/farmq-admin/models/farmq_models.py +++ b/farmq-admin/models/farmq_models.py @@ -432,6 +432,7 @@ class FarmqDatabaseManager: if machine: # 기존 머신 업데이트 machine.hostname = headscale_node_data.get('hostname') + machine.machine_name = headscale_node_data.get('given_name') or headscale_node_data.get('hostname') machine.tailscale_ip = headscale_node_data.get('ipv4') machine.tailscale_status = 'online' if headscale_node_data.get('is_online') else 'offline' machine.last_seen = datetime.now() @@ -442,7 +443,7 @@ class FarmqDatabaseManager: headscale_node_id=headscale_node_data.get('id'), headscale_machine_key=headscale_node_data.get('machine_key'), hostname=headscale_node_data.get('hostname'), - machine_name=headscale_node_data.get('hostname'), + machine_name=headscale_node_data.get('given_name') or headscale_node_data.get('hostname'), tailscale_ip=headscale_node_data.get('ipv4'), tailscale_status='online' if headscale_node_data.get('is_online') else 'offline', last_seen=datetime.now() diff --git a/farmq-admin/templates/machines/list.html b/farmq-admin/templates/machines/list.html index e64c4aa..41f5d7a 100644 --- a/farmq-admin/templates/machines/list.html +++ b/farmq-admin/templates/machines/list.html @@ -113,7 +113,17 @@
{{ machine_data.machine_name or machine_data.hostname }} -
{{ machine_data.hostname }}
+
+ {{ machine_data.machine_name or machine_data.hostname }}.headscale.local + +
+ {% if machine_data.hostname != (machine_data.machine_name or machine_data.hostname) %} +
+ OS: {{ machine_data.hostname }} +
+ {% endif %}
{{ machine_data.headscale_user_name or '미지정' }}
@@ -440,6 +450,16 @@ function deleteNode(nodeId, nodeName) { }); } +// Magic DNS 주소 클립보드 복사 기능 +function copyToClipboard(text) { + navigator.clipboard.writeText(text).then(() => { + showToast(`Magic DNS 주소가 복사되었습니다: ${text}`, 'success'); + }).catch(err => { + console.error('복사 실패:', err); + showToast('복사에 실패했습니다.', 'danger'); + }); +} + // 초기 카운터 설정 document.addEventListener('DOMContentLoaded', function() { filterMachines(); diff --git a/farmq-admin/utils/database_new.py b/farmq-admin/utils/database_new.py index 0d72ad6..e9c8e4e 100644 --- a/farmq-admin/utils/database_new.py +++ b/farmq-admin/utils/database_new.py @@ -340,7 +340,7 @@ def get_all_machines_with_details() -> List[Dict[str, Any]]: machine_data = { 'id': node.id, 'hostname': node.hostname, - 'machine_name': node.hostname, # 표시용 이름 + 'machine_name': node.given_name or node.hostname, # Magic DNS용 이름 (given_name 우선) 'tailscale_ip': node.ipv4, 'ipv6': node.ipv6, 'headscale_user_name': node.user.name if node.user else '미지정',