int mgr_modify_node( struct pbsnode **ppnode, /* do some kind of "set" action on this node */ attribute_def *pdef, /* pbsnode doesn't have attributes but in the future it might so, make code similar to existing */ int limit, /* length of the *pdef array */ svrattrl *plist, /* batch request's svrattrl list begins here */ int privil, /* requester's privilege */ int *bad, /* if there is a "bad pbs_attribute" pass back position via this loc */ int mode) /*passed to attrib's action func not used by this func at this time*/ { int index; int rc = PBSE_NONE; pbs_attribute *new_attr; pbs_attribute *unused = NULL; pbs_attribute *pnew; if (plist == NULL) { return(0); /* nothing to do, return success */ } /* Get heap space for a temporary node-pbs_attribute array and use the * various "node-attribute action" functions defined in the file * "node_attr_def.c" to set the current values of each entry's * structure members */ new_attr = (pbs_attribute *)calloc((unsigned int)limit, sizeof(pbs_attribute)); if (new_attr == NULL) { return(PBSE_SYSTEM); } /* * The function "attr_atomic_node_set" does the following: * successively decodes the new pbs_attribute modifications carried in the * the request list, "plist", into a temporary pbs_attribute (on stack). * Updates each pbs_attribute in the derived node-attribute array using the * decoded values. If a failure of some sort occurs, as evidenced by * a non-zero return code (rc), call attr_atomic_kill() to undo * everything-- calls upon the "at_free" function for each pbs_attribute * to free hanging structures, then frees up the "new" array * return code (rc) shapes caller's reply */ if ((rc = attr_atomic_node_set(plist, unused, new_attr, pdef, limit, -1, privil, bad)) != 0) { attr_atomic_kill(new_attr, pdef, limit); return(rc); } for(index = ND_ATR_state;index < ND_ATR_LAST;index++) { pnew = new_attr + index; if (pnew->at_flags & ATR_VFLAG_MODIFY) { switch(index) { case ND_ATR_power_state: { rc = set_node_power_state(ppnode,pnew->at_val.at_short); } break; case ND_ATR_ttl: { snprintf((*ppnode)->nd_ttl, sizeof((*ppnode)->nd_ttl), "%s", pnew->at_val.at_str); rc = PBSE_NONE; } break; case ND_ATR_acl: { (*ppnode)->nd_acl = pnew->at_val.at_arst; rc = PBSE_NONE; } break; case ND_ATR_requestid: { *(*ppnode)->nd_requestid = pnew->at_val.at_str; rc = PBSE_NONE; } break; case ND_ATR_state: case ND_ATR_np: case ND_ATR_properties: case ND_ATR_ntype: case ND_ATR_jobs: case ND_ATR_status: case ND_ATR_note: case ND_ATR_mom_port: case ND_ATR_mom_rm_port: case ND_ATR_num_node_boards: case ND_ATR_numa_str: case ND_ATR_gpus: case ND_ATR_gpus_str: case ND_ATR_gpustatus: case ND_ATR_mics: case ND_ATR_micstatus: default: rc = PBSE_IVALREQ; break; } } if((rc != PBSE_NONE)||(*ppnode == NULL)) { break; } } free(new_attr); return(rc); } /* END mgr_modify_node() */
int main( int argc, /* I */ char **argv) /* I */ { struct batch_status *bstatus = NULL; int con; char *specified_server = NULL; int errflg = 0; int i; extern char *optarg; extern int optind; char **pa; struct batch_status *pbstat; int flag = ALLI; char *note = NULL; char *power_state = NULL; enum note_flags note_flag = unused; char **nodeargs = NULL; int lindex; int rc = 0; enum NStateEnum ListType = tnsNONE; /* get default server, may be changed by -s option */ progname = strdup(argv[0]); while ((i = getopt(argc, argv, "acdlm:opqrs:x-:N:n:")) != EOF) { switch (i) { case 'a': flag = ALLI; break; case 'c': flag = CLEAR; break; case 'd': flag = DIAG; break; case 'l': flag = LIST; break; case 'm' : flag = MODIFY; power_state = strdup(optarg); if (power_state == NULL) { perror("Error: strdup() returned NULL"); exit(1); } break; case 'o': flag = OFFLINE; break; case 'p': flag = PURGE; break; case 'q': quiet = 1; break; case 'r': flag = RESET; break; case 's': specified_server = optarg; break; case 'x': flag = ALLI; DisplayXML = TRUE; break; case 'N': /* preserve any previous option other than the default, * to allow -N to be combined with -o, -c, etc */ if (flag == ALLI) flag = NOTE; note = strdup(optarg); if (note == NULL) { perror("Error: strdup() returned NULL"); exit(1); } note_flag = set; /* -N n is the same as -N "" -- it clears the note */ if (!strcmp(note, "n")) *note = '\0'; if (strlen(note) > MAX_NOTE) { fprintf(stderr, "Warning: note exceeds length limit (%d) - server may reject it...\n", MAX_NOTE); } if (strchr(note, '\n') != NULL) fprintf(stderr, "Warning: note contains a newline - server may reject it...\n"); break; case 'n': note_flag = list; break; case '-': if ((optarg != NULL) && !strcmp(optarg, "version")) { fprintf(stderr, "Version: %s\nCommit: %s\n", PACKAGE_VERSION, GIT_HASH); exit(0); } else if ((optarg != NULL) && !strcmp(optarg, "about")) { TShowAbout_exit(); } errflg = 1; break; case '?': default: errflg = 1; break; } /* END switch (i) */ } /* END while (i = getopt()) */ if ((note_flag == list) && (flag != LIST)) { fprintf(stderr, "Error: -n requires -l\n"); errflg = 1; } for (pa = argv + optind;*pa;pa++) { if (strlen(*pa) == 0) { errflg = 1; } } if (errflg != 0) { if (!quiet) { fprintf(stderr, "usage:\t%s [-{c|d|l|o|p|r}] [-s server] [-n] [-N \"note\"] [-q] [-m standby|suspend|sleep|hibernate|shutdown] node ...\n", progname); fprintf(stderr, "\t%s [-{a|x}] [-s server] [-q] [node]\n", progname); } exit(1); } con = cnt2server(specified_server); if (con <= 0) { if (!quiet) { fprintf(stderr, "%s: cannot connect to server %s, error=%d (%s)\n", progname, (specified_server) ? specified_server : pbs_default(), con * -1, pbs_strerror(con * -1)); } exit(1); } /* if flag is ALLI, LIST, get status of all nodes */ if ((flag == ALLI) || (flag == LIST) || (flag == DIAG)) { if ((flag == ALLI) || (flag == LIST) || (flag == DIAG)) { if (flag == LIST) { /* allow state specification */ if (argv[optind] != NULL) { for (lindex = 1;lindex < tnsLAST;lindex++) { if (!strcasecmp(NState[lindex], argv[optind])) { ListType = (enum NStateEnum)lindex; optind++; break; } } } } /* allow node specification (if none, then create an empty list) */ if (argv[optind] != NULL) { nodeargs = argv + optind; } else { nodeargs = (char **)calloc(2, sizeof(char **)); nodeargs[0] = strdup(""); nodeargs[1] = '\0'; } } } if ((note_flag == set) && (note != NULL)) { /* set the note attrib string on specified nodes */ for (pa = argv + optind;*pa;pa++) { set_note(con, *pa, note); } } switch (flag) { case DIAG: /* NYI */ break; case CLEAR: /* clear OFFLINE from specified nodes */ for (pa = argv + optind;*pa;pa++) { marknode(con, *pa, ND_offline, DECR, NULL, DECR); } break; case RESET: /* clear OFFLINE, add DOWN to specified nodes */ for (pa = argv + optind;*pa;pa++) { marknode(con, *pa, ND_offline, DECR, ND_down, INCR); } break; case OFFLINE: /* set OFFLINE on specified nodes */ for (pa = argv + optind;*pa;pa++) { marknode(con, *pa, ND_offline, INCR, NULL, INCR); } break; case PURGE: /* remove node record */ /* NYI */ break; case ALLI: if (DisplayXML == TRUE) { char *tmpBuf = NULL, *tail = NULL; int bufsize; mxml_t *DE; DE = NULL; MXMLCreateE(&DE, "Data"); for (lindex = 0;nodeargs[lindex] != '\0';lindex++) { bstatus = statnode(con, nodeargs[lindex]); for (pbstat = bstatus;pbstat;pbstat = pbstat->next) { addxmlnode(DE, pbstat); } /* END for (pbstat) */ pbs_statfree(pbstat); } MXMLToXString(DE, &tmpBuf, &bufsize, INT_MAX, &tail, TRUE); MXMLDestroyE(&DE); fprintf(stdout, "%s\n", tmpBuf); } else { for (lindex = 0;nodeargs[lindex] != '\0';lindex++) { bstatus = statnode(con, nodeargs[lindex]); for (pbstat = bstatus;pbstat;pbstat = pbstat->next) { printf("%s\n", pbstat->name); prt_node_attr(pbstat, 0); putchar('\n'); } /* END for (bpstat) */ pbs_statfree(pbstat); } } break; case LIST: /* list any node that is DOWN, OFFLINE, or UNKNOWN */ for (lindex = 0;nodeargs[lindex] != '\0';lindex++) { bstatus = statnode(con, nodeargs[lindex]); for (pbstat = bstatus;pbstat != NULL;pbstat = pbstat->next) { char *S; S = get_nstate(pbstat); if (filterbystate(pbstat, ListType, S)) { char *n; if ((note_flag == list) && (n = get_note(pbstat))) { printf("%-20.20s %-26.26s %s\n", pbstat->name, S, n); } else { printf("%-20.20s %s\n", pbstat->name, S); } } } pbs_statfree(pbstat); } break; case MODIFY: /* set power state for specified nodes */ for (pa = argv + optind;*pa;pa++) { rc = set_node_power_state(con, *pa, power_state); } break; } /* END switch (flag) */ pbs_disconnect(con); return(rc); } /* END main() */