dsh-ensp 0.1.8 → 0.2.0

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 CHANGED
@@ -159,7 +159,59 @@ Bring eNSP to the front (restore it from the taskbar) and try again.
159
159
 
160
160
  还有一点:**不要用管理员身份运行本工具**。提权只让 `PrintWindow` 能拍到画布,点击照样进不去,还多过一次 UAC。
161
161
 
162
- Windows 不允许一个进程把别人的窗口提到前台,`SetWindowPos`/`ShowWindow`/`BringWindowToTop` 全返回 `ERROR_ACCESS_DENIED`,所以这里没有自动修复,只能由人把 eNSP 放到最上层。细节与实测记录见 [docs/UI-ANCHORS.md](docs/UI-ANCHORS.md)。
162
+ 还有一种情况既不是遮挡也不是坐标:某些执行上下文(服务、计划任务、SSH 会话、agent 沙箱)根本没有输入注入能力。`SendInput` 会被接受并返回成功,但 `GetLastInputInfo` 的 tick 不动,窗口一个事件都收不到。`ensp doctor` 会实测这一点,见下节。
163
+
164
+ ### 排错自检
165
+
166
+ 启动失败时最费时间的不是修,而是判断该修哪里。`ensp doctor` 把“这台机器能不能跑起来”拆成七项逐条检查,每一项都能独立判定,失败时给一句能照做的修法:
167
+
168
+ ```console
169
+ $ ensp doctor --topology lab.topo
170
+ [ok ] ensp-installed: E:\Huawei\eNSP\eNSP_Client.exe
171
+ [ok ] virtualbox: E:\VirtualBox\VBoxManage.exe
172
+ [ok ] console-ports: 2000-2100 free
173
+ [warn] memory: 949 MB free (each router needs ~256 MB)
174
+ fix: Close some applications; devices may boot very slowly or fail to start.
175
+ [ok ] device-images: AR2220 available
176
+ [FAIL] input-injection: SendInput accepted 2 event(s) but the session last-input tick did not change (session 1, console session 1)
177
+ fix: This session cannot deliver mouse input, so the eNSP toolbar button can never be
178
+ pressed. Run the tool from an interactive desktop session ...
179
+ [ok ] anchors: start (987,226) stop (1049,228)
180
+ ```
181
+
182
+ 它不启动 eNSP,只读本机文件并做一次合成输入探测,所以可以在任何失败之后、任何操作之前随手跑。`--shallow` 跳过较慢的输入探测,`--json` 输出完整结构。对应的工具是 `ensp_doctor`。
183
+
184
+ 判断顺序是固定的:exe 在不在 → VirtualBox 在不在 → 这个拓扑要的镜像齐不齐 → 控制台端口空不空 → 输入能不能进去 → 内存够不够 → 锚点合不合理。卡在哪一项,就只修那一项。
185
+
186
+ ### 验收
187
+
188
+ 配置下发成功不等于实验成功。`ensp_verify` 读 `.topo` 拿到每台设备的控制台端口,逐条执行该场景的验收命令,按输出内容判定,而不是看命令有没有报错:
189
+
190
+ ```console
191
+ $ ensp verify ospf-single --topology lab.topo
192
+ ospf-single — 单区域 OSPF
193
+ (curated checks)
194
+ [pass] neighbour-full on R1: display ospf peer brief
195
+ [pass] ospf-route on R1: display ip routing-table protocol ospf
196
+
197
+ accepted: 2/2 checks passed
198
+ ```
199
+
200
+ 约 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` 会告诉某个场景有没有专门断言。
201
+
202
+ 断言不通过时会自己重试,因为路由协议是在命令返回之后才收敛的。`ensp apply` 一结束就验收,OSPF 邻居通常还在 `ExStart` 或 `2-Way`,只取一次快照会把它报成坏的实验。默认给 60 秒(`--wait` 改),通过时会注明等了多久:
203
+
204
+ ```console
205
+ $ ensp verify ospf-single --topology lab.topo
206
+ checking neighbour-full on R1
207
+ waiting 3s for neighbour-full on R1 (not contains "Full")
208
+ ...
209
+ [pass] neighbour-full on R1: display ospf peer brief (converged after 27s)
210
+ ```
211
+
212
+ 两类失败不进重试循环,因为等下去也不会变好:控制台连不上(设备没启动)和 VRP 拒绝命令(命令写错)。前者直接说 `console unreachable: ... ECONNREFUSED`,后者说 `VRP rejected the command`,都不会伪装成“断言不符”。
213
+
214
+ 用法上先 `doctor` 再 `up` 再 `verify`:doctor 回答环境行不行,up 回答设备起没起,verify 回答网络通不通。
163
215
 
164
216
  ## 安装
165
217
 
@@ -191,7 +243,7 @@ ensp status
191
243
  }
192
244
  ```
193
245
 
194
- 提供 12 个工具:`ensp_status`、`ensp_build_topology`、`ensp_open`、`ensp_start`、`ensp_stop`、`ensp_apply`、`ensp_apply_dir`、`ensp_query`、`ensp_probe`、`ensp_scenarios`、`ensp_scenario`、`ensp_preset_config`。
246
+ 提供 14 个工具:`ensp_status`、`ensp_build_topology`、`ensp_open`、`ensp_start`、`ensp_stop`、`ensp_apply`、`ensp_apply_dir`、`ensp_query`、`ensp_probe`、`ensp_doctor`、`ensp_verify`、`ensp_scenarios`、`ensp_scenario`、`ensp_preset_config`。
195
247
 
196
248
  ## 环境要求
197
249
 
@@ -207,15 +259,12 @@ ensp status
207
259
  ## 快速开始
208
260
 
209
261
  ```bash
210
- ensp preset vlan-access # 查看场景方向
211
-
212
- node -e "import('dsh-ensp').then(async m => {
213
- await m.writeTopology('lab.topo', m.twoPcLab())
214
- })"
215
-
262
+ ensp doctor # 先确认这台机器能跑起来
263
+ ensp preset ospf-single --topo lab.topo # 生成拓扑
216
264
  ensp up lab.topo # 启动设备
217
- ensp status --topology lab.topo # 查看控制台状态
218
265
  ensp apply ./configs --topology lab.topo --save
266
+ ensp verify ospf-single --topology lab.topo # 按场景断言验收
267
+ ensp stop
219
268
  ```
220
269
 
221
270
  一次两级 OSPF 实验的完整耗时(本机实测,Windows 11、i5、系统缩放 150%):
package/docs/SCENARIOS.md CHANGED
@@ -39,6 +39,7 @@ ensp up ospf-single.topo
39
39
  - 链路:3 条
40
40
 
41
41
  生成:`ensp preset vlan-access --topo vlan-access.topo`
42
+ - 验收:`ensp verify vlan-access --topology vlan-access.topo`(2 条断言)
42
43
 
43
44
  ### trunk-interconnect — Trunk 互联与多 VLAN 透传
44
45
 
@@ -66,6 +67,7 @@ ensp up ospf-single.topo
66
67
  - 链路:3 条
67
68
 
68
69
  生成:`ensp preset trunk-interconnect --topo trunk-interconnect.topo`
70
+ - 验收:`ensp verify trunk-interconnect --topology trunk-interconnect.topo`(1 条断言)
69
71
 
70
72
  ### vlanif-routing — VLAN 间路由(三层交换机)
71
73
 
@@ -99,6 +101,7 @@ ensp up ospf-single.topo
99
101
  | SW2 | Vlanif200 | 10.0.12.2/24 | 互联 VLAN200 |
100
102
 
101
103
  生成:`ensp preset vlanif-routing --topo vlanif-routing.topo`
104
+ - 验收:`ensp verify vlanif-routing --topology vlanif-routing.topo`(2 条断言)
102
105
 
103
106
  ### stp-rstp — STP / RSTP 生成树
104
107
 
@@ -133,6 +136,7 @@ ensp up ospf-single.topo
133
136
  | SW3 | Vlanif10 | 192.168.10.253/24 | 管理地址 |
134
137
 
135
138
  生成:`ensp preset stp-rstp --topo stp-rstp.topo`
139
+ - 验收:`ensp verify stp-rstp --topology stp-rstp.topo`(2 条断言)
136
140
 
137
141
  ### link-aggregation — 链路聚合 Eth-Trunk
138
142
 
@@ -160,6 +164,7 @@ ensp up ospf-single.topo
160
164
  - 链路:4 条
161
165
 
162
166
  生成:`ensp preset link-aggregation --topo link-aggregation.topo`
167
+ - 验收:`ensp verify link-aggregation --topology link-aggregation.topo`(1 条断言)
163
168
 
164
169
  ### port-security — 端口安全与 MAC 限制
165
170
 
@@ -188,6 +193,7 @@ ensp up ospf-single.topo
188
193
  - 链路:2 条
189
194
 
190
195
  生成:`ensp preset port-security --topo port-security.topo`
196
+ - 验收:`ensp verify port-security --topology port-security.topo`(1 条断言)
191
197
 
192
198
  ### port-isolation — 端口隔离与 MUX VLAN
193
199
 
@@ -216,6 +222,7 @@ ensp up ospf-single.topo
216
222
  - 链路:3 条
217
223
 
218
224
  生成:`ensp preset port-isolation --topo port-isolation.topo`
225
+ - 验收:`ensp verify port-isolation --topology port-isolation.topo`(无专门断言,逐条跑本场景的验证命令)
219
226
 
220
227
  ### super-vlan — VLAN 聚合(Super-VLAN)
221
228
 
@@ -250,6 +257,7 @@ ensp up ospf-single.topo
250
257
  | SW1 | Vlanif30 | 192.168.30.254/24 | sub-VLAN 30 |
251
258
 
252
259
  生成:`ensp preset super-vlan --topo super-vlan.topo`
260
+ - 验收:`ensp verify super-vlan --topology super-vlan.topo`(1 条断言)
253
261
 
254
262
  ### static-route — 静态路由与默认路由
255
263
 
@@ -286,6 +294,7 @@ ensp up ospf-single.topo
286
294
  | R2 | GigabitEthernet0/0/1 | 192.168.2.254/24 | PC2 网关 |
287
295
 
288
296
  生成:`ensp preset static-route --topo static-route.topo`
297
+ - 验收:`ensp verify static-route --topology static-route.topo`(1 条断言)
289
298
 
290
299
  ### rip — RIPv1 / RIPv2
291
300
 
@@ -322,6 +331,7 @@ ensp up ospf-single.topo
322
331
  | R3 | GigabitEthernet0/0/1 | 192.168.3.254/24 | PC2 网关 |
323
332
 
324
333
  生成:`ensp preset rip --topo rip.topo`
334
+ - 验收:`ensp verify rip --topology rip.topo`(2 条断言)
325
335
 
326
336
  ### ospf-single — OSPF 单区域
327
337
 
@@ -363,6 +373,7 @@ ensp up ospf-single.topo
363
373
  | R3 | LoopBack0 | 3.3.3.3/32 | |
364
374
 
365
375
  生成:`ensp preset ospf-single --topo ospf-single.topo`
376
+ - 验收:`ensp verify ospf-single --topology ospf-single.topo`(2 条断言)
366
377
 
367
378
  ### dhcp — DHCP 服务(含中继)
368
379
 
@@ -396,6 +407,7 @@ ensp up ospf-single.topo
396
407
  | R1 | LoopBack0 | 1.1.1.1/32 | router-id |
397
408
 
398
409
  生成:`ensp preset dhcp --topo dhcp.topo`
410
+ - 验收:`ensp verify dhcp --topology dhcp.topo`(1 条断言)
399
411
 
400
412
  ### acl-filter — ACL 访问控制
401
413
 
@@ -428,6 +440,7 @@ ensp up ospf-single.topo
428
440
  | R1 | GigabitEthernet0/0/0 | 192.168.20.253/24 | 同接口从地址 |
429
441
 
430
442
  生成:`ensp preset acl-filter --topo acl-filter.topo`
443
+ - 验收:`ensp verify acl-filter --topology acl-filter.topo`(1 条断言)
431
444
 
432
445
  ### aaa-local — 本地 AAA 与设备登录
433
446
 
@@ -460,6 +473,7 @@ ensp up ospf-single.topo
460
473
  | R1 | GigabitEthernet0/0/1 | 192.168.1.254/24 | 管理网段 |
461
474
 
462
475
  生成:`ensp preset aaa-local --topo aaa-local.topo`
476
+ - 验收:`ensp verify aaa-local --topology aaa-local.topo`(1 条断言)
463
477
 
464
478
  ### vrrp-basics — VRRP 网关冗余
465
479
 
@@ -500,6 +514,7 @@ ensp up ospf-single.topo
500
514
  | SW2 | Vlanif100 | 10.0.100.2/24 | 上行互联 |
501
515
 
502
516
  生成:`ensp preset vrrp-basics --topo vrrp-basics.topo`
517
+ - 验收:`ensp verify vrrp-basics --topology vrrp-basics.topo`(2 条断言)
503
518
 
504
519
  ### network-management — 网络管理(SNMP / NTP / Syslog)
505
520
 
@@ -537,6 +552,7 @@ ensp up ospf-single.topo
537
552
  | SW1 | Vlanif30 | 10.1.30.2/24 | 设备管理地址 |
538
553
 
539
554
  生成:`ensp preset network-management --topo network-management.topo`
555
+ - 验收:`ensp verify network-management --topology network-management.topo`(1 条断言)
540
556
 
541
557
 
542
558
  ## 进阶
@@ -575,6 +591,7 @@ ensp up ospf-single.topo
575
591
  | CORE2 | Vlanif20 | 192.168.20.252/24 | VLAN20 网关(实例2 主) |
576
592
 
577
593
  生成:`ensp preset mstp-load-balance --topo mstp-load-balance.topo`
594
+ - 验收:`ensp verify mstp-load-balance --topology mstp-load-balance.topo`(无专门断言,逐条跑本场景的验证命令)
578
595
 
579
596
  ### ospf-multi-area — OSPF 多区域与 ABR
580
597
 
@@ -613,6 +630,7 @@ ensp up ospf-single.topo
613
630
  | R4 | GigabitEthernet0/0/0 | 10.0.24.4/24 | area 2 |
614
631
 
615
632
  生成:`ensp preset ospf-multi-area --topo ospf-multi-area.topo`
633
+ - 验收:`ensp verify ospf-multi-area --topology ospf-multi-area.topo`(2 条断言)
616
634
 
617
635
  ### ospf-stub-nssa — OSPF 特殊区域(Stub / NSSA)
618
636
 
@@ -649,6 +667,7 @@ ensp up ospf-single.topo
649
667
  | R4 | GigabitEthernet0/0/0 | 10.0.14.4/24 | area 2 |
650
668
 
651
669
  生成:`ensp preset ospf-stub-nssa --topo ospf-stub-nssa.topo`
670
+ - 验收:`ensp verify ospf-stub-nssa --topology ospf-stub-nssa.topo`(2 条断言)
652
671
 
653
672
  ### ospf-lsa-types — OSPF LSA 类型与区域过滤
654
673
 
@@ -696,6 +715,7 @@ ensp up ospf-single.topo
696
715
  | R4 | LoopBack0 | 4.4.4.4/32 | ASBR 外部路由 |
697
716
 
698
717
  生成:`ensp preset ospf-lsa-types --topo ospf-lsa-types.topo`
718
+ - 验收:`ensp verify ospf-lsa-types --topology ospf-lsa-types.topo`(无专门断言,逐条跑本场景的验证命令)
699
719
 
700
720
  ### ospf-virtual-link — OSPF 虚连接
701
721
 
@@ -735,6 +755,7 @@ ensp up ospf-single.topo
735
755
  | R3 | LoopBack0 | 3.3.3.3/32 | 虚拟链路的两端 router-id |
736
756
 
737
757
  生成:`ensp preset ospf-virtual-link --topo ospf-virtual-link.topo`
758
+ - 验收:`ensp verify ospf-virtual-link --topology ospf-virtual-link.topo`(无专门断言,逐条跑本场景的验证命令)
738
759
 
739
760
  ### ospf-troubleshooting — OSPF 邻居排障
740
761
 
@@ -777,6 +798,7 @@ ensp up ospf-single.topo
777
798
  | R3 | LoopBack0 | 2.2.2.2/32 | |
778
799
 
779
800
  生成:`ensp preset ospf-troubleshooting --topo ospf-troubleshooting.topo`
801
+ - 验收:`ensp verify ospf-troubleshooting --topology ospf-troubleshooting.topo`(无专门断言,逐条跑本场景的验证命令)
780
802
 
781
803
  ### nat — NAT(源 NAT / NAT Server)
782
804
 
@@ -812,6 +834,7 @@ ensp up ospf-single.topo
812
834
  | ISP | LoopBack0 | 8.8.8.8/32 | 模拟 Internet 目的地址 |
813
835
 
814
836
  生成:`ensp preset nat --topo nat.topo`
837
+ - 验收:`ensp verify nat --topology nat.topo`(1 条断言)
815
838
 
816
839
  ### ppp-hdlc — HDLC 与 PPP(含 PPPoE)
817
840
 
@@ -847,6 +870,7 @@ ensp up ospf-single.topo
847
870
  | R2 | GigabitEthernet0/0/1 | 10.0.13.2/30 | |
848
871
 
849
872
  生成:`ensp preset ppp-hdlc --topo ppp-hdlc.topo`
873
+ - 验收:`ensp verify ppp-hdlc --topology ppp-hdlc.topo`(无专门断言,逐条跑本场景的验证命令)
850
874
 
851
875
  ### ipv6 — IPv6 基础与路由
852
876
 
@@ -881,6 +905,7 @@ ensp up ospf-single.topo
881
905
  | R2 | LoopBack0 | 2001:db8:2::2/128 | |
882
906
 
883
907
  生成:`ensp preset ipv6 --topo ipv6.topo`
908
+ - 验收:`ensp verify ipv6 --topology ipv6.topo`(2 条断言)
884
909
 
885
910
  ### dhcp-snooping — DHCP Snooping 与 IPSG
886
911
 
@@ -916,6 +941,7 @@ ensp up ospf-single.topo
916
941
  | SW1 | Vlanif10 | 192.168.10.253/24 | 管理地址 |
917
942
 
918
943
  生成:`ensp preset dhcp-snooping --topo dhcp-snooping.topo`
944
+ - 验收:`ensp verify dhcp-snooping --topology dhcp-snooping.topo`(1 条断言)
919
945
 
920
946
  ### arp-security — ARP 安全(防欺骗与防攻击)
921
947
 
@@ -950,6 +976,7 @@ ensp up ospf-single.topo
950
976
  | SW1 | Vlanif10 | 192.168.10.254/24 | 网关兼 DHCP Snooping 设备 |
951
977
 
952
978
  生成:`ensp preset arp-security --topo arp-security.topo`
979
+ - 验收:`ensp verify arp-security --topology arp-security.topo`(无专门断言,逐条跑本场景的验证命令)
953
980
 
954
981
  ### qos-basics — QoS 分类标记与队列
955
982
 
@@ -988,6 +1015,7 @@ ensp up ospf-single.topo
988
1015
  | R2 | GigabitEthernet0/0/0 | 10.0.12.2/24 | |
989
1016
 
990
1017
  生成:`ensp preset qos-basics --topo qos-basics.topo`
1018
+ - 验收:`ensp verify qos-basics --topology qos-basics.topo`(1 条断言)
991
1019
 
992
1020
  ### wlan-basic — WLAN(AC + FIT AP)
993
1021
 
@@ -1021,6 +1049,7 @@ ensp up ospf-single.topo
1021
1049
  | SW1 | Vlanif100 | 192.168.100.254/24 | AP 管理网段 |
1022
1050
 
1023
1051
  生成:`ensp preset wlan-basic --topo wlan-basic.topo`
1052
+ - 验收:`ensp verify wlan-basic --topology wlan-basic.topo`(无专门断言,逐条跑本场景的验证命令)
1024
1053
 
1025
1054
  ### ospfv3-ipv6 — OSPFv3 与 IPv6 双栈
1026
1055
 
@@ -1061,6 +1090,7 @@ ensp up ospf-single.topo
1061
1090
  | R3 | LoopBack0 | 2001:db8:3::3/128 | router-id 用 IPv4 地址 |
1062
1091
 
1063
1092
  生成:`ensp preset ospfv3-ipv6 --topo ospfv3-ipv6.topo`
1093
+ - 验收:`ensp verify ospfv3-ipv6 --topology ospfv3-ipv6.topo`(1 条断言)
1064
1094
 
1065
1095
  ### isis-multi-level — IS-IS 多级别与默认路由注入
1066
1096
 
@@ -1104,6 +1134,7 @@ ensp up ospf-single.topo
1104
1134
  | R4 | LoopBack0 | 4.4.4.4/32 | |
1105
1135
 
1106
1136
  生成:`ensp preset isis-multi-level --topo isis-multi-level.topo`
1137
+ - 验收:`ensp verify isis-multi-level --topology isis-multi-level.topo`(2 条断言)
1107
1138
 
1108
1139
 
1109
1140
  ## 高级
@@ -1145,6 +1176,7 @@ ensp up ospf-single.topo
1145
1176
  | R3 | LoopBack0 | 3.3.3.3/32 | AS 200 业务网段 |
1146
1177
 
1147
1178
  生成:`ensp preset bgp-ebgp-ibgp --topo bgp-ebgp-ibgp.topo`
1179
+ - 验收:`ensp verify bgp-ebgp-ibgp --topology bgp-ebgp-ibgp.topo`(2 条断言)
1148
1180
 
1149
1181
  ### bgp-attributes — BGP 选路属性
1150
1182
 
@@ -1187,6 +1219,7 @@ ensp up ospf-single.topo
1187
1219
  | R4 | GigabitEthernet0/0/1 | 10.0.34.4/24 | |
1188
1220
 
1189
1221
  生成:`ensp preset bgp-attributes --topo bgp-attributes.topo`
1222
+ - 验收:`ensp verify bgp-attributes --topology bgp-attributes.topo`(无专门断言,逐条跑本场景的验证命令)
1190
1223
 
1191
1224
  ### bgp-aggregation — BGP 路由聚合与团体属性
1192
1225
 
@@ -1229,6 +1262,7 @@ ensp up ospf-single.topo
1229
1262
  | R1 | LoopBack2 | 10.10.3.1/24 | 聚合前明细 3 |
1230
1263
 
1231
1264
  生成:`ensp preset bgp-aggregation --topo bgp-aggregation.topo`
1265
+ - 验收:`ensp verify bgp-aggregation --topology bgp-aggregation.topo`(无专门断言,逐条跑本场景的验证命令)
1232
1266
 
1233
1267
  ### bgp-troubleshooting — BGP 邻居排障
1234
1268
 
@@ -1270,6 +1304,7 @@ ensp up ospf-single.topo
1270
1304
  | R3 | LoopBack0 | 3.3.3.3/32 | |
1271
1305
 
1272
1306
  生成:`ensp preset bgp-troubleshooting --topo bgp-troubleshooting.topo`
1307
+ - 验收:`ensp verify bgp-troubleshooting --topology bgp-troubleshooting.topo`(无专门断言,逐条跑本场景的验证命令)
1273
1308
 
1274
1309
  ### stack-istack — 交换机堆叠与 iStack
1275
1310
 
@@ -1309,6 +1344,7 @@ ensp up ospf-single.topo
1309
1344
  | SW3 | Vlanif10 | 192.168.10.253/24 | 接入设备 |
1310
1345
 
1311
1346
  生成:`ensp preset stack-istack --topo stack-istack.topo`
1347
+ - 验收:`ensp verify stack-istack --topology stack-istack.topo`(1 条断言)
1312
1348
 
1313
1349
  ### route-policy-pbr — 路由策略与策略路由
1314
1350
 
@@ -1351,6 +1387,7 @@ ensp up ospf-single.topo
1351
1387
  | R3 | LoopBack0 | 2.2.2.2/32 | 与出口 1 相同的地址,用于观察选路 |
1352
1388
 
1353
1389
  生成:`ensp preset route-policy-pbr --topo route-policy-pbr.topo`
1390
+ - 验收:`ensp verify route-policy-pbr --topology route-policy-pbr.topo`(无专门断言,逐条跑本场景的验证命令)
1354
1391
 
1355
1392
  ### bgp-route-reflector — BGP 路由反射器与联盟
1356
1393
 
@@ -1388,6 +1425,7 @@ ensp up ospf-single.topo
1388
1425
  | EXT | GigabitEthernet0/0/0 | 10.1.24.4/24 | AS 200 |
1389
1426
 
1390
1427
  生成:`ensp preset bgp-route-reflector --topo bgp-route-reflector.topo`
1428
+ - 验收:`ensp verify bgp-route-reflector --topology bgp-route-reflector.topo`(2 条断言)
1391
1429
 
1392
1430
  ### ipsec-vpn — IPsec VPN
1393
1431
 
@@ -1424,6 +1462,7 @@ ensp up ospf-single.topo
1424
1462
  | R2 | GigabitEthernet0/0/1 | 192.168.2.254/24 | 私网侧 |
1425
1463
 
1426
1464
  生成:`ensp preset ipsec-vpn --topo ipsec-vpn.topo`
1465
+ - 验收:`ensp verify ipsec-vpn --topology ipsec-vpn.topo`(无专门断言,逐条跑本场景的验证命令)
1427
1466
 
1428
1467
  ### multicast-pim-sm — 组播 PIM-SM 与 IGMP
1429
1468
 
@@ -1469,6 +1508,7 @@ ensp up ospf-single.topo
1469
1508
  | R3 | GigabitEthernet0/0/1 | 192.168.3.254/24 | 接收者网段 |
1470
1509
 
1471
1510
  生成:`ensp preset multicast-pim-sm --topo multicast-pim-sm.topo`
1511
+ - 验收:`ensp verify multicast-pim-sm --topology multicast-pim-sm.topo`(2 条断言)
1472
1512
 
1473
1513
  ### firewall-zones — 防火墙安全域与策略
1474
1514
 
@@ -1508,9 +1548,10 @@ ensp up ospf-single.topo
1508
1548
  | R-UNTRUST | GigabitEthernet0/0/0 | 200.1.1.2/24 | 外网侧 |
1509
1549
  | FW1 | GigabitEthernet1/0/2 | 10.1.40.1/24 | dmz 区域 |
1510
1550
  | SRV1 | Ethernet0/0/1 | 10.1.40.10/24 | 对外发布的服务器 |
1551
+ - 设备镜像:USG6000V 需要 eNSP 安装时勾选 USG6000V 组件(NGFW 镜像,约 1 GB)。缺镜像时 eNSP 会打开拓扑后自行退出,`ensp up` 会在启动前直接报错说明缺什么。
1511
1552
 
1512
1553
  生成:`ensp preset firewall-zones --topo firewall-zones.topo`
1513
- - 设备镜像:USG6000V 需要 eNSP 安装时勾选 USG6000V 组件(NGFW 镜像,约 1 GB)。缺镜像时 eNSP 会打开拓扑后自行退出,`ensp up` 会在启动前直接报错说明缺什么。
1554
+ - 验收:`ensp verify firewall-zones --topology firewall-zones.topo`(无专门断言,逐条跑本场景的验证命令)
1514
1555
 
1515
1556
  ### bfd-fast-convergence — BFD 快速故障检测
1516
1557
 
@@ -1553,6 +1594,7 @@ ensp up ospf-single.topo
1553
1594
  | R3 | LoopBack0 | 3.3.3.3/32 | |
1554
1595
 
1555
1596
  生成:`ensp preset bfd-fast-convergence --topo bfd-fast-convergence.topo`
1597
+ - 验收:`ensp verify bfd-fast-convergence --topology bfd-fast-convergence.topo`(无专门断言,逐条跑本场景的验证命令)
1556
1598
 
1557
1599
  ### mpls-basic — MPLS 标签转发
1558
1600
 
@@ -1597,6 +1639,7 @@ ensp up ospf-single.topo
1597
1639
  | R4 | GigabitEthernet0/0/0 | 10.0.34.4/24 | |
1598
1640
 
1599
1641
  生成:`ensp preset mpls-basic --topo mpls-basic.topo`
1642
+ - 验收:`ensp verify mpls-basic --topology mpls-basic.topo`(2 条断言)
1600
1643
 
1601
1644
  ### mpls-l3vpn — BGP/MPLS L3VPN
1602
1645
 
@@ -1643,6 +1686,7 @@ ensp up ospf-single.topo
1643
1686
  | CE2 | GigabitEthernet0/0/0 | 192.168.1.20/24 | |
1644
1687
 
1645
1688
  生成:`ensp preset mpls-l3vpn --topo mpls-l3vpn.topo`
1689
+ - 验收:`ensp verify mpls-l3vpn --topology mpls-l3vpn.topo`(2 条断言)
1646
1690
 
1647
1691
  ### dual-homed-isp — 双出口多运营商选路
1648
1692
 
@@ -1683,6 +1727,7 @@ ensp up ospf-single.topo
1683
1727
  | ISP1 | LoopBack0 | 8.8.8.8/32 | 仅 ISP1 宣告,用于观察回程选路 |
1684
1728
 
1685
1729
  生成:`ensp preset dual-homed-isp --topo dual-homed-isp.topo`
1730
+ - 验收:`ensp verify dual-homed-isp --topology dual-homed-isp.topo`(无专门断言,逐条跑本场景的验证命令)
1686
1731
 
1687
1732
  ### firewall-hrp — 防火墙双机热备(HRP)
1688
1733
 
@@ -1726,9 +1771,10 @@ ensp up ospf-single.topo
1726
1771
  | FW2 | GigabitEthernet1/0/2 | 10.1.252.2/24 | |
1727
1772
  | R-UP | GigabitEthernet0/0/0 | 10.1.250.10/24 | 外网侧 |
1728
1773
  | R-DOWN | GigabitEthernet0/0/0 | 10.1.249.10/24 | 内网侧 |
1774
+ - 设备镜像:USG6000V 需要 eNSP 安装时勾选 USG6000V 组件(NGFW 镜像,约 1 GB)。缺镜像时 eNSP 会打开拓扑后自行退出,`ensp up` 会在启动前直接报错说明缺什么。
1729
1775
 
1730
1776
  生成:`ensp preset firewall-hrp --topo firewall-hrp.topo`
1731
- - 设备镜像:USG6000V 需要 eNSP 安装时勾选 USG6000V 组件(NGFW 镜像,约 1 GB)。缺镜像时 eNSP 会打开拓扑后自行退出,`ensp up` 会在启动前直接报错说明缺什么。
1777
+ - 验收:`ensp verify firewall-hrp --topology firewall-hrp.topo`(无专门断言,逐条跑本场景的验证命令)
1732
1778
 
1733
1779
  ### spine-leaf-vxlan — Spine-Leaf 与 VXLAN 大二层
1734
1780
 
@@ -1771,6 +1817,7 @@ ensp up ospf-single.topo
1771
1817
  | LEAF2 | Vlanif10 | 192.168.10.253/24 | |
1772
1818
 
1773
1819
  生成:`ensp preset spine-leaf-vxlan --topo spine-leaf-vxlan.topo`
1820
+ - 验收:`ensp verify spine-leaf-vxlan --topology spine-leaf-vxlan.topo`(无专门断言,逐条跑本场景的验证命令)
1774
1821
 
1775
1822
  ### ipsec-gre-tunnel — IPsec 与 GRE 隧道组合
1776
1823
 
