mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-09-12 21:15:27 +03:00
Integrate the gns3-copilot AI assistant module to provide intelligent automation and interaction capabilities for GNS3 network emulation. Key components: - AI agent framework with LLM integration (supports Qwen vision model) - GNS3 client library for project topology management - Extensive prompt templates for various network operation scenarios - Tool library for node creation, linking, configuration, and management - Support for English level assessment (A1-C2) and specialized personas - Network drawing and topology visualization tools - Linux device automation via Nornir/Telnetlib - Window controller for UI interaction Features: - Multi-modal AI agent with vision capabilities - Automated network topology deployment and configuration - Interactive node and drawing management - File-based project operations (read, write, list) - Specialized prompts for different scenarios and skill levels - Comprehensive tool set for network device management
306 lines
11 KiB
Python
306 lines
11 KiB
Python
"""
|
|
GNS3 project lock/unlock tool for project management.
|
|
|
|
Provides functionality to lock, unlock, or check the lock status of GNS3 projects.
|
|
Locking a project prevents accidental modifications to drawings and nodes.
|
|
"""
|
|
|
|
import logging
|
|
from typing import Any
|
|
|
|
from langchain.tools import BaseTool
|
|
|
|
from gns3_copilot.gns3_client import Project, get_gns3_connector
|
|
|
|
# Configure logging
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class GNS3ProjectLock(BaseTool):
|
|
"""
|
|
Tool to lock, unlock, or check the lock status of a GNS3 project.
|
|
|
|
This tool connects to GNS3 server and performs lock/unlock operations
|
|
on the specified project, or retrieves the current lock status.
|
|
|
|
IMPORTANT: Project lock/unlock operations are only supported in GNS3 API v3.
|
|
Using this tool with GNS3 API v2 will result in an error.
|
|
|
|
Supported operations:
|
|
- "locked": Check if the project is currently locked
|
|
- "lock": Lock all drawings and nodes in the project
|
|
- "unlock": Unlock all drawings and nodes in the project
|
|
"""
|
|
|
|
name: str = "gns3_project_lock"
|
|
description: str = """
|
|
Lock, unlock, or check the lock status of a GNS3 project.
|
|
|
|
IMPORTANT: This tool only works with GNS3 API v3. It is not supported in API v2.
|
|
|
|
Input parameters:
|
|
- project_id: The unique UUID identifier of the project (required)
|
|
- operation: The operation to perform - "locked", "lock", or "unlock" (required)
|
|
|
|
Operations:
|
|
- "locked": Returns the current lock status of the project
|
|
- "lock": Locks all drawings and nodes in the project
|
|
- "unlock": Unlocks all drawings and nodes in the project
|
|
|
|
Returns: Dictionary with operation result including:
|
|
- success: Whether the operation succeeded
|
|
- operation: The operation performed
|
|
- project_id: The project ID
|
|
- locked_status: Current lock status (for "locked" operation)
|
|
- message: Status message
|
|
- error: Error message if operation failed
|
|
|
|
Example output (check locked status):
|
|
{
|
|
"success": true,
|
|
"operation": "locked",
|
|
"project_id": "ff8e059c-c33d-47f4-bc11-c7dda8a1d500",
|
|
"locked_status": false,
|
|
"message": "Project is currently unlocked"
|
|
}
|
|
|
|
Example output (lock project):
|
|
{
|
|
"success": true,
|
|
"operation": "lock",
|
|
"project_id": "ff8e059c-c33d-47f4-bc11-c7dda8a1d500",
|
|
"message": "Project locked successfully"
|
|
}
|
|
|
|
Example output (unlock project):
|
|
{
|
|
"success": true,
|
|
"operation": "unlock",
|
|
"project_id": "ff8e059c-c33d-47f4-bc11-c7dda8a1d500",
|
|
"message": "Project unlocked successfully"
|
|
}
|
|
|
|
Example output (API v2 not supported):
|
|
{
|
|
"success": false,
|
|
"operation": "lock",
|
|
"project_id": "ff8e059c-c33d-47f4-bc11-c7dda8a1d500",
|
|
"error": "Project lock/unlock operations are only supported in GNS3 API v3. Current API version: v2"
|
|
}
|
|
"""
|
|
|
|
def _run(self, tool_input: Any = None, run_manager: Any = None) -> dict:
|
|
"""
|
|
Execute the project lock/unlock operation.
|
|
|
|
Args:
|
|
tool_input: Dictionary containing project_id and operation
|
|
run_manager: Run manager for tool execution (optional)
|
|
|
|
Returns:
|
|
Dictionary with operation result
|
|
"""
|
|
# Log received input
|
|
logger.info("Received input: %s", tool_input)
|
|
|
|
try:
|
|
# Validate input
|
|
if not tool_input or "project_id" not in tool_input:
|
|
return {
|
|
"success": False,
|
|
"error": "Missing required parameter: project_id",
|
|
}
|
|
|
|
if "operation" not in tool_input:
|
|
return {
|
|
"success": False,
|
|
"error": "Missing required parameter: operation",
|
|
}
|
|
|
|
project_id = tool_input["project_id"]
|
|
operation = tool_input["operation"]
|
|
|
|
# Validate operation type
|
|
valid_operations = ["locked", "lock", "unlock"]
|
|
if operation not in valid_operations:
|
|
return {
|
|
"success": False,
|
|
"error": f"Invalid operation '{operation}'. "
|
|
f"Must be one of: {', '.join(valid_operations)}",
|
|
}
|
|
|
|
# Initialize Gns3Connector using factory function
|
|
logger.info("Connecting to GNS3 server...")
|
|
server = get_gns3_connector()
|
|
|
|
if server is None:
|
|
logger.error("Failed to create GNS3 connector")
|
|
return {
|
|
"success": False,
|
|
"error": "Failed to connect to GNS3 server. "
|
|
"Please check your configuration.",
|
|
}
|
|
|
|
# Create project instance and retrieve project details
|
|
project = Project(project_id=project_id, connector=server)
|
|
project.get(get_nodes=False, get_links=False, get_stats=False)
|
|
|
|
# Check if project was found
|
|
if not project.name:
|
|
return {
|
|
"success": False,
|
|
"error": f"Project with ID '{project_id}' not found",
|
|
}
|
|
|
|
# Perform the requested operation
|
|
result: dict[str, Any] = {
|
|
"success": False,
|
|
"operation": operation,
|
|
"project_id": project_id,
|
|
}
|
|
|
|
if operation == "locked":
|
|
# Get current lock status
|
|
logger.info("Getting lock status for project %s", project_id)
|
|
try:
|
|
locked_status = project.get_locked()
|
|
result.update(
|
|
{
|
|
"success": True,
|
|
"locked_status": locked_status,
|
|
"message": f"Project is currently {'locked' if locked_status else 'unlocked'}",
|
|
}
|
|
)
|
|
logger.info("Project lock status: %s", locked_status)
|
|
except ValueError as e:
|
|
# Handle API version incompatibility
|
|
error_msg = str(e)
|
|
if "only supported in GNS3 API v3" in error_msg:
|
|
logger.error("API v2 not supported: %s", error_msg)
|
|
result.update(
|
|
{
|
|
"error": error_msg,
|
|
"message": "Project lock/unlock operations require GNS3 API v3. "
|
|
"Please upgrade your GNS3 server or use v3 API.",
|
|
}
|
|
)
|
|
else:
|
|
logger.error("Error getting lock status: %s", error_msg)
|
|
result.update(
|
|
{
|
|
"error": error_msg,
|
|
"message": f"Failed to get lock status: {error_msg}",
|
|
}
|
|
)
|
|
|
|
elif operation == "lock":
|
|
# Lock the project
|
|
logger.info("Locking project %s", project_id)
|
|
try:
|
|
project.lock_project()
|
|
result.update(
|
|
{
|
|
"success": True,
|
|
"message": f"Project '{project.name}' locked successfully",
|
|
}
|
|
)
|
|
logger.info("Project locked successfully")
|
|
except ValueError as e:
|
|
# Handle API version incompatibility
|
|
error_msg = str(e)
|
|
if "only supported in GNS3 API v3" in error_msg:
|
|
logger.error("API v2 not supported: %s", error_msg)
|
|
result.update(
|
|
{
|
|
"error": error_msg,
|
|
"message": "Project lock/unlock operations require GNS3 API v3. "
|
|
"Please upgrade your GNS3 server or use v3 API.",
|
|
}
|
|
)
|
|
else:
|
|
logger.error("Error locking project: %s", error_msg)
|
|
result.update(
|
|
{
|
|
"error": error_msg,
|
|
"message": f"Failed to lock project: {error_msg}",
|
|
}
|
|
)
|
|
|
|
elif operation == "unlock":
|
|
# Unlock the project
|
|
logger.info("Unlocking project %s", project_id)
|
|
try:
|
|
project.unlock_project()
|
|
result.update(
|
|
{
|
|
"success": True,
|
|
"message": f"Project '{project.name}' unlocked successfully",
|
|
}
|
|
)
|
|
logger.info("Project unlocked successfully")
|
|
except ValueError as e:
|
|
# Handle API version incompatibility
|
|
error_msg = str(e)
|
|
if "only supported in GNS3 API v3" in error_msg:
|
|
logger.error("API v2 not supported: %s", error_msg)
|
|
result.update(
|
|
{
|
|
"error": error_msg,
|
|
"message": "Project lock/unlock operations require GNS3 API v3. "
|
|
"Please upgrade your GNS3 server or use v3 API.",
|
|
}
|
|
)
|
|
else:
|
|
logger.error("Error unlocking project: %s", error_msg)
|
|
result.update(
|
|
{
|
|
"error": error_msg,
|
|
"message": f"Failed to unlock project: {error_msg}",
|
|
}
|
|
)
|
|
|
|
# Log result
|
|
logger.info("Project lock operation result: %s", result)
|
|
|
|
return result
|
|
|
|
except Exception as e:
|
|
logger.error("Error performing lock operation on GNS3 project: %s", str(e))
|
|
return {
|
|
"success": False,
|
|
"error": f"Failed to perform lock operation on GNS3 project: {str(e)}",
|
|
}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Test the tool locally
|
|
print("=== Testing GNS3ProjectLock Tool ===")
|
|
|
|
# Test 1: Check lock status
|
|
print("\n--- Test 1: Check lock status ---")
|
|
test_input_locked = {
|
|
"project_id": "0c0fde25-6ead-4413-a283-ea8fd2324291", # Replace with actual project UUID
|
|
"operation": "locked",
|
|
}
|
|
tool = GNS3ProjectLock()
|
|
result_locked = tool._run(test_input_locked)
|
|
print(f"Result: {result_locked}")
|
|
|
|
# Test 2: Lock project
|
|
print("\n--- Test 2: Lock project ---")
|
|
test_input_lock = {
|
|
"project_id": "0c0fde25-6ead-4413-a283-ea8fd2324291", # Replace with actual project UUID
|
|
"operation": "lock",
|
|
}
|
|
result_lock = tool._run(test_input_lock)
|
|
print(f"Result: {result_lock}")
|
|
|
|
# Test 3: Unlock project
|
|
print("\n--- Test 3: Unlock project ---")
|
|
test_input_unlock = {
|
|
"project_id": "0c0fde25-6ead-4413-a283-ea8fd2324291", # Replace with actual project UUID
|
|
"operation": "unlock",
|
|
}
|
|
result_unlock = tool._run(test_input_unlock)
|
|
print(f"Result: {result_unlock}")
|