Commit a12ed9ed authored by David Johnson's avatar David Johnson

Add domanifest command.

domanifest returns service configuration info (both static,
administrator info and per-experiment info), and also service hook
configuration.
parent 7aa6e503
......@@ -229,6 +229,7 @@ static event_handle_t event_handle = NULL;
COMMAND_PROTOTYPE(doreboot);
COMMAND_PROTOTYPE(donodeid);
COMMAND_PROTOTYPE(domanifest);
COMMAND_PROTOTYPE(dostatus);
COMMAND_PROTOTYPE(doifconfig);
COMMAND_PROTOTYPE(doaccounts);
......@@ -336,6 +337,7 @@ struct command {
} command_array[] = {
{ "reboot", FULLCONFIG_NONE, 0, doreboot },
{ "nodeid", FULLCONFIG_ALL, 0, donodeid },
{ "manifest", FULLCONFIG_ALL, 0, domanifest },
{ "status", FULLCONFIG_NONE, 0, dostatus },
{ "ifconfig", FULLCONFIG_ALL, F_ALLOCATED, doifconfig },
{ "accounts", FULLCONFIG_ALL, F_REMREQSSL, doaccounts },
......@@ -1389,6 +1391,349 @@ COMMAND_PROTOTYPE(donodeid)
return 0;
}
/*
* Return a boot manifest for the node's boot scripts.
*/
COMMAND_PROTOTYPE(domanifest)
{
MYSQL_RES *res = NULL;
MYSQL_ROW row;
char buf[2*MYBUFSIZE];
int nrows;
int disable_type = 0, disable_osid = 0, disable_node = 0;
res = mydb_query("select opt_name,opt_value"
" from virt_client_service_opts"
" where exptidx=%d or vnode='%s'",
2, reqp->exptidx, reqp->nickname);
if (!res) {
info("MANIFEST: %s: DB Error getting expt client service opts!\n",
reqp->nodeid);
}
else if ((nrows = (int)mysql_num_rows(res)) == 0) {
mysql_free_result(res);
res = NULL;
}
while (nrows) {
row = mysql_fetch_row(res);
if (strcmp(row[0],"disable_type") == 0
&& strcmp(row[1],"1") == 0) {
disable_type = 1;
}
else if (strcmp(row[0],"disable_osid") == 0
&& strcmp(row[1],"1") == 0) {
disable_osid = 1;
}
else if (strcmp(row[0],"disable_node") == 0
&& strcmp(row[1],"1") == 0) {
disable_node = 1;
}
else {
info("MANIFEST: %s: unknown expt client service opt %s!\n",
reqp->nodeid,row[0]);
}
}
if (res) {
mysql_free_result(res);
res = NULL;
nrows = 0;
}
/*
* This is a messy query. The rules for the manifest are
* 0) only service and hook entries whose service (service,env,whence)
* tuples exist in the client_services table can be returned;
* 1) only one SERVICE line foreach (service,env) tuple can be
* returned;
* 2) the user can only override (service,env) tuples that have
* user_can_override set to 1;
* (and if there are multiple admin tuples, but the highest-prio
* one allows override, even if less prio ones don't, we still
* allow override!)
* 3) multiple HOOK lines can be returned, and the order in
* which hook lines are generated is by querying the
* client_service_hooks table for node types matching this node;
* the client_service_hooks table for osids matching this node;
* the client_service_hooks table for nodes matching this node;
* the virt_client_service_hooks table for '' nodes
* (wildcard, experiment wide);
* the virt_client_service_hooks table for nodes matching
* this node.
* 4) the user can disable all admin hooks with
* user_can_override set to 1
* 5) the virt_client_service_opts table controls which types of
* admin hooks are disabled, across the experiment, or per-node.
*/
res = mydb_query("select cs.service,cs.env,cs.whence,"
/* 3 */
" vcsnodeblobs.uuid,vcsnode.alt_vblob_id,vcsnode.enable,vcsnode.enable_hooks,vcsnode.fatal,"
/* 8 */
" vcsexptblobs.uuid,vcsexpt.alt_vblob_id,vcsexpt.enable,vcsexpt.enable_hooks,vcsexpt.fatal,"
/* 13 */
" csnode.alt_blob_id,csnode.enable,csnode.enable_hooks,"
/* 16 */
" csnode.fatal,csnode.user_can_override,"
/* 18 */
" csos.alt_blob_id,csos.enable,csos.enable_hooks,"
/* 21 */
" csos.fatal,csos.user_can_override,"
/* 23 */
" cstype.alt_blob_id,cstype.enable,cstype.enable_hooks,"
/* 26 */
" cstype.fatal,cstype.user_can_override"
" from reserved as r"
" left join nodes as n on r.node_id=n.node_id"
" straight_join client_services as cs"
" left join virt_client_service_ctl as vcsexpt on"
" (r.exptidx=vcsexpt.exptidx and vcsexpt.vnode=''"
" and cs.idx=vcsexpt.service_idx"
" and cs.env=vcsexpt.env"
" and cs.whence=vcsexpt.whence)"
" left join blobs as vcsexptblobs on"
" (vcsexpt.exptidx=vcsexptblobs.exptidx"
" and vcsexpt.alt_vblob_id=vcsexptblobs.vblob_id)"
" left join virt_client_service_ctl as vcsnode on"
" (r.exptidx=vcsnode.exptidx"
" and r.vname=vcsnode.vnode"
" and cs.idx=vcsnode.service_idx"
" and cs.env=vcsnode.env"
" and cs.whence=vcsnode.whence)"
" left join blobs as vcsnodeblobs on"
" (vcsnode.exptidx=vcsnodeblobs.exptidx"
" and vcsnode.alt_vblob_id=vcsnodeblobs.vblob_id)"
" left join client_service_ctl as csnode on"
" (csnode.obj_type='node'"
" and r.node_id=csnode.obj_name"
" and cs.idx=csnode.service_idx"
" and cs.env=csnode.env"
" and cs.whence=csnode.whence)"
" left join client_service_ctl as csos on"
" (csos.obj_type='osid' and n.def_boot_osid=csos.obj_name"
" and cs.idx=csos.service_idx and cs.env=csos.env"
" and cs.whence=csos.whence)"
" left join client_service_ctl as cstype on"
" (cstype.obj_type='node_type'"
" and n.type=cstype.obj_name"
" and cs.idx=cstype.service_idx"
" and cs.env=cstype.env and cs.whence=cstype.whence)"
" where r.exptidx=%d and r.node_id='%s'"
" and (vcsnode.enable is not NULL"
" or vcsexpt.enable is not NULL"
" or csnode.enable is not NULL"
" or csos.enable is not NULL"
" or cstype.enable is not NULL)",
28, reqp->exptidx, reqp->nodeid);
if (!res) {
error("MANIFEST: %s: DB Error getting manifest info!\n",
reqp->nodeid);
nrows = 0;
}
else if ((nrows = (int)mysql_num_rows(res)) == 0) {
mysql_free_result(res);
res = NULL;
}
while (nrows) {
char *enabled = NULL;
char *hooks_enabled = NULL;
char *fatal = NULL;
char *blobid = NULL;
int admin_service_not_overrideable = 0;
int admin_idx = 0;
row = mysql_fetch_row(res);
/* figure out which service control entry to use! */
/* start by choosing the per-node or per-experiment stuff */
if (row[5] != NULL) {
enabled = row[5];
hooks_enabled = row[6];
fatal = row[7];
blobid = row[3];
/*
* If there was nothing in blob_blobs for this blob,
* just return the vblob and hope it was a real,
* hardcoded blob in the blob store.
*/
if (blobid == NULL)
blobid = row[4];
}
else if (row[9] != NULL) {
enabled = row[10];
hooks_enabled = row[11];
fatal = row[12];
blobid = row[7];
if (blobid == NULL)
blobid = row[8];
}
if (row[17] != NULL && !disable_node) {
admin_idx = 13;
if (strcmp(row[17],"0") == 0) {
admin_service_not_overrideable = 1;
}
}
else if (row[22] != NULL && !disable_osid) {
admin_idx = 18;
if (strcmp(row[22],"0") == 0) {
admin_service_not_overrideable = 1;
}
}
else if (row[27] != NULL && !disable_type) {
admin_idx = 22;
if (strcmp(row[27],"0") == 0) {
admin_service_not_overrideable = 1;
}
}
/* If the admin seting can't be overridden, or if the
* user didn't specify a control for this node or
* experiment-wide, send the admin setting */
if (admin_service_not_overrideable || enabled == NULL) {
enabled = row[admin_idx+1];
hooks_enabled = row[admin_idx+2];
fatal = row[admin_idx+3];
blobid = row[admin_idx+0];
}
/* the query should prevent against this, but... */
if (enabled == NULL) {
error("MANIFEST: %s: got info from DB for %s, but no enabled!\n",
reqp->nodeid,row[0]);
--nrows;
continue;
}
if (blobid == NULL)
blobid = "";
OUTPUT(buf, sizeof(buf),
"SERVICE NAME=%s ENV=%s WHENCE=%s"
" ENABLED=%s HOOKS_ENABLED=%s FATAL=%s"
" BLOBID=%s\n",
row[0],row[1],row[2],
enabled,hooks_enabled,fatal,blobid);
client_writeback(sock, buf, strlen(buf), tcp);
nrows--;
if (verbose)
info("MANIFEST: %s", buf);
}
if (res) {
mysql_free_result(res);
res = NULL;
nrows = 0;
}
/* grab the admin client side hooks */
res = mydb_query("select cs.service,cs.env,cs.whence,csh.obj_type,"
" csh.hook_blob_id,csh.hook_op,csh.hook_point,"
" csh.argv,csh.fatal,csh.user_can_override"
" from reserved as r"
" left join nodes as n on r.node_id=n.node_id"
" straight_join client_services as cs"
" left join client_service_hooks as csh on"
" (cs.idx=csh.service_idx"
" and cs.env=csh.env"
" and cs.whence=csh.whence)"
" where r.exptidx=%d and r.node_id='%s'"
" and ((csh.obj_type='node'"
" and r.node_id=csh.obj_name)"
" or (csh.obj_type='osid'"
" and n.def_boot_osid=csh.obj_name)"
" or (csh.obj_type='node_type'"
" and n.type=csh.obj_name))",
10,reqp->exptidx,reqp->nodeid);
if (!res) {
error("MANIFEST: %s: DB Error getting manifest admin hook info!\n",
reqp->nodeid);
}
else if ((nrows = (int)mysql_num_rows(res)) == 0) {
mysql_free_result(res);
res = NULL;
}
while (nrows) {
row = mysql_fetch_row(res);
/*
* skip this admin hook if it can be overridden, and if
* the user turned off this type of admin hooks
*/
if (strcmp(row[9],"1") == 0
&& ((strcmp(row[3],"node") == 0 && disable_node)
|| (strcmp(row[3],"osid") == 0 && disable_osid)
|| (strcmp(row[3],"type") == 0 && disable_type))) {
--nrows;
continue;
}
OUTPUT(buf, sizeof(buf),
"HOOK SERVICE=%s ENV=%s WHENCE=%s"
" OP=%s POINT=%s FATAL=%s BLOBID=%s ARGV=\"%s\"\n",
row[0],row[1],row[2],
row[5],row[6],row[8],row[4],row[7]);
client_writeback(sock, buf, strlen(buf), tcp);
nrows--;
if (verbose)
info("MANIFEST: %s", buf);
}
if (res) {
mysql_free_result(res);
res = NULL;
nrows = 0;
}
/* grab the user-specified client side hooks */
res = mydb_query("select cs.service,cs.env,cs.whence,"
" cshblobs.uuid,csh.hook_vblob_id,csh.hook_op,csh.hook_point,"
" csh.argv,csh.fatal"
" from reserved as r"
" left join nodes as n on r.node_id=n.node_id"
" straight_join client_services as cs"
" left join virt_client_service_hooks as csh on"
" (r.exptidx=csh.exptidx"
" and (csh.vnode='' or r.vname=csh.vnode)"
" and cs.idx=csh.service_idx"
" and cs.env=csh.env"
" and cs.whence=csh.whence)"
" left join blobs as cshblobs on"
" (csh.exptidx=cshblobs.exptidx"
" and csh.hook_vblob_id=cshblobs.vblob_id)"
" where r.exptidx=%d and r.node_id='%s'"
" and csh.hook_vblob_id is not NULL",
9,reqp->exptidx,reqp->nodeid);
if (!res) {
error("MANIFEST: %s: DB Error getting manifest user hook info!\n",
reqp->nodeid);
}
else if ((nrows = (int)mysql_num_rows(res)) == 0) {
mysql_free_result(res);
res = NULL;
}
while (nrows) {
row = mysql_fetch_row(res);
OUTPUT(buf, sizeof(buf),
"HOOK SERVICE=%s ENV=%s WHENCE=%s"
" OP=%s POINT=%s FATAL=%s BLOBID=%s ARGV=\"%s\"\n",
row[0],row[1],row[2],
row[5],row[6],row[8],(row[3]) ? row[3] : row[4],row[7]);
client_writeback(sock, buf, strlen(buf), tcp);
nrows--;
if (verbose)
info("MANIFEST: %s", buf);
}
if (res) {
mysql_free_result(res);
res = NULL;
nrows = 0;
}
return 0;
}
/*
* Return status of node. Is it allocated to an experiment, or free.
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment