diff --git a/docs/gns3-copilot/troubleshooting/datetime-timezone-issue.md b/docs/gns3-copilot/troubleshooting/datetime-timezone-issue.md deleted file mode 100644 index 8af547b8c..000000000 --- a/docs/gns3-copilot/troubleshooting/datetime-timezone-issue.md +++ /dev/null @@ -1,180 +0,0 @@ -# Datetime Timezone Issue - -## Problem Description - -The API returns datetime strings without timezone suffixes, causing frontend JavaScript to parse them as local time instead of UTC time. - -### Example - -| Aspect | Value | -|--------|-------| -| Actual time (Beijing) | 2026-03-07 01:30 | -| Backend returns | `2026-03-06T16:31:36.547762` (no timezone) | -| Frontend displays | March 6, 16:31 | -| Should display | March 7, 00:31 (UTC 16:31 + 8 hours) | - -### Root Cause - -- Backend stores UTC time in database as naive datetime (no timezone info) -- FastAPI's `jsonable_encoder` serializes datetime as ISO 8601 **without timezone suffix** -- JavaScript `new Date()` treats strings without 'Z' or timezone offset as **local time** - -``` -Backend intention: 2026-03-06T16:31:36Z (UTC) -Actually returned: 2026-03-06T16:31:36.547762 (no timezone) -JavaScript parses as: local time 16:31 -Should be: UTC 16:31 → Beijing time 00:31 (next day) -``` - ---- - -## Frontend Solutions - -### Solution 1: Use dayjs UTC Parsing (Recommended) - -```typescript -import dayjs from 'dayjs'; -import utc from 'dayjs/plugin/utc'; -import timezone from 'dayjs/plugin/timezone'; - -dayjs.extend(utc); -dayjs.extend(timezone); - -// Parse naive datetime as UTC -const createdAt = '2026-03-06T16:31:36.547762'; -const date = dayjs.utc(createdAt).tz('Asia/Shanghai'); -console.log(date.format('YYYY-MM-DD HH:mm')); // 2026-03-07 00:31 -``` - -### Solution 2: Add 'Z' Suffix Manually - -```typescript -// Utility function to normalize API dates -function parseAPIDate(dateStr: string): Date { - // Add 'Z' suffix if no timezone info present - const normalized = dateStr.includes('Z') || dateStr.includes('+') - ? dateStr - : `${dateStr}Z`; - return new Date(normalized); -} - -// Usage -const date = parseAPIDate('2026-03-06T16:31:36.547762'); -console.log(date.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })); -``` - -### Solution 3: Global Axios Interceptor (Most Thorough) - -```typescript -import axios from 'axios'; - -api.interceptors.response.use((response) => { - // Recursively normalize all date fields - function normalizeDates(obj: any): any { - // Match ISO 8601 datetime pattern without timezone - if (typeof obj === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(obj)) { - return obj.includes('Z') || obj.includes('+') ? obj : `${obj}Z`; - } - if (Array.isArray(obj)) { - return obj.map(normalizeDates); - } - if (obj && typeof obj === 'object') { - return Object.fromEntries( - Object.entries(obj).map(([k, v]) => [k, normalizeDates(v)]) - ); - } - return obj; - } - - response.data = normalizeDates(response.data); - return response; -}); -``` - ---- - -## Backend Context - -### Current Implementation - -**File**: `gns3server/api/server.py:58-64` - -```python -application = FastAPI( - title="GNS3 controller API", - description="This page describes the public controller API for GNS3", - version="v3", - docs_url=None, - redoc_url=None -) -``` - -**File**: `gns3server/db/models/base.py` - -```python -from fastapi.encoders import jsonable_encoder - -class Base: - def asjson(self): - return jsonable_encoder(self.asdict()) -``` - -### Datetime Flow - -1. Database stores naive datetime (no timezone) -2. FastAPI uses `jsonable_encoder` to serialize -3. Output format: `YYYY-MM-DDTHH:MM:SS.ffffff` (no 'Z' suffix) -4. JavaScript interprets as local time - -### Affected Fields - -- `created_at` -- `updated_at` -- `last_login` -- Any other datetime fields in API responses - ---- - -## Testing Checklist - -- [ ] Verify datetime displays correctly in Beijing timezone (UTC+8) -- [ ] Test with other timezones (e.g., UTC-5, UTC+0) -- [ ] Check daylight saving time transitions (if applicable) -- [ ] Verify datetime input/insertion still works correctly - ---- - -## Related Files - -- Backend: `gns3server/api/server.py` -- Backend: `gns3server/db/models/base.py` -- Schemas: `gns3server/schemas/controller/base.py` - - ---- - -## License - -**Copyright © 2025 Yue Guobin (岳国宾)** - -This work is licensed under the [Creative Commons Attribution-ShareAlike 4.0 -International License (CC BY-SA 4.0)](https://creativecommons.org/licenses/by-sa/4.0/). - -![CC BY-SA 4.0](https://i.creativecommons.org/l/by-sa/4.0/88x31.png) - -### Summary - -You are free to: - -- **Share** — Copy and redistribute the material in any medium or format -- **Adapt** — Remix, transform, and build upon the material for any purpose - -Under the following terms: - -- **Attribution** — You must give appropriate credit to **Yue Guobin (岳国宾)**, provide - a link to the license, and indicate if changes were made. -- **ShareAlike** — If you remix, transform, or build upon the material, you must - distribute your contributions under the **same license** (CC BY-SA 4.0). - -Full license text: [DESIGN_DOCS_LICENSE](../DESIGN_DOCS_LICENSE.md) - diff --git a/docs/gns3-copilot/troubleshooting/force-kill-residual-processes.md b/docs/gns3-copilot/troubleshooting/force-kill-residual-processes.md deleted file mode 100644 index c4a60ec07..000000000 --- a/docs/gns3-copilot/troubleshooting/force-kill-residual-processes.md +++ /dev/null @@ -1,179 +0,0 @@ -# Force Kill (kill -9) Causing Residual Processes Issue - -## Problem Description - -When using `kill -9` to forcibly close the gns3server process, restarting gns3server results in the following errors: - -### 1. Dynamips VM Creation Failure -``` -ERROR gns3server.api.routes.compute:133 Compute node error: Dynamips error when running command 'vm create "R1" 1 c7200 -': unable to create VM instance 'R1' -``` - -### 2. Validation Error with project_id as "undefined" -``` -ERROR gns3server.api.server:208 Request validation error in /v3/projects/undefined/nodes/{node_id} (PUT): -1 validation error: - {'type': 'uuid_parsing', 'loc': ('path', 'project_id'), 'msg': 'Input should be a valid UUID, invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `u` at 1', 'input': 'undefined', ...} -``` - -### 3. TCP Port Still in Use Warning -``` -WARNING gns3server.compute.project:355 Project d672144c-4de9-4a97-a23d-307ddc3ab9b1 has TCP ports still in use: {5001} -``` - -## Root Cause - -When using `kill -9` to forcibly terminate the gns3server process, gns3server has no opportunity to properly clean up its spawned child processes, leaving the following residual processes running: - -- **Dynamips hypervisor processes** (dynamips) -- **VPCS virtual PC processes** (vpcs) -- **Docker containers** (although shown as removed in logs, some state may not be cleaned up) -- **Other emulator processes** - -These residual processes will: -1. Occupy the same port numbers and resource IDs -2. Maintain old socket connections -3. Cause the newly started gns3server to be unable to reallocate the same resources - -## Solutions - -### Method 1: Manual Cleanup of Residual Processes (Recommended) - -After forcibly closing gns3server, find and clean up residual processes: - -```bash -# Find dynamips processes -ps aux | grep dynamips - -# Find vpcs processes -ps aux | grep vpcs - -# Terminate residual processes -killall dynamips -killall vpcs -``` - -### Method 2: Use pkill to Clean Related Processes - -```bash -# Clean all GNS3 related processes -pkill -9 dynamips -pkill -9 vpcs -pkill -9 ubridge -``` - -### Method 3: Check Before Restart - -Before restarting gns3server, ensure there are no residual processes: - -```bash -# Check if there are residual GNS3 processes -ps aux | grep -E "(dynamips|vpcs|ubridge|gns3)" | grep -v grep -``` - -## Preventive Measures - -### 1. Use Proper Shutdown Methods - -Prefer the following methods to close gns3server instead of `kill -9`: - -```bash -# If using systemd -sudo systemctl stop gns3server - -# If running directly -# Press Ctrl+C or use normal kill signal -kill -``` - -### 2. Use SIGTERM Instead of SIGKILL - -```bash -# Try normal termination first (allows process to clean up) -kill -15 - -# Wait a few seconds, if process is still running, then use kill -9 -sleep 3 -if ps -p > /dev/null; then - kill -9 -fi -``` - -### 3. Implement Automatic Cleanup Script - -You can create a startup script to check and clean up residual processes: - -```bash -#!/bin/bash -# cleanup_before_start.sh - -# Check and clean residual dynamips processes -if pgrep -f dynamips > /dev/null; then - echo "Found residual dynamips processes, cleaning up..." - killall -9 dynamips -fi - -# Check and clean residual vpcs processes -if pgrep -f vpcs > /dev/null; then - echo "Found residual vpcs processes, cleaning up..." - killall -9 vpcs -fi - -# Wait for ports to be released -sleep 1 - -# Start gns3server -gns3server -``` - -## Technical Details - -### Why Does kill -9 Cause This Problem? - -1. **SIGKILL signal cannot be captured**: Processes cannot capture or ignore the SIGKILL signal, so there's no chance to execute cleanup code -2. **Child processes become orphans**: After the parent process is forcibly terminated, child processes are adopted by init/PID 1, but they don't know the parent has died -3. **Resources not released**: Sockets, ports, file locks, and other resources are not properly released -4. **State inconsistency**: gns3server's internal state (such as port allocation, ID allocation) is cleared, but actual resources are still occupied - -### Code Locations Involved - -- **Dynamips Process Management**: `gns3server/compute/dynamips/` -- **Port Allocation and Tracking**: `gns3server/compute/project.py:355` -- **Node Update API**: `gns3server/api/routes/controller/nodes.py:230` - -## Related Issues - -- [ ] Consider automatically detecting and cleaning up residual processes at gns3server startup -- [ ] Add process health check mechanism -- [ ] Implement more robust port and ID reuse logic -- [ ] Add residual process detection and warnings - - ---- - -## License - -**Copyright © 2025 Yue Guobin (岳国宾)** - -This work is licensed under the [Creative Commons Attribution-ShareAlike 4.0 -International License (CC BY-SA 4.0)](https://creativecommons.org/licenses/by-sa/4.0/). - -![CC BY-SA 4.0](https://i.creativecommons.org/l/by-sa/4.0/88x31.png) - -### Summary - -You are free to: - -- **Share** — Copy and redistribute the material in any medium or format -- **Adapt** — Remix, transform, and build upon the material for any purpose - -Under the following terms: - -- **Attribution** — You must give appropriate credit to **Yue Guobin (岳国宾)**, provide - a link to the license, and indicate if changes were made. -- **ShareAlike** — If you remix, transform, or build upon the material, you must - distribute your contributions under the **same license** (CC BY-SA 4.0). - -Full license text: [DESIGN_DOCS_LICENSE](../DESIGN_DOCS_LICENSE.md) - diff --git a/docs/todo/mypy_type_checking_issues.md b/docs/todo/mypy_type_checking_issues.md deleted file mode 100644 index 4511bd6f2..000000000 --- a/docs/todo/mypy_type_checking_issues.md +++ /dev/null @@ -1,209 +0,0 @@ -# Mypy Static Type Checking Issues - -**Date:** 2026-03-10 -**Status:** Pending -**Priority:** Medium - -## Overview - -This document tracks type checking issues found by `mypy` in the `gns3_copilot` module. These issues should be addressed to improve type safety and catch potential bugs at development time. - -## How to Run Type Checking - -```bash -# Install mypy -pip install mypy - -# Run type checking on gns3_copilot module -mypy gns3server/agent/gns3_copilot/ - -# Install missing type stubs -mypy --install-types -pip install types-requests -``` - -## Issues Summary - -### Total: 35 Type Errors - -| File | Error Count | Priority | -|------|-------------|----------| -| chat_sessions_repository.py | 8 | High | -| context_manager.py | 5 | High | -| agent_service.py | 5 | High | -| gns3_topology_reader.py | 2 | Medium | -| message_converters.py | 1 | Medium | -| connector_factory.py | 1 | Medium | -| custom_gns3fy.py | Missing stubs | Low | -| display_tools_nornir.py | Missing stubs | Low | -| config_tools_nornir.py | Missing stubs | Low | - -## Detailed Issues - -### 1. chat_sessions_repository.py (8 errors) - -**Lines 157, 234, 279, 283, 287, 291, 295** - -#### Error 1: Return value type mismatch (Line 157) -```python -# Issue: Returning ChatSession | None, but function expects ChatSession -error: Incompatible return value type (got "ChatSession | None", expected "ChatSession") -error: Argument 1 to "get_session_by_id" has incompatible type "int | None"; expected "int" -``` - -**Fix:** Add proper null checks and type guards - -#### Error 2: List append type mismatch (Lines 234, 279, 283, 287, 291, 295) -```python -# Issue: Appending int to list[str] -error: Argument 1 to "append" of "list" has incompatible type "int"; expected "str" -``` - -**Fix:** Convert integers to strings before appending, or change list type annotation - ---- - -### 2. context_manager.py (5 errors) - -**Lines 139, 145, 156, 167, 171** - -```python -# Issue: Unsupported indexed assignment on Collection[str] -error: Unsupported target for indexed assignment ("Collection[str]") -``` - -**Problem:** `Collection[str]` is a read-only protocol, doesn't support item assignment. - -**Fix:** Change type annotation to `List[str]` or `MutableSequence[str]` - ---- - -### 3. agent_service.py (5 errors) - -**Lines 267, 617, 634, 653, 675** - -```python -# Issue: Passing Connection | None to function expecting Connection -error: Argument 1 to "ChatSessionsRepository" has incompatible type "Connection | None"; expected "Connection" -``` - -**Fix:** Add null checks before passing connection parameter, or use assertion - ---- - -### 4. gns3_topology_reader.py (2 errors) - -**Lines 137, 138** - -```python -# Issue: len() argument has incompatible union type -error: Argument 1 to "len" has incompatible type "dict[Any, Any] | str | list[tuple[str, str, str, str]] | None"; expected "Sized" -``` - -**Fix:** Add null checks and type narrowing before calling `len()` - ---- - -### 5. message_converters.py (1 error) - -**Line 151** - -```python -# Issue: List type assignment mismatch -error: Incompatible types in assignment (expression has type "list[dict[str, Any]]", variable has type "list[ToolCall]") -``` - -**Fix:** Either convert dict list to ToolCall list, or change variable type annotation - ---- - -### 6. connector_factory.py (1 error) - -**Line 368** - -```python -# Issue: Calling split() on str | None without null check -error: Item "None" of "str | None" has no attribute "split" -``` - -**Fix:** Add null check before calling `split()` method - ---- - -### 7. Missing Type Stubs (Low Priority) - -The following third-party libraries lack type stubs: - -- **requests** → Install: `pip install types-requests` -- **netmiko** → No official stubs available -- **nornir_netmiko** → No official stubs available - -**Recommendation:** Create inline type ignores or stub files for these libraries. - ---- - -## Recommended Fix Strategy - -### Phase 1: High Priority (Critical Type Safety Issues) - -1. **chat_sessions_repository.py** - - Fix null safety issues - - Ensure proper type conversions for list operations - -2. **context_manager.py** - - Change `Collection[str]` to `List[str]` for mutable collections - -3. **agent_service.py** - - Add null checks for database connections - -### Phase 2: Medium Priority (Type Annotations) - -4. **gns3_topology_reader.py** - - Add type narrowing for union types - -5. **message_converters.py** - - Fix type compatibility between dict and ToolCall - -6. **connector_factory.py** - - Add null checks before method calls - -### Phase 3: Low Priority (Third-party Stubs) - -7. Install available type stubs (`types-requests`) -8. Add `# type: ignore` comments for unavoidable third-party issues - ---- - -## Mypy Configuration - -Consider adding a `mypy.ini` or `pyproject.toml` configuration: - -```toml -[tool.mypy] -python_version = "3.13" -warn_return_any = true -warn_unused_configs = true -disallow_untyped_defs = false # Enable gradually -ignore_missing_imports = true # For third-party libs - -[[tool.mypy.overrides]] -module = "gns3server.agent.gns3_copilot.*" -disallow_untyped_defs = true -``` - ---- - -## Resources - -- [Mypy Documentation](https://mypy.readthedocs.io/) -- [Python Type Hints](https://docs.python.org/3/library/typing.html) -- [Mypy Error Codes](https://mypy.readthedocs.io/en/stable/error_code_list.html) - ---- - -## Notes - -- All type issues are in the `gns3_copilot` module -- No type errors found in core GNS3 server code during this check -- Consider enabling type checking in CI/CD pipeline -- Type checking helps catch bugs before runtime