forked from lei.chen/myxce
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>
937 lines
22 KiB
C
937 lines
22 KiB
C
#include <errno.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#include "mylock.h"
|
|
#include "netio.h"
|
|
#include "request.h"
|
|
#include "typemap.h"
|
|
#include "utils.h"
|
|
#include "xce/types.h"
|
|
|
|
#define REQUEST_FROM(req) \
|
|
((req)->from == NULL) \
|
|
? "Unknown" \
|
|
: (((req)->from->name == NULL) ? "Unknown" : (req->from->name))
|
|
|
|
int xce_encode(xce_request_t* req, io_packet_t* pkt)
|
|
{
|
|
struct capn c;
|
|
struct Request rq;
|
|
struct capn_segment* cs;
|
|
Request_ptr rp;
|
|
int rc;
|
|
|
|
TRACE("%s request op %d seq %ld from %s", __func__, req->opcode, req->seq,
|
|
REQUEST_FROM(req));
|
|
|
|
capn_init_malloc(&c);
|
|
cs = capn_root(&c).seg;
|
|
|
|
encode_Request(cs, &rq, req);
|
|
|
|
cs = capn_root(&c).seg;
|
|
rp = new_Request(cs);
|
|
write_Request(&rq, rp);
|
|
|
|
capn_setp(capn_root(&c), 0, rp.p);
|
|
|
|
pkt->sz = capn_size(&c);
|
|
rc = alloc_packet(pkt);
|
|
if (rc < 0) {
|
|
capn_free(&c);
|
|
return -errno;
|
|
}
|
|
|
|
capn_write_mem(&c, (uint8_t*)pkt->data, pkt->sz, 0);
|
|
capn_free(&c);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int xce_decode(io_packet_t* pkt, xce_request_t* req)
|
|
{
|
|
struct capn c;
|
|
struct Request rq;
|
|
Request_ptr rp;
|
|
|
|
capn_init_mem(&c, (const uint8_t*)pkt->data, pkt->sz, 0);
|
|
rp.p = capn_getp(capn_root(&c), 0, 1);
|
|
|
|
read_Request(&rq, rp);
|
|
|
|
decode_Request(req, &rq);
|
|
|
|
TRACE("%s request op %d seq %ld from %s", __func__, req->opcode, req->seq,
|
|
REQUEST_FROM(req));
|
|
capn_free(&c);
|
|
|
|
free_packet(pkt);
|
|
FREEUP(pkt);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void init_reply_by_req(xce_reply_t* reply, xce_request_t* req)
|
|
{
|
|
reply->seq = req->seq;
|
|
reply->opcode = req->opcode;
|
|
}
|
|
|
|
int xce_request(endpoint_t* ep, xce_request_t* req)
|
|
{
|
|
int rc;
|
|
io_packet_t* pkt;
|
|
|
|
pkt = (io_packet_t*)calloc(1, sizeof(*pkt));
|
|
if (pkt == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
req->seq = endpoint_getseq(ep);
|
|
req->from = ep->peer;
|
|
|
|
rc = xce_encode(req, pkt);
|
|
if (rc < 0) {
|
|
free_packet(pkt);
|
|
free(pkt);
|
|
|
|
return rc;
|
|
}
|
|
|
|
endpoint_enq(ep, &(pkt->link));
|
|
return 0;
|
|
}
|
|
|
|
int xce_reply(endpoint_t* ep, xce_peerinfo_t* from, xce_reply_t* reply)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_reply,
|
|
.body_which = Request_body_replymsg,
|
|
};
|
|
/* clang-format on */
|
|
int rc;
|
|
io_packet_t* pkt;
|
|
|
|
TRACE("%s seq %lu opcode %d status %d data which %d", __func__, reply->seq,
|
|
reply->opcode, reply->status, reply->data_which);
|
|
|
|
pkt = (io_packet_t*)calloc(1, sizeof(*pkt));
|
|
if (pkt == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
request.from = from;
|
|
request.body.replymsg = reply;
|
|
|
|
request.seq = endpoint_getseq(ep);
|
|
|
|
rc = xce_encode(&request, pkt);
|
|
if (rc < 0) {
|
|
free_packet(pkt);
|
|
free(pkt);
|
|
|
|
return rc;
|
|
}
|
|
|
|
endpoint_enq(ep, &(pkt->link));
|
|
return 0;
|
|
}
|
|
|
|
int xce_nop_req(endpoint_t* ep)
|
|
{
|
|
xce_request_t request
|
|
= { .opcode = OPCode_nop, .body_which = Request_body_nomsg };
|
|
|
|
if (ep == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_hello_req(endpoint_t* ep, char* msg)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_hello,
|
|
.body_which = Request_body_hellomsg,
|
|
.body = {
|
|
.hellomsg = msg
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((ep == NULL) || (msg == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_join_req(endpoint_t* ep, int role, hostattrs_t* attrs)
|
|
{
|
|
/* clang-format off */
|
|
xce_joindata_t joinmsg = {
|
|
.role = role
|
|
};
|
|
xce_request_t request = {
|
|
.opcode = OPCode_join,
|
|
.body_which = Request_body_joinmsg,
|
|
.body = {
|
|
.joinmsg = &joinmsg
|
|
}
|
|
};
|
|
|
|
if ((role != HostRole_client) &&
|
|
(role != HostRole_worker) &&
|
|
(role != HostRole_apiserver) &&
|
|
(role != HostRole_scheduler)) {
|
|
return -EINVAL;
|
|
}
|
|
/* clang-format on */
|
|
|
|
if (role == HostRole_worker) {
|
|
if (attrs == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
joinmsg.data_which = JoinData_data_attrs;
|
|
joinmsg.data.attrs = attrs;
|
|
}
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_shutdown_req(endpoint_t* ep)
|
|
{
|
|
int rc;
|
|
dataq_t* outq;
|
|
xce_request_t request
|
|
= { .opcode = OPCode_shutdown, .body_which = Request_body_nomsg };
|
|
|
|
if (ep == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = xce_request(ep, &request);
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
outq = &(ep->outq);
|
|
|
|
while (!DATAQ_EMPTY(outq)) {
|
|
sleep(1);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int xce_pushconfig_req(endpoint_t* ep, xce_peerinfo_t* from,
|
|
xce_configdata_t* config)
|
|
{
|
|
int rc = 0;
|
|
/* clang-format off */
|
|
xce_request_t request
|
|
= { .opcode = OPCode_push, .body_which = Request_body_configpushmsg };
|
|
/* clang-format on */
|
|
|
|
if ((ep == NULL) || (config == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
request.body.configpushmsg = config;
|
|
rc = xce_request(ep, &request);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int xce_push_req(endpoint_t* ep, xce_peerinfo_t* from, xce_data_t* data)
|
|
{
|
|
int rc = 0;
|
|
xce_request_t request
|
|
= { .opcode = OPCode_push, .body_which = Request_body_pushmsg };
|
|
|
|
if ((ep == NULL) || (from == NULL) || (data == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
request.body.pushmsg = data;
|
|
|
|
rc = xce_request(ep, &request);
|
|
return rc;
|
|
}
|
|
|
|
int xce_push_data_req(endpoint_t* ep, xce_peerinfo_t* from, xce_data_t* data,
|
|
xce_check_fn_t checkf, void* checkarg, int pktlimit)
|
|
{
|
|
int nrows = 0;
|
|
int pos = 0;
|
|
int rc = 0;
|
|
xce_data_t data1;
|
|
int checkstatus = 0;
|
|
|
|
if ((ep == NULL) || (from == NULL) || (data == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
data1.table = data->table;
|
|
switch (data->table) {
|
|
case Data_data_schedjobs:
|
|
case Data_data_jobs:
|
|
nrows = data->data.jobs->n_total;
|
|
data1.data.jobs = (xce_jobs_data_t*)calloc(1, sizeof(xce_jobs_data_t));
|
|
if (data1.data.jobs == NULL) {
|
|
rc = -ENOMEM;
|
|
}
|
|
break;
|
|
case Data_data_schedworkers:
|
|
case Data_data_workers:
|
|
nrows = data->data.workers->n_total;
|
|
data1.data.workers
|
|
= (xce_workers_data_t*)calloc(1, sizeof(xce_workers_data_t));
|
|
if (data1.data.workers == NULL) {
|
|
rc = -ENOMEM;
|
|
}
|
|
break;
|
|
case Data_data_resources:
|
|
break;
|
|
case Data_data_resvals:
|
|
break;
|
|
default:
|
|
rc = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
if (pktlimit <= 0) {
|
|
pktlimit = nrows;
|
|
}
|
|
|
|
do {
|
|
int nc = nrows - pos;
|
|
|
|
if (nc > pktlimit) {
|
|
nc = pktlimit;
|
|
}
|
|
|
|
if (checkf != NULL) {
|
|
checkstatus = (*checkf)(checkarg);
|
|
if (checkstatus < 0) {
|
|
nc = 0;
|
|
}
|
|
}
|
|
|
|
switch (data->table) {
|
|
case Data_data_schedjobs:
|
|
case Data_data_jobs:
|
|
data1.data.jobs->n_total = data->data.jobs->n_total;
|
|
data1.data.jobs->pos = pos;
|
|
data1.data.jobs->count = nc;
|
|
if (nc == 0) {
|
|
data1.data.jobs->jobs = NULL;
|
|
} else {
|
|
data1.data.jobs->jobs = &(data->data.jobs->jobs[pos]);
|
|
}
|
|
break;
|
|
case Data_data_schedworkers:
|
|
case Data_data_workers:
|
|
data1.data.workers->n_total = data->data.workers->n_total;
|
|
data1.data.workers->pos = pos;
|
|
data1.data.workers->count = nc;
|
|
if (nc == 0) {
|
|
data1.data.workers->workers = NULL;
|
|
} else {
|
|
data1.data.workers->workers
|
|
= &(data->data.workers->workers[pos]);
|
|
}
|
|
break;
|
|
case Data_data_resources:
|
|
break;
|
|
case Data_data_resvals:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
rc = xce_push_req(ep, from, &data1);
|
|
|
|
if (rc < 0) {
|
|
break;
|
|
}
|
|
|
|
pos += nc;
|
|
|
|
} while ((pos < nrows) && (checkstatus >= 0));
|
|
|
|
switch (data->table) {
|
|
case Data_data_schedjobs:
|
|
case Data_data_jobs:
|
|
FREEUP(data1.data.jobs);
|
|
break;
|
|
case Data_data_schedworkers:
|
|
case Data_data_workers:
|
|
FREEUP(data1.data.workers);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xce_get_req(endpoint_t* ep, xce_get_t* get)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_get,
|
|
.body_which = Request_body_getmsg,
|
|
.body = {
|
|
.getmsg = get
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_reply_get(endpoint_t* ep, xce_peerinfo_t* from, xce_reply_t* reply,
|
|
xce_check_fn_t checkf, void* checkarg, int pktlimit)
|
|
{
|
|
int rc = 0;
|
|
int nrows = 0;
|
|
int pos = 0;
|
|
/* clang-format off */
|
|
xce_data_t getdata = {
|
|
.table = reply->data.getdata->table
|
|
};
|
|
xce_reply_t reply1 = {
|
|
.seq = reply->seq,
|
|
.opcode = reply->opcode,
|
|
.status = reply->status,
|
|
.data_which = reply->data_which,
|
|
.data = {
|
|
.getdata = &getdata
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
int checkstatus = 0;
|
|
xce_data_t* data = reply->data.getdata;
|
|
|
|
if ((ep == NULL) || (from == NULL) || (reply == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (getdata.table) {
|
|
case Data_data_schedjobs:
|
|
case Data_data_jobs:
|
|
nrows = data->data.jobs->n_total;
|
|
getdata.data.jobs
|
|
= (xce_jobs_data_t*)calloc(1, sizeof(xce_jobs_data_t));
|
|
break;
|
|
case Data_data_schedworkers:
|
|
case Data_data_workers:
|
|
nrows = data->data.workers->n_total;
|
|
getdata.data.workers
|
|
= (xce_workers_data_t*)calloc(1, sizeof(xce_workers_data_t));
|
|
break;
|
|
case Data_data_resources:
|
|
nrows = data->data.resources->n_total;
|
|
getdata.data.resources
|
|
= (xce_resource_data_t*)calloc(1, sizeof(xce_resource_data_t));
|
|
break;
|
|
case Data_data_resvals:
|
|
nrows = data->data.resvals->n_total;
|
|
getdata.data.resvals
|
|
= (xce_resval_data_t*)calloc(1, sizeof(xce_resval_data_t));
|
|
break;
|
|
default:
|
|
rc = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
if (rc < 0) {
|
|
/* FIXME we need to reply no data */
|
|
return rc;
|
|
}
|
|
|
|
if (pktlimit <= 0) {
|
|
pktlimit = nrows;
|
|
}
|
|
|
|
do {
|
|
int nc = nrows - pos;
|
|
|
|
if (nc > pktlimit) {
|
|
nc = pktlimit;
|
|
}
|
|
|
|
if (checkf != NULL) {
|
|
checkstatus = (*checkf)(checkarg);
|
|
|
|
if (checkstatus < 0) {
|
|
nc = 0;
|
|
}
|
|
}
|
|
|
|
switch (getdata.table) {
|
|
case Data_data_schedjobs:
|
|
case Data_data_jobs:
|
|
getdata.data.jobs->n_total = data->data.jobs->n_total;
|
|
getdata.data.jobs->pos = pos;
|
|
getdata.data.jobs->count = nc;
|
|
if (nc == 0) {
|
|
getdata.data.jobs->jobs = NULL;
|
|
} else {
|
|
getdata.data.jobs->jobs = &(data->data.jobs->jobs[pos]);
|
|
}
|
|
break;
|
|
case Data_data_schedworkers:
|
|
case Data_data_workers:
|
|
getdata.data.workers->n_total = data->data.workers->n_total;
|
|
getdata.data.workers->pos = pos;
|
|
getdata.data.workers->count = nc;
|
|
if (nc == 0) {
|
|
getdata.data.workers->workers = NULL;
|
|
} else {
|
|
getdata.data.workers->workers
|
|
= &(data->data.workers->workers[pos]);
|
|
}
|
|
break;
|
|
case Data_data_resources:
|
|
getdata.data.resources->n_total = data->data.resources->n_total;
|
|
getdata.data.resources->pos = pos;
|
|
getdata.data.workers->count = nc;
|
|
if (nc == 0) {
|
|
getdata.data.resources->resources = NULL;
|
|
} else {
|
|
getdata.data.resources->resources
|
|
= &(data->data.resources->resources[pos]);
|
|
}
|
|
break;
|
|
case Data_data_resvals:
|
|
getdata.data.resvals->n_total = data->data.resvals->n_total;
|
|
getdata.data.resvals->pos = pos;
|
|
getdata.data.resvals->count = nc;
|
|
if (nc == 0) {
|
|
getdata.data.resvals->vals = NULL;
|
|
} else {
|
|
getdata.data.resvals->vals = &(data->data.resvals->vals[pos]);
|
|
}
|
|
break;
|
|
default:
|
|
/* should never goes here */
|
|
break;
|
|
}
|
|
|
|
rc = xce_reply(ep, from, &reply1);
|
|
if (rc < 0) {
|
|
break;
|
|
}
|
|
|
|
pos += nc;
|
|
} while ((pos < nrows) && (checkstatus >= 0));
|
|
|
|
switch (getdata.table) {
|
|
case Data_data_schedjobs:
|
|
case Data_data_jobs:
|
|
FREEUP(getdata.data.jobs);
|
|
break;
|
|
case Data_data_schedworkers:
|
|
case Data_data_workers:
|
|
FREEUP(getdata.data.workers);
|
|
break;
|
|
case Data_data_resources:
|
|
FREEUP(getdata.data.resources);
|
|
break;
|
|
case Data_data_resvals:
|
|
FREEUP(getdata.data.resvals);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int extract_data(dataset_t* dataset, xce_data_t* getdata)
|
|
{
|
|
int ntotal;
|
|
int rc = 0;
|
|
int pos = 0;
|
|
int count = 0;
|
|
|
|
TRACE("%s ...", __func__);
|
|
|
|
switch (getdata->table) {
|
|
case Data_data_schedjobs:
|
|
case Data_data_jobs:
|
|
if (getdata->data.jobs->count <= 0) {
|
|
return 1;
|
|
}
|
|
|
|
ntotal = getdata->data.jobs->n_total;
|
|
pos = getdata->data.jobs->pos;
|
|
count = getdata->data.jobs->count;
|
|
|
|
if (dataset->rows == NULL) {
|
|
dataset->rows = (xce_job_t**)calloc(ntotal, sizeof(xce_job_t*));
|
|
dataset->nrows = 0;
|
|
}
|
|
|
|
memcpy((void*)(((char*)dataset->rows) + sizeof(xce_job_t*) * pos),
|
|
getdata->data.jobs->jobs, count * sizeof(xce_job_t*));
|
|
memset(getdata->data.jobs->jobs, 0x0, count * sizeof(xce_job_t*));
|
|
|
|
break;
|
|
case Data_data_schedworkers:
|
|
case Data_data_workers:
|
|
if (getdata->data.workers->count <= 0) {
|
|
return 1;
|
|
}
|
|
|
|
ntotal = getdata->data.workers->n_total;
|
|
if (dataset->rows == NULL) {
|
|
dataset->rows
|
|
= (xce_worker_t**)calloc(ntotal, sizeof(xce_worker_t*));
|
|
dataset->nrows = 0;
|
|
}
|
|
pos = getdata->data.workers->pos;
|
|
count = getdata->data.workers->count;
|
|
|
|
memcpy((void*)(((char*)dataset->rows) + sizeof(xce_worker_t*) * pos),
|
|
getdata->data.workers->workers, count * sizeof(xce_worker_t*));
|
|
memset(getdata->data.workers->workers, 0x0,
|
|
count * sizeof(xce_worker_t*));
|
|
|
|
break;
|
|
case Data_data_resources:
|
|
if (getdata->data.resources->count <= 0) {
|
|
return 1;
|
|
}
|
|
|
|
ntotal = getdata->data.resources->n_total;
|
|
if (dataset->rows == NULL) {
|
|
dataset->rows
|
|
= (xce_resource_t**)calloc(ntotal, sizeof(xce_resource_t*));
|
|
dataset->nrows = 0;
|
|
}
|
|
pos = getdata->data.resources->pos;
|
|
count = getdata->data.resources->count;
|
|
|
|
memcpy((void*)(((char*)dataset->rows) + sizeof(xce_resource_t*) * pos),
|
|
getdata->data.resources->resources,
|
|
count * sizeof(xce_resource_t*));
|
|
|
|
memset(getdata->data.resources->resources, 0x0,
|
|
count * sizeof(xce_resource_t*));
|
|
break;
|
|
case Data_data_resvals:
|
|
if (getdata->data.resvals->count <= 0) {
|
|
return 1;
|
|
}
|
|
|
|
ntotal = getdata->data.resvals->n_total;
|
|
if (dataset->rows == NULL) {
|
|
dataset->rows
|
|
= (xce_resval_t**)calloc(ntotal, sizeof(xce_resval_t*));
|
|
dataset->nrows = 0;
|
|
}
|
|
|
|
pos = getdata->data.resvals->pos;
|
|
count = getdata->data.resvals->count;
|
|
|
|
memcpy((void*)(((char*)dataset->rows) + sizeof(xce_resval_t*) * pos),
|
|
getdata->data.resvals->vals, count * sizeof(xce_resval_t*));
|
|
|
|
memset(getdata->data.resvals->vals, 0x0, count * sizeof(xce_resval_t*));
|
|
break;
|
|
default:
|
|
rc = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
dataset->nrows += count;
|
|
if (dataset->nrows < ntotal) {
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int xce_jobdispatch_req(endpoint_t* ep, xce_job_dispatch_t* info)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_jobdispatch,
|
|
.body_which = Request_body_dispatchmsg,
|
|
.body = {
|
|
.dispatchmsg = info
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
/* clang-format off */
|
|
if ((ep == NULL) ||
|
|
(info == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
/* clang-format on */
|
|
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_notify_req(endpoint_t* ep, xce_notify_data_t* data)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_notify,
|
|
.body_which = Request_body_notifymsg,
|
|
.body = {
|
|
.notifymsg = data
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((ep == NULL) || (data == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_jobsubmit_req(endpoint_t* ep, xce_job_submit_t* submit)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_jobsub,
|
|
.body_which = Request_body_jobsubmsg,
|
|
.body = {
|
|
.jobsubmsg = submit
|
|
}
|
|
};
|
|
/*clang-format on*/
|
|
|
|
/* clang-format off */
|
|
if ((ep == NULL) ||
|
|
(submit == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
/* clang-format on */
|
|
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_startjob_req(endpoint_t* ep, xce_job_exec_t* execinfo)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_startjob,
|
|
.body_which = Request_body_jobstartmsg,
|
|
.body = {
|
|
.jobstartmsg = execinfo
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_clusterconf_req(endpoint_t* ep)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_clusterconf,
|
|
.body_which = Request_body_nomsg
|
|
};
|
|
/* clang-format on */
|
|
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_update_req(endpoint_t* ep, xce_update_data_t* data)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_update,
|
|
.body_which = Request_body_updatemsg,
|
|
.body = {
|
|
.updatemsg = data
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((ep == NULL) || (data == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_jobctrl_req(endpoint_t* ep, xce_jobctrl_t* ctrinfo)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_jobcontrol,
|
|
.body_which = Request_body_jobctrlmsg,
|
|
.body = {
|
|
.jobctrlmsg = ctrinfo
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((ep == NULL) || (ctrinfo == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (ctrinfo->jobid == 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (ctrinfo->action) {
|
|
case JobControl_u_siginfo:
|
|
break;
|
|
case JobControl_u_ckptoption:
|
|
if (ctrinfo->u.ckptoption->method == NULL) {
|
|
ctrinfo->u.ckptoption->method = "default";
|
|
}
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
break;
|
|
}
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_queuectrl_req(endpoint_t* ep, xce_queuectrl_t* ctrlinfo)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_queuecontrol,
|
|
.body_which = Request_body_queuectrlmsg,
|
|
.body = {
|
|
.queuectrlmsg = ctrlinfo
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((ep == NULL) || (ctrlinfo == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ((ctrlinfo->queue == NULL) || (strlen(ctrlinfo->queue) == 0)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (ctrlinfo->action == QUEUE_DO_NONE) {
|
|
return 0;
|
|
}
|
|
|
|
if ((ctrlinfo->action < 0) || (ctrlinfo->action > QUEUE_ACTIVE)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
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 */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_runtasks,
|
|
.body_which = Request_body_runtaskmsg,
|
|
.body = {
|
|
.runtaskmsg = runinfo
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((ep == NULL) || (runinfo == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (runinfo->nhosts <= 0) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_set_pend_reason_req(endpoint_t* ep, xce_preason_set_t* reasons)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_setpreason,
|
|
.body_which = Request_body_preasonmsg,
|
|
.body = {
|
|
.preasonmsg = reasons
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((ep == NULL) || (reasons == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xce_request(ep, &request);
|
|
}
|
|
|
|
int xce_clear_reason_req(endpoint_t* ep, xce_clear_reason_t* reason)
|
|
{
|
|
/* clang-format off */
|
|
xce_request_t request = {
|
|
.opcode = OPCode_clrpreason,
|
|
.body_which = Request_body_clrpreasonmsg,
|
|
.body = {
|
|
.clrpreasonmsg = reason
|
|
}
|
|
};
|
|
/* clang-format on */
|
|
|
|
if ((ep == NULL) || (reason == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return xce_request(ep, &request);
|
|
}
|