@@ -1812,6 +1859,7 @@ ensp up ospf-single.topo
1812
1859
  | R2 | Tunnel0/0/0 | 10.1.1.2/24 | |
1813
1860
 
1814
1861
  生成:`ensp preset ipsec-gre-tunnel --topo ipsec-gre-tunnel.topo`
1862
+ - 验收:`ensp verify ipsec-gre-tunnel --topology ipsec-gre-tunnel.topo`(无专门断言,逐条跑本场景的验证命令)
1815
1863
 
1816
1864
  ### wlan-roaming — WLAN 漫游与 AC 高可用
1817
1865
 
@@ -1850,6 +1898,7 @@ ensp up ospf-single.topo
1850
1898
  | SW2 | Vlanif100 | 192.168.100.253/24 | |
1851
1899
 
1852
1900
  生成:`ensp preset wlan-roaming --topo wlan-roaming.topo`
1901
+ - 验收:`ensp verify wlan-roaming --topology wlan-roaming.topo`(无专门断言,逐条跑本场景的验证命令)
1853
1902
 
1854
1903
  ### campus-network — 园区网综合(双核心 + 接入 + 出口)
1855
1904
 
@@ -1897,6 +1946,7 @@ ensp up ospf-single.topo
1897
1946
  | FW1 | GigabitEthernet1/0/1 | 10.1.250.254/24 | untrust 区域 |
1898
1947
  | FW1 | GigabitEthernet1/0/2 | 10.1.40.1/24 | dmz 区域 |
1899
1948
  | SRV1 | Ethernet0/0/1 | 10.1.40.10/24 | 对外发布服务器 |
1949
+ - 设备镜像:USG6000V 需要 eNSP 安装时勾选 USG6000V 组件(NGFW 镜像,约 1 GB)。缺镜像时 eNSP 会打开拓扑后自行退出,`ensp up` 会在启动前直接报错说明缺什么。
1900
1950
 
1901
1951
  生成:`ensp preset campus-network --topo campus-network.topo`
1902
- - 设备镜像:USG6000V 需要 eNSP 安装时勾选 USG6000V 组件(NGFW 镜像,约 1 GB)。缺镜像时 eNSP 会打开拓扑后自行退出,`ensp up` 会在启动前直接报错说明缺什么。
1952
+ - 验收:`ensp verify campus-network --topology campus-network.topo`(无专门断言,逐条跑本场景的验证命令)
@@ -8,6 +8,7 @@ Automation for Huawei eNSP: generate topologies, boot devices, push configuratio
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) that each name the fix, then verifies the scenario against what the devices actually report instead of trusting that commands were accepted
11
12
  - Usable as a CLI, an MCP server, or a DeepSeek Harness plugin
12
13
 
13
14
  Scroll down and open "dsh-ensp>" under the included components to reach its settings.
@@ -8,6 +8,7 @@
8
8
  - 逐条下发配置,任一命令出错即中断并回报行号、命令与设备原始输出
9
9
  - 内置 50 个场景预设,覆盖 VLAN、STP、堆叠、链路聚合、路由、BGP、MPLS、组播、NAT、ACL、QoS、IPsec、IPv6、WLAN、防火墙与高可用等主题
10
10
  - 启动前检查机型镜像是否齐全,缺镜像时直接说明缺哪个组件,而不是让 eNSP 打开后静默退出
11
+ - 七项环境自检(镜像、端口、内存、输入注入能力)逐条给结论与修法,配置下发后再按场景断言验收,而不是只看命令有没有报错
11
12
  - 提供 CLI、MCP Server 与 DeepSeek Harness 插件三种调用方式
12
13
 
13
14
  向下翻页后点击“包含的组件”内的“dsh-ensp>”进入设置界面。
