feat(controller-status): ctrlstatus client command (task 4.1)
This commit is contained in:
parent
03813bf560
commit
9e87d2c92e
2 changed files with 123 additions and 1 deletions
|
|
@ -43,7 +43,7 @@
|
|||
- _Depends: 3.1_
|
||||
|
||||
- [ ] 4. Test client command + wait-primary integration
|
||||
- [ ] 4.1 Add the `ctrlstatus` client command
|
||||
- [x] 4.1 Add the `ctrlstatus` client command
|
||||
- Add a client command that issues the any-node status call and prints the fields in human-readable form: the current primary, the answering node framed as "answered by <node> (<role>)" distinct from the primary, the configured controllers and count, the loaded config version and committed config version, the content checksum as hex, term, commit/apply positions, fenced state, and cluster name; render an empty primary as "unknown". The command exit status reflects success or failure of the query.
|
||||
- Observable: piping `ctrlstatus` through the client prints the status fields (with "answered by" and "unknown" rendering) and exits zero on success / non-zero with the error printed on failure.
|
||||
- _Requirements: 1.3, 3.3, 5.1, 5.2, 8.1, 8.2, 8.3_
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ extern int cmd_echo(int, char*[]);
|
|||
extern int cmd_expect_jobs(int, char*[]);
|
||||
extern int cmd_expect_job(int, char*[]);
|
||||
extern int cmd_wait_primary(int, char*[]);
|
||||
extern int cmd_ctrlstatus(int, char*[]);
|
||||
static int worker_house_keeping(void*);
|
||||
|
||||
/* Session verdict / loop state (xce-test-e2e-primitives task 1.1).
|
||||
|
|
@ -208,6 +209,7 @@ static command_t client_commands[] = {
|
|||
{ "expect-job", cmd_expect_job, "assert a JobId is present" },
|
||||
{ "wait-primary", cmd_wait_primary,
|
||||
"wait until a primary serves [timeout_ms]" },
|
||||
{ "ctrlstatus", cmd_ctrlstatus, "show controller/cluster status" },
|
||||
{ "shutdown", cmd_shutdown, "shutdown xce controller" },
|
||||
{ "jobrun", cmd_jobrun, "run a job" },
|
||||
{ "jobsub", cmd_jobsub, "submit a job" },
|
||||
|
|
@ -1191,6 +1193,126 @@ int cmd_wait_primary(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
/* Map a ctrl_role_t raw value (CtrlStatus.responderRole, see ha.h:60-63 and
|
||||
* design.md "Schema — reply payload") to a display string. PRIMARY==0,
|
||||
* STANDBY==1, INIT==2, ELECTING==3; anything else is reported verbatim so an
|
||||
* unexpected role is never silently rendered as a known one. */
|
||||
static const char* ctrlstatus_role_str(uint8_t role)
|
||||
{
|
||||
switch (role) {
|
||||
case 0:
|
||||
return "primary";
|
||||
case 1:
|
||||
return "standby";
|
||||
case 2:
|
||||
return "initializing";
|
||||
case 3:
|
||||
return "electing";
|
||||
default:
|
||||
return "unknown-role";
|
||||
}
|
||||
}
|
||||
|
||||
/* `ctrlstatus` (controller-status task 4.1, Req 1.3/3.3/5.1/5.2/8.1/8.2/8.3,
|
||||
* design.md "cmd_ctrlstatus (test client) — State contract").
|
||||
*
|
||||
* Issues the any-node status read (xcecli_ctrlstatus, is_write=false: whatever
|
||||
* controller answers — primary or standby hint view — rides the configured
|
||||
* failover/rotation) and prints the identity/health fields in human-readable
|
||||
* form.
|
||||
*
|
||||
* On failure (no reachable controller etc.) it prints a typed error and returns
|
||||
* the negative rc so the session records the command as failed and exits
|
||||
* non-zero (Req 8.3). On success it prints the fields and returns 0 (Req 8.2). */
|
||||
int cmd_ctrlstatus(int argc, char* argv[])
|
||||
{
|
||||
xce_ctrlstatus_t* status = NULL;
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
(void)argv;
|
||||
|
||||
if (argc != 1) {
|
||||
printf("ctrlstatus\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = xcecli_ctrlstatus(active_ctx->ctx, &status);
|
||||
|
||||
if (rc < 0) {
|
||||
char ebuf[128];
|
||||
|
||||
ebuf[0] = '\0';
|
||||
xce_strerror_r(-rc, ebuf, sizeof(ebuf));
|
||||
SET_ERROR(-rc);
|
||||
|
||||
switch (-rc) {
|
||||
case E_XCE_NOMASTER:
|
||||
fprintf(stderr, "ctrlstatus failed: no-master (%s)\n", ebuf);
|
||||
break;
|
||||
case E_XCE_NOT_READY:
|
||||
fprintf(stderr, "ctrlstatus failed: not-ready (%s)\n", ebuf);
|
||||
break;
|
||||
case ETIMEDOUT:
|
||||
fprintf(stderr, "ctrlstatus failed: timeout (%s)\n", ebuf);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "ctrlstatus failed: %s\n", ebuf);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Current primary (Req 2.x): an empty primaryName means no elected/known
|
||||
* primary — render the well-defined "unknown" (Req 1.3/2.2/2.3) rather than
|
||||
* an empty or stale value. */
|
||||
printf("Primary: %s\n",
|
||||
NULLSTR(status->primaryName) ? "unknown" : status->primaryName);
|
||||
|
||||
/* Answering node + role, framed as a property of the responder and kept
|
||||
* DISTINCT from the authoritative Primary line above (Req 3.1/3.2/3.3): a
|
||||
* transient responder role (electing/initializing) must not be misread as
|
||||
* the cluster's primary state. */
|
||||
printf("answered by %s (%s)\n",
|
||||
NULLSTR(status->responderName) ? "unknown" : status->responderName,
|
||||
ctrlstatus_role_str(status->responderRole));
|
||||
|
||||
printf("Cluster: %s\n",
|
||||
NULLSTR(status->clusterName) ? "unknown" : status->clusterName);
|
||||
|
||||
/* Configured controller topology + count (Req 4.1/4.2). */
|
||||
printf("Controllers (%u):\n", status->peerCount);
|
||||
for (i = 0; i < status->peers.count; i++) {
|
||||
xce_ctrlpeer_t* peer = status->peers.list[i];
|
||||
|
||||
if (peer == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\t%s\t%s:%u\n", NULLSTR(peer->name) ? "?" : peer->name,
|
||||
NULLSTR(peer->host) ? "?" : peer->host, peer->port);
|
||||
}
|
||||
|
||||
/* Config version + committed config version (Req 5.1) and the content
|
||||
* checksum as the hex string the controller already exposes (Req 5.2). */
|
||||
printf("configVersion: %llu\n", (unsigned long long)status->configVersion);
|
||||
printf("committedConfigVersion: %llu\n",
|
||||
(unsigned long long)status->committedConfigVersion);
|
||||
printf("configChecksum: %s\n",
|
||||
NULLSTR(status->configChecksum) ? "unknown" : status->configChecksum);
|
||||
|
||||
/* HA health / progress (Req 6.x). */
|
||||
printf("term: %llu\n", (unsigned long long)status->term);
|
||||
printf("committedLsn: %llu\n", (unsigned long long)status->committedLsn);
|
||||
printf("appliedLsn: %llu\n", (unsigned long long)status->appliedLsn);
|
||||
printf("fenced: %s\n", status->fenced ? "true" : "false");
|
||||
|
||||
xcecli_free_ctrlstatus(status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_jobinfo(xce_job_t* job)
|
||||
{
|
||||
char idstring[128];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue