feat: P0-2a C-side plumbing for host control

Add the full call chain for host control operations from the Go API
server through the C library to the controller:

- schema/controller.capnp: HostControl struct + hostctrlmsg @21
  in Request.body union
- include/typemap.h: xce_hostctrl_t* hostctrlmsg in body union
  (placed after @20 clrpreasonmsg, matching capnp ordinal)
- include/client.h, xceapi.h, request.h: declarations for
  xcecli_hostctrl, xce_hostctrl, xce_hostctrl_req
- lib/client.c: xcecli_hostctrl (validate + delegate to xce_hostctrl)
- lib/xceapi.c: xce_hostctrl (validate ctx state + send + wait reply)
- lib/request.c: xce_hostctrl_req (validate hostname/empty/nil,
  accept only HOST_OPEN/HOST_CLOSE, reject HOST_TAG/UNTAG)
- lib/helper.c: Request_body_hostctrlmsg cases in
  xce_request_body() and xce_request_msg_name()
- controller/cluster.c: OPCode_hostcontrol dispatch
- controller/include/cluster.h: do_hostcontrol_op declaration
- controller/worker.c: do_hostcontrol_op + fix pre-existing
  goto-clean bug in worker_ctrl that leaked write lock and
  reference on HOST_OPEN/HOST_CLOSE no-op paths

TDD: 8 xce_hostctrl_req validation tests (null ep, null ctrl,
null/empty hostname, HOST_DO_NONE no-op, HOST_TAG/UNTAG reject,
negative action reject, HOST_OPEN/CLOSE accept via xce_request).

116/116 xcelib tests pass. CGO_ENABLED=0 Go backend tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-04-17 07:46:41 +00:00
parent ac7ac99ced
commit dcb1b4fe25
15 changed files with 187 additions and 4 deletions

View file

@ -844,6 +844,37 @@ int xce_queuectrl_req(endpoint_t* ep, xce_queuectrl_t* ctrlinfo)
return xce_request(ep, &request);
}
int xce_hostctrl_req(endpoint_t* ep, xce_hostctrl_t* ctrlinfo)
{
/* clang-format off */
xce_request_t request = {
.opcode = OPCode_hostcontrol,
.body_which = Request_body_hostctrlmsg,
.body = {
.hostctrlmsg = ctrlinfo
}
};
/* clang-format on */
if ((ep == NULL) || (ctrlinfo == NULL)) {
return -EINVAL;
}
if ((ctrlinfo->hostname == NULL) || (strlen(ctrlinfo->hostname) == 0)) {
return -EINVAL;
}
if (ctrlinfo->action == HOST_DO_NONE) {
return 0;
}
if (ctrlinfo->action != HOST_OPEN && ctrlinfo->action != HOST_CLOSE) {
return -EINVAL;
}
return xce_request(ep, &request);
}
int xce_runtask_req(endpoint_t* ep, xce_taskrun_t* runinfo)
{
/* clang-format off */