package/package.json CHANGED
@@ -1,70 +1,70 @@
1
- {
2
- "name": "dsh-ensp",
3
- "version": "0.1.8",
4
- "description": "Automate Huawei eNSP labs: generate .topo files, start and stop devices, and push configuration one command at a time with per-command error reporting.",
5
- "keywords": [
6
- "dsh",
7
- "dsh-plugin",
8
- "deepseek-harness",
9
- "ensp",
10
- "huawei",
11
- "vrp",
12
- "network-simulation",
13
- "mcp",
14
- "automation"
15
- ],
16
- "type": "module",
17
- "license": "GPL-3.0-or-later",
18
- "main": "./src/dsh/index.mjs",
19
- "exports": {
20
- ".": "./src/dsh/index.mjs",
21
- "./dsh": "./src/dsh/index.mjs",
22
- "./core": "./src/core/index.mjs",
23
- "./topology": "./src/core/topology.mjs",
24
- "./build": "./src/core/build.mjs",
25
- "./console": "./src/core/console.mjs",
26
- "./launcher": "./src/core/launcher.mjs",
27
- "./provision": "./src/core/provision.mjs",
28
- "./presets": "./src/core/presets.mjs",
29
- "./calibrate": "./src/core/calibrate.mjs",
30
- "./mcp": "./src/mcp/server.mjs"
31
- },
32
- "bin": {
33
- "ensp": "src/cli/ensp.mjs",
34
- "dsh-ensp-mcp": "src/mcp/server.mjs"
35
- },
36
- "files": [
37
- "src",
38
- "docs",
39
- "scripts",
40
- "cordis.patch.yml",
41
- "screenshots.json",
42
- "README.md",
43
- "LICENSE"
44
- ],
45
- "scripts": {
46
- "test": "node --test tests/core.test.mjs",
47
- "probe": "node src/cli/ensp.mjs probe",
48
- "docs": "node scripts/gen-scenarios-doc.mjs",
49
- "docs:check": "node scripts/gen-scenarios-doc.mjs --check"
50
- },
51
- "engines": {
52
- "node": ">=18"
53
- },
54
- "dsh": {
55
- "bundle": {
56
- "patch": "./cordis.patch.yml"
57
- }
58
- },
59
- "author": {
60
- "name": "lizi600jin"
61
- },
62
- "repository": {
63
- "type": "git",
64
- "url": "git+https://github.com/lizi600jin/dsh-ensp.git"
65
- },
66
- "homepage": "https://github.com/lizi600jin/dsh-ensp#readme",
67
- "bugs": {
68
- "url": "https://github.com/lizi600jin/dsh-ensp/issues"
69
- }
70
- }
1
+ {
2
+ "name": "dsh-ensp",
3
+ "version": "0.2.0",
4
+ "description": "Automate Huawei eNSP labs: generate .topo files, start and stop devices, and push configuration one command at a time with per-command error reporting.",
5
+ "keywords": [
6
+ "dsh",
7
+ "dsh-plugin",
8
+ "deepseek-harness",
9
+ "ensp",
10
+ "huawei",
11
+ "vrp",
12
+ "network-simulation",
13
+ "mcp",
14
+ "automation"
15
+ ],
16
+ "type": "module",
17
+ "license": "GPL-3.0-or-later",
18
+ "main": "./src/dsh/index.mjs",
19
+ "exports": {
20
+ ".": "./src/dsh/index.mjs",
21
+ "./dsh": "./src/dsh/index.mjs",
22
+ "./core": "./src/core/index.mjs",
23
+ "./topology": "./src/core/topology.mjs",
24
+ "./build": "./src/core/build.mjs",
25
+ "./console": "./src/core/console.mjs",
26
+ "./launcher": "./src/core/launcher.mjs",
27
+ "./provision": "./src/core/provision.mjs",
28
+ "./presets": "./src/core/presets.mjs",
29
+ "./calibrate": "./src/core/calibrate.mjs",
30
+ "./mcp": "./src/mcp/server.mjs"
31
+ },
32
+ "bin": {
33
+ "ensp": "src/cli/ensp.mjs",
34
+ "dsh-ensp-mcp": "src/mcp/server.mjs"
35
+ },
36
+ "files": [
37
+ "src",
38
+ "docs",
39
+ "scripts",
40
+ "cordis.patch.yml",
41
+ "screenshots.json",
42
+ "README.md",
43
+ "LICENSE"
44
+ ],
45
+ "scripts": {
46
+ "test": "node --test tests/core.test.mjs",
47
+ "probe": "node src/cli/ensp.mjs probe",
48
+ "docs": "node scripts/gen-scenarios-doc.mjs",
49
+ "docs:check": "node scripts/gen-scenarios-doc.mjs --check"
50
+ },
51
+ "engines": {
52
+ "node": ">=18"
53
+ },
54
+ "dsh": {
55
+ "bundle": {
56
+ "patch": "./cordis.patch.yml"
57
+ }
58
+ },
59
+ "author": {
60
+ "name": "lizi600jin"
61
+ },
62
+ "repository": {
63
+ "type": "git",
64
+ "url": "git+https://github.com/lizi600jin/dsh-ensp.git"
65
+ },
66
+ "homepage": "https://github.com/lizi600jin/dsh-ensp#readme",
67
+ "bugs": {
68
+ "url": "https://github.com/lizi600jin/dsh-ensp/issues"
69
+ }
70
+ }
@@ -18,6 +18,7 @@ import { fileURLToPath } from 'node:url'
18
18
  import { SCENARIOS, SCENARIO_IDS, byLevel } from '../src/core/presets.mjs'
19
19
  import { LABS, LAB_IDS, hasLab, labAddressing, labDevices, labModels } from '../src/core/labs.mjs'
20
20
  import { imageNotesFor } from '../src/core/compat.mjs'
21
+ import { hasChecks, EXPECTATIONS } from '../src/core/acceptance.mjs'
21
22
 
22
23
  const here = path.dirname(fileURLToPath(import.meta.url))
23
24
  const root = path.resolve(here, '..')
@@ -128,9 +129,13 @@ function render(catalogue = SCENARIOS) {
128
129
  out.push(`| ${row.device} | ${row.port} | ${row.ip} | ${row.note || ''} |`)
129
130
  }
130
131
  }
131
- out.push('', `生成:\`ensp preset ${id} --topo ${id}.topo\``)
132
132
  const notes = imageNotesFor(labModels(id))
133
133
  for (const [model, note] of notes) out.push(`- 设备镜像:${model} ${note}`)
134
+ out.push('', `生成:\`ensp preset ${id} --topo ${id}.topo\``)
135
+ const verifyLine = hasChecks(id)
136
+ ? `- 验收:\`ensp verify ${id} --topology ${id}.topo\`(${EXPECTATIONS[id].length} 条断言)`
137
+ : `- 验收:\`ensp verify ${id} --topology ${id}.topo\`(无专门断言,逐条跑本场景的验证命令)`
138
+ out.push(verifyLine)
134
139
  }
135
140
  out.push('')
136
141
  }