dsh-ensp 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -34
- package/docs/UI-ANCHORS.md +9 -9
- package/docs/plugin-detail.en.md +5 -4
- package/docs/plugin-detail.zh.md +7 -6
- package/package.json +1 -1
- package/src/cli/ensp.mjs +3 -1
- package/src/core/doctor.mjs +1 -1
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
生成 eNSP 可直接打开并正常显示的 `.topo` 文件。支持内置场景,也可自定义设备与链路。
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
机型与接口布局定义在 `src/core/models.mjs`,覆盖 16 个机型。解析拓扑时,端口名优先取自设备自身声明的 `<interface>` 块;同一型号在加装扩展卡后端口排布可能不同,声明块是唯一可靠依据。
|
|
29
29
|
|
|
30
30
|
```js
|
|
31
31
|
import { twoPcLab, writeTopology } from 'dsh-ensp'
|
|
@@ -45,11 +45,11 @@ const topo = autoLayout(
|
|
|
45
45
|
)
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
拓扑格式有几处约束来自 eNSP
|
|
48
|
+
拓扑格式有几处约束来自 eNSP 本身:接口分组必须与机型一致,链路锚点必须落在图标包围盒内。任一项写错,eNSP 会打开空白画布且不报错。规则见 [`docs/ENSP-FORMAT.md`](docs/ENSP-FORMAT.md)。
|
|
49
49
|
|
|
50
50
|
### 启动与停止设备
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
自动定位工具栏按钮,无需手动点击。启动后按设备逐一确认就绪,随后最小化窗口,桌面可继续使用。
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
55
|
ensp probe # 重新标定按钮位置
|
|
@@ -57,7 +57,7 @@ ensp up lab.topo # 打开、启动、确认就绪、最小化
|
|
|
57
57
|
ensp stop # 关闭全部设备
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
eNSP
|
|
60
|
+
eNSP 只允许运行一个实例。异常退出可能遗留不占线程的僵尸进程,该进程持续持有单实例锁,导致下一次启动只打开空白窗口。工具在启动前会识别并清理此类进程。
|
|
61
61
|
|
|
62
62
|
### 下发配置
|
|
63
63
|
|
|
@@ -87,7 +87,7 @@ if (!result.ok) {
|
|
|
87
87
|
|
|
88
88
|
### 等待协议收敛
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
路由协议异步收敛,配置下发完成不代表邻居已建立。此类判定一律轮询,直到状态达成或超时。
|
|
91
91
|
|
|
92
92
|
```js
|
|
93
93
|
import { waitForOspfFull, waitForOspfRoute, waitForOutput } from 'dsh-ensp'
|
|
@@ -97,7 +97,7 @@ await waitForOspfRoute({ port: 2000, prefix: '2.2.2.2/32' })
|
|
|
97
97
|
await waitForOutput({ port: 2000, command: 'display ip routing-table', until: /2\.2\.2\.2/ })
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
三个函数均返回 `{ ok, converged, output, attempts, waitedMs }`。固定等待在慢机器上会误判,在快机器上会浪费。
|
|
101
101
|
|
|
102
102
|
### 场景预设
|
|
103
103
|
|
|
@@ -110,16 +110,16 @@ ensp preset --search bgp # 按关键词搜索
|
|
|
110
110
|
ensp preset campus-network --topo campus.topo # 生成该场景的拓扑
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
每个场景提供三项信息:需要创建的对象、配置顺序、用于确认结果的检查命令。具体命令由使用者按设备补全。
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
场景自带拓扑蓝图:设备、链路、地址规划均为现成内容,加 `--topo` 即生成 eNSP 可打开的 `.topo`,无需先绘图再规划地址。蓝图不含配置命令,场景仍为骨架。
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
118
|
ensp preset ospf-single --topo ospf-single.topo
|
|
119
119
|
ensp up ospf-single.topo
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
场景清单与蓝图均可生成、可校验。`docs/SCENARIOS.md` 由 `src/core/presets.mjs` 与 `src/core/labs.mjs` 渲染,`npm run docs:check` 在两者不一致时返回非零,CI 亦执行该检查。
|
|
123
123
|
|
|
124
124
|
```bash
|
|
125
125
|
npm run docs # 重新生成 docs/SCENARIOS.md
|
|
@@ -128,9 +128,9 @@ npm run docs:check # 只检查是否过期
|
|
|
128
128
|
|
|
129
129
|
### 设备镜像检查
|
|
130
130
|
|
|
131
|
-
部分机型只有设备目录条目、没有随装镜像,最典型的是 `USG6000V`(eNSP
|
|
131
|
+
部分机型只有设备目录条目、没有随装镜像,最典型的是 `USG6000V`(eNSP 安装时需勾选该组件)。这类机型可以正常放入画布并保存为 `.topo`,但 eNSP 打开后会先渲染再自行退出,表现为控制台全部无响应。
|
|
132
132
|
|
|
133
|
-
`ensp up`
|
|
133
|
+
`ensp up` 会在启动客户端之前读取 `res/items.xml` 与各插件的镜像文件,把无法启动的设备连同缺失项一并报出:
|
|
134
134
|
|
|
135
135
|
```console
|
|
136
136
|
$ ensp up firewall-hrp.topo
|
|
@@ -140,13 +140,13 @@ error: topology uses devices this eNSP installation cannot start:
|
|
|
140
140
|
This is not a bug in the topology: eNSP opens it, renders it, then quits. ...
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
`ensp preset ... --topo`
|
|
143
|
+
`ensp preset ... --topo` 生成文件时给出同样的提示,`ensp_build_topology` 的返回值包含 `unsupportedDevices`。该检查只读取本机文件,不启动 eNSP。各场景的设备清单见 [docs/SCENARIOS.md](docs/SCENARIOS.md) 中的“设备镜像”一行。
|
|
144
144
|
|
|
145
145
|
### 窗口遮挡检查
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
启动设备需要点击 eNSP 工具栏按钮,而合成点击由持有该像素的窗口接收。其他程序覆盖 eNSP 时,鼠标事件被该程序接收,eNSP 收不到任何输入。
|
|
148
148
|
|
|
149
|
-
|
|
149
|
+
插件在点击前通过 `WindowFromPoint` 检查落点归属,不属于 eNSP 则不执行点击:
|
|
150
150
|
|
|
151
151
|
```console
|
|
152
152
|
$ ensp up lab.topo
|
|
@@ -155,17 +155,23 @@ The mouse events would go to that window, so nothing was clicked.
|
|
|
155
155
|
Bring eNSP to the front (restore it from the taskbar) and try again.
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
标定前会以 5×4 采样网格检查窗口可见性,任一采样点被其他窗口占用即停止。标定读取屏幕像素,被遮挡时得到的是其他窗口的画面。点击完成后再次校验落点归属。
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
插件无法将 eNSP 窗口提到前台。Windows 仅允许持有前台权限的进程切换前台窗口,跨进程调用 `SetForegroundWindow` 会被拒绝。运行前请将 eNSP 置于最上层。
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
### 运行权限
|
|
163
163
|
|
|
164
|
-
|
|
164
|
+
本工具需要以管理员身份运行。
|
|
165
|
+
|
|
166
|
+
eNSP 客户端要求管理员权限,始终以高完整性级别运行。Windows 的用户界面特权隔离(UIPI)会丢弃低完整性进程发出的输入消息,模拟点击也在其中。普通权限下 `SendInput` 返回成功但输入队列不变,eNSP 收不到事件,表现为点击无效;以管理员身份启动后可正常注入输入。
|
|
167
|
+
|
|
168
|
+
管理员权限解决输入注入,不解决窗口置顶。eNSP 仍需保持可见并在最上层。
|
|
169
|
+
|
|
170
|
+
服务、计划任务、SSH 会话等非交互上下文不具备输入注入能力,提升权限也无法改变。`ensp doctor` 的 `input-injection` 项用于判定当前会话是否可用。
|
|
165
171
|
|
|
166
172
|
### 排错自检
|
|
167
173
|
|
|
168
|
-
|
|
174
|
+
启动失败时,定位故障项通常比修复本身更耗时。`ensp doctor` 将环境检查拆为七项,逐项判定,失败时给出可执行的修法:
|
|
169
175
|
|
|
170
176
|
```console
|
|
171
177
|
$ ensp doctor --topology lab.topo
|
|
@@ -176,34 +182,33 @@ $ ensp doctor --topology lab.topo
|
|
|
176
182
|
fix: Close some applications; devices may boot very slowly or fail to start.
|
|
177
183
|
[ok ] device-images: AR2220 available
|
|
178
184
|
[FAIL] input-injection: SendInput accepted 2 event(s) but the session last-input tick did not change (session 1, console session 1)
|
|
179
|
-
fix:
|
|
180
|
-
pressed. Run the tool from an interactive desktop session ...
|
|
185
|
+
fix: Run the tool elevated (as administrator) from an interactive desktop session.
|
|
181
186
|
[ok ] anchors: start (987,226) stop (1049,228)
|
|
182
187
|
```
|
|
183
188
|
|
|
184
|
-
|
|
189
|
+
该命令不启动 eNSP,只读取本机文件并执行一次合成输入探测,可在任意失败之后或操作之前运行。`--shallow` 跳过较慢的输入探测,`--json` 输出完整结构。对应工具为 `ensp_doctor`。
|
|
185
190
|
|
|
186
|
-
|
|
191
|
+
检查顺序固定:客户端可执行文件、VirtualBox、拓扑所需镜像、控制台端口、输入注入、内存、锚点。定位到哪一项失败,只需修复该项。
|
|
187
192
|
|
|
188
193
|
### 验收
|
|
189
194
|
|
|
190
|
-
|
|
195
|
+
配置下发成功不等于实验通过。`ensp_verify` 从 `.topo` 读取各设备的控制台端口,逐条执行该场景的验收命令,按输出内容判定,不依据命令是否报错:
|
|
191
196
|
|
|
192
197
|
```console
|
|
193
198
|
$ ensp verify ospf-single --topology lab.topo
|
|
194
|
-
ospf-single
|
|
195
|
-
|
|
199
|
+
ospf-single · 单区域 OSPF
|
|
200
|
+
[curated checks]
|
|
196
201
|
[pass] neighbour-full on R1: display ospf peer brief
|
|
197
202
|
[pass] ospf-route on R1: display ip routing-table protocol ospf
|
|
198
203
|
|
|
199
204
|
accepted: 2/2 checks passed
|
|
200
205
|
```
|
|
201
206
|
|
|
202
|
-
约 30
|
|
207
|
+
约 30 个场景配置了针对性断言(OSPF 需 `Full`、BGP 需 `Established`、VRRP 需 `Master`/`Backup`、MPLS VPN 需 `Established` 与 VPN 路由表),其余场景回退为执行场景内列出的验证命令。判定逻辑位于 `src/core/acceptance.mjs` 的 `EXPECTATIONS`,断言支持 `contains`、`notContains`、`matches`、`minLines`。对应工具为 `ensp_verify`,`ensp_scenario` 会标明某场景是否具有针对性断言。
|
|
203
208
|
|
|
204
|
-
|
|
209
|
+
断言中的设备名按角色映射到实际拓扑:蓝图使用 `R1`/`R2`,课程作业可能使用 `RA`/`RB`/`RC`,校验时取第一台具备控制台的设备(`R2` 取第二台),名称不同不影响判定。
|
|
205
210
|
|
|
206
|
-
|
|
211
|
+
断言不通过时会自动重试。路由协议在命令返回之后才收敛,`ensp apply` 结束后立即验收时,OSPF 邻居通常仍处于 `ExStart` 或 `2-Way`,单次采样会误判为失败。默认等待 60 秒,可通过 `--wait` 调整,通过时注明确切等待时长:
|
|
207
212
|
|
|
208
213
|
```console
|
|
209
214
|
$ ensp verify ospf-single --topology lab.topo
|
|
@@ -213,9 +218,9 @@ $ ensp verify ospf-single --topology lab.topo
|
|
|
213
218
|
[pass] neighbour-full on R1: display ospf peer brief (converged after 27s)
|
|
214
219
|
```
|
|
215
220
|
|
|
216
|
-
|
|
221
|
+
以下两类失败不进入重试循环,重试不会改变结果:控制台不可达(设备未启动)与 VRP 拒绝命令(命令有误)。前者报告 `console unreachable: ... ECONNREFUSED`,后者报告 `VRP rejected the command`,均不伪装为断言不符。
|
|
217
222
|
|
|
218
|
-
|
|
223
|
+
推荐顺序为 `doctor`、`up`、`verify`:doctor 判定环境,up 判定设备,verify 判定配置效果。
|
|
219
224
|
|
|
220
225
|
## 安装
|
|
221
226
|
|
|
@@ -254,14 +259,16 @@ ensp status
|
|
|
254
259
|
| 项 | 要求 |
|
|
255
260
|
|---|---|
|
|
256
261
|
| 操作系统 | Windows。eNSP 仅有 Windows 版本 |
|
|
257
|
-
| eNSP |
|
|
262
|
+
| eNSP | 已安装且可正常运行 |
|
|
258
263
|
| Node.js | 18 或更高版本 |
|
|
259
|
-
| 权限 |
|
|
264
|
+
| 权限 | 以管理员身份运行本工具与 eNSP,两者需为同一权限级别 |
|
|
260
265
|
|
|
261
266
|
系统缩放设为 125% 或 150% 时,程序会自行完成坐标换算,不需要手动调分辨率。若 eNSP 升级后按钮位置改变,执行 `ensp probe` 重新标定。
|
|
262
267
|
|
|
263
268
|
## 快速开始
|
|
264
269
|
|
|
270
|
+
在管理员身份下执行(见上文“运行权限”):
|
|
271
|
+
|
|
265
272
|
```bash
|
|
266
273
|
ensp doctor # 先确认这台机器能跑起来
|
|
267
274
|
ensp preset ospf-single --topo lab.topo # 生成拓扑
|
|
@@ -295,7 +302,7 @@ ensp stop
|
|
|
295
302
|
|
|
296
303
|
仅自行使用而不对外分发时,上述要求不适用。
|
|
297
304
|
|
|
298
|
-
未选用 MIT 或 Apache-2.0
|
|
305
|
+
未选用 MIT 或 Apache-2.0,是因为两者允许二次修改后闭源,与二次修改亦须开源的要求不符。
|
|
299
306
|
|
|
300
307
|
### 致谢
|
|
301
308
|
|
package/docs/UI-ANCHORS.md
CHANGED
|
@@ -95,10 +95,10 @@
|
|
|
95
95
|
| `GetCursorPos` / `SetCursorPos` | `err=203` |
|
|
96
96
|
|
|
97
97
|
**第二层:前台锁。** 用 `Start-Process -Verb RunAs` 提到 High 之后(本机 UAC 是
|
|
98
|
-
`ConsentPromptBehaviorAdmin=0`,提升不弹窗),UIPI
|
|
99
|
-
`BringWindowToTop`
|
|
100
|
-
`SetCursorPos` 依然 `False`。原因是 Windows
|
|
101
|
-
|
|
98
|
+
`ConsentPromptBehaviorAdmin=0`,提升不弹窗),UIPI 那层放行,`SendMessage` 的 errno 从 5 变成 183,
|
|
99
|
+
`BringWindowToTop` 返回 `True`。但前台窗口仍是其他进程,`SetForegroundWindow` 依然 `False`、
|
|
100
|
+
`SetCursorPos` 依然 `False`。原因是 Windows 的前台锁:只有持有前台权限的进程才能改前台,
|
|
101
|
+
从后台启动的进程没有该权限,`AttachThreadInput` 也拿不到(`attach=False err=5`)。
|
|
102
102
|
|
|
103
103
|
已排除“不同窗口站/桌面”:`GetProcessWindowStation()` = `WinSta0`、`GetThreadDesktop()` = `Default`、
|
|
104
104
|
`OpenInputDesktop(0,false,0x0001)` 返回的桌面名也是 `Default`;所有进程 `SessionId` 均为 1,
|
|
@@ -108,12 +108,12 @@
|
|
|
108
108
|
另一条路也堵着:`PrintWindow` 从 Medium 上下文返回全白(`ok=False`),从 High 上下文**能**拍到真画布
|
|
109
109
|
(这是唯一一处提权有实质收益的地方),但拍到画面不等于能把点击送进去。
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
结论:eNSP 窗口必须由用户自行保持在最上层,并且用户处于那个交互桌面。插件能做的是尽早、
|
|
112
|
+
明确、可操作地报错,而不是点空了继续等。这也是 `ensp up` 要求启动时短暂占用前台的原因。
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
`
|
|
116
|
-
|
|
114
|
+
提权的作用需要与置顶区分开。提到 High 不会让插件取得前台权限,`SetForegroundWindow` 仍然失败,
|
|
115
|
+
所以置顶问题必须由用户解决。但提权是输入注入的前提:Medium 上下文里 `SendInput` 虽然返回成功,
|
|
116
|
+
输入队列却不变,eNSP 收不到点击;以管理员身份运行后输入注入恢复正常。因此本工具需要以管理员身份运行。
|
|
117
117
|
|
|
118
118
|
## 设备控制台
|
|
119
119
|
|
package/docs/plugin-detail.en.md
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
|
|
2
2
|
# dsh-ensp
|
|
3
3
|
|
|
4
|
-
Automation for Huawei eNSP: generate topologies, boot devices, push configuration line by line and verify every command
|
|
4
|
+
Automation for Huawei eNSP: generate topologies, boot devices, push configuration line by line, and verify the result of every command.
|
|
5
5
|
|
|
6
|
-
- Generates `.topo` files eNSP opens directly, from a scenario blueprint (devices, links and addressing included) or from custom devices and links
|
|
7
|
-
- Locates the toolbar buttons to start and stop devices, confirms each
|
|
6
|
+
- Generates `.topo` files that eNSP opens directly, from a scenario blueprint (devices, links and addressing included) or from custom devices and links
|
|
7
|
+
- Locates the toolbar buttons to start and stop devices, confirms each device individually, then minimises the window
|
|
8
8
|
- Pushes configuration one command at a time; the first error aborts the batch and reports the line, the command and the device's raw output
|
|
9
9
|
- Ships 50 scenario presets covering VLAN, STP, stacking, link aggregation, routing, BGP, MPLS, multicast, NAT, ACL, QoS, IPsec, IPv6, WLAN, firewalls and high availability
|
|
10
10
|
- Checks that every device image is installed before launching, and names the missing component instead of letting eNSP open the topology and quit silently
|
|
11
|
-
- Runs seven preflight checks (images, ports, memory, input injection)
|
|
11
|
+
- Runs seven preflight checks (images, ports, memory, input injection), each with a stated fix, then verifies the scenario against what the devices actually report
|
|
12
|
+
- Must run elevated, with the eNSP window visible (see the run-permissions section in the repository documentation)
|
|
12
13
|
- Usable as a CLI, an MCP server, or a DeepSeek Harness plugin
|
|
13
14
|
|
|
14
15
|
Scroll down and open "dsh-ensp>" under the included components to reach its settings.
|
package/docs/plugin-detail.zh.md
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
|
|
2
2
|
# dsh-ensp
|
|
3
3
|
|
|
4
|
-
面向华为 eNSP
|
|
4
|
+
面向华为 eNSP 的自动化工具:生成拓扑、启动设备、逐条下发配置,并在每条命令后核对结果。
|
|
5
5
|
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
6
|
+
- 生成 eNSP 可直接打开的 `.topo` 文件,可用场景蓝图(含设备、链路、地址规划)或自定义设备与连线
|
|
7
|
+
- 自动定位工具栏按钮完成设备启停,启动后按设备逐一确认就绪,随后最小化窗口
|
|
8
|
+
- 逐条下发配置,任一命令出错即中断,并回报行号、命令与设备原始输出
|
|
9
9
|
- 内置 50 个场景预设,覆盖 VLAN、STP、堆叠、链路聚合、路由、BGP、MPLS、组播、NAT、ACL、QoS、IPsec、IPv6、WLAN、防火墙与高可用等主题
|
|
10
|
-
-
|
|
11
|
-
-
|
|
10
|
+
- 启动前检查机型镜像是否齐全,缺镜像时说明缺失组件,避免 eNSP 打开后静默退出
|
|
11
|
+
- 提供七项环境自检(镜像、端口、内存、输入注入能力),逐条给出结论与修法;配置下发后按场景断言验收
|
|
12
|
+
- 需要以管理员身份运行,并保持 eNSP 窗口可见(详见仓库文档“运行权限”)
|
|
12
13
|
- 提供 CLI、MCP Server 与 DeepSeek Harness 插件三种调用方式
|
|
13
14
|
|
|
14
15
|
向下翻页后点击“包含的组件”内的“dsh-ensp>”进入设置界面。
|
package/package.json
CHANGED
package/src/cli/ensp.mjs
CHANGED
|
@@ -93,7 +93,9 @@ ${C.bold('EXAMPLES')}
|
|
|
93
93
|
ensp mcp
|
|
94
94
|
|
|
95
95
|
${C.bold('NOTES')}
|
|
96
|
-
· eNSP must be installed and runnable
|
|
96
|
+
· eNSP must be installed and runnable. It requires administrator rights.
|
|
97
|
+
· Run this tool elevated too: a normal-integrity process cannot inject the mouse
|
|
98
|
+
input that starts devices, and SendInput will silently report success.
|
|
97
99
|
· Starting devices briefly focuses the eNSP window (it has to be clicked),
|
|
98
100
|
then the window is minimised again. Run doctor first if a start does nothing.
|
|
99
101
|
· Readiness is verified per device by polling its console, never by sleeping.
|
package/src/core/doctor.mjs
CHANGED
|
@@ -248,7 +248,7 @@ export function doctor(options = {}) {
|
|
|
248
248
|
: `SendInput accepted ${input.sent} event(s) but the session last-input tick did not change (session ${input.session}, console session ${input.consoleSession})`,
|
|
249
249
|
input.ok
|
|
250
250
|
? undefined
|
|
251
|
-
: '
|
|
251
|
+
: 'Run the tool elevated (as administrator) from an interactive desktop session. A normal-integrity process cannot inject mouse input into eNSP, which runs at high integrity, and services or scheduled tasks cannot inject input at all.',
|
|
252
252
|
),
|
|
253
253
|
)
|
|
254
254
|
}
|