Metadata-Version: 2.3
Name: ksen-hyperv
Version: 0.1.2
Summary: Add your description here
Author: yongg
Author-email: yongg <2814744065@qq.com>
Requires-Dist: pyyaml>=6.0.2
Requires-Dist: pywin32>=307 ; sys_platform == 'win32'
Requires-Dist: typer>=0.16.0
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# ksen-hyperv

`ksen-hyperv` 是一个面向 Windows Hyper-V 的 Python 管理库。它通过
`pywin32` 访问 `root\virtualization\v2` WMI 命名空间，可用于查询本机虚拟机、
获取运行状态和 IP 地址，以及执行启动、关机、暂停和保存状态等操作。

## 功能

- 枚举本机 Hyper-V 虚拟机及其状态
- 按虚拟机名称查询状态
- 获取虚拟机 IP 地址，可优先返回 IPv4
- 启动虚拟机
- 优雅关闭虚拟机，并在关闭集成组件不可用时回退到硬关机
- 强制关闭虚拟机
- 暂停虚拟机
- 保存虚拟机状态
- 等待 Hyper-V 异步 WMI 任务完成并报告错误
- 使用 Typer CLI 按 YAML 配置建立宿主机到虚拟机的 TCP 端口转发

## 环境要求

- Windows，且已启用 Hyper-V
- Python 3.12 或更高版本
- 能够访问本机 Hyper-V WMI 服务的账户

管理 Hyper-V 通常需要管理员权限。若遇到“访问被拒”等 WMI 错误，请以管理员
身份启动 PowerShell、终端或承载本程序的服务。

## 安装

使用 `pip` 从源码安装：

```powershell
pip install .
```

使用 [uv](https://docs.astral.sh/uv/) 安装项目依赖：

```powershell
uv sync
```

`pywin32` 仅会在 Windows 平台安装。

## 端口转发 CLI

创建 `forward.yaml`：

```yaml
tk-creator:
  13389: 3389
tk-fully:
  13390: 3390
```

顶层键是 Hyper-V 虚拟机名称；其下每一项为
`宿主机监听端口: 虚拟机目标端口`。然后在管理员 PowerShell 中运行：

```powershell
ksen-hyperv forward .\forward.yaml
```

默认监听 `0.0.0.0`。如只希望本机访问，可指定：

```powershell
ksen-hyperv forward .\forward.yaml --listen-address 127.0.0.1
```

命令会按名称确认每台虚拟机存在、获取其 IPv4 地址，并使用 Windows
`netsh interface portproxy` 应用 TCP 转发。它不会自动启动已关闭的虚拟机；
虚拟机无可用 IP 时会报错。此操作通常需要管理员权限，并且 Windows 防火墙仍需
允许相应的宿主机监听端口。

## 快速开始

```python
from ksen_hyperv import HyperVManager, VMState

manager = HyperVManager()

# 列出全部虚拟机
for name, state in manager.list_vms():
    print(f"{name}: {state.value}")

vm_name = "my-vm"

# 查询状态和 IP
state = manager.get_vm_state(vm_name)
ip = manager.get_vm_ip(vm_name)
print(f"state={state.value if state else 'Not Found'}, ip={ip}")

# 启动虚拟机
if state == VMState.OFF:
    manager.start_vm(vm_name)
```

## API

### `HyperVManager`

| 方法 | 返回值 | 说明 |
| --- | --- | --- |
| `list_vms()` | `list[tuple[str, VMState]]` | 返回所有虚拟机的名称和状态 |
| `get_vm_state(name)` | `VMState \| None` | 查询状态；虚拟机不存在时返回 `None` |
| `get_vm_ip(name, prefer_ipv4=True)` | `str \| None` | 查询 IP；无可用地址时返回 `None` |
| `start_vm(name)` | `bool` | 启动虚拟机 |
| `stop_vm(name, force=False)` | `bool` | 优雅关机，失败时告警并回退到硬关机 |
| `stop_vm(name, force=True)` | `bool` | 直接硬关机，相当于断电 |
| `pause_vm(name)` | `bool` | 暂停虚拟机 |
| `save_vm(name)` | `bool` | 保存虚拟机状态 |

状态变更方法成功时返回 `True`。启动、暂停和保存操作具有幂等性：虚拟机已处于
目标状态时会直接返回 `True`。

### `VMState`

可用状态如下：

| 枚举值 | 字符串值 | 含义 |
| --- | --- | --- |
| `VMState.OFF` | `Off` | 已关闭 |
| `VMState.STARTING` | `Starting` | 正在启动 |
| `VMState.RUNNING` | `Running` | 运行中 |
| `VMState.PAUSED` | `Paused` | 已暂停 |
| `VMState.SAVED` | `Saved` | 状态已保存 |
| `VMState.STOPPING` | `Stopping` | 正在停止 |
| `VMState.OTHER` | `Other` | 其他或未识别状态 |

## 常用示例

### 启动、暂停和保存状态

```python
from ksen_hyperv import HyperVManager

manager = HyperVManager()
manager.start_vm("my-vm")
manager.pause_vm("my-vm")
manager.save_vm("my-vm")
```

### 关闭虚拟机

```python
from ksen_hyperv import HyperVManager

manager = HyperVManager()

# 优先请求来宾系统正常关机
manager.stop_vm("my-vm")

# 直接断电式关机，请谨慎使用
manager.stop_vm("my-vm", force=True)
```

优雅关机依赖虚拟机中的 Hyper-V 关闭集成服务。如果该组件未启用或调用失败，
当前实现会发出 Python warning，并自动回退为硬关机。

### 不优先选择 IPv4

```python
from ksen_hyperv import HyperVManager

manager = HyperVManager()
address = manager.get_vm_ip("my-vm", prefer_ipv4=False)
print(address)
```

`prefer_ipv4=False` 表示返回 Hyper-V 提供的第一个有效地址，不保证该地址一定是
IPv6。IP 查询依赖来宾网络适配器信息；虚拟机关闭、集成服务不可用或尚未获取
地址时会返回 `None`。

## 异常处理

```python
from ksen_hyperv import HyperVManager

try:
    manager = HyperVManager()
    manager.start_vm("my-vm")
except ValueError as exc:
    # 虚拟机名称不存在
    print(exc)
except RuntimeError as exc:
    # Hyper-V 不可用、WMI 调用失败或状态变更失败
    print(exc)
```

初始化 `HyperVManager` 时会检查 Hyper-V WMI 服务是否可用。底层异步任务默认
每秒轮询一次，最长等待 120 秒；超时或任务失败会转换为 `RuntimeError`。

## 开发

安装开发依赖：

```powershell
uv sync --group dev
```

项目结构：

```text
src/ksen_hyperv/
├── __init__.py          # 公共导出
├── hyperv_manager.py    # 面向用户的管理 API
└── _wmi_client.py       # WMI 查询、状态切换和异步任务封装
```

仓库中的现有测试会连接真实的本机 Hyper-V，并可能改变指定虚拟机的运行状态。
运行前请先检查测试文件中的虚拟机名称和操作，避免影响正在使用的虚拟机。

## 注意事项

- 本库只管理本机 Hyper-V，不支持远程 Hyper-V 主机。
- 虚拟机名称按 Hyper-V 中的 `ElementName` 精确匹配。
- `force=True` 或优雅关机失败后的回退会执行硬关机，可能导致来宾系统未保存的
  数据丢失。
- 暂停、保存、启动等操作受虚拟机当前状态和 Hyper-V 策略限制；无效状态会以
  异常形式返回。
