绕过前端直接调度华为云 KooLabs 云实验:从 Vue 路由到调度 API
想用脚本把云实验跑起来,第一反应是自动化点页面。我在这上面卡了两天,最后发现页面根本不是"点"的问题——卡片是 Vue 路由渲染的,`a[href]` 里只有分享按钮,点标题、点卡片容器、用 JS 找 `cursor:pointer` 的祖先再点,URL 始终停在 `/lab/`,路由一步都不跳。
真正的入口在接口层。记一下这条链路,都是实测出来的。
## 一、先找到鉴权 token 藏在哪
云实验的接口域是 `data.edu.huaweicloud.com`,但它**不用** `X-Auth-Token`。打开 `/lab` 页面后执行:
```javascript
sessionStorage.getItem('setToken')
```
拿到一个 685 字符的 JWT。这个值挂在自定义头里:
```
auth-token:
```
注意是 `auth-token`,全小写带连字符,和华为云 OpenAPI 的 `X-Auth-Token` 完全是两套东西。用错头会直接 401 或 403,而且错误信息不会告诉你头名写错了。
## 二、实验列表和剩余名额
两个不同前缀,很容易混:
```
GET /rest/developer/user/hdsandboxexpservice/v1/ware
→ {"result":{"experiment_list":[{"id":2325,"title":"10分钟入门装载国产操作系统的ECS",...}]}}
GET /rest/developer/servlet/hdsandboxuserservice/v1/
→ {"result":[{"experiment_id":2325,"free_quota":13},{"experiment_id":2417,"free_quota":33}]}
```
`free_quota` 是当日免费名额。这个数字每天刷新,是为后面埋的坑。
另外 `/rest/developer/servlet/hdsandboxexpservice/v1/s...`(被截断的那个)返回的是实验方向分类,不是实验本体,别拿错。
## 三、调度接口:全部是 POST
调度前缀是 `/rest/developer/user/hdsandboxschedulerservice/exercise`。这里有个反直觉的地方——**所有 GET 都返回 405**:
```
GET /exercise/2325/check-operation-status → 404
GET /exercise/check-operation-status?experiment_id=2325 → 405 Method Not Allowed
POST /exercise/check-operation-status?experiment_id=2325 → 200
```
405 是个好信号,它说明路径是对的,只是方法错了。404 反而说明路径本身不对。排障时先看状态码能省很多时间。
`POST /check-operation-status` 返回:
```json
{"result":{"remainUserTimes":2067,"preOccupyFreeSlots":true,
"operationStatisticsId":null,"spotsEnough":false,
"experiment_spot":0,"price":5,"times":3600}}
```
`price: 5` 是消耗的**实验点**(平台赠送的虚拟额度,不是钱),`times: 3600` 是可用时长(秒)。
启动:
```
POST /exercise/start {"experiment_id": 2325}
→ {"result": 504107}
```
返回的 `504107` 是 `operationStatisticsId`,即本次实验会话的 ID。
之后轮询实例:
```
POST /exercise/get-instance-info {"experiment_id": 2325}
```
实例就绪时 `result.instance_info` 会从 `null` 变成对象,分配期间一直是:
```json
{"result":{"instance_info":null,"stop_query_result":null,"account":null,"status":"0"}}
```
这个 `status: "0"` 很关键——它不是"正常",是"还没分配"。我第一次误判成启动成功,白等五分钟。
拿到实例后取免密登录链接:
```
POST /exercise/get-login-link {"experiment_id": 2325}
```
失败时会返回 `HD.314710026: cannot binding lab instance`,意思就是"实例还没绑到你身上",回到上一步继续等。
## 四、结束实验:字段名是下划线
结束接口有个坑,错误信息很误导:
```
POST /exercise/end {"experiment_id": 2325, "doneScene": 2}
→ 400 {"error_msg":"Invalid param error;doneScene 不能为空"}
```
明明传了 `doneScene`,它还说"不能为空"。换成下划线就好了:
```
POST /exercise/end {"experiment_id": 2325, "done_scene": 2}
→ 200 {"result": null}
```
`result: null` 就是成功。参数名是 `done_scene`,报错信息里的驼峰是后端框架自动转出来的,照着报错改参数名会被带偏。
我也试过把参数放 query:
```
POST /exercise/end?experiment_id=2325&doneScene=2
→ 400 {"error_msg":"Invalid param error, cannot convert the request"}
```
"cannot convert the request" 说明类型转换失败,通常意味着参数该在 body 里。这两个错误的区分挺有用:**「不能为空」是字段名不对,「无法转换」是位置不对**。
## 五、几个错误码的含义
| 错误码 | 含义 | 怎么处理 |
|---|---|---|
| `HD.31400001 Not Found` | 路径不对 | 换路径,别改方法 |
| `HD.31400001 Method Not Allowed` | 方法不对 | GET 换 POST |
| `HD.31420014 reduce lab points fail no auth do lab` | 扣实验点失败 | 当日免费名额耗尽,或账号无实验权限 |
| `HD.31420023 lab instance not exist or has end` | 实例不存在/已结束 | 会话过期或被回收 |
| `HD.314710026 cannot binding lab instance` | 实例未绑定 | 还没分配成功,继续轮询 |
`HD.31420014` 这个最坑:它不是"点数不够",`remainUserTimes` 显示还有 2067,但当日 `free_quota` 用完后,付费通道又走不通,就报这个。换句话说**免费名额是每日上限,不是余额扣减**。
## 六、一个实践上的建议
如果你的目标只是"让任务算完成",注意平台判定的是**实验操作行为**,不是"启动"这个动作本身。我启动过两次实验,成长中心的任务状态一直是未完成——因为环境里的任务(比如创建 VPC)没做。所以光调通 `start` 不够,得真的进沙箱把实验手册里的步骤走完。
反过来,`end` 一定要调。不调的话会话会挂到时长上限(`times: 3600`)才回收,期间那门实验的名额一直被你占着,当天想再开一门就会撞上 `HD.31420014`。这是我踩过的最贵的坑——自己把名额堵死了。
- 点赞
- 收藏
- 关注作者
评论(0)