Skip to main content
Glama
test_vm_management.py6.48 kB
import pytest import libvirt from unittest.mock import Mock, patch from kvm_mcp_server import list_vms, start_vm, stop_vm, reboot_vm, get_vnc_ports @pytest.fixture def mock_domain(): domain = Mock() domain.name.return_value = "test-vm" domain.ID.return_value = 1 domain.state.return_value = (libvirt.VIR_DOMAIN_RUNNING, 0) domain.maxMemory.return_value = 2048 * 1024 # 2GB in KB domain.maxVcpus.return_value = 2 return domain @pytest.fixture def mock_conn(mock_domain): conn = Mock() conn.listAllDomains.return_value = [mock_domain] conn.lookupByName.return_value = mock_domain return conn @pytest.mark.asyncio @patch('libvirt.open') async def test_list_vms_success(mock_libvirt_open, mock_conn): """Test successful listing of VMs""" mock_libvirt_open.return_value = mock_conn result = await list_vms("list_vms", {}) assert len(result) == 1 vm = result[0] assert vm["name"] == "test-vm" assert vm["id"] == 1 assert vm["state"] == "running" assert vm["memory"] == 2048 # MB assert vm["vcpu"] == 2 @pytest.mark.asyncio @patch('libvirt.open') async def test_list_vms_connection_error(mock_libvirt_open): """Test VM listing with connection error""" mock_libvirt_open.return_value = None result = await list_vms("list_vms", {}) assert len(result) == 1 assert "error" in result[0] assert "Failed to connect to libvirt daemon" in result[0]["error"] @pytest.mark.asyncio @patch('libvirt.open') async def test_list_vms_libvirt_error(mock_libvirt_open): """Test VM listing with libvirt error""" mock_libvirt_open.side_effect = libvirt.libvirtError("Test error") result = await list_vms("list_vms", {}) assert len(result) == 1 assert "error" in result[0] assert "Test error" in result[0]["error"] @pytest.mark.asyncio @patch('libvirt.open') async def test_start_vm_success(mock_libvirt_open, mock_conn, mock_domain): """Test successful VM start""" mock_libvirt_open.return_value = mock_conn mock_domain.create.return_value = 0 result = await start_vm("start_vm", {"name": "test-vm"}) assert result["status"] == "success" assert "started successfully" in result["message"] mock_domain.create.assert_called_once() @pytest.mark.asyncio @patch('libvirt.open') async def test_start_vm_missing_name(mock_libvirt_open): """Test VM start with missing name""" result = await start_vm("start_vm", {}) assert result["status"] == "error" assert "VM name not provided" in result["message"] mock_libvirt_open.assert_not_called() @pytest.mark.asyncio @patch('libvirt.open') async def test_start_vm_connection_error(mock_libvirt_open): """Test VM start with connection error""" mock_libvirt_open.return_value = None result = await start_vm("start_vm", {"name": "test-vm"}) assert result["status"] == "error" assert "Failed to connect to libvirt daemon" in result["message"] @pytest.mark.asyncio @patch('libvirt.open') async def test_stop_vm_success(mock_libvirt_open, mock_conn, mock_domain): """Test successful VM stop""" mock_libvirt_open.return_value = mock_conn mock_domain.shutdown.return_value = 0 result = await stop_vm("stop_vm", {"name": "test-vm"}) assert result["status"] == "success" assert "stopped successfully" in result["message"] mock_domain.shutdown.assert_called_once() @pytest.mark.asyncio @patch('libvirt.open') async def test_stop_vm_missing_name(mock_libvirt_open): """Test VM stop with missing name""" result = await stop_vm("stop_vm", {}) assert result["status"] == "error" assert "VM name not provided" in result["message"] mock_libvirt_open.assert_not_called() @pytest.mark.asyncio @patch('libvirt.open') async def test_stop_vm_connection_error(mock_libvirt_open): """Test VM stop with connection error""" mock_libvirt_open.return_value = None result = await stop_vm("stop_vm", {"name": "test-vm"}) assert result["status"] == "error" assert "Failed to connect to libvirt daemon" in result["message"] @pytest.mark.asyncio @patch('libvirt.open') async def test_reboot_vm_success(mock_libvirt_open, mock_conn, mock_domain): """Test successful VM reboot""" mock_libvirt_open.return_value = mock_conn mock_domain.reboot.return_value = 0 result = await reboot_vm("reboot_vm", {"name": "test-vm"}) assert result["status"] == "success" assert "rebooted successfully" in result["message"] mock_domain.reboot.assert_called_once() @pytest.mark.asyncio @patch('libvirt.open') async def test_reboot_vm_missing_name(mock_libvirt_open): """Test VM reboot with missing name""" result = await reboot_vm("reboot_vm", {}) assert result["status"] == "error" assert "VM name not provided" in result["message"] mock_libvirt_open.assert_not_called() @pytest.mark.asyncio @patch('libvirt.open') async def test_reboot_vm_connection_error(mock_libvirt_open): """Test VM reboot with connection error""" mock_libvirt_open.return_value = None result = await reboot_vm("reboot_vm", {"name": "test-vm"}) assert result["status"] == "error" assert "Failed to connect to libvirt daemon" in result["message"] @pytest.mark.asyncio @patch('subprocess.check_output') @patch('libvirt.open') async def test_get_vnc_ports_success(mock_libvirt_open, mock_check_output, mock_conn, mock_domain): """Test successful VNC port retrieval""" mock_libvirt_open.return_value = mock_conn mock_check_output.return_value = b"Id Name State\n----------------------------------\n 1 test-vm running\n" result = await get_vnc_ports("get_vnc_ports", {}) assert result["status"] == "success" assert "vnc_ports" in result assert isinstance(result["vnc_ports"], dict) @pytest.mark.asyncio @patch('subprocess.check_output') @patch('libvirt.open') async def test_get_vnc_ports_no_vms(mock_libvirt_open, mock_check_output, mock_conn): """Test VNC port retrieval with no running VMs""" mock_libvirt_open.return_value = mock_conn mock_check_output.return_value = b"Id Name State\n----------------------------------\n" result = await get_vnc_ports("get_vnc_ports", {}) assert result["status"] == "success" assert "vnc_ports" in result assert result["vnc_ports"] == {}

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/steveydevey/kvm-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server